On Tue, Jul 6, 2021 at 10:03 AM Adam Frederick <[email protected]> wrote:

> Please excuse my naivete, but upon making PSR 15 classes, I noticed an
> issue which I have not found satisfactorily resolved online or in this
> discussion group.
>
> The idea behind interoperability is to make sure things work on different
> systems.  Part of doing this is making sure there is a standard interface
> for normal activity.  Part of normal activity of a middleware would be
> altering the response body.  But, this presents a problem, since there is
> no standard method for going about creating a new stream within middleware.
>
> What is the standard for accessing a Psr\Http\Message\StreamInterface
> implementation from within middleware?
> - if I want to modify the body, I have to make a new stream (seeking and
> writing will often not fit)
> I would suggest, given the commonallity of not caring about streams in
> some middleware, the response gains two functions:
> 1. "withBodyString()"
> 2. possibly "getBodyString()" for expectation (just does __toString())
>

We deliberately chose not to provide methods for altering the message body
in either the request or response, and to specifically NOT force the idea
that content MUST be a string. There are many cases where strings do not
make sense (e.g.,returning images, binary archives, etc.), and limiting the
body content to a string made no sense. (On top of this, there are
performance considerations when the content gets sufficiently large, and
modeling the content as a stream allows PSR-7 implementations to do
optimizations that address those issues.) Since it is easy to model string
content with the StreamInterface, however, withBody() exists to allow you
to inject a custom StreamInterface instance into your request or response.

If you want to force a replacement, compose a PSR-17 StreamInterfaceFactory
into your middleware or handler, or instantiate a concrete PSR-7
implementation if you have specific needs you wish to address (e.g.,
modeling an image or binary archive)

Further, I would suggest two combined things for middleware:
> 1. ServerRequestInterface should also implement all the PSR 17
> interfaces.  Thus, middleware would access a factory like
> `$handler->createResponse()`.  This itself, the extended interface
> implementation, could be a PSR.
>

We deliberately chose not to have any of the PSR-17 interfaces extend from
the others. The reason is that there were too many combinations, and most
times, you only need 1, 2, or 3 capabilities, making it relatively easy to
compose them into your classes via dependency injection. If you find
yourself needing multiple capabilities regularly, create your own interface
that extends the set of interfaces you use regularly, and type-hint on that
in your middleware or handlers.


> 2. Middleware constructor interface dependencies should be resolved,
> allowing injection of factories.
> Combined, the ServerRequestInterface could just inject itself wherever a
> PSR 17 factory was required.  However, #2 puts the demand of interface
> dependency injection the the implementer.
>

Constructors cannot be specified in interfaces. Well, they can, but PHP
does not require implementations to honor them.

The reason is pretty simple: constructors should be specific to a given
class.

If we were to add a constructor to a middleware or handler interface, we'd
limit what could be injected, meaning that users would not be able to
inject other collaborators, such as a database, cache, etc.

And let's not forget: PSR-15 PREDATES PSR-17 anyways.

But the fact that PHP won't do it, and it would preclude having custom
constructors, means it's simply not an option.


>
> Without a standard, constructing middleware relies on knowing what the
> framework will do.  If the assumption is that middleware will have the
> factories injected, this should be stated in the standard as the standard.
>

There are no assumptions.

You can instantiate a response, URI, stream, etc. directly in your
middleware. (and thus tie yourself to a specific implementation)

Or you could inject factories, and use the factories to create the
instances.

It's up to you as a developer to define what your class needs to do its
work. PSR-7, PSR-15, and PSR-17 are very loosely coupled to allow exactly
this.

-- 
Matthew Weier O'Phinney
[email protected]
https://mwop.net/
he/him

-- 
You received this message because you are subscribed to the Google Groups "PHP 
Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/php-fig/CAJp_myWhE9dVT5xP-W3z4n5iJZ3nZWt1dhQRqPdpy5Co0RnYXw%40mail.gmail.com.

Reply via email to