Integrating ZFDebug and Doctrine Query Profiling into your Zend Application

This past week I noticed that one of my applications was running extremely slow. Now I still don’t know why it wasn’t so slow before I had made the fix I am about to explain, but the point of this post is – ZFDebug is AWESOME!

Here is how to implement it in a Zend_Application environment (the site also has examples) -

  1. Visit http://code.google.com/p/zfdebug/ and download the latest version of ZFDebug
  2. Visit http://www.danceric.net/2009/06/06/zfdebug-and-doctrine-orm/ and download his latest version of the doctrine ZFDebug Plugin
  3. You will need to download the ZFdebug package and place that inside of your library folder.
  4. Then place the Doctrine Plugin inside the library as well – I put my custom classes under an App folder – this plugin was placed in: Application/Library/App/Debug/Doctrine.php
//Application/Bootstrap.php

    protected function _initDoctrine()
    {
        $this->getApplication()->getAutoloader()
                               ->pushAutoloader(array('Doctrine', 'autoload'));

        $manager = Doctrine_Manager::getInstance();
        $manager->setAttribute(Doctrine::ATTR_AUTO_ACCESSOR_OVERRIDE, true);
        $manager->setAttribute(
            Doctrine::ATTR_MODEL_LOADING,
            Doctrine::MODEL_LOADING_CONSERVATIVE
        );
        
        $manager->setAttribute(Doctrine::ATTR_AUTOLOAD_TABLE_CLASSES, true);
        
        $connections = $this->getOption('doctrine');
        
        foreach($connections as $name => $dsn) {
			$conn = Doctrine_Manager::connection($dsn, $name);
			$conn->setAttribute(Doctrine::ATTR_USE_NATIVE_ENUM, true);
			$conn->setAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER, true);
			$conn->setCharset('utf8');
        }
        
        return $conn;
    }

    protected function _initZFDebug()
    {
        
        $zfdebugConfig = $this->getOption('zfdebug');
        
        //This will go off the app.ini settings
        if ($zfdebugConfig['enabled'] != 1) {
            
            return;
            
        }
        
        // Ensure Doctrine connection instance is present, and fetch it
        $this->bootstrap('Doctrine');
        $doctrine = $this->getResource('Doctrine');
        
        $autoloader = Zend_Loader_Autoloader::getInstance();
        $autoloader->registerNamespace('ZFDebug_');
        
        $options = array(
            'plugins' => array('Variables', 
                               'App_Debug_Doctrine',
                               'File' => array('base_path' => APPLICATION_PATH),
                               'Memory', 
                               'Time', 
                               'Registry', 
                               'Exception',
                                )
        );
    
        $debug = new ZFDebug_Controller_Plugin_Debug($options);
        
        $this->bootstrap('frontController');
        $frontController = $this->getResource('frontController');
        $frontController->registerPlugin($debug);
        
    }
//Application/Configs/application.ini
[production]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Initialize Database Connection in Doctrine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Database Connection 1
doctrine.db1 = "mysql://user1:password1@127.0.0.1/Database1"
;; Database Connection 2
doctrine.db2 = "mysql://user2:password2@127.0.0.1/Database2"
;;Disable the debug toolbar in production
zfdebug.enabled = 0

[development : production]
;;Zend Framework Debug Toolbar to Display On Page
zfdebug.enabled = 1

/**
 * ZFDebug Doctrine ORM plugin created by Danceric
 * http://www.danceric.net/2009/06/06/zfdebug-and-doctrine-orm/
 */

class App_Debug_Doctrine extends ZFDebug_Controller_Plugin_Debug_Plugin implements ZFDebug_Controller_Plugin_Debug_Plugin_Interface
{
    /**
     * Contains plugin identifier name
     *
     * @var string
     */
    protected $_identifier = 'doctrine';

    /**
     * @var array Doctrine connection profiler that will listen to events
     */
    protected $_profilers = array();

    /**
     * Create ZFDebug_Controller_Plugin_Debug_Plugin_Variables
     *
     * @param Doctrine_Manager|array $options
     * @return void
     */
    public function __construct(array $options = array())
    {
        if(!isset($options['manager']) || !count($options['manager'])) {
            if (Doctrine_Manager::getInstance()) {
                $options['manager'] = Doctrine_Manager::getInstance();
            }
        }

        foreach ($options['manager']->getIterator() as $connection) {
            $this->_profilers[$connection->getName()] = new Doctrine_Connection_Profiler();
            $connection->setListener($this->_profilers[$connection->getName()]);
        }
    }

    /**
     * Gets identifier for this plugin
     *
     * @return string
     */
    public function getIdentifier()
    {
        return $this->_identifier;
    }

    /**
     * Gets menu tab for the Debugbar
     *
     * @return string
     */
    public function getTab()
    {
        if (!$this->_profilers)
            return 'No Profiler';

        foreach ($this->_profilers as $profiler) {
            $time = 0;
            foreach ($profiler as $event) {
                $time += $event->getElapsedSecs();
            }
            $profilerInfo[] = $profiler->count() . ' in ' . round($time*1000, 2)  . ' ms';
        }
        $html = implode(' / ', $profilerInfo);

        return $html;
    }

    /**
     * Gets content panel for the Debugbar
     *
     * @return string
     */
    public function getPanel()
    {
        if (!$this->_profilers)
            return '';

        $html = '

Database queries

'; foreach ($this->_profilers as $name => $profiler) { $html .= '

Connection '.$name.'

    '; foreach ($profiler as $event) { if (in_array($event->getName(), array('query', 'execute', 'exec'))) { $info = htmlspecialchars($event->getQuery()); } else { $info = '' . htmlspecialchars($event->getName()) . ''; } $html .= '
  1. [' . round($event->getElapsedSecs()*1000, 2) . ' ms] '; $html .= $info; $params = $event->getParams(); if(!empty($params)) { $html .= '
      bindings:
    • '. implode('
    • ', $params) . '
    '; } $html .= '
  2. '; } $html .= '
'; } return $html; } }

You should now be good to go – make sure you are also including the Jquery Library in your framework in order for all the javascript to function correctly.

Thanks to the authors of these scripts for creating a great debug toolbar!

Tuesday, November 3rd, 2009 Zend Framework

1 Comment to Integrating ZFDebug and Doctrine Query Profiling into your Zend Application

  • Petter says:

    Hello,

    this is code for doctrine 1.x but if I use doctrine 2.0 I receive error:
    Fatal error: Class ‘Doctrine_Manager’ not found in /var/www/html/grouper/library/Core/Controller/Plugin/Debug/Plugin/Doctrine.php on line 65

    How can I repair it ?
    Best regards
    Petter

  • Leave a Reply

    You must be logged in to post a comment.

    [ad code=1 align=center]