Application Middleware
Overview
DomainFlow Core’s middleware system lets you define callables that process a “payload” in sequence before reaching a final callback. It’s a flexible mechanism for tackling cross-cutting concerns—like authentication, logging, or caching—without tightly coupling them to the rest of your application logic.
Key Concepts
- Middleware Stack: A list of callable functions that each have the opportunity to act on a payload.
- Pipeline: The process of executing each middleware in series, passing the transformed (or unmodified) payload along until it reaches a final callback.
- Short-Circuit: A middleware can bypass subsequent handlers by returning early or throwing an exception, depending on your use case.
Method Descriptions
getRegisteredMiddleware()
Signature
public function getRegisteredMiddleware(): array
Purpose
Returns an array of all middleware callables that have been registered. You can use this for debugging or to dynamically inspect which middleware you’ve added.
Parameter | Type | Required? | Description |
---|---|---|---|
None | N/A | N/A | N/A |
Usage Example
$stack = $app->getRegisteredMiddleware();
containsMiddleware($middleware)
Signature
public function containsMiddleware(callable $middleware): bool
Purpose
Checks whether a specific middleware callable is already registered.
Parameter | Type | Required? | Description |
---|---|---|---|
$middleware | callable | Yes | The middleware callable to look for. |
Usage Example
if (!$app->containsMiddleware($authMiddleware)) {
$app->useMiddleware($authMiddleware);
}
useMiddleware($middleware)
Signature
public function useMiddleware(callable $middleware): void
Purpose
Adds a middleware callable to the end of the stack. This middleware is a function with the following expected signature:
function ($payload, callable $next) {
// Perform actions on $payload
// Call $next($payload) to pass control forward
}
Parameter | Type | Required? | Description |
---|---|---|---|
$middleware | callable | Yes | A function accepting a payload and a $next callback. |
Usage Example
$app->useMiddleware(function ($payload, $next) {
// e.g. Log something before proceeding
return $next($payload);
});
pipeline($payload, $final)
Signature
public function pipeline(mixed $payload, callable $final): mixed
Purpose
Executes the middleware stack with an initial $payload
and a final callable $final
that runs last, after all middleware have been applied. Returns whatever the final callback (or the last middleware) produces.
Parameter | Type | Required? | Description |
---|---|---|---|
$payload | mixed | Yes | The data passed through the middleware stack. |
$final | callable | Yes | A callback that runs after the last middleware. |
Usage Example
$result = $app->pipeline($request, function ($payload) {
// Final processing step, e.g. sending a response
return 'Done';
});
- If any middleware throws an exception, the pipeline halts and an internal error event is fired.
Comparative Descriptions
useMiddleware()
vs.on()
(Event System)useMiddleware()
chains callables that modify a single payload in order.on()
(from the event system) notifies multiple listeners concurrently for an event, rather than sequentially processing a single piece of data.pipeline()
vs. Traditional Function Calls- Rather than calling functions manually in a certain order,
pipeline()
automatically composes them. Each middleware decides whether to pass control to the next or stop the sequence.
Practical Examples
// Register some middleware
$app->useMiddleware(function ($payload, $next) {
// Example: simple logging
error_log("Middleware #1 start");
$result = $next($payload);
error_log("Middleware #1 end");
return $result;
});
$app->useMiddleware(function ($payload, $next) {
// Example: check a condition
if (!isset($payload['user'])) {
// Possibly short-circuit with an error or custom response
return 'No user found.';
}
return $next($payload);
});
// Execute the pipeline with a final callback
$response = $app->pipeline(['user' => 'Alice'], function ($payload) {
// Final logic
return "Hello, " . $payload['user'];
});
echo $response; // "Hello, Alice"
Extensibility
- Stack Order: The order you call
useMiddleware()
defines the execution sequence. You can reorder them if needed. - Conditional Middleware: Check environment or user roles before adding certain middleware (e.g., debugging middleware only in development).
- Framework Modules: Large applications often have separate modules that each contribute their own set of middleware to the stack, enabling a more pluggable design.
With middleware, DomainFlow Core simplifies how you handle cross-cutting application logic—whether it’s for security, performance, or auditing—without tangling it into every part of your codebase.