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:
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:
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:
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:
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