[PSR-7] un-interoperable with standard session handling?

603 views
Skip to first unread message

Rasmus Schultz

unread,
Aug 6, 2015, 12:33:03 PM8/6/15
to PHP Framework Interoperability Group
Has anyone successfully built a PSR-7 based project with standard session management?

My first impulse was to implement a SessionHandler class with a pair of methods to initialize it from a ServerRequestInterface, and apply the cookie back to  a ResponseInterface instance e.g. via middleware.

However, it turns out, there does not appear to be any way to suppress the built-in PHP behavior that causes it to send a cookie.

That means, session handling has to lead a separate life, outside of our shiny new HTTP components.

Or, we have to throw away standard session handling entirely, and a wealth of off-the-shelf components that rely on it, and rebuild everything from the ground up - which is what we ended up doing - and it's a lot more work than expected.

So now, anything that relies on the session_*() functions or the $_SESSION superglobal is off-limits and can't be part of our stack.

The alternative is worse (in my opinion) - that is, let the standard session module just do it's thang, and wave goodbye to all the benefits this was supposed to give in terms of testing; suddenly, any controller that does anything related to sessions, has to be run in an actual server context, because the HTTP components do not cover that.

Any ideas on how we can fix this in the future?

Because this really sucks, and I am inches from recommending we drop PSR-7 and middleware entirely, because of this, and go back to the old-fashioned way of doing things, simple resource models and a delivery system with header() calls and echo statements... the price in terms of complexity is too high, and the benefits are too small. Just my opinion, but we were hoping this would make this simpler, not more complicated.

Thus far, we have spent 3 months building a stack that is feature-equivalent to a stack I built in plain PHP in under a week, but with thousands of lines more code, mass amounts of duplication of concerns that were already covered by PHP itself, a degree of underlying complexity that delivers a real hit to performance, and apparently complexity that breeds more complexity in everything we do.

The whole thing seems like a poor fit for PHP at large, and I'm failing to see the point. 80% of our developers would never even know the difference, as the API (controllers, views, services, etc.) that we expose to them is very simple either way. The underlying "neatness" and unit-testable qualities of a few key components is something we could have dealt with in a few integration tests.

Tell me how all of this work is supposed to pay off, because I don't get it?

PS: try not to see this as an angry attack on PSR-7, please. I am very frustrated by the whole experience, granted, but if there's something really great I'm overlooking, I am genuinely hoping to learn what that may be. At this point, I just don't get it.

Woody Gilk

unread,
Aug 6, 2015, 12:59:50 PM8/6/15
to php...@googlegroups.com
Rasmus,

I have to question the base assumption here, which seems to be that sessions are inherently related to HTTP request/response lifecycle and should therefore be supported by PSR-7. I don't agree with this assumption and I think questioning the validity of PSR-7 because of it is extremely short sighted.

On Thu, Aug 6, 2015 at 11:33 AM, Rasmus Schultz <ras...@mindplay.dk> wrote:
My first impulse was to implement a SessionHandler class with a pair of methods to initialize it from a ServerRequestInterface, and apply the cookie back to  a ResponseInterface instance e.g. via middleware.

I don't think this is necessary at all. I assume this approach would be used for testing, but...
 
However, it turns out, there does not appear to be any way to suppress the built-in PHP behavior that causes it to send a cookie.

That means, session handling has to lead a separate life, outside of our shiny new HTTP components.

Or, we have to throw away standard session handling entirely, and a wealth of off-the-shelf components that rely on it, and rebuild everything from the ground up - which is what we ended up doing - and it's a lot more work than expected.

So now, anything that relies on the session_*() functions or the $_SESSION superglobal is off-limits and can't be part of our stack.

The alternative is worse (in my opinion) - that is, let the standard session module just do it's thang, and wave goodbye to all the benefits this was supposed to give in terms of testing; suddenly, any controller that does anything related to sessions, has to be run in an actual server context, because the HTTP components do not cover that.

There's another option: use native sessions, but do all your session get/set through a separate class. I've been using this very simple wrapper to work around using the global $_SESSION while still being able to mock it for testing: https://gist.github.com/shadowhand/5a1b2c904a5d521823e0

This obviously doesn't help you test 3rd party stuff, but most likely dependencies would be getting mocked so it wouldn't matter.
 
Because this really sucks, and I am inches from recommending we drop PSR-7 and middleware entirely, because of this, and go back to the old-fashioned way of doing things, simple resource models and a delivery system with header() calls and echo statements... the price in terms of complexity is too high, and the benefits are too small. Just my opinion, but we were hoping this would make this simpler, not more complicated.

To be perfectly honest, this sounds like you don't understand the scope and real benefits of PSR-7. In my experience working through several projects that immediately switched to PSR-7, it is neither complex or difficult. The consistency of the interface has been fantastic and has simplified a number of things that used to be quite difficult (URI rebuilding, input collection, etc).

Regards,

--
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/cfc6e290-755d-4957-aedd-34dfd64ea1b8%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Rasmus Schultz

unread,
Aug 6, 2015, 1:28:37 PM8/6/15
to PHP Framework Interoperability Group
> I have to question the base assumption here, which seems to be that sessions are inherently related to HTTP request/response lifecycle and should therefore be supported by PSR-7

No, that's not the assumption - I presented that idea earlier, and was told (basically) that sessions is inherently not part of HTTP, it just happens to be one use of cookies, but as such, that's where the relationship ends: sending a cookie.

Sending that cookie is where these two concerns meet, and although this doesn't relate to PSR, which deals with HTTP only, it is inherently part of the PHP request/response lifecycle, and a key component at that. I haven't built many apps that don't require session state.

So while this is out of scope for PSR-7, it's still an absolute requirement, and if you've chosen PSR-7, it has to interoperate, somehow, on some level.

> There's another option: use native sessions, but do all your session get/set through a separate class

This was already the common solution before PSR-7, so yeah. The problem is, even if you could take a third-party component and override methods that call session_() functions or reads/writes the $_SESSION superglobal, you can't do that for every third-party component, and so you're still left with something non-interoperable.

A key point of the PSR-7 spec, as I understand it, is framework interoperability, such as is the overarching mission of FIG - but without support for sessions, while we're certainly close to interoperability, we're not there.

> To be perfectly honest, this sounds like you don't understand the scope and real benefits of PSR-7. In my experience working through several projects that immediately switched to PSR-7, it is neither complex or difficult. The consistency of the interface has been fantastic and has simplified a number of things that used to be quite difficult (URI rebuilding, input collection, etc).

I understand all of that, and it's all wonderful. However, a bunch of other things that used to be trivial, are now complicated - this includes session handling, although that is far from the only problem I have encountered.

It's not that I don't understand the benefits - I have been very excited about PSR-7 up until about a week ago when I had to start rewriting PHP's session management from the ground up, dealing with mutual exclusion, potential race conditions, security concerns, and so on. It's all very nice and shiny and testable, and if the cost if we can't ever use code that touches $_SESSION or the session_() functions, then so be it.

The problem is, looking back at the result, and comparing with a much simpler solution using plain PHP, we have taken on quite a lot of third-party code (some of which has caused trouble already more than once) and written a bunch of new code, which we didn't need before, which we will now have to maintain and support in the future. We wanted less code and less complexity, fewer dependencies, less learning curve, and now instead we have more.

With that said, I do have difficulty judging whether most of the other (non-session) problems we've had are due to the spec, or due to the implementation.

If I may ask, which PSR-7 implementation are you using?

Woody Gilk

unread,
Aug 6, 2015, 2:06:00 PM8/6/15
to php...@googlegroups.com
On Thu, Aug 6, 2015 at 12:28 PM, Rasmus Schultz <ras...@mindplay.dk> wrote:
If I may ask, which PSR-7 implementation are you using?

So far I've used zend/diactoros and guzzle/psr7.

FWIW, I've always thought that session handling in PHP was fairly terrible and a serious pain to customize. PSR-7 does nothing to make it better or worse.

Rasmus Schultz

unread,
Aug 6, 2015, 2:13:22 PM8/6/15
to php...@googlegroups.com
So far I've used zend/diactoros and guzzle/psr7.

Yeah, that's where I ended up. Are you using stratigility as well, or just diactoros? (maybe that's the sting.)

I've always thought that session handling in PHP was fairly terrible and a serious pain to customize. PSR-7 does nothing to make it better or worse.

Yeah, session management in PHP is infamously fubar ;-)

There are plenty of off-the-shelf libraries to deal with that though - while arguably PSR-7 doesn't change that situation, it does block you from using any of the existing solutions to deal with the nasty... (or accepting the other mentioned wonky trade-offs...)


--
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/vHDBBb915kM/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.

Jeremy Lindblom

unread,
Aug 6, 2015, 4:37:25 PM8/6/15
to php...@googlegroups.com
Haven't projects like StackPHP and Laravel that do middleware around Symfony's HTTP kernel been doing sessions successfully with middleware? I can't speak from experience, so maybe people familiar with those projects could comment.

--
Jeremy Lindblom (@jeremeamia)
Software Engineer at Amazon Web Services (until tomorrow)
Co-author of the AWS SDK for PHP (@awsforphp)
President of the Seattle PHP User Group (@seaphp)
PHP-FIG Representative for the Guzzle project


Rasmus Schultz

unread,
Aug 6, 2015, 5:09:10 PM8/6/15
to php...@googlegroups.com
From the ground up, sure - I'm doing that too.

Interoperable with $_SESSION? I don't see how, since sending the cookie happens internally and can't be influenced by user code, e.g. isn't something a session handler can control.

Unless maybe there's some crazy way you can capture the cookie after PHP session module issues it, but before headers are sent, and then clear the headers?? I don't know... I'm tired of trying ;-)


Evert Pot

unread,
Aug 6, 2015, 5:32:48 PM8/6/15
to php...@googlegroups.com
On 2015-08-06 5:09 PM, Rasmus Schultz wrote:
> From the ground up, sure - I'm doing that too
> <https://github.com/mindplay-dk/stately>.
>
> Interoperable with $_SESSION? I don't see how, since sending the cookie
> happens internally and can't be influenced by user code, e.g. isn't
> something a session handler can control.
>
> Unless maybe there's some crazy way you can capture the cookie
> /after/ PHP session module issues it, but before headers are sent, and
> then clear the headers?? I don't know... I'm tired of trying ;-)

It makes perfect sense to me that it doesn't work well with $_SESSION.
It's 100% by design.

The underlying idea is that psr-7 applications send request and response
objects statelessly throughout the application.

Accessing superglobals, header(), stdin/stdout, etc all break this core
idea, because they all operate on the global state.

A well-designed PSR-7 application would hypothetically allow me to
instantiate a request object with a session id of some other user, and
completely let the application complete the request *as if* it was on
behalf of the other user/session.

Using PHP's built-in session system, or any other super-global breaks this.

In fact, I think it's an excellent test to see if your application or
library is well designed according to the PSR-7 philosophy.

Evert

Rasmus Schultz

unread,
Aug 6, 2015, 5:51:49 PM8/6/15
to php...@googlegroups.com

I don't disagree, but what you're also saying then, is that PSR-7 based projects by definition cannot (or at least should not) interop with anything that uses the standard PHP session API.

And since there is no PSR for sessions, bottom line, everyone implements their own, meaning no two components are likely to share the same session management, or at least it would just be luck of they happen to do so ;-)

What upsets me, is that this is WORSE than the situation we had with standard session management - at least we had one cookie, one storage API, and although, granted, it was pretty terrible, at least there was a common way of doing sessions.

So if standard session management dies with PSR-7, that means we need a new standard - so that all these new session implementations can be interoperable.

Right?

Or do we suddenly not care about that anymore for some reason? :-)

--
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/vHDBBb915kM/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.

Paul M. Jones

unread,
Aug 6, 2015, 5:56:44 PM8/6/15
to php...@googlegroups.com

> On Aug 6, 2015, at 16:51, Rasmus Schultz <ras...@mindplay.dk> wrote:
>
> I don't disagree, but what you're also saying then, is that PSR-7 based projects by definition cannot (or at least should not) interop with anything that uses the standard PHP session API.

I don't take that from this exchange at all, only that PHP-standard sessions operate outside PSR-7. That PHP sends (and reads) a single cookie does not exactly bust PSR-7. It's sub-optimal, but work-around-able.


--
Paul M. Jones
pmjo...@gmail.com
http://paul-m-jones.com

Modernizing Legacy Applications in PHP
https://leanpub.com/mlaphp

Solving the N+1 Problem in PHP
https://leanpub.com/sn1php


Woody Gilk

unread,
Aug 6, 2015, 5:59:28 PM8/6/15
to php...@googlegroups.com

On Thu, Aug 6, 2015 at 4:51 PM, Rasmus Schultz <ras...@mindplay.dk> wrote:
I don't disagree, but what you're also saying then, is that PSR-7 based projects by definition cannot (or at least should not) interop with anything that uses the standard PHP session API.

This might be the crux of the issue, because no component (in any layer except the HTTP layer) should be aware of global state. I would argue that basically any component that relies on $_SESSION is broken by design.

Matthew Weier O'Phinney

unread,
Aug 6, 2015, 6:10:56 PM8/6/15
to php...@googlegroups.com
On Thu, Aug 6, 2015 at 11:33 AM, Rasmus Schultz <ras...@mindplay.dk> wrote:
> Has anyone successfully built a PSR-7 based project with standard session
> management?

Yes: my own website (source is at
https://github.com/weierophinney/mwop.net), and a few others I've
built. I used Aura.Session along with Stratigility/Diactoros.

The crux, as others have pointed out in this thread, is that session
management falls outside the PSR-7 specification. Sessions are
essentially a persistent store that is identified by a cookie value;
the value of that cookie is sent by the server to the client via the
Set-Cookie, and returned by the client on later requests to the server
via the Cookie header.

In other words, we have a cache-based solution where the cache
identifier is provided by data in the HTTP request. That's the only
relation sessions have to PSR-7: the transfer of that identifier
between client and server and vice versa, and that transfer is already
handled via HTTP headers, which *are* part of the specification.

My point is: you *can* use sessions inside a PSR-7 application. Choose
a good library (Aura.Session and Zend\Session, for example, are each
standalone and provide abstraction around session access for you), and
you can configure and inject it into middleware that needs it.

Yes, it means that you may not have interop around sessions at this
time; however, that is not a failing of PSR-7; we specifically
excluded sessions as they are a *tangential*, not *integral* concern
of server-side messages. Sessions require a separate PSR.

(On that note, I actually think one of the cache PSRs may be the way
forward; I'd love to see usage of a cache object for interacting with
the session instead, as it fits most of its concerns, including expiry
of data.)
> --
> 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/cfc6e290-755d-4957-aedd-34dfd64ea1b8%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



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

Rasmus Schultz

unread,
Aug 8, 2015, 4:13:25 AM8/8/15
to php...@googlegroups.com

The problem with just using PHP sessions (vs rewriting the thing from the ground up) is that, whether you're dispatching it from middleware or not, whether you're using an abstraction or not, the sending of the session ID cookie is outside of the header model.

That affects testing, though as somebody pointed out, that can still be addressed by mocking the abstraction in test, so...

I guess that'll have to do, but I'm really looking forward to that session PSR, so we can do this in a clean, interoperable way, rather than working around that crusty old standard session library ;-)

Is that PSR under way?

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/vHDBBb915kM/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.

Beau Simensen

unread,
Aug 10, 2015, 6:24:15 PM8/10/15
to PHP Framework Interoperability Group
On Saturday, August 8, 2015 at 3:13:25 AM UTC-5, Rasmus Schultz wrote:

Is that PSR under way?


Not that I'm aware of! I've heard people mumbling about related PSR-7 PSR's like middleware, client, server, and session, but nothing formalized or organized enough to actually be working on it yet.

Rasmus Schultz

unread,
Nov 2, 2016, 4:39:58 PM11/2/16
to PHP Framework Interoperability Group
I took a stab at a very rough draft of a session abstraction:


Nothing is final, it's not complete either, and I'm not trying to start a debate about it at this time - I don't have the energy or time at the moment.

Just dumping it here for reference, or as a possible starting point, if somebody else wants to wrestle with this...
Reply all
Reply to author
Forward
0 new messages