Actions
Run callbacks for side effects such as notifications, audit entries, or integrations. Their return values are ignored.
Extension points for PHP · Hooks 2.x Beta
Run actions, transform values, and collect contributions through clear, named extension points.
Framework-independent at its core, with first-class Laravel integration.
Three useful hook points
Run callbacks for side effects such as notifications, audit entries, or integrations. Their return values are ignored.
Pass one value through a sequence of callbacks. Each callback receives the current value and returns the next one.
Ask several callbacks for a contribution and keep one result from each. Hooks does not merge or flatten them for you.
Common use cases
See how actions, filters, collectors, processors, and renderers fit into invoices, dashboards, checkout, navigation, and Laravel applications.
Actions · framework-independent core
An exporter can expose a synchronous configuration point for modules that need to add columns or other options. Unlike a domain event, this hook stays inside the current workflow, so each callback can adjust this export request immediately.
Learn about actions →use App\Reports\ExportOptions;use Magdicom\Hooks;
$hooks = new Hooks();$options = new ExportOptions('sales');$hooks->addAction('report.export.configure', static function (ExportOptions $options): void { $options->includeColumn('customer_region');});
$hooks->doAction('report.export.configure', $options);use App\Reports\ExportOptions;
// The exporter owns this object for the current request.$options = new ExportOptions('sales');hooks()->addAction('report.export.configure', static function (ExportOptions $options): void { $options->includeColumn('customer_region');});
hooks()->doAction('report.export.configure', $options);Filters · same hook model
Filters pass a value through callbacks in order. The PHP and Laravel versions differ only in how the shared Hooks object is reached.
Learn about filters →use Magdicom\Hooks;
$hooks = new Hooks();$hooks->addFilter('invoice.total', static fn (int $total): int => $total - 1000);$total = $hooks->applyFilters('invoice.total', 10000);// 9000 centshooks()->addFilter('invoice.total', static fn (int $total): int => $total - 1000);$total = hooks()->applyFilters('invoice.total', 10000);// 9000 centsCollectors · independent results
Collectors keep one result from each callback. A dashboard can ask for widgets without knowing which modules provide them.
Learn about collectors →use Magdicom\Hooks;
$hooks = new Hooks();$hooks->addCollector('dashboard.widgets', static fn (string $userId): array => [ 'key' => 'revenue', 'user_id' => $userId,]);$userId = 'user-42';$widgets = $hooks->collect('dashboard.widgets', $userId);hooks()->addCollector('dashboard.widgets', static fn (string $userId): array => [ 'key' => 'revenue', 'user_id' => $userId,]);$userId = 'user-42';$widgets = hooks()->collect('dashboard.widgets', $userId);Install the beta
Use the framework-independent core package in any PHP application or reusable package.
composer require magdicom/hooks:"^2.0@beta"Install the wrapper and explicitly permit the matching beta core package.
composer require magdicom/laravel-hooks:"^2.0@beta" magdicom/hooks:"^2.0@beta"Both beta packages are named explicitly so Composer can resolve them. You do not need to change your global minimum-stability setting.
Choose the right tool
Keep exploring