>
> That makes a HUGE assumption, however, that the message instance knows 
> exactly how to construct the stream instance composed into it.
>
> Let me give some examples. In Diactoros, we have several stream types:
>
> - CallbackStream expects a single constructor argument, a callable.
> - PhpInputStream expects a single constructor argument, a resource.
> - RelativeStream expects two arguments, a StreamInterface to decorate, and 
> an integer offset
> - Our primary Stream implementation has two arguments, a resource or 
> string representing the resource to create (e.g., "php://memory"), and a 
> filesystem mode (e.g., 'r', 'a+', 'rw', etc.)
>

Right, but in general, the concern of withBodyString() can be covered by 
some default stream that implements the interface.
 

> We actually had a number of discussions about this in the PSR-17 WG, and 
> even considered adding some combinations to the http-factory-util package, 
> but there were soooo many variants, and we were concerned people would 
> typehint on the intersection interfaces in the util package instead of the 
> ones defined in the spec, which would hamper interop.
>

I agree, the countless combinations is not a good idea.  That is why I 
recommend a full combo only, and I don't see that as being restrictively 
un-optimized. 
 

>
> It may be time to revisit that, as I think a few of these have come up as 
> "generally useful":
>
> - ResponseFactoryInterface&StreamFactoryInterface (per the above)
> - RequestFactoryInterface&UriFactoryInterface&StreamFactoryInterface
> - 
> ServerRequestFactoryInterface&UriFactoryInterface&StreamFactoryInterface&UploadedFileFactoryInterface
> - and one combining all of them (e.g., the one from Nyholm/psr7)
>
> That could happen either as an errata/addendum to PSR-17, or a separate 
> spec.
>

Yes, these are individually useful, but I don't see there being an adequate 
optimization need to make subsets instead of a full set.
 

> What are you suggesting, exactly? That we add an example demonstrating 
> this (using constructor injection to provide PSR-17 factories within PSR-15 
> implementations for purposes of creating PSR-7 instances) to the metadoc 
> for PSR-15? Or documentation detailing how you resolve the interface 
> typehint to an implementation? Or something else?
>

Initially I was suggesting that you make it part of a standard that 
implementors of middleware must provide IoC DI to the middleware 
constructor.  But, this appears to be outside the scope of the standard (it 
would be dealing with how frameworks deal with middleware construction)
 

> This is exactly what PSR-17 suggests, though! It exists to allow 
> typehinting in your constructors against the PSR-17 factories in your 
> classes so as to prevent directly instantiating a concrete PSR-7 
> implementation. How the framework does that is really up to the framework. 
> But this was the intent of PSR-17, and it is spelled out clearly in section 
> 2 of its metadoc.
>

Right, and I was suggesting making it a standard that the framework must 
uphold IoC DI for middleware construction.  This would require both an 
addendum to defining middleware ( to say factories are injected ), and a 
PSR that tells frameworks to inject factories.
 

> Your middleware packages should depend on and typehint against PSR-7, 
> PSR-15, and PSR-17, versus specific implementations. If you typehint 
> against those, there are certain guarantees provided for you; most salient 
> to your concerns is the fact that PSR-17's stream factory interface 
> specifically only addresses resource and file-backed streams, which means 
> that you can depend on them to (a) be empty, and (b) be writable. As such, 
> writing your middleware to target the PSR-17 interfaces as constructor 
> dependencies gives you the interop you're looking for.
>

Right, but I was considering what is perhaps a non issue.  I was 
considering making middleware for a framework which did not do IoC DI.  
And, again, my issue is, if IoC DI is the de facto standard, why not make 
it the actual standard.
 

> Again, that is the specific, stated goal of PSR-17, that you inject the 
> factories in your middleware in order to produce PSR-7 artifacts.
>  
>
>> But, I think an easier mechanism would be to have an 
>> extended RequestHandlerInterface that implements the factories.  "PSR 21 
>> ExtendedRequestHandlerInterface implements ...."
>>
>
> This violates the separation of concerns principle, and introduces new 
> questions:
>
> - How does the handler know how to create these artifacts?
>
There's actually two considerations here.
1. Since both the response and request objects already know how to create 
new objects of their class by modification of themselves, it is within 
their realm of concern to create blank objects.  Since these objects are 
not merely containers (since you can directly modify the content of the 
headers), it should be expectable that the normal structure of the response 
can be modified by these objects without additional tools.
2. Since the request handler must return a response, it should know how to 
return a response - it is within the realm of concern to be able to do this.

> - What PSR-7 implementation will the handler use?
>
This shouldn't matter since it uses an interface.  If the middleware 
requires a specific implementation, that is different than what the 
framework is giving, it would require it as a dependency.

> - Or is it composing PSR-17 instances to do the work? If so, how does it 
> get access to those? And if it's composing them... why not just call on 
> those factories directly instead of proxying to them?
>
Access to those would either be through the handler, or through the request 
and response objects.
Calling the factories directly, either through DI or require/autoload has 
downsides.

For example, with IoC DI, apart from the issue with making the assumption 
the framework will provide IoC DI, I could have middleware that has 
configuration parameters like

class Middleware implements \Psr\Http\Server\MiddlewareInterface{
public function __construct(ResponseFactoryInterface $responseFactory, 
ServerRequestFactoryInterface $ServerRequestFactory, UriFactoryInterface 
$uriFactory, $config_param1, $config_param2)
public function process(ServerRequestInterface $request, 
RequestHandlerInterface $handler): ResponseInterface {}
}
The problem with this being, prior to presenting this middleware to the 
framework, you have 3 factory requirements you must resolve prior to adding 
your own configuration parameters.  (I mentioned how you can still do this 
with DI IoC with the framework in discord, so it is just an inconvenience)

>
> Your second example actually raises more questions for me (see above). 
> (Some call this style "spooky magic from a distance" as it looks 
> convenient, but when you dig, you get a lot of questions about how things 
> actually work, and how you can modify them.)
>

I actually think this is the most obvious part.  The framework chooses its 
own factory default implementations.
 

> The first (using DI) is something a framework should cover in its initial 
> tutorials. In some frameworks, reflection-based DI will resolve them for 
> you. In others, you will provide configuration detailing which 
> implementation the DI container should use. Others will have you create and 
> wire in a factory that will handle this detail (and this is where PSR-11 
> comes into play, as the factory can then retrieve instances from the 
> container to resolve dependencies).
>
> The point, however, is that:
>
> - Your middleware is decoupled from a specific framework or PSR-7/PSR-17 
> implementation. This allows both composition into different frameworks, as 
> well as substitution for its own dependencies.
>
Again, it is coupled to frameworks that use IoC DI.  However, I think I 
will stop pointing this out since, as said elsewhere, it is "de facto 
standard" and no one seems to want to standardize it to make it de jure
 

> - The code is declarative: you know what you need to provide it in order 
> to create an instance. This makes it testable and self-documenting. Your 
> users can find the PSR-7/PSR-17 combination that works for them and 
> directly instantiate the class using concrete implementations.
>
I can't think of a case needing a specialized testing PSR7 or PSR17 
implementation.  If there were such a case, I imagine the frameworks would 
allow adjusting the default factories used by the request handler
 

> Am I understanding correctly that you're concerned with the "how do I get 
> my PSR-17 instances to my middleware" question? Particularly so that your 
> middleware can operate with multiple frameworks?
>

Not entirely.  I want my middleware to work on _all_ frameworks that meet 
the standards.  As such, the activities which are within the realm of 
concerns of the middleware, specifically modifying the response or request, 
should be standardized, and that standard should mean all frameworks that 
comply with the standard can run my middleware.  

Perhaps the issue here is the application of separation of concerns. The 
factories are correctly separate as interfaces for their individual 
concerns.  But the concern of the request handler is all of the factories, 
b/c the concern of the request handler is both the request and the 
response.  Or, taken a different way, the concern of the response object is 
everything related to changing and viewing the response (all associated 
factories), and the concern of the request is everything related to 
changing and viewing the request (all associated factories).

 

-- 
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 php-fig+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/php-fig/2df9f595-6c84-4040-aa30-fe97927163d2n%40googlegroups.com.

Reply via email to