On Saturday, May 13, 2017 at 12:31:20 PM UTC-5, Woody Gilk wrote:
>
> On Sat, May 13, 2017 at 12:12 PM, Rasmus Schultz <[email protected]
> <javascript:>> wrote:
>
>> What do you mean by "middleware that does not return a response"?
>>
>
> Ultimately it will. In PSR-15 this is done via delegate. My question is
> more about how the interfaces proposed by David would do this delegation.
> Right now I don't see how it would be possible without passing a factory to
> a middleware, which (I thought) he was attempting to avoid.
>
I don't think that was what he was attempting to avoid. I think his was an
attempt to solve the DI problem (the thing I care about) while still not
having to pass the delegate to every middleware handle/__invoke call (I
believe the idea that Rasmus is exploring). From what I see, this is done
by injecting a factory concept into the workflow.
The factory would receive the next/delegate at runtime and could thus be
instantiated by an autowiring DI container upfront without any problems.
It still requires the individual middleware & factory combo to have a way
to ensure that the middleware instance stores the next/delegate prior to
being invoked. Which means, most likely, that the middleware themselves
cannot be autowired and *must* be created manually by the factory.
In my mind, it moves the magic around in a way that is slightly more
automated (meaning, I'd only be able to whine about DI concerns at a
fraction of the volume of before because the *middleware factory* can still
be autowired...) at the expense of adding an explicit factory to the
workflow of every middleware.
While I think this is a great way to move the discussion forward, I'm not
happy about the idea that every middleware is going to effectively require
two classes be written. I would guess that most factories are going to end
up being proxies and will have all of the dependencies of the original
middleware just to pass them on via constructor injection.
Here is what this would look like using an actual middleware I've used in
the past. I've kept the delegate naming for now just to show what we're
actually talking about here in practical terms.
BEFORE
class UserIdMetadataEnrichment implements MiddlewareInterface
{
private $metadataEnricherChain;
private $userIdentityMapper;
public function __construct(
MetadataEnricherChain $metadataEnricherChain,
UserIdentityMapper $userIdentityMapper
)
{
$this->metadataEnricherChain = $metadataEnricherChain;
$this->userIdentityMapper = $userIdentityMapper;
}
public function __invoke(RequestInterface $request, DelegateInterface
$delegate)
{
// ... do stuff
}
}
AFTER
class UserIdMetadataEnrichmentFactory implements MiddlewareFactoryInterface
{
private $metadataEnricherChain;
private $userIdentityMapper;
public function __construct(
MetadataEnricherChain $metadataEnricherChain,
UserIdentityMapper $userIdentityMapper
)
{
$this->metadataEnricherChain = $metadataEnricherChain;
$this->userIdentityMapper = $userIdentityMapper;
}
public function createMiddleware(DelegateInterface $delegate)
{
return new UserIdMetadataEnrichment(
$delegate,
$this->metadataEnricherChain,
$this->userIdentityMapper
)
}
}
class UserIdMetadataEnrichment implements MiddlewareInterface
{
private $metadataEnricherChain;
private $userIdentityMapper;
private $delegate;
public function __construct(
DelegateInterface $delegate,
MetadataEnricherChain $metadataEnricherChain,
UserIdentityMapper $userIdentityMapper
)
{
$this->metadataEnricherChain = $metadataEnricherChain;
$this->userIdentityMapper = $userIdentityMapper;
$this->delegate = $delegate;
}
public function __invoke(RequestInterface $request)
{
// ... do stuff
}
}
At the end of the day it comes down to whether the delegate/next of a
middleware should be a runtime dependency or an instance dependency. I
think that is the core of what Rasmus is exploring here. It seems like he
has decided it should not be a runtime dependency. I disagree.
If the same middleware class is used in several points throughout an
application, why might each individual instance know about the delegate it
is responsible for? In which situations would this impact how the
middleware will actually run?
I've neither seen nor written middleware where the same instance mounted
several places throughout an application did not work as intended and
expected.
TL;DR?
The original proposal treats the delegate as a runtime dependency along
with the request in question at that point in time. Rasmus is proposing the
delegate becomes an instance dependency tying each instance of the
middleware explicitly to a specific point in the application when it is
constructed, requiring every instance of a middleware to be instantiated
individually instead of reusing a shared instance and finding some way to
get access to the delegate by some other means (constructor or setter
injection?). David's proposal tries to resolve these two by providing a
factory that allows a single factory instance to receive the delegate at
runtime from any point in the application with the intention to create a
middleware instance on the spot that ties the request and delegate to each
other at that point in time.
--
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 post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/php-fig/e9af0c97-575d-4a76-8e22-01275f7f37a2%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.