phpbotgram

MiddlewareManager
in package
implements ArrayAccess, Countable, IteratorAggregate

FinalYes

Ordered registry of dispatcher-side `BaseMiddleware` instances for a single update type (mirrors aiogram's `aiogram.dispatcher.middlewares.manager.MiddlewareManager`).

The manager is owned by a TelegramEventObserver (per-update-type observer) and composes the registered middlewares around the terminal handler step in registration order: the first registered middleware is the outermost link of the chain.

Shape parallels Client/Session/Middleware/RequestMiddlewareManager (same register/unregister/decorator-factory/ArrayAccess/Countable surface) but the chain semantics differ: each link here accepts (handler, event, data) and delegates by calling $handler($event, $data) — there is no Bot/method/ timeout positional convention.

Tags
implements

Table of Contents

Interfaces

ArrayAccess
Countable
IteratorAggregate

Properties

$middlewares  : array<int, BaseMiddleware>

Methods

__invoke()  : BaseMiddleware)
Decorator-factory entry point (mirrors aiogram's `MiddlewareManager.__call__`).
count()  : int
getIterator()  : Traversable<int, BaseMiddleware>
Iterate the registered middlewares in registration order. Enables `foreach ($manager as $mw)` in callers that need to read the raw list (e.g. `TelegramEventObserver::resolveMiddlewares()` walking the chain head for inherited inner middleware).
offsetExists()  : bool
offsetGet()  : BaseMiddleware
Strict by design — callers must guard with `offsetExists` / `isset` first.
offsetSet()  : void
offsetUnset()  : void
register()  : BaseMiddleware
Append a middleware to the chain. Returns the middleware unchanged so the decorator-style call site can keep a reference (parity with upstream `register()` which appends and returns the middleware).
unregister()  : bool
Remove a middleware by identity. Returns `true` if the middleware was removed, `false` if no matching instance was registered. Upstream's `list.remove()` raises `ValueError` on absent items; we return a bool instead so callers can branch without try/catch boilerplate.
wrap()  : callable(object, array<string, mixed>): mixed
Compose the registered middlewares around a terminal `(event, data)` step, returning a closure that runs the full chain when invoked.

Properties

Methods

__invoke()

Decorator-factory entry point (mirrors aiogram's `MiddlewareManager.__call__`).

public __invoke([BaseMiddleware|null $middleware = null ]) : BaseMiddleware)

$manager($middleware) registers inline and returns the middleware; $manager() returns a registration closure suitable for use as a decorator-like callable.

Parameters
$middleware : BaseMiddleware|null = null
Return values
BaseMiddleware)

getIterator()

Iterate the registered middlewares in registration order. Enables `foreach ($manager as $mw)` in callers that need to read the raw list (e.g. `TelegramEventObserver::resolveMiddlewares()` walking the chain head for inherited inner middleware).

public getIterator() : Traversable<int, BaseMiddleware>
Return values
Traversable<int, BaseMiddleware>

offsetExists()

public offsetExists(mixed $offset) : bool
Parameters
$offset : mixed
Return values
bool

offsetGet()

Strict by design — callers must guard with `offsetExists` / `isset` first.

public offsetGet(mixed $offset) : BaseMiddleware
Parameters
$offset : mixed
Tags
throws
OutOfBoundsException

when offset is non-int or out of range.

Return values
BaseMiddleware

offsetSet()

public offsetSet(mixed $offset, mixed $value) : void
Parameters
$offset : mixed
$value : mixed

offsetUnset()

public offsetUnset(mixed $offset) : void
Parameters
$offset : mixed

unregister()

Remove a middleware by identity. Returns `true` if the middleware was removed, `false` if no matching instance was registered. Upstream's `list.remove()` raises `ValueError` on absent items; we return a bool instead so callers can branch without try/catch boilerplate.

public unregister(BaseMiddleware $middleware) : bool
Parameters
$middleware : BaseMiddleware
Return values
bool

wrap()

Compose the registered middlewares around a terminal `(event, data)` step, returning a closure that runs the full chain when invoked.

public wrap(callable(object, array<string, mixed>): mixed $terminal) : callable(object, array<string, mixed>): mixed

Chain order: middlewares execute in registration order on the way in (first registered runs first) and unwind in reverse on the way out, so for [A, B, C] and terminal T the call order is A.before → B.before → C.before → T → C.after → B.after → A.after.

The terminal and intermediate closures accept object $event (not TelegramObject) so the same manager can transport synthetic events such as ErrorEvent through the dispatcher's error channel.

If no middlewares are registered, the terminal is returned unchanged (zero-allocation fast path).

No cache (Fix I10): the WeakMap-backed wrap cache was removed because every caller — Router::propagateEvent (outer chain, post Fix I2) and TelegramEventObserver::triggerCore (inner chain) — allocates a fresh terminal closure on each invocation, so the cache never hit. The overhead of maintaining the WeakMap (one allocation per register/unregister, the lookup miss per wrap() call) was pure deadweight. Profiling can re-add the cache if a real hit scenario emerges.

Parameters
$terminal : callable(object, array<string, mixed>): mixed
Return values
callable(object, array<string, mixed>): mixed
On this page

Search results