MiddlewareManager
in package
implements
ArrayAccess, Countable, IteratorAggregate
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
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
$middlewares
private
array<int, BaseMiddleware>
$middlewares
= []
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)count()
public
count() : int
Return values
intgetIterator()
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
booloffsetGet()
Strict by design — callers must guard with `offsetExists` / `isset` first.
public
offsetGet(mixed $offset) : BaseMiddleware
Parameters
- $offset : mixed
Tags
Return values
BaseMiddlewareoffsetSet()
public
offsetSet(mixed $offset, mixed $value) : void
Parameters
- $offset : mixed
- $value : mixed
offsetUnset()
public
offsetUnset(mixed $offset) : void
Parameters
- $offset : mixed
register()
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).
public
register(BaseMiddleware $middleware) : BaseMiddleware
Parameters
- $middleware : BaseMiddleware
Return values
BaseMiddlewareunregister()
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
boolwrap()
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