Response with attribute

I’m using some middlewares, and I would like to pass arguments on the backleg.

Meaning: I would like the equivalent of $request->setAttribute(), e.g. $response->setAttribute() . However, such a function does not exist.

How can I send information to my outer middlewares? The only thing that is returned is the $response, and I don’t see anything that would allow this. I guess I could “hijack” the header/body to set these attributes, then unset them in the outbound middleware, but that seems hardly ideal.

Any ideas for a better solution?

Yes, you can do this with the Request object as it follows PSR-7. You are passing both the Request and Response along to the next callable. In your middleware, you would do

public function __invoke(Request $request, Response $response, $next)
{
    $request = $request->withAttribute('foo', 'bar');
    $response = $next($request, $response);
    return $response;

Then later in your app (or in later middleware) you can retrieve it from Request again.

$foo = $request->getAttribute('foo'); // bar

I failed at making sense in my OP, I see :slight_smile:

I can’t use $request, because I’m on my way out of the route already.
MW (middleware)
MW1 -> MW2 -> MW3 -> route (here I want to set an attribute) -> MW3 -> MW2 -> MW1 (here I want to get the attribute and do stuff with it) -> response (which should then not have the attribute anymore, neither in header nor body)

As the middlewares only ever return the $response via $next, the $request is not updated on the way back out of the route.

Yes, I misunderstood, sorry.

Upon further research, it seems this is an issue with PSR-7 itself. Just googling for “PSR7 attribute on response” yields a lot of discussion threads about this particular issue (and a number of related issues). Didn’t find a clear suggestion on how to work around it, except to (mis)use the $response->withHeader() , so I’ll stick with that for now, but I’m very interested in better ideas :slight_smile: .

Sorry for necropost, but unfortunately this is still an unfixed “issue” that comes up every once in a while.

Since response has no way to set an attribute, my way of doing it is just passing a mutable “container class” as a request attribute, and then collecting data from it after handling the request in a middleware.

public function controllerMethod($req, $res)
{
	$req->getAttribute('bag')->someAttribute = 123;

	return $this->get('view')->render('blah.html');
}

// Some middleware
$app->add(function ($req, $handler) {
	$bag = new stdClass;

    // We're storing a mutable container class in an immutable Request,
    // which kinda defeats its purpose.
	$res = $handler->handle($req->withAttribute('bag', $bag));

	if ($bag->someAttribute === 123) {
		// do something after the request
	}

    return $res;
});

You can also just use the DI container to store the class, without bothering at all with request and response.

This is in no way a proper design practice! I want you to roast me and come up with something better!

The best way would obviously be to just add attributes to a response, which is unfortunately not implemented or not PSR-compliant (which one is it?):

public function controllerMethod($req, $res)
{
	return $this->get('view')->render(
        $res->withAttribute('someAttribute', 123), 'blah.html');
}

// Some middleware
$app->add(function ($req, $handler) {
	$res = $handler->handle($req);

	if ($res->getAttribute('someAttribute') === 123) {
		// do something after the request
	}

    return $res;
});

Welcome @7ex00

Since response has no way to set an attribute…

I would argue that this assertion is incorrect, since you can set an attribute as (already) mentioned above.

Update: Only PSR-7 request interface contains methods to set attributes:

The server request provides one additional property, “attributes”, to allow consumers the ability to introspect, decompose, and match the request against application-specific rules (such as path matching, scheme matching, host matching, etc.). As such, the server request can also provide messaging between multiple request consumers.

Yes, the PSR-7 response interface contains no methods for attributes because it is designed to represent only the HTTP response message itself, without any implementation-specific metadata or contextual information.

When following good / best practices, you would fetch additional data from your “service” or from the request etc. and pass it as array or object to your use-case specific renderer, e.g. html template render or JSON renderer etc. So there is no need to use the response object for such kind of “meta” data.