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() A callback for a synchronous side effect. A registration handle.
addFilter() A callback that transforms the current value. A registration handle.
addCollector() A callback that contributes one raw result. A registration handle.

addAction()

public function addAction(
  string $hookPoint,
  array|callable $callback,
  int $priority = 10,
): RegistrationHandle
Use it when:

you need to register a synchronous side effect.

Applies to: Actions

Returns: A RegistrationHandle.

Configuration: Yes; the callback remains until removed.

addFilter()

public function addFilter(
  string $hookPoint,
  array|callable $callback,
  int $priority = 10,
): RegistrationHandle
Use it when:

you need to register a value transformation.

Applies to: Filters

Returns: A RegistrationHandle.

Configuration: Yes; the callback remains until removed.

addCollector()

public function addCollector(
  string $hookPoint,
  array|callable $callback,
  int $priority = 10,
): RegistrationHandle
Use it when:

you need to register one independent contribution.

Applies to: Collectors

Returns: A RegistrationHandle.

Configuration: Yes; the callback remains until removed.

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() Returns the registration id.
hookPoint() Returns the exact hook name.
type() Returns action, filter, or collector.
priority() Returns the registration priority.
remove() Removes this exact registration.
belongsTo() Checks exact Hooks object ownership.

id()

public function id(): int
Use it when:

you need to identify a registration among otherwise equivalent callbacks.

Applies to: Registration handles

Returns: The internal registration id.

hookPoint()

public function hookPoint(): string
Use it when:

you need to inspect where the handle was registered.

Applies to: Registration handles

Returns: The exact string hook name.

type()

public function type(): string
Use it when:

you need to inspect what kind of registration the handle represents.

Applies to: Registration handles

Returns: The registration type: action, filter, or collector.

priority()

public function priority(): int
Use it when:

you need to inspect ordering metadata.

Applies to: Registration handles

Returns: The assigned priority.

remove()

public function remove(): bool
Use it when:

you need to remove precisely the registration represented by this handle.

Applies to: Registration handles

Returns: true when this exact registration is removed; false when already removed.

Configuration: Yes; it changes the registry.

belongsTo()

public function belongsTo(Hooks $hooks): bool
Use it when:

you need to verify exact object ownership before removing or sharing a handle.

Applies to: Registration handles

Returns: true only for the Hooks instance that created the handle.

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() Whether any registration exists. bool.
hasAction() Whether an action exists or matches. Type-aware bool.
hasFilter() Whether a filter exists or matches. Type-aware bool.
hasCollector() Whether a collector exists or matches. Type-aware bool.
count() Count registrations. int.
listeners() List all handles at a point. RegistrationHandle[].
actions() List action handles. RegistrationHandle[].
filters() List filter handles. RegistrationHandle[].
collectors() List collector handles. RegistrationHandle[].

has()

public function has(string $hookPoint): bool
Use it when:

you need to know whether a hook point has any listener.

Applies to: All hook types

Returns: true when any registration exists; otherwise false.

With no listeners: false.

hasAction()

public function hasAction(
  string $hookPoint,
  array|callable|null $callback = null,
  int $priority = 10,
): bool
Use it when:

you need to inspect an action or match its callback and priority.

Applies to: Actions

Returns: A type-aware boolean; omitting the callback checks whether any action exists.

With no listeners: false when no matching action exists.

hasFilter()

public function hasFilter(
  string $hookPoint,
  array|callable|null $callback = null,
  int $priority = 10,
): bool
Use it when:

you need to inspect a filter without invoking it.

Applies to: Filters

Returns: A type-aware boolean; callback matching includes priority.

With no listeners: false when no matching filter exists.

hasCollector()

public function hasCollector(
  string $hookPoint,
  array|callable|null $callback = null,
  int $priority = 10,
): bool
Use it when:

you need to inspect a collector without invoking it.

Applies to: Collectors

Returns: A type-aware boolean; actions and filters are not included.

With no listeners: false when no matching collector exists.

count()

public function count(?string $hookPoint = null): int
Use it when:

you need a registration count for diagnostics or lifecycle checks.

Applies to: All hook types

Returns: The number of registrations, optionally limited to one hook point.

listeners()

public function listeners(string $hookPoint): array
Use it when:

you need every registration at a point regardless of type.

Applies to: All hook types

Returns: Handles sorted by priority and registration order.

actions()

public function actions(string $hookPoint): array
Use it when:

you need only the action registrations at a point.

Applies to: Actions

Returns: Action handles in dispatch order.

filters()

public function filters(string $hookPoint): array
Use it when:

you need only the filter registrations at a point.

Applies to: Filters

Returns: Filter handles in dispatch order.

collectors()

public function collectors(string $hookPoint): array
Use it when:

you need only the collector registrations at a point.

Applies to: Collectors

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() Remove the first matching action callback. bool.
removeFilter() Remove the first matching filter callback. bool.
removeCollector() Remove the first matching collector callback. bool.

removeAction()

public function removeAction(
  string $hookPoint,
  array|callable $callback,
  int $priority = 10,
): bool
Use it when:

you want callback-based removal of one action at a specific priority.

Applies to: Actions

Returns: true when the first matching registration is removed; otherwise false.

Configuration: Yes; it changes the registry.

removeFilter()

public function removeFilter(
  string $hookPoint,
  array|callable $callback,
  int $priority = 10,
): bool
Use it when:

you want callback-based removal of one filter at a specific priority.

Applies to: Filters

Returns: true when the first matching registration is removed; otherwise false.

Configuration: Yes; it changes the registry.

removeCollector()

public function removeCollector(
  string $hookPoint,
  array|callable $callback,
  int $priority = 10,
): bool
Use it when:

you want callback-based removal of one collector at a specific priority.

Applies to: Collectors

Returns: true when the first matching registration is removed; otherwise false.

Configuration: Yes; it changes the registry.

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() Remove all hook types at a point or the whole registry.
removeAllActions() Remove action registrations.
removeAllFilters() Remove filter registrations.
removeAllCollectors() Remove collector registrations.

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.

removeAll()

public function removeAll(?string $hookPoint = null): int
Use it when:

you need to clear every hook type at one point, or the whole registry when the argument is omitted.

Applies to: All hook types

Returns: The number of registrations removed.

Configuration: Yes; it changes the registry.

removeAllActions()

public function removeAllActions(?string $hookPoint = null): int
Use it when:

you need to clear action registrations for one point or the registry.

Applies to: Actions

Returns: The number of action registrations removed.

Configuration: Yes; it changes the registry.

removeAllFilters()

public function removeAllFilters(?string $hookPoint = null): int
Use it when:

you need to clear filter registrations for one point or the registry.

Applies to: Filters

Returns: The number of filter registrations removed.

Configuration: Yes; it changes the registry.

removeAllCollectors()

public function removeAllCollectors(?string $hookPoint = null): int
Use it when:

you need to clear collector registrations for one point or the registry.

Applies to: Collectors

Returns: The number of collector registrations removed.

Configuration: Yes; it changes the registry.

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() Create a Hooks registry. Hooks instance.
doAction() Invoke action listeners. void.
applyFilters() Transform a value sequentially. Final mixed value.
collect() Gather raw collector results. array.

Registration methods return a RegistrationHandle and default to priority 10:

construct()

public function __construct(?Resolver $resolver = null)
Use it when:

you want to create an isolated core registry, optionally with a custom resolver.

Applies to: Core Hooks instances

Returns: A new Hooks object using NativeResolver when no resolver is supplied.

Exceptions: Exceptions from a custom resolver can surface during later resolution.

Configuration: The resolver is retained by this Hooks instance.

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() Configure a collector processor. self.
hasProcessor() Check processor configuration. bool.
processor() Inspect the processor reference. Processor, callable, class name, or null.
clearProcessor() Remove processor configuration. bool.
setRenderer() Configure a collector renderer. self.
process() Collect and process results. Processor output.
processWith() Process one call with a supplied processor. Processor output.
render() Collect and render results. string.
renderWith() Render one call with a supplied renderer. string.

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

setProcessor()

public function setProcessor(
  string $hookPoint,
  ResultProcessor|callable|string $processor,
): self
Use it when:

you want a persistent reduction for a collector.

Applies to: Collectors

Returns: The same Hooks instance.

Exceptions: InvalidProcessorException when a resolved class does not implement ResultProcessor.

Configuration: Yes; replaces the processor/renderer slot for this collector.

processor()

public function processor(string $hookPoint): ResultProcessor|callable|string|null
Use it when:

you want to inspect the persistent processor reference.

Applies to: Collectors

Returns: The configured reference, or null.

process()

public function process(
  string $hookPoint,
  mixed ...$arguments,
): mixed
Use it when:

you want to collect and reduce results using persistent configuration.

Applies to: Collectors

Returns: The configured processor output.

With no listeners: The processor receives an empty array.

Exceptions: MissingProcessorException when unset; InvalidProcessorException for an invalid class.

processWith()

public function processWith(
  string $hookPoint,
  ResultProcessor|callable|string $processor,
  mixed ...$arguments,
): mixed
Use it when:

you need a one-off processing strategy.

Applies to: Collectors

Returns: The supplied processor output.

With no listeners: The supplied processor receives an empty array.

Exceptions: InvalidProcessorException for an invalid class; custom exceptions propagate.

Configuration: No; the supplied processor is used for this call only.

setRenderer()

public function setRenderer(
  string $hookPoint,
  Renderer|callable|string $renderer,
): self
Use it when:

you want a persistent string renderer for a collector.

Applies to: Collectors

Returns: The same Hooks instance.

Exceptions: InvalidRendererException when configuration or resolved output is invalid.

Configuration: Yes; it replaces the shared collector slot.

render()

public function render(
  string $hookPoint,
  mixed ...$arguments,
): string
Use it when:

you want the configured renderer to produce a string.

Applies to: Collectors

Returns: The configured renderer's string output.

With no listeners: The renderer receives an empty array.

Exceptions: MissingRendererException when unset; InvalidRendererException for invalid configuration or non-string output.

renderWith()

public function renderWith(
  string $hookPoint,
  Renderer|callable|string $renderer,
  mixed ...$arguments,
): string
Use it when:

you need a one-off rendering strategy.

Applies to: Collectors

Returns: The supplied renderer's string output.

With no listeners: The renderer receives an empty array.

Exceptions: InvalidRendererException for invalid configuration or non-string output.

Configuration: No; the supplied renderer is used for this call only.

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() Reports whether any hook type has a registration. All hook types
hasAction() Checks for any action or a matching callback. Actions
hasFilter() Checks for any filter or a matching callback. Filters
hasCollector() Checks for any collector or a matching callback. Collectors
count() Counts registrations. All hook types
listeners() Returns handles at the point in dispatch order. All hook types
actions() Returns action handles. Actions
filters() Returns filter handles. Filters
collectors() Returns collector handles. Collectors
removeAction() Removes the first matching action. Actions
removeFilter() Removes the first matching filter. Filters
removeCollector() Removes the first matching collector. Collectors
removeAll() Removes all hook types at a point or globally. All hook types
removeAllActions() Removes action registrations. Actions
removeAllFilters() Removes filter registrations. Filters
removeAllCollectors() Removes collector registrations. Collectors

These public methods provide diagnostics rather than dispatch:

Method Purpose and return value Applies to
debug() Enable or disable debug logging. self.
setSourceFile() Store a source-file label. self.
getSourceFile() Read the source-file label. string.

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.

debug()

public function debug(callable|null $callback): self
Use it when:

you need optional diagnostic logging while investigating registrations or dispatch.

Applies to: Core diagnostics

Returns: The same Hooks instance.

Configuration: Yes; it changes diagnostic configuration only.

setSourceFile()

public function setSourceFile(?string $path = null): self
Use it when:

you want to attach a source-file label to diagnostic output.

Applies to: Core diagnostics

Returns: The same Hooks instance.

Configuration: Yes; it stores a source label only.

getSourceFile()

public function getSourceFile(): string
Use it when:

you need to read the current diagnostic source label.

Applies to: Core diagnostics

Returns: The configured label, or `Unknown` when none was set.

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

Contract Method What it is used for
Resolver resolve() Creates an object for a resolver-backed callback, processor, or renderer.
ResultProcessor process() Reduces collector results to an application-defined value.
Renderer process() 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.

interface Resolver
{
public function resolve(string $className): object;
}
interface ResultProcessor
{
public function process(array $results, ProcessingContext $context): mixed;
}
interface Renderer extends ResultProcessor
{
public function process(array $results, ProcessingContext $context): string;
}

ProcessingContext exposes:

Method Purpose and return value
__construct() Stores the hook point and invocation arguments.
hookPoint() Returns the current hook point.
arguments() Returns the original arguments in 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.

The context methods use these signatures:

public function __construct(string $hookPoint, mixed ...$arguments)
public function hookPoint(): string
public function arguments(): array

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.