[PSR-15] FrameInterface

982 views
Skip to first unread message

Rob Allen

unread,
Jul 12, 2016, 10:26:42 AM7/12/16
to PHP Framework Interoperability Group
Hi,

In the proposed PSR-15, there's a FrameInterface.

Where did the word "Frame" come from and in what context is it used. It means nothing to me and I don't think I'm alone in having no clue how I would be able to infer that $frame might have a next() method. It's very weird and I think it's a negative when looking at the function signature as it's a meaningless word unless you know some back story that I clearly don't?

I would love an explanation as it looks to me like an area of confusion for people new to writing middleware.

For what it's worth, I don't especially mind the interface itself, though I'm not sure what it adds other than more typing. It's the choice of name that I'm questioning.

Regards,

Rob...

Woody Gilk

unread,
Jul 12, 2016, 10:33:50 AM7/12/16
to PHP Framework Interoperability Group
The term "frame" comes from Anthony Farrera:
http://blog.ircmaxell.com/2016/05/all-about-middleware.html

It refers to moving from one middleware frame to another.

Do you have any suggestions for a better name?


--
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+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/d892ba6d-2887-4968-bf89-09b45b0d3625%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--

Matthieu Napoli

unread,
Jul 12, 2016, 10:38:02 AM7/12/16
to PHP Framework Interoperability Group
Hi Rob,

I second your question.
And beyond the name I don't see why we need a "frame" to use "next": why not pass $next directly (as a callable)? Or if we want something that can be type-hinted then why not pass $next as a MiddlewareInterface?

Matthieu

Beau Simensen

unread,
Jul 12, 2016, 10:39:53 AM7/12/16
to PHP Framework Interoperability Group
On Tuesday, July 12, 2016 at 3:26:42 PM UTC+1, Rob Allen wrote:
Where did the word "Frame" come from and in what context is it used. It means nothing to me and I don't think I'm alone in having no clue how I would be able to infer that $frame might have a next() method. It's very weird and I think it's a negative when looking at the function signature as it's a meaningless word unless you know some back story that I clearly don't?

I would love an explanation as it looks to me like an area of confusion for people new to writing middleware.

I believe it has something to do with the concept of call stacks / stack frames? Reading a bit real fast on that I'm not 100% sure it fits entirely but I think that was the intention.


"A call stack is composed of 1 or many several stack frames. Each stack frame corresponds to a call to a function or procedure which has not yet terminated with a return." 



Matthieu Napoli

unread,
Jul 29, 2016, 5:14:46 AM7/29/16
to PHP Framework Interoperability Group
Thanks. However I'm still looking for a good reason why we have this interface: why not simply `callable $next` ?

- FrameInterface doesn't represent any actual usage or existing middlewares today
- FrameInterface is more complex than `callable`

Matthieu

Andrew Carter

unread,
Jul 29, 2016, 5:41:07 AM7/29/16
to PHP Framework Interoperability Group
Type safety, IDE type hinting.

A callable can be anything, an interface guarantees parameter types and, in PHP 7, return types.

Interfaces also indicate explicit implementation of the standard - rather than implicit implementation on the basis that the passed parameter could be executed.

All other reasons I've forgotten as to why interface type hints are a good thing.

Glenn Eggleton

unread,
Jul 29, 2016, 8:47:59 AM7/29/16
to PHP Framework Interoperability Group


On Friday, July 29, 2016 at 5:41:07 AM UTC-4, Andrew Carter wrote:
Type safety, IDE type hinting.

A callable can be anything, an interface guarantees parameter types and, in PHP 7, return types.

This dynamic property is an asset, not a liability, which is why there is so much confusion as to why we must now encapsulate everything in a wrapper object which I believe makes the code less readable.

 

Interfaces also indicate explicit implementation of the standard - rather than implicit implementation on the basis that the passed parameter could be executed.

I agree, but in this case being able to supply various different combinations as a callable is an awesomething thing.

Woody Gilk

unread,
Jul 29, 2016, 9:42:41 AM7/29/16
to PHP Framework Interoperability Group
On Fri, Jul 29, 2016 at 4:14 AM, Matthieu Napoli <matt...@mnapoli.fr> wrote:
>
> - FrameInterface doesn't represent any actual usage or existing middlewares today
> - FrameInterface is more complex than `callable`


From Anthony's blog post
http://blog.ircmaxell.com/2016/05/all-about-middleware.html :

> The fact that $next parameter is simply a callable also suffers from the same problem as above. It means that there's no longer any enforcement or ability to auto-complete or check types.
>
> Instead, $next should be a formal interface which would allow for type validation.

I agree with his position. Having a formal interface ensures correct
return type declarations in PHP 7. It shifts responsibility from the
user having to know what is expected to be able to have a direct type
hint that ensures accuracy.

I recommend reading the entire article, it covers a lot why PSR-15
looks like it does, and why we need PSR-17.

Matthieu Napoli

unread,
Jul 29, 2016, 10:15:30 AM7/29/16
to PHP Framework Interoperability Group
Thanks Woody and Andrew for your answers,

Type safety is a valid point. I'm all for type safety, however in this case I'm not convinced it's worth it since it's just a callable that takes a request and returns a response. It can't be any simpler (except maybe no arguments), and sometimes simplicity can outweigh doing everything by the book.

I think it's worth considering, especially because if you look at existing PSR-7 middlewares (expressive, slim, etc.), they use "callable $next".

We have no idea how convenient it is (or not) to have that FrameInterface, because currently nobody uses that. It's risky to standardize something that nobody uses.

TL/DR: reality trumps theory.

Also I want to say how important the meta document is: it should contain justification for everything that was decided in a PSR.

Alessandro Pellizzari

unread,
Jul 29, 2016, 10:20:16 AM7/29/16
to php...@googlegroups.com
On 12/07/2016 15:33, Woody Gilk wrote:

> The term "frame" comes from Anthony Farrera:
> http://blog.ircmaxell.com/2016/05/all-about-middleware.html
> <http://blog.ircmaxell.com/2016/05/all-about-middleware.html?m=1>
>
> It refers to moving from one middleware frame to another.
>
> Do you have any suggestions for a better name?

Chain?

function __invoke(Request $req, Chain $chain) {
$res = $chain->next();
return $this->doSomething($req, $res);
}

I think it's a bit more intuitive than $frame. You know you are
executing the next() function in the Chain of middlewares.

Bye.


Glenn Eggleton

unread,
Jul 29, 2016, 10:20:36 AM7/29/16
to PHP Framework Interoperability Group
+1

Andrew Carter

unread,
Jul 29, 2016, 10:38:02 AM7/29/16
to PHP Framework Interoperability Group
They use "callable $next" and they have a different structure (double pass).

It makes even more sense to have type safety if we're introducing a different middleware signature that's different to one that's commonly used in the wild. This would prevent incompatible middleware from being accidentally chained together.

Cheers,

Andrew

Alexandru Pătrănescu

unread,
Jul 29, 2016, 10:42:22 AM7/29/16
to php...@googlegroups.com
I think it can be both.
 - A FrameInterface to be used when developing middleware.
 - A CallableFrame class that's wrapping the callable if you really want to call it in a simple way. Maybe sometimes it's worth to have a very simple final class also in the PSR along with interfaces.

For middleware developers the type safety will be a plus.

Coming back to the name, I don't think FrameInterface is correct.
If the method is next(), it could be something that is a collection and I can suggest StackInterface as a name.
If the method is run(), it could be as simple as NextFrameInterface or just NextInterface.

Regards,
Alex


--
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+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Glenn Eggleton

unread,
Jul 29, 2016, 10:49:52 AM7/29/16
to php...@googlegroups.com
At minimum in order to make this usable to a wider audience the name need to be changed.
My suggestiong instead of FrameInterace: 
MiddlewareStackInterface which leads to a concrete class, MiddlewareStack... then ->next() makes perfect sense.
TypeHinting would then bee function (Request $request, MiddlewareStackInterface $stack); $stack->next($request);

--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/V12AAcT_SxE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.

To post to this group, send email to php...@googlegroups.com.

Woody Gilk

unread,
Aug 14, 2016, 9:02:30 AM8/14/16
to PHP Framework Interoperability Group
StackInterface is already included in the PSR-15 proposal [1] and
contains the collection of middleware. Passing the entire stack to a
middleware is not a good separation of concerns because a middleware
should not be able to modify the stack once the stack is being
processed.

I am definitely in favor of using an existing design pattern rather
than trying to define a new one. Stacks and Frames are an existing
pattern and I would prefer to keep the name intact.

As for compatibility, it is trivial to create a factory that wraps an
existing middleware into a compatible one, as outlined by Anthony's
blog post.

[1]: https://github.com/php-fig/fig-standards/blob/master/proposed/http-middleware/middleware.md#26-psrhttpmiddlewarestackinterface
> https://groups.google.com/d/msgid/php-fig/CAFGtT7ZFgP68bthH-PhgHtkJR85ZD21MUFR51CfojFwJRO8A-w%40mail.gmail.com.

Matthieu Napoli

unread,
Aug 14, 2016, 1:08:12 PM8/14/16
to PHP Framework Interoperability Group
The term "Frame" is extremely confusing, I think it's a big issue with the current version. I'm sure if you showed the current signature to PHP developers a majority of them would not understand what that parameter is.

On the other hand `$response = $next($request)` is so simple and widespread…

Yes we loose type safety but there's only one parameter and it's an HTTP request, it cannot get simpler than that. Do we really want to complicate the standard for no actual gain in real scenarios ?

With PSR-7 middlewares the callable type-hint is not an issue, let's not solve a problem that doesn't exist?

Rob Allen

unread,
Aug 14, 2016, 1:30:16 PM8/14/16
to php...@googlegroups.com

> On 14 Aug 2016, at 18:08, Matthieu Napoli <matt...@mnapoli.fr> wrote:
>
> The term "Frame" is extremely confusing, I think it's a big issue with the current version. I'm sure if you showed the current signature to PHP developers a majority of them would not understand what that parameter is.

This is my fundamental problem too. The word "frame" may be the correct computer-science term, but it's not used in any PHP data structures tutorial that I could find or on the PHP SPL documentation website.

I can live with a class, but I don't think it's really necessary. I do think that the class name and parameter name must be obviously named to normal people. For a method that takes one parameter, $next->next($request) is weird and looks over-engineered compared to $next($request), so I wonder why we aren't using __invoke in that interface too. I assume that's been answered somewhere, but it's not in the meta doc.

Regards,

Rob...

Matthieu Napoli

unread,
Aug 14, 2016, 1:33:03 PM8/14/16
to Rob Allen, php...@googlegroups.com
so I wonder why we aren't using __invoke in that interface too

That's a very good idea, it might be a good middle ground:


interface Next

{

    public function __invoke(ServerRequestInterface $request) : ResponseInterface;

}

Larry Garfield

unread,
Aug 14, 2016, 1:48:00 PM8/14/16
to php...@googlegroups.com
I believe the argument MWOP made in the past is that many existing middleware systems already use __invoke(), so PSR-15 using __invoke() as well would make bridge code harder.  A separate method makes having an object that just calls the method from an existing __invoke() (or vice versa) trivial.

--Larry Garfield

Matthieu Napoli

unread,
Aug 14, 2016, 2:09:55 PM8/14/16
to Larry Garfield, php...@googlegroups.com
so I wonder why we aren't using __invoke in that interface too

That's a very good idea, it might be a good middle ground:


interface Next

{

    public function __invoke(ServerRequestInterface $request) : ResponseInterface;

}


I believe the argument MWOP made in the past is that many existing middleware systems already use __invoke(), so PSR-15 using __invoke() as well would make bridge code harder.  A separate method makes having an object that just calls the method from an existing __invoke() (or vice versa) trivial.

Right but that applies to middlewares.

$next on the other hand is a throwable object/callable that wraps the next middleware because the next middleware expect another $next passed as parameter (at least from the implementations I've seen or implemented myself), so there shouldn't be any conflicts right?

Woody Gilk

unread,
Aug 14, 2016, 2:20:22 PM8/14/16
to PHP Framework Interoperability Group
I'm comfortable with this approach. The type hint would still have to
be included, though:

public function process(ServerRequestInterface $request, NextInterface $next)
{
return $next($request);
}

I also don't love name NextInterface but... naming things is hard.
--
Woody Gilk
http://about.me/shadowhand



>
> --
> 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+u...@googlegroups.com.
> To post to this group, send email to php...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/php-fig/etPan.57b0ab4a.72d7b9d0.16394%40mnapoli.fr.

Alexandru Pătrănescu

unread,
Aug 15, 2016, 3:20:50 AM8/15/16
to PHP Framework Interoperability Group
I'm comfortable with this approach.

Great.
 
But MiddlewareInterface is using process instead of __invoke. Should we settle on one approach for both?


Alex

Woody Gilk

unread,
Aug 15, 2016, 8:03:12 AM8/15/16
to PHP Framework Interoperability Group

I see no reason to use __invoke for middleware. The spec requires a formal interface be used.



For more options, visit https://groups.google.com/d/optout.

Glenn Eggleton

unread,
Aug 15, 2016, 8:31:51 AM8/15/16
to PHP Framework Interoperability Group
Naming things are hard if and only if their function is hard to define.... I still don't see any added value in turning the $next into a formal interface.

Moving on from that: 

NextMiddlewareInterface might be okay for a name...

NextMiddlewareInterface -> process ( Request )

Woody Gilk

unread,
Aug 15, 2016, 8:34:19 AM8/15/16
to PHP Framework Interoperability Group
A formal interface enforces type hints. A simple closure cannot be
enforced the same way.
> https://groups.google.com/d/msgid/php-fig/c025e5d9-991b-43b5-af97-3bb7df023870%40googlegroups.com.

Michael Cullum

unread,
Aug 15, 2016, 8:35:53 AM8/15/16
to FIG, PHP
Glenn & Woody,

Please make sure you are aware of the self-throttling rules.

--
Many thanks,
Michael C
FIG Secretary

To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+unsubscribe@googlegroups.com.

To post to this group, send email to php...@googlegroups.com.

Oscar Otero

unread,
Aug 15, 2016, 9:15:25 AM8/15/16
to php...@googlegroups.com
Hello. Maybe this is a bad idea, but just in case:
Why not merge frameInterface with StackInterface in just one interface, let’s say ‘DispatcherInterface’?
For example:

interface DispatcherInterface
{
    public function dispatch(RequestInterface $reques) : ResponseInterface;
}

interface ServerMiddlewareInterface
{
    public function process(ServerRequestInterface $request, DispatcherInterface $next): ResponseInterface
}

So, each time the method “dispatch” is called, the next frame is executed and the response returned. So a typical middleware should be:

class AddFooHeader implements ServerMiddlewareInterface
{
    public function process(ServerRequestInterface $request, DispatcherInterface $next)
    {
        $response = $next->dispatch($request);
        return $response->withHeader(‘Foo’, ‘Bar’);
    }
}

And to execute this:

$response = $dispatcher->dispatch($request);

IMHO, It’s simpler and easier to understand.


And in addition to that, we could add methods to return the psr-7 factories to use them inside the middleware:

interface DispatcherInterface
{
    public function dispatch(RequestInterface $reques) : ResponseInterface;
    public function getResponseFactory();
    public function getStreamFactory();
    //etc...
}



Woody Gilk

unread,
Aug 15, 2016, 9:59:43 AM8/15/16
to PHP Framework Interoperability Group
Oscar, doing that would be a violation of SRP and would allow
middleware to modify or inspect the stack. We should protect against
mistakes by design.
>> https://groups.google.com/d/msgid/php-fig/c025e5d9-991b-43b5-af97-3bb7df023870%40googlegroups.com.
>>
>> For more options, visit https://groups.google.com/d/optout.
>
>
>
> --
> 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+u...@googlegroups.com.
> To post to this group, send email to php...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/php-fig/CAAqcDMjHWYx9Udft0uUj6EC9zbOr5d8E2vQFEgxEe5FAomF5ng%40mail.gmail.com.
> For more options, visit https://groups.google.com/d/optout.
>
>
> --
> 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+u...@googlegroups.com.
> To post to this group, send email to php...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/php-fig/148B5B01-2B07-4996-97A7-5C30142BB15C%40gmail.com.

Oscar Otero

unread,
Aug 15, 2016, 1:16:32 PM8/15/16
to php...@googlegroups.com
Ok, thanks for your quick response, Woody.
An yes, I admit the factory methods is a violation of SRP.
But IMHO, the responsability of the stack is to execute the frames, and the DispatcherInterface example does just this (execute & move to the next), so I think there’s no violation here. The stack is inmutable so cannot be modified by any middleware, just executed. I don’t see more danger here than using a FrameInterface.
This is just an idea to reduce this specification to the minimum required.

---
Oscar Otero




Rasmus Schultz

unread,
Aug 16, 2016, 9:42:51 AM8/16/16
to PHP Framework Interoperability Group
The term "frame" means nothing to me - I assume the analogy is to stack frames? If so, that is something of a stretch.

I feel the term "frame" is going to require a somewhat confusing explanation.

I've suggested the term "delegate", because that's all these objects are - they're just delegates that dispatch the next middleware, so something like MiddlewareDelegateInterface would be more meaningful, in my opinion.

Most programmers should already know what a delegate is.

Any opinions on this?


On Tuesday, July 12, 2016 at 4:26:42 PM UTC+2, Rob Allen wrote:
Hi,

In the proposed PSR-15, there's a FrameInterface.


Where did the word "Frame" come from and in what context is it used. It means nothing to me and I don't think I'm alone in having no clue how I would be able to infer that $frame might have a next() method. It's very weird and I think it's a negative when looking at the function signature as it's a meaningless word unless you know some back story that I clearly don't?

I would love an explanation as it looks to me like an area of confusion for people new to writing middleware.

For what it's worth, I don't especially mind the interface itself, though I'm not sure what it adds other than more typing. It's the choice of name that I'm questioning.

Regards,

Rob...

Matthew Weier O'Phinney

unread,
Aug 17, 2016, 10:05:57 AM8/17/16
to php...@googlegroups.com
That was indeed the argument.

Since many (most) existing middleware systems already use either
callables or a class/interface that implements `__invoke()` for the
`$next` argument, specifying the interface within this PSR to define
`__invoke()` has the potential to make it completely incompatible with
these existing systems without major changes.

As an example, consider a middleware that targets this PSR, but is
dropped into Expressive or Slim, and then calls on $next:

return $next($request);

In each of these cases, a second argument *is required currently*,
which means that this invocation will result in a fatal error.

If we instead use another method entirely, the above becomes something like:

return $frame->next($request); // or:
return $delegate->next($request); // or:
return $delegate->process($request); // etc.

As a result, these existing libraries can implement the interface
without breaking backwards compatibility:

class Next implements DelegateInterface
{
public function __invoke(ServerRequestInterface $request,
ResponseInterface $response)
{
// ...
}

public function next(ServerRequestInterface $request)
{
// ...
}
}

allowing them to mix-and-match middleware written for the previous
version with middleware targeting this PSR. Since the new interface
method only indicates one required argument, the implementation can
even pass the response to ensure backwards compatibility, and provide
tools for scanning middleware to warn about implementations that need
to be updated.

While I appreciate that we want to standardize on what is already
being done, the fact that the calling patterns of existing middleware
dispatchers vary currently means that having a discrete, unique method
ensures greater compatibility once the specification is finalized,
easing the way to adoption by existing libraries.

--
Matthew Weier O'Phinney
mweiero...@gmail.com
https://mwop.net/

Matthieu Napoli

unread,
Aug 17, 2016, 12:47:15 PM8/17/16
to PHP Framework Interoperability Group
Thanks a lot for the detailed response Matthew.

If you already discussed that then sorry for wasting your time (and others too), your answer sounds valid to me I wasn't expecting such a high level of backward compatibility with existing systems.

To avoid repeating that discussion in a few months I have taken the liberty of picking a few of your sentences and write a summary of that in the META document: https://github.com/php-fig/fig-standards/pull/807

Now it seems the only topic worth discussing is the name? Rasmus you suggested `DelegateInterface` instead of `FrameInterface`, that sounds like an improvement to me (I have nothing better to suggest), what do others think?

Stefano Torresi

unread,
Aug 17, 2016, 5:54:58 PM8/17/16
to PHP Framework Interoperability Group
In my humble opinion, there is nothing wrong with "FrameInterface::next()": I think it communicates intent and context by suggesting the analogy with call stack frames.

"MiddlewareDelegateInterface::process()" on the other hand, while technically correct, is in my opinion too generic and ambiguous: it could mean a lot of things other than "the rest of the middleware stack".
On a side note, I personally find Delegate the most generic and ambiguous composition pattern ever conceived.

Would an explanation of the rationale behind the "frame" term in the metadocs be satisfactory for those who were surprised by its choice?

--
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+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Rob Allen

unread,
Aug 18, 2016, 3:57:35 AM8/18/16
to php...@googlegroups.com
I don't like "frame" as it feels elitist to me. Canvas 10,000 PHP developers and ask them if they can guess what a "Frame" would be used for in a PHP application. I don't think you'll get 70% correct answers. To my mind, it makes it harder to understand and hence creates a barrier.

As I've said before, I'd prefer not to have an interface at all, but if you must have one, then please try to be inclusive with us non-computer scientists.

Given that you want an interface, I like `DispatcherInterface` personally as that's what the object does. The docblock for `next()` in the proposed document even states: "Dispatch the next available middleware and return the response".


Regards,

Rob...
Message has been deleted

kapitanluffy pirata

unread,
Oct 15, 2017, 2:41:18 AM10/15/17
to PHP Framework Interoperability Group
Hi, I have the same idea as Oscar but I call the dispatcher as MiddlewareStack. 

Can someone explain how this violates SRP? As far as I can understand it, 
the stack/dispatcher is only responsible for handling/delegating the request to the next middleware. 

That's why the interface only has "handle" as the method


interface MiddlewareStackInterface
{
   
public function handle(RequestInterface $request) : ResponseInterface;
}



While the middleware is responsible of processing the request and returning a response. 


interface MiddlewareInterface
{
   
public function process(ServerRequestInterface $request, MiddlewareStackInterface $stack): ResponseInterface
}



By passing the stack/dispatcher in the middleware, you may choose to create the response or 
let the stack/dispatcher handle/delegate the request to the next middleware 
(which I think is the same responsibility, or I am interpreting SRP wrong?).

Michael C
FIG Secretary

Woody Gilk

unread,
Oct 18, 2017, 2:20:18 PM10/18/17
to PHP Framework Interoperability Group
The current interfaces are different than what you have listed here and the discussion has been resolved. I recommend looking at the current proposal if you have additional questions.

To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+unsubscribe@googlegroups.com.

To post to this group, send email to php...@googlegroups.com.

Hari K T

unread,
Nov 18, 2017, 10:31:57 AM11/18/17
to PHP Framework Interoperability Group
Reply all
Reply to author
Forward
0 new messages