Pop PHP
Database

Profiler

The profiler records every statement the adapter runs, with the parameters bound to it, how long it took and any error it raised. It is the tool for finding the query that is costing you, and for seeing what a record class actually sent.

Turning It On#

Register a query listener and the adapter builds the profiler itself, so there is nothing to construct:

PHP
use Pop\Db\Record;

$db = Record::getDb();

$db->listen('Pop\Debug\Handler\QueryHandler');

$db->select('SELECT * FROM `users` WHERE `id` < ?', [3]);
$db->query('SELECT * FROM orders');

Everything the adapter runs from that point on is recorded, whether it came from a raw query, a builder or a record class.

Reading the Steps#

getProfiler() reads back what happened. Each statement is a step, carrying the query as it was sent, the parameters bound to it, and how long it took:

PHP
use Pop\Db\Record;

$db = Record::getDb();

foreach ($db->getProfiler()->getSteps() as $step) {
    printf("%s [%s]\n", $step->getQuery(), $step->getElapsed());
    print_r($step->getParams());
}

echo $db->getProfiler()->getElapsed();

That prints each statement with its elapsed time, then the total for the run.

Call Returns
getSteps() every step recorded so far
getCurrentStep() the most recent step, which is the one to read right after a single query
getElapsed() the total elapsed time, measured against now until finish() is called
getStart() / finish() / getFinish() when the profiler began, and the end time finish() stamps on it

A step answers for itself with getQuery(), getParams() and getElapsed(), plus hasErrors() and getErrors(). A statement the database rejects is recorded as a step of its own, carrying the driver's message, so the profiler shows you the failure alongside the queries that ran around it.

Writing the Log#

The listener argument is the class that receives the profiler. Pop\Debug\Handler\QueryHandler from pop-debug is the one to reach for, and listen() returns the handler it built, so you can hand it to a debugger and choose when the log is written:

PHP
use Pop\Db\Record;
use Pop\Debug\Debugger;
use Pop\Debug\Storage\File;

$db = Record::getDb();

$queryHandler = $db->listen('Pop\Debug\Handler\QueryHandler');

$debugger = new Debugger();
$debugger->addHandler($queryHandler);
$debugger->setStorage(new File(__DIR__ . '/../logs'));

$db->select('SELECT * FROM `users` WHERE `id` < ?', [3]);

$debugger->save();

Writing as It Runs#

Hand listen() a profiler that already holds a debugger — its third argument — and every query is written the moment it finishes, with no save() of your own. That is the shape for catching a slow query on a request you cannot reproduce:

PHP
use Pop\Db\Record;
use Pop\Db\Adapter\Profiler\Profiler;
use Pop\Debug\Debugger;
use Pop\Debug\Storage\File;

$db = Record::getDb();

$debugger = new Debugger(null, new File(__DIR__ . '/../logs'));

$db->listen('Pop\Debug\Handler\QueryHandler', null, new Profiler($debugger));

$db->select('SELECT * FROM `users` WHERE `id` < ?', [3]);

See Also#

  • Querying — the adapter whose statements are being recorded
  • Debugging — the pop-debug handlers and storage adapters the log is written through
  • Records & the ORM — seeing the SQL a record class sends
  • pop-db README — the full profiler API surface