Pretty, Painless and Productive debug with DebugKit

CakePHP DebugKit has been released some time ago now, you know.
Since the release some things have changed: it’s no longer dependent of it’s own view – actually it is, but DebugView will now be hackilly automagically declared as a subclass of the view class being used in the request, it is much more extensible and is planned to be useful on non-html outputs, and it’s no longer dependent of javascripts libraries. Next major change will be the integration with firebug to allow ajax debugging and maybe some other goodies. Aren’t you just excited about that?
For TDD lovers like me it isn’t much impactant at a glance, but take a closer look, after all, even enjoying writing test cases – peehh… liar. No one likes to write test cases, ok? Test Engineers maybe, but it’s just so boring – from time to time you’ll face a simple case or project, or just one with an extremely short deadline, and find yourself debugging all the inside outs of the app. And that happened to me in the past few weeks.
So, I saw myself cutting down debug time and pain with the interface designed by Mark Story , and decided to share a word about how to take some more out of it.
First things first
Of course I won’t talk about the “installation” process. If you want to get started with the kit, check clone it out from github, refer to the wiki, ‘install’ and get the feeling of how it works. Of course it’s easy.
Customized panels
Although the kit comes packed with almost everything you need to debug the heart of your buggy app – – you may want to cover, control and debug other aspects and processes in your project.
To create a customized panel at least two things are needed: a subclass of DebugPanel placed on vendors folder and named as Panel, the file has to have the same name but underscored, and an element named just like the panel, but with the ‘.ctp’ extension, that will be the content of the tab on the panel.
Did someone shout: “Hello World example!”? I hope not (don’t you dare asking this…). So…
DebugPanel class interface gives you 4 gifts:
- you can specify a plugin to which your panel belongs to, so that the element can be searched in it’s right place;

var $plugin = 'Shooter';

- you can specify a custom name for the element to be rendered;

var $elementName = 'triggers/analysis';

- you can access the Controller in it’s startup with the ’startup’ callback;

function startup(&$Controller) {
$this->params['modelClass'] = $Controller->modelClass;
}

- and you can access the Controller before the rendering process, and return data to be passed to the panel’s element with the ‘beforeRender’ callback.

function beforeRender($&Controller) {
return $this->params;
}

Playing with the element is easy. The data returned by the panel on ‘beforeRender’ callback will be available on $content var, and to make all those pretty lists that are pimped by the javascript controller you can use the HtmlToolbarHelper::makeNeatArray() method:

Debug the bug
<?php echo $htmlToolbar->makeNeatArray($content) ?>

…a piece of cake isn’t it? Now let’s debug the vars being passed to the view:
in the APP/vendors folder, create a file and name it ‘view_vars_panel.php’, and write:

class ViewVarsPanel extends DebugPanel {
function beforeRender(&$Controller) {
return $Controller->viewVars;
}
}

now, in the APP/views/elements folder, create a file and name it ‘view_vars_panel.ctp’, and write:

Vars set by the Controller
<?php echo $htmlToolbar->makeNeatArray($content) ?>

and finally, in the AppController, or wherever you have set the DebugKit.ToolbarComponent, change the declaration to:

var $components = array(
'DebugKit.Toolbar' => array('panels' => array('viewVars'))
//sure, you can add the rest of your components here
);

Ctrl + Tab, choose your browser, F5
… wait a little… and… here it is:
Your brand new customized debug panel!
Oh come on! that was too easy and quick!
Now, wait, where are all the other panels? “oh you little bastard…”… when specifying panels to be loaded, make sure you specify all panels you want to be used:

var $components = array(
'DebugKit.Toolbar' => array(
'panels' => array('viewVars', 'session', 'request', 'sqlLog', 'timer', 'log', 'memory')
)
//sure, you can still add the rest of your components here
);

Ufff… and there are them again… – that was close…
Benchmarking
Well, it’s not all about debugging sire. DebugKit is packed with it’s own debugger class which holds some functionalities that are planned to integrate the core in the near future, and it happens to be that some of the features are timer handlers for benchmarking purposes. Cool!
When benchmarking you won’t need a custom panel, although you could write one to fit your needs, all timers are shown on “Timer” panel.
Timers are initialized and finalized by static methods of DebugKitDebugger class, and they can have an ID and a message:

DebugKitDebugger::startTimer('timer_id', 'My timer message, describing what is it');
[... your complex code goes here ..]
DebugKitDebugger::stopTimer('timer_id');

Now a merchand a use case of the [7640] changes a real world example:

class Schedule extends AppModel {
function _findAgenda($state, $query, $results = array()) {
if ($state === 'before') {
$default = array(
// Uses LinkableBehavior to bash out all the data I need!
'link' => array('Employee' => 'Person', 'Task' => array('Project' => 'Company'))
,'order' => array('Schedule.check_in' => 'DESC')
,'fields' => array(
'Schedule.employee_id', 'Schedule.task_id'
,'Employee.position', 'Person.name'
,'Task.title', 'Task.project_id', 'Project.title'
,'Project.company_id', 'Company.trade_name'
)
);
$mandatory = array(
'fields' => array($this->getVirtualField('date'), $this->getVirtualField('day_part'))
,'group' => null
);
$query = $this->_mergeQueryParams(compact('default', 'query', 'mandatory'));
return $query;
} elseif (empty($results)) {
return null;
}

DebugKitDebugger::startTimer(
'agenda_structure_generation',
'handling the data to generate the agenda structure'
);

foreach($results as $key => $record) {
unset($results[$key]);
$keyName = $record['Schedule']['date'];
$groupKey = $record['Schedule']['day_part'];
if (!isset($results[$keyName])) {
$results[$keyName] = array();
}
if (!isset($results[$keyName][$groupKey])) {
$results[$keyName][$groupKey] = array();
}
$results[$keyName][$groupKey][] = $record;
}

DebugKitDebugger::stopTimer('agenda_structure_generation');

return $results;
}
}

And – I wish I could put a picture here showing the result… – erhm? can I? really!? … don’t tell them, please – you’ll see the results by opening the “Timer” panel on the toolbar.
Closing
Now along with all the mentioned super cool features, the most impressive and useful functionality is the “disable toolbar” feature: click on the cake icon and it’s done! Now, click it again and it’s back! It’s just too much magic for a single tool, isn’t it??
Oh ok, I’m out of here.
Hope you learned something.
Is it too painfull to give some feedback?
Make sure you catch on my typos, there might be tons of it, it’s past 4am here.
And yes, I wrote the plain js debug kit javascript controller… I tried man, but I can’t help it, I’m just too narcisist! – Will talk about it in an upcoming post… no, not about my narcisism, doh… about contributing and giving a hand to open source projects that make your monthly revenue bigger and easier.
Tagged: Debug, DebugKit, Git & GitHub, Merchandising, Open Source, Plugin, Tutorial