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 $nextcallback. | 
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.