But now let us return to request processing: After the ServiceManager has been adequately prepared, it has also been used for the first time, to generate the ModuleManager via the registered factory before loading the module is initiated.

<?php
$serviceManager->get('ModuleManager')->loadModules();



Generation of the ModuleManager

The ModuleManagerFactory serves the purpose of providing the ModuleManager service. As we

remember, a factory is always used when the generation of an object becomes more complex. In

the scope of this generation, initially a new EventManager is requested from the ServiceManager

and is placed at the disposal of the ModuleManager. The ModuleManager is therefore able to generate events and to inform registered “Listeners” beforehand. The following events are triggered by the ModuleManager (at a later point in time!):

loadModules: Is initiated when the modules are loaded.

loadModule.resolve: Is initiated for each module that is to be loaded when the necessary

data are read in.

loadModule: Is initiated during loading of a module for every module when the data that have

been read in are exported.

loadModules.post: Is initiated after all modules have been loaded.



Module-oriented listeners

However, the ModuleManagerFactory does much more. To begin with, it generates a large number

of listeners that are registered for the above-mentioned events.

ModuleAutoloader: Ensures that the Module class of the individual modules can be automatically loaded.

ModuleResolverListener: Instantiates the Module.php of the respective module.

AutoloaderListener: Invokes the getAutoloaderConfig() method in Modules, in order to

obtain information on how the modules’ classes can be automatically loaded.

OnBootstrapListener: Checks to determine whether Modules have an onBootstrap() method

and registers the invocation of this method for the bootstrap event that will be triggered at a later point in time by the Application.

InitTrigger: Checks to determine whether Modules have the init() method at their disposal.

If they do, it is invoked.

ConfigListener: Checks to determine whether Modules have agetConfig() method at their

disposal, which, if present, is invoked and the returned module configurations array is united

with the other configurations.

LocatorRegistrationListener: Insures that instances of all Module classes that implement

the ServiceLocatorRegisteredInterface are injected into the ServiceManager‘.

ServiceListener: Calls the getServiceConfig(), getControllerConfig(), getControllerPluginConfig(),getViewHelperConfig() methods in the Module class, if present (or reads out die the

corresponding configurations; further details on this in the following), processes the merged

configurations of all modules, applies them to the m ServiceManager and adds further

Standard-Services to the latter.



Standard services, Part 2

After a number of standard services have been made available in the course of the generation of the

ServiceManager—among them, in addition to the EventManager, even the ModuleManager itself—the ServiceListener additionally registers (at the request of its factory) a colourful assortment of

additional Services, which are required in the course of the request processing. At this point a brief

comment is appropriate: at this point in time the operational mode of each service can and should

not be completely understood! Many of the services that are registered by the ModuleManager at this time will cross our path again in the course of this chapter or book. The following list thus should serve much more as a reference and outlook to that which is still to come. The following services are thus—listed here according to manner of registration—registered.



Invocables

RouteListener (Zend\Mvc\RouteListener): Listens later to the Mvc result onRoute and then

ensures that the router is charged with the resolution on the appropriate controller.

DispatchListener (Zend\Mvc\DispatchListener): Listens later to the Mvc result onRoute

and then ensures that the ControllerLoader loads the previously selected controller and runs

it.



Factories

Application (Zend\Mvc\Service\ApplicationFactory): The Application (generated by the deposited factory) represents, so to speak, the entire processing chain and in general the entire application.

Configuration (Zend\Mvc\Service\ConfigFactory): The generated Config service returns the merged configuration for the application. It is also available via the Config alias.

ConsoleAdapter (Zend\Mvc\Service\ConsoleAdapterFactory): Service for accessing the command line.

DependencyInjector (Zend\Mvc\Service\DiFactory): Zend Framework has its own implementation of the so-called “dependency injection”, with whose help complex object graphs based on a comprehensive configuration are automatically “merged”. Instead of the

DependencyInjector keys, one can also use its aliases Di or Zend\Di\LocatorInterface. We will look at Zend\Di in more detail later.

Router, HttpRouter, ConsoleRouter (Zend\Mvc\Service\RouterFactory): Based on the request URL, the factory-generated Router service determines the controller that is to be invoked—if necessary, also in the “command line mode”.

Request (Zend\Mvc\PhpEnvironment\Request): Provides access to all request information, e.g. the request parameters.

Response (Zend\Http\PhpEnvironment\Response): Represents the answer generated in the course of processing to the client.

ViewManager: The ViewManager performs a function for the administration of views and their

processing that is similar to that performed by the ModuleManager for the modules and the

ServiceManager for the services. It ensures that the data will sometime become, for example,

web pages with HTML markup.

ViewJsonRenderer (Zend\Mvc\Service\ViewJsonRendererFactory): Allows the realisation

of RESTful3 controllers and thus of web services, which conforms to the REST architecture

style. This topic is discussed in a chapter of its own in the book.

ViewJsonStrategy (Zend\Mvc\Service\ViewJsonStrategyFactory): Ensures that the ViewJsonRenderer will be invoked when required. In the scope of this Strategy, for example, the system checks

to see whether the ViewModel returned by the controller is of the JsonModel type.

ViewFeedRenderer (Zend\Mvc\Service\ViewFeedRendererFactory): Allows the realisation

of RSS or Atom feeds of the “view data” returned by a controller.

ViewFeedStrategy (Zend\Mvc\Service\ViewJsonStrategyFactory): Ensures that the ViewFeedRenderer will be invoked when required. Part of this Strategy the determination of whether the

ViewModel returned by the controller is of the FeedModel type.

ViewResolver (Zend\Mvc\Service\ViewResolverFactory): Makes it possible to find “view

templates”.

ViewTemplateMapResolver (Zend\Mvc\Service\ViewResolverFactory): Makes it possible for

the ViewResolver to find View-Templates on the basis of a map.


And additionally:

ViewTemplatePathStack (Zend\Mvc\Service\ViewTemplatePathStackFactory): Makes it possible for the ViewResolver to find View-Templates on the basis of a list of paths.

ControllerLoader (Zend\Mvc\Service\ControllerLoaderFactory): TheControllerLoader

can load a controller that was previously localised by a routing.

ControllerPluginManager (Zend\Mvc\Service\ControllerPluginManagerFactory): Makes

the ControllerPluginManager and, thus, a number of plugins, which can be used in controllers, are available; among them, for example, the redirect plugin by means of which forwarding can be realised. This service can also be requested via the ControllerPluginBroker keys, Zend\Mvc\Controller\PluginBroker or Zend\Mvc\Controller\PluginManager.

ViewHelperManager (Zend\Mvc\Service\ViewHelperManagerFactory): Generates the ViewHelperManager, which is responsible for the administration of so-called “view helpers”.


The latter three services are particularly interesting, because they, in turn, comprise the new

ServiceManager”, termed “Scoped ServiceManager” in ZF jargon. Whew, now things are beginning to get a bit complicated! So let’s take a slow look at things—step by step. To begin with we

should remember that there is the one “central ServiceManager” in the system. All of the important

“application services” are generated by using it. It is both a ServiceManager in a technical sense

and the conceptional “central ServiceManager” for us. However, there are specific services that

the ServiceManager itself does not provide, but instead are made available by specialised “subServiceManagers” or “scoped ServiceManagers”, respectively, which can also provide services via

the known mechanisms, i.e. “invocables”, “factories”, etc. All of them are also ServiceManagers in

a technical sense. In this context, let’s again take a look at the last chapter, in which we wrote our own controller. There we find the following passage in the module.config.php:

<?php
// [..]
'controllers' => array(
    'invokables' => array(
        'Helloworld\Controller\Index'
            => 'Helloworld\Controller\IndexController'
    )
)
// [..]


When this configuration fragment is interpreted, this results in reference to the appropriate

controller class under the Helloworld\Controller\Index key, which is registered as an “invocable”

in the ControllerLoader, one of the standard “scoped ServiceManagers”. Thus, if this controller

is subsequently identified as appropriate in the scope of routing and must then be instantiated, the

system uses the ControllerLoader to do this. In this context, one can then also characterise a

controller as a service.


This procedure of the specialised Sub-ServiceManager has several advantages for certain types of

services. For example, in this manner the central ServiceManager for the application services is

itself not overloaded with innumerable services, and it is easy to determine all of the controllers, a

task that would otherwise not be nearly as easy. Here are the different ServiceManagers again at a

glance:

Application Services (Zend\ServiceManager\ServiceManager): Configuration via the service_-manager key or the getServiceConfig() method (defined in the ServiceProviderInterface).

Controllers (Zend\Mvc\Controller\ControllerManager): Configuration via controllers key

or getControllerConfig() method (defined in ControllerProviderInterface). It can be obtained in the “central ServiceManager” via the ControllerLoader service designation.

Controller plugins (Zend\Mvc\Controller\PluginManager): Configuration via the controller_-plugins key or getControllerPluginConfig() method (defined in ControllerPluginProviderInterface).

It can be obtained in the “central ServiceManager” via the ControllerPlugin manager service designation.

“View helpers” (Zend\View\HelperPluginManager): configuration via the view_helpers key

or the getViewHelperConfig() method. (defined in the ViewHelperProviderInterface).

It can be obtained in the “central ServiceManager” via the ViewHelperManager service

designation.



Loading the modules

After the ModuleManager has been prepared and the required listeners have been registered, the

actual loading of the modules is initiated by invocation of the loadModules() method of the

ModuleManager. At this time, relatively little really happens here because the actual processing, for example the invocation of the above-mentioned methods of the Module.php, indeed

occurs in the many registered listeners. Initially, the loadmodules.pre event is triggered, and

then the loadModule.resolve event and loadModule, for every activated module. Finally, the

loadModules.post event is again triggered. And that was really everything.



The Module Event Object

The concept of the EventManager is that in addition to being the trigger for an event and the listeners registered for the event (receivers), the event itself—represented as independent object—still exists. It is made available to all listeners. This object serves to transfer additional event-relevant information, for example a reference to the location in the code where the event is triggered. Moreover, additional data, which are helpful for the event processing in the listeners, can be transferred. Thus, the module which is now being loaded is generally of interest for a listener during loadModule.


To do justice to the fact that, depending on the context of the event, other data are of interest, the

EventManager of Zend Framework 2 permits deposition of situation-dependent special event classes. For the event principle in the scope of the ModulManager, there is as special ModuleEvent class, which for example bears both the module in question and additionally the name of the module.



Activation of a module

In order for a module to be taken into account at all, an explicit activation in application.config.php

in the config directory is required:

<?php
return array(
    'modules' => array(
        'Application',
        'Helloworld'
    )
);



Methods of the module class

As we have seen, a large number of methods in the Module class of a module are invoked if we have implemented them. In Framework there are two relevant possibilities of finding out whether this

is the case. Either the Module class implements a specific interface (this can indeed be tested via

instance of) or the respective method is simply implemented (this can be checked via

the method_exists()‘ invocation).

Let’s now again take a detailed look at the methods in the Module class, which are automatically

invoked by Framework and can be used by application developers:

getAutoloadingConfig() (defined in AutoloaderProviderInterface): We have already

created this method in our Helloworld module. It provides information on how the classes of

the module can be automatically loaded. If we omit this method, the classes of the module

(for example its controller) normally cannot be loaded and serious problems occur when the

corresponding URL is invoked. Consequently, it should always be ensured that information

on how the classes can be automatically loaded has been made available to Framework.

Incidentally, in a purely technical context, Framework takes the information to incorporate

an appropriate loader implementation for this module via spl_autoload_register().

init() (defined in InitProviderInterface): This method allows the application developer

to initialise his or her own module, thus, for example, to register his or her own listeners

for certain events. If necessary, the ModuleManager is consigned to the method and the latter

can thus access the appropriate events (of the ModuleManager) or access the modules. The

important thing is that this “method” is always invoked, that means for every request—and

indeed for every module. One should also realize that this is a good place to ruin the loading

time of an application. Thus, only very few and ideally only light-weight operations should

be performed in the scope of the init() method. If one is attempting to improve the speed of

a ZF2 application, one should always first take a look at the init() methods of the activated

modules.