zend-framework-mvczend-framework3zend-log

How do I configure the default ZendLog factory for a Zend Framework MVC app?


I have a ZendFramework application. Its running Zend Framework 3. I added zend-log, and injected it into the constructor of the IndexController I log a message in the index action of the index controller like so.

public function __construct(Logger $logger) 
{
    $this->logger = $logger;
}

public function indexAction()
{
    $this->logger->info('Example Log Message');
    return new ViewModel();
}

I was able to generate a factory for this with vendor/bin/generate-factory-for-class. I added it to the module config like so.

'controllers' => [
    'factories' => [
        Controller\IndexController::class => Controller\IndexControllerFactory::class,
    ],
],

When I run the index controller I get the following error:

/var/www/vendor/zendframework/zend-log/src/Logger.php:434
No log writer specified

I know I can add a writer with the following:

$logger->addWriter($writer);

My question is where is the logger suppoed to be configured? Do I just add it to the ['service_manager' => 'factories' => [ . . . ] ] in the module config? Where should I put the factory class I write? In with the other services?

I'm struggling to solve this the "right" way.


Solution

  • Usually, logger config is kept in module.config.php. But surelly, it can be situated elsewhere. There is no right way, but not knowing what you are trying to achieve, I'd suggest you follow the tradition.

    Add to your module.config.php:

    'service_manager' => [
        'factories' => [
            'log' => \Zend\Log\LoggerServiceFactory::class,
        ],
    ],
    
    'log' => [
        'writers' => [
            [
                'name' => 'stream',
                'options' => [
                    'stream' => "test.log"
                ]
            ]
        ]
    ]
    

    Your controller factory might look like this:

    class IndexControllerFactory implements FactoryInterface
    {
        public function __invoke (ContainerInterface $container, $requestedName, array $options = null)
        {
            $indexController = new IndexController();
            $indexController->setLogger ($container->get ('log'));
    
            return $indexController;
        }
    }
    

    and the controller itself:

    use Zend\Log\LoggerAwareInterface;
    use Zend\Log\LoggerAwareTrait;
    use Zend\Mvc\Controller\AbstractActionController;
    use Zend\View\Model\ViewModel;
    
    class IndexController extends AbstractActionController implements LoggerAwareInterface
    {
        use LoggerAwareTrait;
    
        public function testAction ()
        {
            $this->logger->info("test");
        }
    }