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.

 

Author: Bart McLeod

Zend Framework MVC specialist. Also interested in PHP, Zend Framework in general, Three.js and VRML.

8 thoughts on “Logging with FirePHP in ZF2”

  1. I think
    [sourcecode language=”php”]
    $this->log->info(‘It works’);
    [/sourcecode]
    should be :
    [sourcecode language=”php”]
    $this->getServiceLocator()->get(‘log’)->info(‘It works’);
    [/sourcecode]

  2. Thanks Abdul, you are right. I was assuming a situation where you have already injected the log into the controller (into $this->log). However, injecting it is an unnecessary step, since we have getServiceLocator(). I will edit the post to reflect this.

  3. Hi, really good article. But I do it in a little different way: i install firephp with composer with this simple command in my project home:

    php composer.phar require “firephp/firephp-core” : “dev-master” && php composer.phar update -o

    Best Wishes!

  4. Just replying to myself here. While you can use $this->getServiceLocator() to pull any service into the controller, this is not the idea of dependency injection. It only means you now depend on a string (‘log’ in this case). Using either setter injection or constructor injection you can avoid this.

  5. I do it the same way nowadays and it works great indeed. It took me a little while to get used to Composer, but now that I’m used to it I think it’s a great tool.

Leave a Reply

Your email address will not be published. Required fields are marked *