2

I'm pretty new to zf2 but I already setup a site working with it. I got some understanding of the serviceManager but now I'm stuck.

Here is the context : I want to implement a logger available on any class of my zf2 application.

In my global.php I create the factory for the logger :

'service_manager' => array(
    'factories' => array(
        'Zend\Db\Adapter\Adapter'
                => 'Zend\Db\Adapter\AdapterServiceFactory',
        'Zend\Log\Logger' => function($sm){
            $logger = new Zend\Log\Logger;
            $writer = new Zend\Log\Writer\Stream('./data/log/'.date('Y-m-d').'-error.log','wb'); 
            $logger->addWriter($writer);     
            return $logger;
        },
    ),

Now I want to have it injected in every class implementing LoggerAwareInterface. So in my Module.php I have this initializer in my getServiceConfig function

        'initializers' => array(
                'logger' => function($service, $sm) {
                    if ($class instanceof LoggerAwareInterface) {
                        $logger = $sm->get('Zend\Log\Logger');
                        $class->setLogger($logger);
                    }
                }
        ),

Example given, I want to inject it in a class named PartController, so I set it as an invokable in module.config.php

return array(
    'controllers' => array(
        'invokables' => array(
            'Part\Controller\Part' => 'Part\Controller\PartController',
        ),
    ),

This class is implementing LoggerAwareInterface

class PartController extends AbstractActionController implements LoggerAwareInterface

The issue I have is that the logger is not initialized in PartController, what I checked with a var_dump in my PartController.

I tried to dump all the services checked by the initializer, and PartController doesn't appear ...

What am I doing wrong ? And why is the PartController not registered in the serviceManager although it is in the invokables section of my module.config.php ?

Thanks in advance to everyone.

1 Answers1

3

If you want your initializer to apply to a controller, you need to tell the ControllerManager about it, you can do that by implementing the getControllerConfig method defined by Zend\ModuleManager\Feature\ControllerProviderInterface, ie.,

<?php
// ..some namespace

use Zend\ModuleManager\Feature\ControllerProviderInterface;

class Module implements ControllerProviderInterface
{
    // .. 

    public function getControllerConfig()
    {
        return array(
            'initializers' => array(
                'LoggerAwareInitializer' => function($instance, $sm) {
                    if ($instance instanceof LoggerAwareInterface) {
                        $logger = $sm->getServiceLocator()->get('Zend\Log\Logger');
                        $instance->setLogger($logger);
                    }
                },
            ),
        );
    }

}
Sam
  • 16,435
  • 6
  • 55
  • 89
Crisp
  • 11,417
  • 3
  • 38
  • 41
  • Thanks Crisp, but it is not totally solved. Now the serviceManager is throwing an Exception : Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for Zend\Log\Logger. The line which is failing is : $logger = $sm->get('Zend\Log\Logger'); – moinsundemi May 04 '13 at 19:55
  • ah, you need to call `getServiceLocator()` since that `$sm` is the controller manager instance, see the edit – Crisp May 04 '13 at 20:07
  • Perfect, now I have my logger in PartController. I could have guessed that myself because when I dumped the sm I saw that the logger was in the serviceLocator. Shame on me. But now, could your explain me two things, maybe in a new answer : - Why did I need to call getControllerConfig and not getServiceConfig ? - How to inject the logger in any model, view, or any other class inmplementing LoggerAwareInterface ? And thank you very much ! – moinsundemi May 04 '13 at 20:24
  • Just a hint: ALWAYS name your initializers. I recall some of the ZF-Folks telling me that unnamed stuff sometimes leads to ... fun ... :D – Sam May 05 '13 at 09:18