Pablo Viquez Blog

Mi vida y cosas relacionadas

Skip to: Content | Sidebar | Footer

Zend_Log, FirePHP and Zend_Application. How to

25 November, 2009 (16:23) | PHP, debug, tech | By: Pablo Viquez

I wanted to enable logging of exceptions to my PHP log file and also display them using FireBug.

On a standard setup of Zend Framework, the Zend error handler plugin (Zend_Controller_Plugin_ErrorHandler) enable by default and it was designed for:

  • Errors due to missing controllers or actions
  • Errors occurring within action controllers

I wanted to keep using the error handler plugin and didn’t want to log the exceptions by using: Zend_Controller_Front::throwExceptions() or Zend_Controller_Response_Abstract::renderExceptions() or any other way since eventually might get complicated, besides, I think that the error handler plugin works fine and if it gets updated in the future, I won’t have to do a major refactor.

So this is how I did it:

Create the Zend Log Object

Using Zend_Application can be very helpful here, because you can init the logger and automatically store the object in the registry, making available to the controllers later on.

Summary, if you want an object created on the boostrap class, to be available on the controllers later, you need to return it from the init method, in this case, we’re initializing the Zend_Log, so we need to return the object.

<?php
class App_Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{

    /**
     * Initializes the logging on the application
     *
     * We're using 2 ways for logging exceptions:
     * 1. PHP Error log file.
     * 2. Firebug for Development environments only.
     *
     * @return Zend_Log
     */
    protected function _initLogger()
    {
        // Create the Zend_Log object
        $logger = new Zend_Log();

        // Create the resource for the error log file
        // if you dont want to use the error suppressor "@"
        // you can always use: is_writable
        // http://php.net/manual/function.is-writable.php
        $stream = @fopen(ini_get('error_log'), 'a');
        if ($stream) {
            $stdWritter = new Zend_Log_Writer_Stream($stream);
            $stdWritter->addFilter(Zend_Log::DEBUG);
            $stdWritter->addFilter(Zend_Log::INFO);
            $logger->addWriter($stdWritter);
        }

        // Create the Firebug writter - Development only
        if ($this->_application->getEnvironment() != 'production') {
            // Init firebug logging
            $fbWriter = new Zend_Log_Writer_Firebug();
            $logger->addWriter($fbWriter);
        }

        return $logger;
    }

I have now the log object but I’m not logging anything yet, so I need to implement the logging part.

Log the Exception

For this part, I thought in 2 ways to do it:

  1. Extend the error handler plugin and log errors there.
  2. Log the errors on the error controller.

I choose the second one for several reasons:

  1. Easier.
  2. If the error handler changes somehow, you dont have to change your code.
  3. Extending the error plugin, might lead to repeated code and eventually deprecated code.

By default, Zend_Controller_Plugin_ErrorHandler will forward to ErrorController::errorAction() in the default module.

Now in order to retrieve a resource created in the bootstrap we need to access the bootstrap registered in the front controller, and from there we can get our logger:

// The method _initLogger on the class App_Bootstrap
// returns a Zend_Log object that is available
// on the Zend_Registry. To retrieve it we need to request the
// bootstrap from the Front controller and then get the logger.
$boot = $this->getInvokeArg('bootstrap');
if ($boot->hasResource('logger')) {
    $log_object = $boot->getResource('logger');
}

So using the Zend Framework default error controller (the one provided on the reference), with the logging will be something like this:

class ErrorController extends Zend_Controller_Action
{
    /**
     * Error action. This method is called by
     * Zend_Controller_Plugin_ErrorHandler
     *
     * @see Zend_Controller_Plugin_ErrorHandler
     * @return void
     */
    public function errorAction()
    {
        $errors = $this->_getParam('error_handler');

        // Log the Error.
        $boot = $this->getInvokeArg('bootstrap');
        if ($boot->hasResource('logger')) {
            $boot->getResource('logger')->err($errors->exception);
        }

        // Default error handling...
        switch ($errors->type) {
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:

                // 404 error -- controller or action not found
                $this->getResponse()->setHttpResponseCode(404);
                $this->view->message = 'Page not found';
                break;
            default:
                // application error
                $this->getResponse()->setHttpResponseCode(500);
                $this->view->message = 'Application error';
                break;
        }

        $this->view->exception = $errors->exception;
        $this->view->request   = $errors->request;
    }
}

Result

The final result looks like this:

Firefox with Firebug enabled:

Firefox Screenshot with Firebug enabled

PHP error log file:

[pviquez /usr/home/pviquez]$ cat php_error.log
2009-11-25T15:23:19-06:00 ERR (3): exception 'Zend_Exception' with message 'The logging is working!' in /usr/home/pviquez/app/deploy/application/modules/admin/controllers/IndexController.php:33
Stack trace:
#0 /usr/home/pviquez/app/deploy/library/Zend/Controller/Action.php(513): Admin_IndexController->indexAction()
#1 /usr/home/pviquez/app/deploy/library/Zend/Controller/Dispatcher/Standard.php(289): Zend_Controller_Action->dispatch('indexAction')
#2 /usr/home/pviquez/app/deploy/library/Zend/Controller/Front.php(946): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http))
#3 /usr/home/pviquez/app/deploy/library/Zend/Application/Bootstrap/Bootstrap.php(77): Zend_Controller_Front->dispatch()
#4 /usr/home/pviquez/app/deploy/library/Zend/Application.php(346): Zend_Application_Bootstrap_Bootstrap->run()
#5 /usr/home/pviquez/app/deploy/public/index.php(23): Zend_Application->run()
#6 {main}

References

Comments

Pingback from Pablo Viquez’s Blog: Zend_Log, FirePHP and Zend_Application. How to | Development Blog With Code Updates : Developercast.com
Time November 30, 2009 at 11:11 am

[...] Viquez has written up a mini-tutorial on getting your Zend Framework application’s errors to log out to the Firebug panel (from the [...]

Pingback from Pablo Viquez’s Blog: Zend_Log, FirePHP and Zend_Application. How to | Webs Developer
Time November 30, 2009 at 12:02 pm

[...] Viquez has written up a mini-tutorial on getting your Zend Framework application’s errors to log out to the Firebug panel (from the [...]

Pingback from Tweets that mention Pablo Viquez Blog » Zend_Log, FirePHP and Zend_Application. How to — Topsy.com
Time December 1, 2009 at 4:36 am

[...] This post was mentioned on Twitter by Cam Olivier, catch_down. catch_down said: http://tinyurl.com/yjwuyx9 Pablo Viquez Blog » Zend_Log, FirePHP and Zend_Application. How to [...]

Comment from Matthew Purdon
Time December 17, 2009 at 9:01 pm

Hey Pablo,

Great article! I did some similar work for 39 Clues, you can check it out on my blog: http://codenaked.org/archives/12-Debugging-with-FirePHP.html

Later

Comment from Pablo Viquez
Time December 17, 2009 at 10:01 pm

@Matt Thanks!, your is pretty awesome :D

when are you coming to CR again?

Comment from Matthew Purdon
Time December 18, 2009 at 7:53 am

I don’t know exactly, I definitely have plans to in the not so distant future though.

Comment from Letsnurture
Time March 18, 2010 at 4:40 am

Hi folks,

Its nice to hear about firephp with firebug.

It was desperately needed to debug the php web application especially when working with the open source php framework like Zend Framework, Symphony, CakePHP… and open source cms system like Joomla, drupal…..

Thanks a lot

Letsnurture

Write a comment