Logging with FirePHP in ZF2

Yesterday I wanted to set up logging to FirePHP in CuddleFish (my pet project business framework). I thought it would be easy, and looking back, it is very easy. Before I figured out how to set it up, it was not so easy, so I’d better blog about it to remind myself of how it’s done.

First of all, you have to set up FirePHP. You can download it from the FirePHP website or install it using pear:
[bash]
pear channel-discover pear.firephp.org
pear install firephp/FirePHPCore
[/bash]

Next, in the Module.php file of your module, you can add a service that provides the configured logger:

[php]
// at the top of the file:
use Zend\Log\Logger;
use \Zend\Log\Writer\FirePhp as FirePhpWriter;
use \Zend\Log\Writer\FirePhp\FirePhpBridge;

// Note that I place FirePHPCore in vendor
require_once ‘vendor/FirePHPCore/FirePHP.class.php’;

// further down
public function getServiceConfig()
{
return array(
‘factories’ => array(
// [..] other factories for other serivces left out
‘log’ => function($sm) {
$log = new Logger();
$writer = new FirePhpWriter(new FirePhpBridge(new \FirePHP()));
$log->addWriter($writer);
return $log;
},
),
);
}
[/php]

Simplifying it

In fact, since we require_once the core FirePHP class, there is no need to pass it to the constructor of the writer using the bridge. I only came to realize this while writing this post. When the FirePHP class exists, it will be used automatically by the writer. So the simplified code becomes:

[php]
// at the top of the file:
use Zend\Log\Logger;
use \Zend\Log\Writer\FirePhp as FirePhpWriter;

// Note that I place FirePHPCore in vendor
require_once ‘vendor/FirePHPCore/FirePHP.class.php’;

// further down
public function getServiceConfig()
{
return array(
‘factories’ => array(
// [..] other factories for other serivces left out
‘log’ => function($sm) {
$log = new Logger();
$writer = new FirePhpWriter();
$log->addWriter($writer);
return $log;
},
),
);
}
[/php]
Now if you need the log somewhere, say in a controller, you can pass it in using the factory for the controller and call:
[php]
$this->info(‘It works’);
[/php]

Alternatively you can call getServiceLocator() inside the controller to get the ServiceManager and get the log instance:
[php]
$this->getServiceLocator()->get(‘log’)->info(‘Will work equally well’);
[/php]

There is however a downside to this: If you have a lot of calls to the log, it is more code to type than just calling $this->log->info(‘something’);

If you have an initalizer in your controller, you can set the log there:
[php]
// inside initializer
$this->log = $this->getServiceLocator()->get(‘log’);
[/php]

If you use a factory to create your controller, you can add a method setLog() to your controller:
[php]
public function setLog($log)
{
$this->log = $log;
}
[/php]

The factory can be a closure in the controller configuration, like we did for the log:
[php]
public function getControllerConfig()
{
return array(
‘factories’ => array(
‘index’ => function($controllers) {
$sm = $controllers->getServiceLocator();
$controller = new Controller\IndexController();
$controller->setLog($sm->get(‘log’));
return $controller;
},
),
);
}
[/php]
Now the log is available as $this->log right after instantiation of the controller.