Understanding ZF2 Configuration

In Zend Framework 2 we no longer have the commanding application.ini, instead we got the option to configure our website or rather the modules on a per-module-basis. Furthermore, the modules are able to overwrite each others configuration. With this in mind, it makes it even more important to understand how ZF2 manages the configuration files of several modules internally. In this blog i will guide you guys through the internal process of the framework.

Where does configuration come from?

Before we go into the internals, let’s get a quick overview of where configuration usually comes from. Ultimately there’s only three places, that deliver configuration:

  1. ./config/application.config.php
  2. each Modules class Module
  3. ./config/autoload/(.*?).php

But wait, what about ./modules/(ModuleName)/config/module.config.php? Well, this file only exists for separation concerns. This config file will be called by the Module->getConfig(), so ultimately the config provider is the Module class itself. Knowing that let’s go through the configuration process.

Zend\Mvc\Application::init()

The very first configuration file that will be loaded is the /config/application.config.php. When we take a quick look at the ZendSkeletonApplications index.php you’ll see that the application-config will be pulled into the Zend\Mvc\Application.

1
2
3
4
5
6
7
8
<?php
chdir(dirname(__DIR__));
// Setup autoloading
require 'init_autoloader.php';
// Run the application!
Zend\Mvc\Application::init(require 'config/application.config.php')->run();

Taking a look into Application::init() you’ll notice that not much is happening. Basically the application.config.php will be set as an internal Service called ApplicationConfig and then the most interesting thing that happens is the following highlighted line. The Modules are going to be loaded. And this is where all the magic is happening, so let’s dive into that.

1
2
3
4
5
6
7
8
public static function init($configuration = array())
{
$smConfig = isset($configuration['service_manager']) ? $configuration['service_manager'] : array();
$serviceManager = new ServiceManager(new Service\ServiceManagerConfig($smConfig));
$serviceManager->setService('ApplicationConfig', $configuration);
$serviceManager->get('ModuleManager')->loadModules();
return $serviceManager->get('Application')->bootstrap();
}

ModuleManager->loadModules()

Now we get into the core of configuration, the ModuleManager. The ModuleManager itself actually does pretty much nothing, when it comes to configuration. What it does however is to trigger a couple of Events. The important Events triggered for us are:

  • ModuleEvent::EVENT_LOAD_MODULES
  • ModuleEvent::EVENT_LOAD_MODULES_POST
  • ModuleEvent::EVENT_LOAD_MODULE_RESOLVE
  • ModuleEvent::EVENT_LOAD_MODULE

Out of those, the most important one currently is ModuleEvent::EVENT_LOAD_MODULE. Now we need to find out what get’s triggered by this event. The targets of events are called “listeners”, so what’s more natural then to take a look at all the classes under Zend\ModuleManager\Listener\{name}Listener.php.

When it comes to the configuration of ZF2 the classes / listeners of relevance would be the Zend\ModuleManager\Listener\ConfigListener and Zend\ModuleManager\Listener\ServiceListener, let’s dive into them!

ConfigListener vs. ServiceListener

The big “duel” we’re interested in is the one about the ConfigListener vs. the ServiceListener. Let’s first go through the roles of each of them.

The ConfigListener

Ultimately what the ConfigListener does is to call the function getConfig() of the Module-Classes. This happens for every single Module. And all Module->getConfig() will be merged into one internal configuration.

The ServiceListener

The Role of the ServiceListener is similar. The ServiceListener ultimately calls all the other config functions of the Module classes. The exact functions that will be called are:

  • getServiceConfig() translates to $config['service_manager']

  • getControllerConfig() translates to $config['controllers']

  • getControllerPluginConfig() translates to $config['controller_plugins']

  • getViewHelperConfig() translates to $config['view_helpers']

  • getValidatorConfig() translates to $config['validators']

  • getFilterConfig() translates to $config['filters']

  • getFormElementConfig() translates to $config['form_elements']

  • getRouteConfig() translates to $config['route_manager']

The Load-Order

The very interesting question is now: Who’s last?

To make the long story short, the first function to be called is getConfig() and after that all functions provided by the several ServiceListener are called in the above listed order. So ultimately the specific functions like getServiceConfig() or getViewHelperConfig() will take priority over the configuration served by getConfig().

The /autoload/ configuration

The last things to load would be the configuration files served under config/autoload/{,*.}{global,local}.php. Those files could practically overwrite everything, again ;)

The load order here is alphabetically. The whole directory will be fetched and all matching PHP files will be merged into the existing configuration.

Conclusion

Internally a lot of stuff happens, when setting up the modules. And it is important to know about the load-order of the configuration steps. Finding out about this sure will leave me away from needless debugging time in the future. So whenever you encounter some problems with your configuration, now you know where to look for errors.

  1. application.config.php
  2. $module->getConfig()
  3. $module->get{,*}Config() (or ServiceListeners)
  4. /config/autoload/{,.*}{global,local}.php

url:http://samminds.com/2013/04/understanding-zf2-configuration/