It’s been almost a month now since the release of Zend Framework 1.8, and although I was very excited about some of the new features, it’s taken me awhile to digest that excitement into something bloggable. As a result, I apologize if I’m a bit late to the party…but I’d like to take a moment nonetheless to discuss the implications of my favorite 1.8 feature: Zend_Application_Resource_Modules.
Zend Framework has provided what it calls a “conventional modular directory structure” for quite some time now: specifically, Zend Framework modules are supposed to “[allow] you to separate different MVC applications into self-contained units, and re-use them with different front controllers”. Unfortunately, up until 1.8, I have never found this to be entirely accurate. Based on module architectures I’d seen in full-stack content management systems, I’d always kind of hoped that installing a module would be as easy as this:
- Download the source code and copy it into your application’s modules directory.
- Hooray, it works now!
Now, this was true enough for modules that only provided a couple controllers and view scripts, but the second you introduced, say, controller plugins or models in the include_path, you’d have to modify your application-level bootstrap file, providing it with detailed knowledge of what the module provides. Because of this, the framework hasn’t really inspired a lot of distributable, reusable third-party modules; after all, the process for installing them would actually have looked something like this:
- Download the source code and copy it into your application’s modules directory.
- Adjust your application entry point (index.php) to include the module’s models folder in the include_path.
- Adjust your application-level bootstrap file to register the new modules directory with the front controller, if you haven’t configured it that way already.
- Adjust your application-level bootstrap file to register any plugins or plugin paths it might provide.
- Install any database schemas that might have come with the module.
- Hooray, it works now!
The problem here is that the parent application (and the person installing it) has to know all sorts of nitty-gritty details about how the module does its business. In my opinion, a truly “self-contained” module would be able to handle a lot of the above process all by itself, without any modifications to the parent application; otherwise, it’s not really self-contained, and not particularly easy to distribute to other developers.
Enter 1.8
However, as I mentioned earlier, this situation has changed dramatically in Zend Framework 1.8, due to a wonderful little component called Zend_Application_Resource_Modules. Among other things, it provides the following:
- Modules can now provide their own bootstrapping logic; no more need to register module-provided plugins, paths, etc. in the application-wide bootstrap file.
- Autoloading of common types of module-provided classes is now automatically set up for you; no more need to add modules to your include_path, or even to require_once your module class files before you use them.
See the benefit? All of the application-level configuration we used to have to do can now be encapsulated in a bootstrap process provided as a part of the module itself. This cuts the above workflow down to something like this:
- Download the source code and copy it into your application’s modules directory.
- Install any database schemas that might have come with the module.
- Hooray, it works now!
Suddenly, the prospect of downloading somebody else’s reusable module is a lot more appealing.
Some further issues
You’ll notice, however, that this still doesn’t quite match my first ideal workflow. Although Zend_Application_Resource_Modules provides a lot of assistance in getting your modules bootstrapped once they’re installed, it cannot yet provide much assistance with the installation process itself. As a result, if you’re trying to install a distributed module that involves database schemas, you’ll still have to install those by hand.
It’s also worth noting that Zend_Application_Resource_Modules does not yet provide a way to track and enforce module dependencies. For the most part this isn’t necessary; by the time everything is bootstrapped, all module-provided code is available through autoloading. However, there are a couple of situations in which it would be necessary:
- If Module A needs to use a class provided by Module B during Module A’s own bootstrap, Module B must have been bootstrapped first…otherwise the autoloader for Module B’s classes won’t be ready yet.
- If Module A provides a plugin that, for whatever reason, assumes that a plugin from Module B always fires before it, then Module B’s plugins need to be registered before Module A’s.
I’m working (in my copious spare time) on a distributable module of my own right now that could really benefit from both dependency tracking and database installation…but with how much better module architecture has already gotten in 1.8, I can only assume that future releases will be even more elegant. In the meantime, keep an eye out for my new module; I’d love the benefit of community review once it’s ready.