As far as I can see, the essential difference between PSR-15 and your 
proposal is about the responsibility for dispatching the next middleware:
1. with your version: it is determined at *compile time*, by implementing 
the appropriate interface; thus the stack should be responsible for it only.
2. with the PSR-15 version: it is determined at *run time*, thus the stack 
and the middleware are responsible for dispatching the next middleware.

Django, StackPHP and Guzzle for example, have chosen an approach which 
seems to align better to your version. In essence, their middlewares could 
be typed as:

(RequestInterface -> ResponseInterface) -> (RequestInterface -> 
ResponseInterface)

Or, if we want to use PHP interfaces only, then we could type them:

interface ExchangeInterface
{
    public function __invoke(RequestInterface $request): ResponseInterface;
}

interface MiddlewareInterface
{
    public function __invoke(ExchangeInterface $next): ExchangeInterface;
}

At first glance that could solve your issues with the current PSR-15, the 
*exchanger* does not seem to be responsible for dispatching the next 
exchanger and middlewares are simple exchange factories. And moreover we do 
not need middleware dispatchers anymore.

Unfortunately that isn't very attractive in PHP, a middleware would look 
like:

class UnicornMiddleware implements MiddlewareInterface
{
    public function __invoke(ExchangeInterface $next): ExchangeInterface {
        return new class($next) implements ExchangeInterface {
            private $next;

            public function __construct($next)
            {
                $this->next = $next;
            }

            public function __invoke(RequestInterface $request): 
ResponseInterface
            {
                return (($this->next)($request))->withHeader('X-PoweredBy', 
'Unicorns');
            }
        };
    }
}

That's probably one of the reasons why StackPHP uses `__construct` and 
Guzzle uses closures. But even worse, the inner ExchangeInterface instance 
is still responsible for dispatching the next middleware :(

Are the PSR-15 interfaces so bad? From the perspective of a functional 
programmer, we can do some simple currying 
<https://en.wikipedia.org/wiki/Currying> to change the typing to get better 
interfaces:

(RequestInterface -> ResponseInterface) -> (RequestInterface -> 
ResponseInterface)
// using curry:
(RequestInterface -> ResponseInterface) -> RequestInterface -> 
ResponseInterface
// and again:
((RequestInterface -> ResponseInterface) -> RequestInterface) -> 
ResponseInterface

Again, if we use PHP `interfaces` only, the last version could look like 
this in PHP:

interface ExchangeInterface
{
    public function __invoke(RequestInterface $request): ResponseInterface;
}

interface MiddlewareInterface
{
    public function __invoke(ExchangeInterface $next, RequestInterface 
$request);
}

Aside from the parameter order, the similarities to the PSR-15 version are 
already obvious (Sadly, the names and implied contracts are very different 
and PSR-15 does not describe a functional middleware pattern anymore :cry: 
).

Anyway, the example above becomes much simpler with the current PSR-15 
interfaces:

class UnicornMiddleware implements ServerMiddlewareInterface
{
    public function process(ServerRequestInterface $request, 
DelegateInterface $delegate) {
        return $delegate->process($request)->withHeader('X-PoweredBy', 
'Unicorns');
    }
}

Thus I believe your proposal does not fit better to the middleware pattern.

-- 
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 post to this group, send email to php-fig@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/php-fig/b0794cd8-089a-4753-bbf5-9a3d0e833b06%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to