Upgrade from 1.x
Upgrade from 1.x
Section titled “Upgrade from 1.x”Hooks 2.x replaces version 1’s registration and output model with explicit actions, filters, collectors, processors, and renderers. This guide shows how to move the common patterns; it is not a copy of the version-1 manual.
The mappings below follow the core and Laravel package upgrade guides. The 2.x packages are beta releases, so test your migration against the versions your application supports.
Before you migrate
Section titled “Before you migrate”Install the beta packages explicitly in your application:
composer require magdicom/hooks:"^2.0@beta"For Laravel, install both packages:
composer require magdicom/laravel-hooks:"^2.0@beta" magdicom/hooks:"^2.0@beta"Do not change global Composer minimum-stability settings. See installation for PHP and Laravel requirements.
Choose the new hook type
Section titled “Choose the new hook type”Version 1’s registration method covered several jobs. In 2.x, choose the method that matches what the caller needs:
| Version 1 intent | Version 2 registration and invocation | Result |
|---|---|---|
register() for side effects |
addAction() + doAction() |
Synchronous void execution; callback returns are ignored |
register() for transformations |
addFilter() + applyFilters() |
Sequentially transformed value |
register()/all() for result gathering |
addCollector() + collect() |
One raw result per listener |
There is no single replacement for every old register() call. Look at what each registration does, then choose actions, filters, or collectors.
Side effects: register() to actions
Section titled “Side effects: register() to actions”<?php
declare(strict_types=1);
use Magdicom\Hooks;
$hooks = new Hooks();$hooks->addAction('invoice.paid', static function (int $invoiceId): void { // Send a synchronous notification or write an audit entry.});
$hooks->doAction('invoice.paid', 42);doAction() returns void. If callers used the old callback’s return value, migrate that code to a filter or collector instead.
Transformations: register() to filters
Section titled “Transformations: register() to filters”<?php
declare(strict_types=1);
use Magdicom\Hooks;
$hooks = new Hooks();$hooks->addFilter('profile.label', static function (string $label): string { return strtoupper($label);});
$label = $hooks->applyFilters('profile.label', 'administrator');The current value is the first callback argument, and each callback’s return value becomes the next value. With no listeners, applyFilters() returns the original value.
Result gathering: register()/all() to collectors
Section titled “Result gathering: register()/all() to collectors”<?php
declare(strict_types=1);
use Magdicom\Hooks;
$hooks = new Hooks();$hooks->addCollector('dashboard.widgets', static fn (): array => ['owner']);$hooks->addCollector('dashboard.widgets', static fn (): array => ['activity']);
$cards = $hooks->collect('dashboard.widgets');// [['owner'], ['activity']]collect() returns one raw entry per listener. It does not recreate implicit version-1 aggregation, flattening, or output state.
all() and toArray() to collect()
Section titled “all() and toArray() to collect()”For result lists, the migration is:
// Version 2$results = $hooks->collect('dashboard.widgets');This replaces both old all() result gathering and all()->toArray(). If you need a merged or flattened shape, configure a collector processor such as MergeProcessor or FlattenProcessor, or transform the raw array yourself. collect() never merges entries automatically.
first() and last() to processors
Section titled “first() and last() to processors”When the old code selected one collector result, configure the intended reduction explicitly:
<?php
declare(strict_types=1);
use Magdicom\Hooks;use Magdicom\Processors\FirstProcessor;use Magdicom\Processors\LastProcessor;
$hooks = new Hooks();$hooks->addCollector('checkout.banner', static fn (): string => 'Primary');$hooks->addCollector('checkout.banner', static fn (): string => 'Fallback');
$hooks->setProcessor('checkout.banner', new FirstProcessor());$first = $hooks->process('checkout.banner');
$hooks->setProcessor('checkout.banner', new LastProcessor());$last = $hooks->process('checkout.banner');FirstProcessor and LastProcessor return null for an empty result list. Selection is a collector decision; actions and filters do not have first() or last() methods.
Parameters: global arrays to explicit arguments
Section titled “Parameters: global arrays to explicit arguments”If version 1 stored parameters globally, pass the values at invocation time:
<?php
declare(strict_types=1);
use Magdicom\Hooks;
$hooks = new Hooks();$hooks->addFilter('invoice.total', static function (int $price, string $currency): int { return $currency === 'USD' ? $price : $price + 1;});
$price = $hooks->applyFilters('invoice.total', 100, 'USD');For a larger shared input, pass one typed context object as an explicit argument:
<?php
declare(strict_types=1);
use Magdicom\Hooks;
final readonly class RenderContext{ public function __construct( public string $locale, public string $userId, ) { }}
$hooks = new Hooks();$context = new RenderContext('en', 'user-42');$hooks->doAction('profile.rendered', $context);The Hooks core does not maintain a hidden global parameter array. Processors and renderers can use ProcessingContext to read the hook point and original invocation arguments.
String aggregation to renderers
Section titled “String aggregation to renderers”When the old code assembled collector output as a string, use a renderer with an explicit separator:
<?php
declare(strict_types=1);
use Magdicom\Hooks;use Magdicom\Processors\ConcatenateRenderer;
$hooks = new Hooks();$hooks->addCollector('navigation.labels', static fn (): string => 'Hooks');$hooks->addCollector('navigation.labels', static fn (): string => 'Beta');$hooks->setRenderer('navigation.labels', new ConcatenateRenderer(' · '));
$output = $hooks->render('navigation.labels');// 'Hooks · Beta'ConcatenateRenderer accepts supported scalar, string, null, and Stringable values. It returns an empty string for an empty result list; unsupported values throw UnexpectedValueException.
Removed chaining and legacy output state
Section titled “Removed chaining and legacy output state”These version-1 APIs are removed in 2.x:
register(), all(), first(), last(), toArray(), toString(), __toString(), setParameter(), setParam(), setParameters(), and setParams().
Rewrite chained version-1 calls as explicit steps:
- register a named action, filter, or collector;
- invoke it with explicit arguments;
- collect raw results when needed;
- process or render those results explicitly.
There is no shared legacy output or chaining state after dispatch. Decide explicitly where aggregation, selection, string conversion, and parameter ownership belong in the new code.
Version 1 reference
Section titled “Version 1 reference”This guide does not recreate the complete version-1 manual. Use the historical Hooks releases and source when you need the old package documentation, then use this page to plan the move to 2.x Beta.