Skip to content

Query Events

glynn edited this page Jun 4, 2026 · 2 revisions

Query Events let you hook into the lifecycle of a query — running a callback before or after a select, insert, update or delete, scoped either to a single table or to any table.

A before-* event that returns anything other than null will short circuit the query, and its return value becomes the result of the call. This makes events useful for caching, validation or auditing.

Event names

The available events are exposed as constants on Pixie\Event:

Constant Value
Event::BEFORE_SELECT before-select
Event::AFTER_SELECT after-select
Event::BEFORE_INSERT before-insert
Event::AFTER_INSERT after-insert
Event::BEFORE_UPDATE before-update
Event::AFTER_UPDATE after-update
Event::BEFORE_DELETE before-delete
Event::AFTER_DELETE after-delete

Use Event::ANY_TABLE (:any) or pass null as the table to fire for every table.

registerEvent()

Register an event against the query builder. The callback receives the QueryBuilderHandler as its first argument, followed by the result and execution time for after-* events.

/**
 * @param string      $event   One of the Event::* constants
 * @param string|null $table   Table to scope to (null / ':any' for all tables)
 * @param Closure     $action  The handler
 * @return void
 */
public function registerEvent(string $event, ?string $table, Closure $action): void

Usage

// Short circuit a select with a cached value.
$builder->registerEvent(Event::BEFORE_SELECT, 'posts', function (QueryBuilderHandler $query) {
    return get_transient('my_cached_posts') ?: null; // non-null short circuits the query
});

// React after an insert.
$builder->registerEvent(Event::AFTER_INSERT, 'posts', function (QueryBuilderHandler $query, $insertId, float $time) {
    do_action('my_post_inserted', $insertId);
});

Object based events

Since v0.2.0

Events are now modelled as Pixie\Event value objects, with lazy static constructors for each event type. EventHandler::register() accepts an Event object directly. The original registerEvent() continues to work unchanged.

use Pixie\Event;

$handler = $connection->getEventHandler();

// Lazy static constructors: beforeSelect / afterSelect / beforeInsert / afterInsert
//                           beforeUpdate / afterUpdate / beforeDelete / afterDelete
$handler->register(
    Event::beforeSelect('posts', fn($query) => null)
);

// Or the generic factory for a custom / explicit event name:
$handler->register(
    Event::on(Event::AFTER_DELETE, 'posts', fn($query, $rows, $time) => null)
);

An Event exposes getName(), getTable() and getAction(). The registered objects can be read back with EventHandler::getRegisteredEvents(), while getEvents() still returns the closures keyed by table then event name for backwards compatibility.

removeEvent()

$builder->removeEvent(Event::BEFORE_SELECT, 'posts');

Clone this wiki locally