Skip to content

API reference

Use this page when you need the exact public methods behind actions, filters, and collectors. It explains how to register, inspect, order, and remove callbacks, with signatures and return values in one place.

The published signatures and edge cases here match magdicom/hooks v2.0.0-beta.2. Start with the guide for your hook type, then use this page when you need a complete method summary.

Hooks has one registration method for each hook type:

Method What it registers Return value
addAction(string $hookPoint, array|callable $callback, int $priority = 10): RegistrationHandle A callback whose return value is ignored and whose purpose is a synchronous side effect. A handle for this exact action registration.
addFilter(string $hookPoint, array|callable $callback, int $priority = 10): RegistrationHandle A callback that receives the current value and returns the value passed to the next filter. A handle for this exact filter registration.
addCollector(string $hookPoint, array|callable $callback, int $priority = 10): RegistrationHandle A callback whose return value becomes one raw entry in the collector result list. A handle for this exact collector registration.

All three accept a hook name, a PHP callable or callable array, and an optional priority. The default priority is 10; lower numbers run first, and equal priorities keep registration order. The callback is invoked only when the matching dispatch method runs.

Registrations belong to the Hooks instance that created them. The default priority is 10. Lower numbers run first, and equal priorities retain registration order.

use Magdicom\Hooks;
$hooks = new Hooks();
$hooks->addAction('profile.updated', static function (int $profileId): void {
// Runs first.
}, priority: 5);
$hooks->addAction('profile.updated', static function (int $profileId): void {
// Runs second.
});
$hooks->doAction('profile.updated', 42);

The returned RegistrationHandle identifies that exact registration, including its hook point, type, priority, and registration id.

Each handle exposes:

Method Purpose and return value
id(): int Returns the internal registration id. It identifies this registration among otherwise equivalent callbacks.
hookPoint(): string Returns the exact string hook name used during registration.
type(): string Returns the registration type, such as action, filter, or collector.
priority(): int Returns the priority assigned to the registration.
remove(): bool Removes this exact registration and returns true; returns false if it was already removed.
belongsTo(Hooks $hooks): bool Checks whether this handle was created by that exact Hooks object.

The handle is a reference to a registration, not a copy of the callback. Keep it when a temporary extension needs to remove exactly the listener it added.

remove() is registration-id based. It removes the exact registration and returns true; calling it after that registration has already been removed returns false:

use Magdicom\Hooks;
$hooks = new Hooks();
$handle = $hooks->addFilter('email.subject', static fn (string $value): string => strtoupper($value));
$handle->remove(); // true
$handle->remove(); // false

This matters when you register equivalent or duplicate callbacks. A handle belongs to the particular Hooks object that returned it. belongsTo($hooks) checks that exact ownership rather than comparing configuration.

Use the inspection methods when you need to decide whether an extension point is populated, count registrations, or examine the handles that were returned by registration. They do not invoke callbacks.

Method What it tells you Return details
has(string $hookPoint): bool Whether at least one action, filter, or collector is registered at the hook point. true for any registration type; false when the point is empty.
hasAction(string $hookPoint, array|callable|null $callback = null, int $priority = 10): bool Whether an action is registered. With a callback, checks that callback at the given priority. Type-aware boolean result; a missing callback asks whether any action exists.
hasFilter(string $hookPoint, array|callable|null $callback = null, int $priority = 10): bool Whether a filter is registered. With a callback, checks that exact callback and priority. Type-aware boolean result; an action with the same callback does not satisfy it.
hasCollector(string $hookPoint, array|callable|null $callback = null, int $priority = 10): bool Whether a collector is registered. With a callback, checks that exact callback and priority. Type-aware boolean result; actions and filters are not included.
count(?string $hookPoint = null): int How many registrations exist across all hook types. With a hook point, counts only that point; without one, counts the entire registry.
listeners(string $hookPoint): array Every registration at the point, regardless of type. Returns RegistrationHandle objects sorted by priority and registration order.
actions(string $hookPoint): array The action registrations at the point. Returns action handles in dispatch order.
filters(string $hookPoint): array The filter registrations at the point. Returns filter handles in dispatch order.
collectors(string $hookPoint): array The collector registrations at the point. Returns collector handles in dispatch order.

For hasAction(), hasFilter(), and hasCollector(), omit the callback when you only need to know whether that type has any registration. Pass the callback when callback identity and priority matter. The default priority is 10; the priority argument is relevant to callback matching.

<?php
declare(strict_types=1);
use Magdicom\Hooks;
$hooks = new Hooks();
$callback = static fn (string $value): string => trim($value);
$hooks->addFilter('email.subject', $callback, priority: 20);
$hasAny = $hooks->has('email.subject');
$hasFilter = $hooks->hasFilter('email.subject');
$hasExactPriority = $hooks->hasFilter('email.subject', $callback, priority: 20);
$hasWrongPriority = $hooks->hasFilter('email.subject', $callback, priority: 10);

The handle collections are useful when you need metadata or exact removal later. For example:

use Magdicom\Hooks;
$hooks = new Hooks();
$sendReceipt = static function (int $invoiceId): void {
// Send the receipt for the paid invoice.
};
$applyDiscount = static fn (int $total): int => $total - 100;
$billingWidget = static fn (): array => ['key' => 'revenue'];
$hooks->addAction('invoice.paid', $sendReceipt, priority: 20);
$hooks->addFilter('invoice.total', $applyDiscount);
$hooks->addCollector('dashboard.widgets', $billingWidget);
$totalRegistrations = $hooks->count();
$invoiceRegistrations = $hooks->count('invoice.paid');
$allInvoiceListeners = $hooks->listeners('invoice.paid');
$invoiceActions = $hooks->actions('invoice.paid');
$invoiceFilters = $hooks->filters('invoice.paid');
$widgetCollectors = $hooks->collectors('dashboard.widgets');
$firstListener = $allInvoiceListeners[0] ?? null;
$firstListener?->priority();

The arrays contain handles, not callback return values. They are snapshots of the registrations at the time you call the inspection method. Use RegistrationHandle::remove() when you want to remove the exact registration represented by one of those handles; use the callback-based removal methods when you intentionally want to match by callback and priority.

Removal by callback is type-aware:

Method What it removes Return value
removeAction(string $hookPoint, array|callable $callback, int $priority = 10): bool The first matching action callback at that hook point and priority. true when a matching registration was removed; otherwise false.
removeFilter(string $hookPoint, array|callable $callback, int $priority = 10): bool The first matching filter callback at that hook point and priority. true when a matching registration was removed; otherwise false.
removeCollector(string $hookPoint, array|callable $callback, int $priority = 10): bool The first matching collector callback at that hook point and priority. true when a matching registration was removed; otherwise false.

These methods remove the first matching callback of the requested type and priority. They do not accept a RegistrationHandle; call the handle’s remove() method for exact registration-id removal. A callback registered as an action is not removed by removeFilter().

Bulk methods remove registrations and return the number removed:

Method What it removes
removeAll(?string $hookPoint = null): int All actions, filters, and collectors at one hook point, or every registration when the argument is omitted.
removeAllActions(?string $hookPoint = null): int Only action registrations at one hook point, or all action registrations when omitted.
removeAllFilters(?string $hookPoint = null): int Only filter registrations at one hook point, or all filter registrations when omitted.
removeAllCollectors(?string $hookPoint = null): int Only collector registrations at one hook point, or all collector registrations when omitted.

Each method returns the number of registrations it removed. A hook point limits the operation; omitting it is a registry-wide operation for the selected type.

Passing a hook point limits removal to that point. Omitting it removes the relevant type across the registry; removeAll() removes all types.

Hooks sorts listeners by ascending priority and then by registration id. Equal-priority callbacks therefore run in a predictable order.

Before dispatch, Hooks creates a sorted listener snapshot. Adding or removing registrations while a callback runs does not alter the list selected for that invocation. The change appears on a later invocation:

<?php
declare(strict_types=1);
use Magdicom\Hooks;
$hooks = new Hooks();
$late = static function (): void {
// Added during dispatch, so it does not run in that same snapshot.
};
$hooks->addAction('order.cancelled', static function () use ($hooks, $late): void {
$hooks->addAction('order.cancelled', $late);
});
$hooks->doAction('order.cancelled');
$hooks->doAction('order.cancelled'); // The new listener is available here.

Nested collect(), process(), and render() calls use their own snapshots. Exceptions reach the caller, and a later invocation can still use the registry.

For value transformation and raw result behavior, see the hook type pages. Processor, renderer, resolver, and callback behavior is covered in the advanced core reference.

The following summary covers the public methods on Magdicom\Hooks. Private helpers are left out.

Method Purpose and return value Applies to / relevant exceptions
__construct(?Resolver $resolver = null) Creates a Hooks registry. Returns the new object; uses NativeResolver when no resolver is supplied. Core; resolver construction errors can bubble from a custom resolver
doAction(string $hookPoint, mixed ...$arguments): void Invokes the action snapshot with the arguments exactly as passed. Callback returns are ignored. Actions; listener and callback exceptions bubble
applyFilters(string $hookPoint, mixed $value, mixed ...$arguments): mixed Passes the current value first, then explicit arguments, through each filter and returns the final value. Filters; listener and callback exceptions bubble
collect(string $hookPoint, mixed ...$arguments): array Returns one raw result per collector listener in dispatch order. Collectors; listener and callback exceptions bubble

Registration methods return a RegistrationHandle and default to priority 10:

addAction(string $hookPoint, array|callable $callback, int $priority = 10): RegistrationHandle
addFilter(string $hookPoint, array|callable $callback, int $priority = 10): RegistrationHandle
addCollector(string $hookPoint, array|callable $callback, int $priority = 10): RegistrationHandle

They apply respectively to actions, filters, and collectors. A callback may be a callable, object method array, or class-name method array; invalid callback resolution or callback exceptions surface when the callback is prepared or invoked.

Method Purpose and return value Applies to / relevant exceptions
setProcessor(string $hookPoint, ResultProcessor|callable|string $processor): self Stores or replaces the processor slot and returns the same Hooks object for deliberate method chaining. Collectors; class-name processors must implement ResultProcessor, otherwise InvalidProcessorException is raised when invoked
hasProcessor(string $hookPoint): bool Reports whether the endpoint has a configured processing slot. Collectors
processor(string $hookPoint): ResultProcessor|callable|string|null Returns the stored processor reference unchanged, or null. Collectors
clearProcessor(string $hookPoint): bool Removes the processing slot and reports whether one existed. Collectors
setRenderer(string $hookPoint, Renderer|callable|string $renderer): self Stores or replaces the same slot used by setProcessor() and returns the Hooks object. Collectors; invalid renderer configuration is reported by render()
process(string $hookPoint, mixed ...$arguments): mixed Collects raw results, creates ProcessingContext, invokes the configured processor, and returns its output unchanged. Collectors; MissingProcessorException when unset, InvalidProcessorException for an invalid class reference
processWith(string $hookPoint, ResultProcessor|callable|string $processor, mixed ...$arguments): mixed Collects raw results and applies the supplied processor for this call only. It does not read or change persistent processor configuration. InvalidProcessorException for an invalid resolved class
render(string $hookPoint, mixed ...$arguments): string Collects raw results, invokes the configured renderer, and requires string output. Collectors; MissingRendererException when unset and InvalidRendererException for invalid class or non-string callable output
renderWith(string $hookPoint, Renderer|callable|string $renderer, mixed ...$arguments): string Collects raw results and applies the supplied renderer for this call only. It does not read or change persistent processor configuration. InvalidRendererException for invalid configuration or non-string callable output

setProcessor() and setRenderer() share one collector endpoint slot. collect() always bypasses that slot. See processors and renderers for built-in behavior.

processWith() and renderWith() are one-off alternatives when the caller wants to choose the processing or rendering strategy at invocation time. They collect the endpoint once and leave any persistent slot untouched. See one-off processing and one-off rendering for examples.

Method Purpose and return value Applies to
has(string $hookPoint): bool Reports whether any hook type has a registration at the point. All hook types
hasAction(string $hookPoint, array|callable|null $callback = null, int $priority = 10): bool Checks for any action, or a matching callback at the requested priority. Actions
hasFilter(string $hookPoint, array|callable|null $callback = null, int $priority = 10): bool Checks for any filter, or a matching callback at the requested priority. Filters
hasCollector(string $hookPoint, array|callable|null $callback = null, int $priority = 10): bool Checks for any collector, or a matching callback at the requested priority. Collectors
count(?string $hookPoint = null): int Counts registrations across all types, optionally restricted to one point. All hook types
listeners(string $hookPoint): array Returns all registration handles at the point, sorted by priority and registration id. All hook types
actions(string $hookPoint): array Returns action handles in dispatch order. Actions
filters(string $hookPoint): array Returns filter handles in dispatch order. Filters
collectors(string $hookPoint): array Returns collector handles in dispatch order. Collectors
removeAction(string $hookPoint, array|callable $callback, int $priority = 10): bool Removes the first matching action callback and priority. Actions
removeFilter(string $hookPoint, array|callable $callback, int $priority = 10): bool Removes the first matching filter callback and priority. Filters
removeCollector(string $hookPoint, array|callable $callback, int $priority = 10): bool Removes the first matching collector callback and priority. Collectors
removeAll(?string $hookPoint = null): int Removes all hook types at one point, or the entire registry when omitted; returns the number removed. All hook types
removeAllActions(?string $hookPoint = null): int Removes action registrations and returns the number removed. Actions
removeAllFilters(?string $hookPoint = null): int Removes filter registrations and returns the number removed. Filters
removeAllCollectors(?string $hookPoint = null): int Removes collector registrations and returns the number removed. Collectors

These public methods provide diagnostics rather than dispatch:

Method Purpose and return value Applies to
`debug(callable null $callback): self` Enables debug logging when a callable is supplied, disables it for null, and returns the same Hooks object.
setSourceFile(?string $path = null): self Stores an optional source-file label and returns the same Hooks object. Core registry diagnostics
getSourceFile(): string Returns the configured source-file label, or 'Unknown' when none was set. Core registry diagnostics

These methods do not change action, filter, or collector behavior. The debug callback and source label are metadata, not a replacement for explicit arguments or application logging.

Processors, renderers, and class callbacks use these core contracts:

Contract Method What it is used for
Resolver resolve(string $className): object Creates the object for a resolver-backed class callback, processor, or renderer.
ResultProcessor process(array $results, ProcessingContext $context): mixed Reduces collector results to an application-defined value.
Renderer process(array $results, ProcessingContext $context): string Reduces collector results specifically to a string. Renderer extends ResultProcessor.

The processor and renderer receive the raw list returned by collect() plus a ProcessingContext; they do not receive callbacks individually.

ProcessingContext exposes:

Method Purpose and return value
__construct(string $hookPoint, mixed ...$arguments) Stores the hook point and the arguments passed to process() or render().
hookPoint(): string Returns the hook point currently being processed or rendered.
arguments(): array Returns the original invocation arguments as a list, in their original order.

The ProcessingContext constructor stores the original invocation arguments as a list. RegistrationHandle exposes the lifecycle methods above. NativeResolver::resolve(string $className): object creates a class with new $className(); the Laravel wrapper replaces this with container-backed resolution.

RegistrationHandle::__construct(...) is public in the released class but is an implementation-created value: normal callers should obtain handles from addAction(), addFilter(), or addCollector() rather than constructing one. Its internal remover closure preserves exact registration-id behavior.

The Laravel wrapper does not add a second dispatch API. Its access points resolve the same core object:

Access path Use it when Behavior
hooks(): Magdicom\Hooks You need a short application-level call. Returns the shared singleton and accepts no invocation arguments. Put arguments on doAction(), applyFilters(), collect(), process(), or render().
app(Magdicom\Hooks::class) A service or framework integration needs the typed container binding. Resolves the same singleton as the helper.
app('hooks') Existing Laravel code uses the registered string alias. Resolves the same singleton through the hooks alias.
Magdicom\LaravelHooks\Facades\Hooks You prefer Laravel facade syntax. Forwards static-looking calls to the same container-managed root; it is not static state in the core package.

Use the Laravel integration guide for container lifecycle, auto-discovery, resolver timing, and long-running process guidance.