Let us draw up a service of our own for our “Hello world” module in an exemplary manner. To achieve this, we initially add another Service subdirectory in the src/Helloworld directory of our module

Module.php
config/
    module.config.php
public/
    p_w_picpaths/
    css/
    js/
src/
    Helloworld/
        Controller/
IndexController.php
Service/
    GreetingService.php
view/
    Helloworld/
        Index/
            index.phtml


There we create a GreetingService class. This class must not implement any special interfaces or be derived from any basic classes; it is thus a so-called “POPO”, a “Plain Old PHP Object”. The only important thing is that we do not forget to make the class available in the right namespace.

<?php
namespace Helloworld\Service;
class GreetingService
{
    public function getGreeting()
    {
        if(date("H") <= 11)
            return "Good morning, world!";
        else if (date("H") > 11 && date("H") < 17)
            return "Hello, world!";
        else
            return "Good evening, world!";
    }
}



Make the service available as an invocable

To use this class as a service in our controller and to be able to display a time-oriented greeting, we must add the class to the ServiceManager as Service. We can do this is the scope of our module in two ways: In the course of module configuration (module.config.php) by adding the section

<?php
// [..]
'service_manager' => array(
    'invokables' => array(
        'greetingService' => 'Helloworld\Service\GreetingService'
    )
)
// [..]

or programmatically by adding the getServiceConfig() function in the Module.php:

<?php
public function getServiceConfig()
{
    return array(
        'invokables' => array(
            'greetingService'=>'Helloworld\Service\GreetingService'
        )
    );
}

Both ways lead to the objective. Our service is now available in the form of an “invocable”. We can request the service in the IndexController of our “Hello World” module and use it:

<?php
// [..]
public function indexAction()
{
    $greetingSrv = $this->getServiceLocator()->get('greetingService');
    return new ViewModel(
        array('greeting' => $greetingSrv->getGreeting())
    );
}


Making the controller available via a factory class

However, we do have one problem now: The controller is dependent on a service (and the ServiceManager), which it actively accesses. Admittedly, it does not instantiate the class itself, which is good; thus, it does provide us with a possibility of making an alternative implementation available in the ServiceManager, if necessary, but it actively ensures that all dependencies have been resolved. At the latest, that will create problems for us when we desire to perform unit testing.


A possible alternative in this case would be the previously mentioned “dependency injection” or inversion of control”. In this context, the required collaborators are automatically made available and must no longer be actively requested. In the framework of the ServiceManager, we can realise this procedure, for example, via a preceding factory.


To achieve thus we prepare the IndexControllerFactory factory in the same directory in which the IndexController has been deposited:

<?php
namespace Helloworld\Controller;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class IndexControllerFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $ctr = new IndexController();
        $ctr->setGreetingService(
            $serviceLocator->getServiceLocator()
                            ->get('greetingService')
        );
        return $ctr;
    }
}


In addition, we alter the module.config.php in the controllers section as follows:

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


From now on, our IndexController is thus no longer generated by instantiation of a defined class,but by the deposited factory, which was previously organised by the controller's collaborators and in this case placed at the disposal of the controller by “Setter Injection”. We still have to add the corresponding “Setter” to the IndexController and in the course of the action itself to access the corresponding member variable, instead of accessing the ServiceLocator.

<?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())
        );
    }
    public function setGreetingService($service)
    {
        $this->greetingService = $service;
    }
}

Thus, a factory class can be used for both the generation of a service and for the generation of a controller. Indeed, it is as follows: The Zend\ServiceManager is employed in ZF2 in several ways. Once in the form which we have already discussed: as central instance via which even the Application itself is generated, i.e. the “container” for the entire application, if you wish to call it that. And then there is, as we will soon discuss in more detail, a number of specialised “ServiceManagers”, for example one only for the application’s controller. In this context, the following lines of the IndexControllerFactory are of particular interest:

<?php
public function createService(ServiceLocatorInterface $serviceLocator)
{
    [..]
    $ctr->setGreetingService(
        $serviceLocator->getServiceLocator()->get('greetingService')
    );
// [..]
}
// [..]

It is apparent that initially getServiceLocator() is invoked in the $serviceLocator. The reason for this is the fact that the factory’s createService() method is always transferred to the ServiceManager”, which has been charged with the generation of the service, thus, in this case, the

ControllerLoader(is automatically called up by Framework) which was reserved for the generation of controllers. However, this in turn does not have any access to the GreetingService, which we prepared beforehand and which we only made available in the “central ServiceManager” (it is indeed ultimately not a controller). In order that the services of the “central ServiceManager” can now be made available despite this, the ControllerLoader accesses the central ServiceManager via the getServiceLocator(), and makes the former available to it by just these methods. Somewhat later in this chapter you will learn more about the details of this mechanism.



Making the controller available via a factory callback

However, with the IndexControllerFactory we now have an additional class in our source code.For the time being, this is basically not a problem, but it could be a bit too much of a good thing in a case like this, in which it is not much of a challenging task to generate the factory. A light-weight alternative, which also makes it possible for us to avoid direct dependence, is the use of a callback function as a factory in the module.config.php:

<?php
// [..]
'controllers' => array(
    'factories' => array(
    'Helloworld\Controller\Index' => function($serviceLocator) {
        $ctr = new Helloworld\Controller\IndexController();
        $ctr->setGreetingService(
            $serviceLocator->getServiceLocator()
                            ->get('greetingService')
            );
        return $ctr;
    }
    )
)


The code for the generation of the IndexController, which was previously located in the IndexControllerFactory, has now been moved directly into the module.config.php.



Make the service available via Zend\Di

Regardless of which form of Factory is used, in all of them the generation of the respective object occurs programmatically, this means that appropriate PHP code must be written. Zend\Di provides an alternative option with whose help we can generate entire object graphs via configuration files.

We will go into more detail later.