Skip to main content
Geneva, Switzerland Call our support
English

Filter hooks and events

Extending behavior without forking core.

Filters vs events

  • Filters — Transform data as it flows through core (return modified value)
  • Events — React after something happens (side effects, logging)

Registering a filter

In plugin boot():

use App\Filter\FilterHook;

$context->addFilter(FilterHook::MENU_ITEMS, function (array $items, array $ctx): array {
    $items[] = ['label' => 'Status', 'href' => '/status', 'target' => '', 'css_class' => ''];
    return $items;
}, 10);

Lower priority runs first (default 10). Declare used filters in plugin.jsonhooks.filters.

Common filter hooks

ConstantValueTransforms
FilterHook::SEO_METAseo.metaResolved meta array
FilterHook::MENU_ITEMSmenu.itemsPublic menu items for a location
FilterHook::API_ENTRY_RESPONSEapi.entry.responseREST entry detail JSON
FilterHook::CONTENT_SAVEcontent.saveEntry save POST body before validation
FilterHook::HTML_SANITIZEhtml.sanitizeSanitized HTML after HTMLPurifier

Listening to events

use App\Event\ContentEntrySavedEvent;

$context->listenEvent(ContentEntrySavedEvent::class, function (ContentEntrySavedEvent $e) use ($ctx): void {
    // React to save
});

Declare events in plugin.jsonhooks.events. Use listenEvent() not raw event bus so manifest validation applies.

Capability enforcement

When a plugin declares capabilities or hooks, Struxa enforces the contract at boot—e.g. pdo() requires database.read or database.write; addFilter() requires matching capability for that hook.

Performance

Filter callbacks over 25 ms and boot over 50 ms are logged. Check Extensions → Plugins performance column and Site Health warnings.