Query Backtrace with Zend_Db_Profiler_Firebug + FirePHP + Xdebug

FirePHP Query Backtrace

FirePHP Query Backtrace

Why? I needed to see a full backtrace of every query.

How? In order for this to work, you’ll need to patch Zend_Db_Profiler_Firebug.

== How I created the patch file ==

I created the patch using the instructions on http://framework.zend.com/wiki/display/ZFDEV/Submitting+a+Bug+Fix you need to create a side-by-side copy of the library/ directory from the untouched source and name it library.original.

$ cd /usr/local/zend/1.9.2
$ cp -R ../ZendFramework-1.9.2-minimal/library library.original
$ ls -al
drwxr-xr-x   3 laptop  staff   102 Sep  5 08:22 library
drwxr-xr-x   3 laptop  staff   102 Sep  5 08:26 library.original

Now we can run the diff command from the instruction page.

$ diff --exclude='*.original' --exclude='*~' --exclude='*.rej' --ignore-space-change -ruN library.original/ library/ > ZF-ver-1.9.2-Zend_Db_Profiler_Firebug-changes-tbellefy.patch

Download the patch file here: ZF-ver-1.9.2-Zend_Db_Profiler_Firebug-changes-tbellefy.patch

== Using the patch ==

To patch the file on your server, download the patch file to the root directory of your Zend Framework. You should have something like this:

$ cd /usr/local/zend/1.9.2
$ wget http://timbellefy.com/wp-content/uploads/2009/09/ZF-ver-1.9.2-Zend_Db_Profiler_Firebug-changes-tbellefy.patch

Always do a –dry-run first. –verbose helps.

$ patch --dry-run --verbose --backup --strip=0 --unified --input=ZF-ver-1.9.2-Zend_Db_Profiler_Firebug-changes-tbellefy.patch

If everything looks ok, remove the –dry-run and apply the patch.

Usage: Using the Zend_Db_Profiler_Firebug is really simple. You just pass a profiler object to the Zend_Db::factory() and everything happens under the hood. The example I was using involves Zend_Queue so we need to create the queues database.

Example Setup:

$ mysql -uroot -ppassword
mysql> create database `queues`;
mysql> quit
$ mysql -uroot -ppassword queues < library/Zend/Queue/Adapter/Db/queue.sql

Now create an index.php file that you can access with Firefox, something like http://localhost/index.php that contains the following code. By the way, this example uses the non-Front Controller style from here: http://framework.zend.com/manual/en/zend.db.profiler.html#zend.db.profiler.profilers.firebug.

<?php
set_include_path('/usr/local/zend/1.9.2/library');
require_once 'Zend/Loader/Autoloader.php';
$autoloader = Zend_Loader_Autoloader::getInstance();

$request  = new Zend_Controller_Request_Http();
$response = new Zend_Controller_Response_Http();
$channel  = Zend_Wildfire_Channel_HttpHeaders::getInstance();
$channel->setRequest($request);
$channel->setResponse($response);
ob_start();

// Create a Firebug Profiler.
$profiler = new Zend_Db_Profiler_Firebug('All DB Queries');
$profiler->setEnabled(true);

// Pass the Firebug Profiler to the Zend_Db::factory().
$options = array(
    'name'          => 'myqueue',
    'driverOptions' => array(
        'host'      => 'localhost',
        'port'      => '3306',
        'username'  => 'root',
        'password'  => 'password',
        'dbname'    => 'queues',
        'type'      => 'pdo_mysql',
        Zend_Db::PROFILER => $profiler
    )
);

// Create a database-based queue and add a message.
$queue = new Zend_Queue('Db', $options);
$queue->send('My Test Message');

// Flush profiling data to browser.
$channel->flush();
$response->sendHeaders();

echo "done.";

Make sure you have Firebug open and click on the Console tab. Open Firefox to http://localhost/index.php. You should see a line with something like: “All DB Queries (11 @ 0.00019 sec)”. Click to expand and you should see every query listed in order. The last column now contains a full backtrace leading up to each query! Click on one of the backtrace lines and it will pop open into a larger window for you.

Hope this helps you.

FirePHP Query Backtrace

FirePHP Query Backtrace

My setup:
Firefox 3.5.2
Firebug 1.4.2
FirePHP 0.3.1
Xdebug 2.0.5
PHP 5.3.0
Zend Framework 1.9.2
MySQL 5.1.32
Mac OSX 10.5.8

1 Comment

AJAX In Symfony 1.2

Prototype will automatically process an AJAX response as long as the correct content-type header is returned.
~/symfony/branches/1.2/lib/plugins/sfProtoculousPlugin/lib/helper/JavascriptHelper.php

/**
 * Returns 'eval(request.responseText)', which is the Javascript function that
 * 'form_remote_tag()' can call in 'complete' to evaluate a multiple update return document
 * using 'update_element_function()' calls.
 */
function evaluate_remote_response()
{
  return 'eval(request.responseText)';
}

This function automatically creates the “request.responseJSON;” object that we use below.

Top of ~/apps/$app/templates/layout.php

<div id="indicator" style="display:none;">Loading...</div>
<h1>Basic letter</h1>
Dear <span>name_here</span>,
Your e-mail was received and will be answered shortly.

Bottom of ~/apps/$app/templates/layout.php

echo link_to_remote('Refresh the letter', array(
  'url'      => 'post/list',
  //'complete' => 'updateJSON(request)',
  'loading'  => visual_effect('appear', 'indicator'),
    'complete' => visual_effect('fade', 'indicator').
                  visual_effect('highlight', 'title').'updateJSON(request);'
));

echo javascript_tag("
function updateJSON(request)
{
  json = request.responseJSON;
  for (var i = 0; i < json.length; i++)
  {
     Element.update(json[i][0], json[i][1]);
  }
}
");

In ~/apps/$appname/config/view.yml

all:
  javascripts: [%SF_PROTOTYPE_WEB_DIR%/js/prototype]

In ~/apps/$appname/modules/post/actions/actions.class.php

class postActions extends sfActions
{
  public function executeIndex(sfWebRequest $request)
  {
  }

  public function executeList(sfWebRequest $request)
  {
      $this->setLayout(false);
      sfConfig::set('sf_web_debug', false);
      sfConfig::set('sf_debug', false);

    if ($this->getRequest()->isXmlHttpRequest()) {
        $this->getResponse()->setHttpHeader('Content-Type','application/json; charset=utf-8');
    }
    //$output = array(array("title" => "My basic letter", "name" => "Mr Brown"));
    //return $this->renderText(json_encode($output));

    $output = '[["title", "My basic letter"], ["name", "Mr Brown"]]';
    return $this->renderText('('.$output.')');

  }
}

, ,

No Comments

Hello world!

Welcome to WordPress. This is your first post. Edit or delete it, then start blogging!

No Comments