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.
