ZF2 ServiceManager configuration walkthrough

ZF2 is all about extensibility, and the new ServiceManager and Config make it very easy, if you know how. Extensibility comes with some complexity, and it may be a bit harder to try and trace where everything is going, especially when using events.

With the ZF2 Configuration manager and Service Locator configurations, it’s not always as simple to know where to find the defaults, and how to best override them. This post might remind you of the factoryfactoryfactoryfactory post from joelonsoftware

I wanted to implement some custom navigation stuff and soon began to wonder how the config works, and how I can manipulate it to inject my custom view helpers or navigation pages. This post will cover the buildup of the service manager, and I plan to do some follow up posts to go into some of the main service factories.

As mentioned before, the ServiceManager sometimes seems like it does some magic and boom there’s the class you requested. But I only like magic in my spare time.

Let’s start at the big bang: calling Application::init()

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();
}

The passed config array is checked for the ‘service_manager’ key if so its value is passed to a new instance of Zend\Mvc\Service\ServiceManagerConfig.
The original configuration array is then stored under the ‘ApplicationConfig’ key. this is the _original_ config array from config/application.config.php!

Zend\Mvc\Service\ServiceManagerConfig is the class that performs the ‘main’ configuration of the ServiceManager:

  • configures ServiceManager, ModuleManager and EventManager:
    • The ServiceManager is sets itself as an instance with the key ‘ServiceManager’ and aliases ‘Zend\ServiceManager\ServiceLocatorInterface’, ‘Zend\ServiceManager\ServiceManager’
    • An EventManagerFactory is added to create standalone EventManagers via the key ‘EventManager’
    • A second EvenManager is added as an invokable under the key ‘SharedEventManager’, this is not shared and thus is to be used as a global event manager
  • global initializers are added to inject the correct classes when the servcie manager creates instances of ‘ServiceLocatorAwareInterface’, ‘ServiceManagerAwareInterface’, ‘EventManagerAwareInterface’ classes

So now the ServiceManager is configured to use the ‘Zend\Mvc\Service\ModuleManagerFactory‘ to create the ‘ModuleManager’. Without going in to the specifics of all the stuff the factory does, here’s what we need to know:

This is where we start getting some insight on how and where we need to search for what stuff. This ServiceListener adds defaults for many commonly used services:
‘Application’, ‘Config’, ‘ViewManager’, ‘ViewHelperManager’, ‘Router’, ‘Request’, ‘Response’, ‘ControllerLoader’, ….

it also adds an alias ‘Configuration’ for ‘Config’.

This ‘Config’ will contain the configuration merged from all modules and the ‘ApplicationConfig’

A quick overview of what we can pull out of the ServiceManager at this point:

// note: all servicemanager keys are case insensitive
// assume application is set up and we have a valid ServiceLocator
$sl = $serviceLocator;

$sl === $sl->get('ServiceManager'); //true
$sl === $sl->get('Zend\ServiceManager\ServiceLocatorInterface'); //true
$sl === $sl->get('Zend\ServiceManager\ServiceManager'); //true

// ServiceManager > ServiceManagerConfig > ServiceListener > ViewHelperManager
$appConfig = $sl->get('ApplicationConfig'); // raw array from config/application.config.php

// ServiceManager > ServiceManagerConfig > ServiceListener > ConfigFactory > Config
$config = $sl->get('Config'); // app config merged with config from all your modules
$config === $sl->get('Configuration'); // true

// ServiceManager > ServiceManagerConfig > ServiceListener > ViewManagerFactory > ViewManager
$viewManager = $sl->get('ViewManager');

That’s it for now. Expect some more articles to go further down the chain.

update: customizing the ViewHelper config