Application

Learn how data can be shared between different middleware

Sharing Data

Using HTTP Request Object

With PSR-7 Http Message Interfaces it is possible to inject objects/values into the request object as attributes. These objects/values are then passed down to each middleware/route callback/handler/controller via the http request object.

Setting a Value
$app->addMiddleware(function ($request, $response, $next) {
    // pass the 'name' attribute to other middleware via the request object
    $request = $request->withAttribute('name', 'John Doe');
    
    return $next($request, $response);
});
Reading a Value

The request object exposes attributes passed along with it through the getAttribute() method:

$app->addMiddleware(function ($request, $response, $next) {
    // get the 'name' from the request
    $name = $request->getAttribute('name');

    $response->getBody()->write("Hello, $name");

    return $next($request, $response);
});

Using \BitFrame\Application Object

\BitFrame\Application can be used as a very basic DI container or simply to store and retrieve data that is shared between all middleware. This too is done via the request object, but internally the application stores and passes the \BitFrame\Data\ApplicationData object.

Setting a Value
$app['name'] = 'John Doe';

$app->addMiddleware(function ($request, $response, $next) {
    // retrieve stored application data
    $data = $request->getAttribute(\BitFrame\Data\ApplicationData::class);

    // overwrite name
    $data['name'] = 'John Wick';
    
    return $next($request, $response);
});
Reading a Value
$app->addMiddleware(function ($request, $response, $next) {
    // retrieve stored application data
    $data = $request->getAttribute(\BitFrame\Data\ApplicationData::class);

    // output: "Hello, John Wick"
    $response->getBody()->write("Hello, {$data['name']}");
    
    return $next($request, $response);
});
Defaults

Internally BitFrame passes the following parameters via the request object:

  • '\BitFrame\Data\ApplicationData': Stores application data which can be shared between middlewares associated with the application instance.
  • '\BitFrame\Router\RouteCollectionInterface': Stores routes added to the application instance such that the passed routes can be used by a router.

These default parameter keys are reserved for \BitFrame\Application use.

Passing Arguments

Whether you're handling routes or adding a middleware, in addition to the methods explained earlier, you can inherit variables (for example, from the parent scope) into middleware/router methods/functions as explained below.

Named Classes

For named classes, you can simply pass arguments to the constructor at the time of instantiating an object instance.

Anonymous Class

If you're using an anonymous class, you can pass arguments through to their constructors like so:

use \Psr\Http\Message\ServerRequestInterface;
use \Psr\Http\Message\ResponseInterface;
use \Psr\Http\Server\RequestHandlerInterface;
use \Psr\Http\Server\MiddlewareInterface;

$name = 'John Doe';

// pass $name to constructor
$app->addMiddleware(new class($name) implements MiddlewareInterface {
    private $name;

    public function __construct(string $name)
    {
        $this->name = $name;
    }

    public function process(
        ServerRequestInterface $request, 
        RequestHandlerInterface $handler
    ): ResponseInterface 
    {
        $response->getBody()->write("Hello, {$this->name}");

        return $handler->handle($request);
    }
});
Named Functions

You can use a variable defined in the global namespace inside a named function using the global language construct.

Inheriting variables from the global scope is different from using variables from the parent scope. Global variables exist in the global scope, which is the same no matter what function is executing.

As an alternative to using global, you could define an anonymous function assigned to a variable and use the use language construct to inherit variables from the parent scope like so:

$name = 'John Doe';

$func = function ($request, $response, $next) use ($name) {
    $response->getBody()->write("Hello, $name");
    
    return $next($request, $response);
};

// pass $name to closure
$app->addMiddleware($func);
Anonymous Functions

If you're using an anonymous function, you can pass arguments using the use language construct like so:

$name = 'John Doe';

// pass $name to closure
$app->addMiddleware(function ($request, $response, $next) use ($name) {
    $response->getBody()->write("Hello, $name");
    
    return $next($request, $response);
});

Remember to add a response emitter middleware to output the response.

Comments

Let us know if you have something to say or add