Now, where the ServiceManager has been equipped with the required services, and the ModuleManagerhas loaded the application’s modules, the Application itself can be started and the request processing, initiated. This occurs in 3 steps, partly in the init() method of the application itself

and partly in the index.php: Starting the application (bootstrap()), followed by the execution

(run()) and last but not least returning the generated results (send()):

<?php
$application = $serviceManager->get('Application');
$application->bootstrap()
$application->run();
$application->send();




Generation of the application & bootstrapping

The application object is generated via the factory that is registered in the ServiceManager. In the

scope of the generation, the Application invokes a number of standard services, among them both

the Request, as the basis for further processing, and the Response, which is to be filled with life in

the scope of the processing. In addition, the Application gets a reference to the ModuleManager and its own instance of the EventManager (which is indeed deposited in the ServiceManager such that

it is not shared; thus a new instance of this service is returned). The latter ensures—analogously to

the ModuleManager—that the Application can trigger events and inform listeners. The Application

sets off a number of events in the scope of the processing.

bootstrap: Is executed when the application is started.

route: Occurs when a controller and an action are determined for the URL.

dispatch: Takes place when a determined controller is identified and invoked.

render: Occurs when the result for the return is prepared on the basis of templates.

finish: Is executed when the application has been completed.


In the course of bootstrapping the Application likewise registers (incidentally in this case the

Application itself and not the ApplicationFactory) a number of listeners, which it also obtains via

the ServiceManager: RouteListener for the route event, DispatchListener for the dispatch event

and the ViewManager for a colourful bunch of additional listeners, which perform the processing of

templates and layouts. More about this in the next section.


Furthermore, the Application then creates the MVC-specific event object (MvcEvent), which is

registered with the EventManager as event object. MvcEvent then enables the listeners to access

Request, Response, Application and the Router.


Finally, the bootstrap event is initiated and the registered listeners are run. They can also

particularly be the application’s individual modules, which have registered for just this event.




Execution

The run() method, which is executed subsequent to bootstrapping, then actuates a number of

“levers” that had already been placed in the correct position. To begin with, the Application

triggers the route event. The RouteListener, which was registered for this event beforehand, is

run and the Router from the MvcEvent is asked to perform its services: i.e. to match the URL to

a defined route. In this case, a route is the description of a URL on the basis of a defined pattern.

We will take a detailed look at the mechanics of routing later. At the moment, we only have to

remember that the Router now either finds a route that fits the invoked URL and thus determines

the appropriate controller as well as the appropriate action or, on the contrary, the Router returns

with bad news and did not turn up any search results at all. But let’s initially remain on the successful path in this case. The appropriate route is deposited in the form of a RouteMatch object in MvcEvent by the RouteListener. MvcEvent is thus increasingly proving to be a central object in which a number of other important objects and data are available. Then the dispatch event is initiated, the ControllerLoader is invoked and uses the MvcEvent to find the identified controller, which is to be instantiated. To achieve this, the DispatchListener requests the ControllerLoader from the

ServiceManager (which, technically speaking, in its own right is also again a “ServiceManager”)

and then the actual controller from it (i.e. from the ControllerLoader). In the course of this,

the controller is also equipped with an EventManager of its own. Now, it can thus actuate events

and manage listeners. Then the controller’s dispatch() method is invoked, and performs the

further processing itself. If any intermittent problems occur in this enterprise, the dispatch.error

event is triggered; otherwise, the result of the dispatch() invocation is deposited in MvcEvent and

additionally returned and thereupon the dispatch process within the controller is concluded.

In Zend Framework, controllers are so conceived that they only have to have one dispatch() method at their disposal. This is externally invoked, in the process the Requestobject is transferred, and the controller is expected to return an object of the Zend\Stdlib\ResponseInterface type when

the work has been completed. In order for the principle of controller and action to function,

as one is accustomed to and expects, this logic must be implemented in the controller itself;

otherwise only the dispatch method would be invoked, but not the appropriate “action” method.

To insure that that one does not have to do this oneself, one’s own controller inherits this from

the Zend\Mvc\Controller\AbstractActionController. Subsequently, any arbitrary actions can be

deposited in the controller when one adheres to the convention that the method name must end

with “action”:

<?php
namespace Helloworld\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class IndexController extends AbstractActionController
{
    private $greetingService;
    public function indexAction()
    {
        return new ViewModel(
            array(
            'greeting' => $this->greetingService->getGreeting(),
            'date' => $this->currentDate()
            )
        );
    }
}


Back in the Application , the two results render and finish are now initiated and the run() method

concluded. Incidentally, the following fact is very interesting and helpful.: Normally, an action

returns an object of the ViewModel type at the end of processing. It thus implicitly signals the

subsequent processing steps that the result must still be processed before it can be returned.

<?php
public function indexAction()
{
    return new ViewModel( 
        array(
            'greeting' => $this->greetingService->getGreeting(),
            'date' => $this->currentDate()
        )
    );
}


However, a very practical implementation detail is the fact that when a Response object is returned

instead of a ViewModel, the downstream render activities are omitted.

<?php
public function indexAction()
{
    $resp = new \Zend\Http\PhpEnvironment\Response;
    $resp->setStatusCode(503);
    return $resp;
}


This mechanism is helpful if one desires, for example, to briefly return a 503 code, because the

application is just undergoing scheduled maintenance or when one desires to return data of a specific Mime type, for example the contents of an p_w_picpath, of a PDF document or something similar.



ViewManager

Before the processing has ended, the ViewManager comes into play again. In the previous section,

we have already seen that the onBootstrap() method is executed in the scope of the bootstrapping

of the Application (because it is registered for the corresponding event) and that an entire series

of additional preparations are made there. Up to now, we have blended this out for simplicity’s

sake, but now we also have to look at the details in this case. After the ViewManager with its

many collaborators has completed its work, we have actually worked our way through the entire

processing chain once.


To begin with, the ViewManager obtains the Config from the ServiceManager, which at this time

already represents the merged “total configuration” of the application and of the modules. The

ViewManager looks for the view_manager key and uses the configurations deposited there. Then the old game of registering diverse listeners and the provision of additional services begins again.



View-oriented listeners

The following listeners are generated and all of them are attached to the dispatch event of the

ActionController class (or more exactly: of the EventManager of the ActionController):

CreateViewModelListener: Ensures that, after execution of the controller, an object of the

ViewModel type is available for the rendering, even if only NULL or an array was made available

by the controller.

RouteNotFoundStrategy: Generates a ViewModel for the case that no controller was determined and no “View Model” could be generated (404 error).

InjectTemplateListener: Adds the appropriate template to the ViewModel for subsequent

rendering.

InjectViewModelListener: Adds the ViewModel to MvcEvent. This listener is also registered

for the dispatch.error event of the Application in order to also be able to make a ViewModel

available in case of error.


The dispatch event is incidentally somewhat nasty: it occurs twice in the system It is once

triggered by the Application, and again by the ActionController. Even if the designation of the

event is identical (it can indeed be freely selected), due to the fact that it is triggered by different

EventManagers, we are dealing with two completely different events.


Incidentally, at this time, the EventManager of the respective , specific manifestation of the

ActionController does not yet exist because the latter has not yet been generated at all. In this case,

this problem is avoided by using the SharedEventManager. With the aid of the SharedEventManager, listeners for the events of an EventManager, which does not even exist at the time of registration, can be registered. For the time being, we’ll simple leave things as they are. We’ll take a more detailed look at how this mechanism is realized in the next chapter.



View-oriented services

In addition, a number of view-oriented services are made available in the ServiceManager:

View and View Model: To begin with there is the View itself with its View Model, the

representation of the “payload” generated from a request for the response.

DefaultRenderingStrategy: Can access the View and is registered for the render Event of the

Application. If this event occurs, the View is transferred to the ViewModel, which is obtained

from the MvcEvent and then prompts the View to render just that.

ViewPhpRendererStrategy: However, the actual rendering is not performed by the Viewitself,

but is instead delegated to the ViewPhpRendererStrategy, which initially specifies the

appropriate renderer and transfers the finished result to the Response‘ subsequent

to processing.

RouteNotFoundStrategy: Defines the appropriate behaviour in case of a 404 situation.

ExceptionStrategy: Defines the appropriate behaviour in case of a “dispatch errors”.

ViewRenderer: Takes over the actual rendering work, i.e. the merging of the ViewModel data

and the appropriate template.

ViewResolver: In order to localise the respective template, the ViewRenderer accesses the

ViewResolver.

ViewTemplatePathStack: Makes it possible for the “resolver” to localise a template on the

basis of deposited paths.

ViewTemplateMapResolver: Makes it possible for the “resolver” to localise a template on the

basis of a “key value assignment”.

ViewHelperManager: Makes it possible to access “ViewHelpers” in templates; this simplifies

the generation of dynamic markup.


In case of an error in the scope of routing or in the course of dispatching, respectively, the

Application triggers a dispatch.error event. This signalises that an error has occurred in the

processing.