Middleware
Middleware lets you hook into the driver at specific steps while a query is being run. It is the intended way to add things like logging, profiling, debugging or rewriting a query before it is executed, without having to change the driver itself.
A middleware is a function with the following signature:
function ($result, $params, $next) {
// Do something with $result
return $next($result);
}
$result is the value for the current step (described below), $params holds any extra data
for the step and $next passes the result to the next middleware in the chain. You should
always call $next($result) and return its value so the chain continues, unless you
deliberately want to stop it.
Steps
Middleware is attached to a step. The driver runs these steps in the following order while processing a query:
PdoDriver::STEP_BEFORE_RUN- Before a query is run.$resultis the raw query and$params[0]is the type of the call (run,first,fetchAll, etc.).PdoDriver::STEP_OPEN- After a connection is opened.$resultis the PDO instance.PdoDriver::STEP_BEFORE_PREPARE- Before a statement is prepared.$resultis the PDO statement and$params[0]is the raw query.PdoDriver::STEP_AFTER_PREPARE- After a statement is prepared.$resultis the PDO statement and$params[0]is the raw query.PdoDriver::STEP_AFTER_RUN- After a query is run.$resultis the result of the call and$params[0]is the raw query.PdoDriver::STEP_CLOSE- After a connection is closed.$resultis null.
The connection steps (STEP_OPEN, STEP_CLOSE) only run when the connection is actually
opened or closed, so they will not fire on every query.
Adding middleware
You can pass middleware when configuring the driver:
use ArekX\PQL\Drivers\Pdo\PdoDriver;
$driver->configure([
'middleware' => [
PdoDriver::STEP_BEFORE_RUN => [
function ($result, $params, $next) {
// $result is the raw query about to run
error_log('Running: ' . $result->getQuery());
return $next($result);
},
],
],
]);
You can also add a single middleware to a step at any time with appendMiddleware():
$driver->appendMiddleware(PdoDriver::STEP_AFTER_RUN, function ($result, $params, $next) {
return $next($result);
});
useMiddleware() replaces the whole list of middleware for a step, while appendMiddleware()
adds one to the end of the existing list.
Example: query logging
A simple way to log every query and how long it took:
use ArekX\PQL\Drivers\Pdo\PdoDriver;
$queries = [];
$driver->configure([
'middleware' => [
PdoDriver::STEP_BEFORE_RUN => [
function ($result, $params, $next) use (&$queries) {
$queries[] = $result->getQuery();
return $next($result);
},
],
],
]);
Every query that runs through the driver is now collected in $queries.