If I have seen further it is by standing on the shoulders of giants.
It’s a really exciting time at the moment with Zend Framework 2 gaining so much traction, after being stable for some time now.
Though I and countless others really enjoyed the 1.x series, it did leave some things to be desired – to be fair.
But the more I explore of the 2.x series, the more I honestly can say that I’m very impressed with it. It may not be as fast as the previous series, but with respect to development, there’s so much going for it it’s worth shouting about.
So it really is rewarding and exciting to begin covering all that it has to offer us. In part one of this series, I looked at a central concept of the revised framework – Dependency Injection.
In this, the second part, I’m moving on to give a good introduction to the next most important aspect – Modules.
In today’s post, we’ll be looking at what they are, some thoughts and quotes from the key developers involved and working code to get you started.
Quoting directly from the manual, here, in a nutshell, is what you can expect from 2.x Module.
Zend Framework 2.0 introduces a new and powerful approach to modules. This new module system is designed with flexibility, simplicity, and re-usability in mind. A module may contain just about anything: PHP code, including MVC functionality; library code; view scripts; and/or public assets such as images, CSS, and JavaScript.
Want another take on it? Matthew Weier O’Phinney says it most succinctly on his blog:
In ZF2, a module is simply a namespaced directory, with a single “Module” class under it; no more, and no less, is required.
And here’s the description from the Modules author himself, Evan Coury:
A re-usable piece of functionality that can be used to construct a more complex application.
Modules are comprised of three key concepts:
I’m not going to do you the injustice of parroting the manual; but instead say it as I understand it. In the 1.x series, an application could be seen as a series of, at least partially, coupled components.
The 2.x series breaks from that dynamic and supports a true inter-relation of uncoupled modules. Each of the modules can stand alone, be designed to work together cohesively, or be the application all in and of itself. This is made possible through the 3 previously mentioned components.
For the best example of this working, checkout the excellent and rapidly growing ZF Modules project. It’s still a fairly new project, but you can see that as new as it is, there’s likely a module to suit your needs.
For example:
Each module that you write, can, if desired, provide its own views, layouts, images, css and javascript files, and anything else that it needs.
Or, it can make use of other modules – so that you only write the minimal amount of code that’s required.
Now, that’s my simplistic explanation of the new modules system in ZF2. Let’s work through some code and see how to create one.
Using the recommended structure for a ZF2 module, create a new directory under the module directory, that you’ll find when you start with the Zend Skeleton application.
I’ve created one and called it Generic. There’s no special reason for this name, other than to make it clear it’s mine. Under that, create a new file called Module.php.
This is the Bootstrap file that you would have been used to in the 1.x series. It’s just about as simple as the previous approach. All it needs to contain is the following:
namespace Generic; class Module { } |
That’s it. With that, you have a functioning module. Note that you need to use PHP namespaces when working with ZF2.
Everything under your module will need to respect that when it’s developed. Namespaces aren’t the only change you need to be aware of. For more, check out the next section.
Now I said that the module in its current form will function – but it won’t be loaded. For that, you need to add your module to /config/application.config.php. My version, from the Zend Skeleton application looks as follows:
return array( 'modules' => array( 'Application', 'Generic' // << My Generic Module ), 'module_listener_options' => array( 'config_glob_paths' => array( 'config/autoload/{,*.}{global,local}.php', ), 'module_paths' => array( './module', './vendor', ), ), ); |
You can see that it has two key array keys: modules and module_listener_options. If your module’s namespace isn’t listed in modules, then the Module Autoloader will not load it. This may seem a bit confusing coming from the 1.x series. But it makes sense.
If you’d like a really good understanding behind the reasons why modules aren’t autoloader, check out this post from ZF project lead Matthew Weier O’Phinney.
I’ll sum it up by saying that, it’s a good approach to take. Consider the following scenarios:
In the module_listener_options array key, you’ll see:
'config_glob_paths' => array( 'config/autoload/{,*.}{global,local}.php', ), |
What this does is to tell the ModuleManager which configurations to compile together in to the aggregate configuration for the application.
So if/when you create a config directory in your module and add in the standard module.config.php, then its configuration will be merged with the other modules in the application.
Now, the module configuration that I’ve covered so far is the stock one. It’s made possible by the following function in Module.php:
public function getConfig() { return include __DIR__ . '/config/module.config.php'; } |
It returns an array or Traversable object that contains the environment delineated configuration for your application, i.e., production, staging, development etc.
In it you can include a number of configurations areas, such as dependency injection, routing, views and more.
Now, you have to make sure that the Module Autoloader can make best use of your module implement the getAutoloaderConfig function.
This informs the Module Autoloader where to find the required classes. Here’s the stock function that I’ve used:
public function getAutoloaderConfig() { return array( 'Zend\Loader\ClassMapAutoloader' => array( __DIR__ . '/autoload_classmap.php', ), 'Zend\Loader\StandardAutoloader' => array( 'namespaces' => array( __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__, ), ), ); } |
Now what I’ve covered so far is a basic module. There are a few other directories that you’ll likely use
Under source are all the PHP files for your application. Similar in style to the 1.x series it can also include directories for:
All of your view templates, in directories that match the controller names in the module and with names that match the controller actions. Not much different from 1.x.
This is, in my not so humble opinion, a very welcome inclusion in 2.x. I felt so often that testing was really an after thought previously?
Despite there being a lot of documentation around, there always seemed to be problems getting it started, consistency in the information provided or gaps in what was written.
I’ve followed along with the manual and am very happy to say that it worked first time for me, no issues and no hassles whatsoever. It was a real pleasure to see how easy and integral it was.
Nothing gives more confidence than solid tests when developing applications. Right?
Unless you’re developing a very specific application, the possibility of not localising or internationalising it is very slim. So, like testing, localisation is baked in, right from the get go.
If you’re getting started with the skeleton application, which I strongly suggest you do, you’ll see it contains an Application module that has it’s language directory pre-populated with PO and MO files for a wide assortment of languages.
Don’t worry if you’re not too familiar with it, grab a copy of Poedit for your platform and open up one of them and you’ll see the base language and translation side by side – ready for you to add to or modify.
You may be familiar with an option in the 1.x series that allowed you to compile a class list so that it didn’t have be searched on every invocation.
Well, an even better setup is integrated in to the 2.x series. Under your module, you can add a file, called autoload_classmap.php.
In that, you return a list of classes in a manner compliant with the new ZF2 autoloader. For my, Generic, module it returns an empty array as I have no production concerns to be worries about.
However, you can use the built in classmap_generator.php script to do this. You’ll find it in the /bin directory of the ZF2 source.
For a good understanding of the new autoloader, check out the great post by Rob Allen.
As you may have seen in the code snippet above, there was an array key called module_paths in the configuration returned from application.config.php.
This is part of what makes the new module structure so flexible. The directories specified there are the paths that the Module Autoloader searches when loading modules.
So, if you want to stick with the recommended structure, then keep ‘./module’ in there. If you want to go with a different structure, change the name. I like the configuration provided.
You keep your modules under ./modules and add 3rd party libraries under ./vendor. That way you know what’s yours and what’s external.
It’s a simple approach which I believe will pay off big maintenance dividends down the track in a project. Tell me I’m not right about that one!
Though all this change is very exciting, please be aware that you can’t just make a simple transition to the 2.x series. The 2.x series takes a lot of the PHP 5.3 advancements in to account.
To make a smooth transition as possible ensure that you’re all over the following concepts:
So, there you have it. I hope you enjoyed this introduction to one of the key aspects of Zend Framework 2 – the ModuleManager. Through the definition of it, seeing what some of the core developers have said and the working code example, I’m confident that you’ll be able to get up and running with it very quickly.
Please don’t feel cheated with this introduction. To be honest, there’s a hell of a lot that can be involved in making full use of the new Modules system, despite what I said at the start.
My aim here was to give you a simple and effective introduction that we can build on progressively.
Do you see it as the improvement it is, over the 1.x series? Are there any points that you feel were missed? Tell me in the comments?
If you're new to or migrating to the Zend Framework this book will help you get up and running quickly.
Whether you're completely new to Zend Framework, have experience in PHP or other MVC-based frameworks, this book will teach you what you need to know to successfully develop applications with Zend Framework 2. Register your interest TODAY to get your copy of the book when it's released in April
Why Kohana is an Excellent Alternative to Zend Framework
20 Jul 2012

Writing a simple blog with Zend Framework and mongoDB
07 Nov 2010

Zend Framework 2 – Hydrators, Models and the TableGateway Pattern
15 May 2013

Zend Framework 2 Event Manager – A Gentle Introduction
15 Jan 2013
[...] http://www.maltblue.com/tutorial/zend-framework-2-modules-the-applications-heart [...]