Rasmus Schultz <ras...@mindplay.dk>: Mar 06 04:54AM -0800
Hi Amanda,
I'm interested in this, and I mostly agree with your approach and
philosophy.
I did some work today trying to move this idea forward, and would propose
some changes.
First, I'd like to replace the mutable ServerRequestSessionInterface with
an immutable SessionManagerInterface, which would be responsible for:
1. opening the session: parsing session cookies and obtaining the stored
session data.
2. committing the session: applying the session cookies and storing the
session data.
This seems to be more in tune with PSR-7/15 and makes it obvious how to
integrate them.
use Psr\Http\Message\ServerRequestInterface; use
Psr\Http\Message\ResponseInterface; interface SessionManagerInterface { /**
* Initiates a new session or resumes an existing session based on the
request context. * * @param ServerRequestInterface $request * * @return
SessionInterface */ public function open(ServerRequestInterface $request):
SessionInterface; /** * Commits session data to storage and applies session
cookies to the response. * * @param SessionInterface $session * @param
ResponseInterface $response * * @return ResponseInterface */ public
function commit(SessionInterface $session, ResponseInterface $response):
ResponseInterface; }
Secondly, I'd propose some changes to simplify the SessionInterface to
clarify its role as the bearer session state (and session identifier) and
simplifying its semantics:
1. Removing the start and close methods - this is the responsibility of
the SessionManagerInterface service, and should happen implicitly.
2. Removing the getId method - leaving session identifiers as an
implementation detail of the SessionManagerInterface service.
3. Changing the return type of regenerateId from bool to void. (it
always returned true.)
4. Added a getAll method, allowing the session values to be enumerated.
5. Removed clear in favor of destroy, as these are are ambiguous and can
be confusing - to my knowledge, there is no reason you would clear the
session data without also destroying the session? If you're clearing the
session data anyway, you might as well generate a new session identifier to
avoid creating a secuity risk.
interface SessionInterface { /** * Retrieves a session value associated
with a given key. * * @param string $key * @param mixed $default Default
value if the session key does not exist. * * @return mixed */ public
function get(string $key, mixed $default = null): mixed; /** * Sets a
session value for a given key. * * @param string $key * @param mixed $value
*/ public function set(string $key, mixed $value): void; /** * Removes a
session value for a given key. * * @param string $key */ public function
remove(string $key): void; /** * Checks if the session has a value for the
given key. * * @param string $key * * @return bool */ public function
has(string $key): bool; /** * Clears all session data and generates a new
internal session identifier. */ public function destroy(): void; /** *
Renew the current session by generating a new internal session identifier.
*/ public function regenerateId(): void; /** * Returns all session data as
an associative array. * * @return array */ public function getAll(): array;
}
To those who commented with "we don't need this", I would disagree - I
think there are clear cut use cases for this, starting with stateful
handlers or middlewares, in particular things like routers or controller
abstractions that need to store state between requests. I think it's a good
idea to have a standard way to do this that is compatible with PSR-7/15.
Further more, as Amanda explained, we need this because there is no obvious
way to use sessions in a PSR-7/15 context. Using $_SESSION creates serious
problems with testing, and PSR standards do not provide any alternative.
This is a problem that needs to be solved.
I would point out that a session abstraction doesn't need to cover every
imaginable use case - and doesn't need to have full parity with every
existing framework or library out there, and and it should not aim to be a
replacement for session abstractions in existing frameworks.
Looking at some of the available libraries for session management,
interfaces like these should work fine (via adapters) for e.g. all of the
following:
-
https://github.com/psr7-sessions/storageless/blob/9.2.x/src/Storageless/Session/SessionInterface.php
- https://github.com/yiisoft/session/blob/master/src/SessionInterface.php
-
https://github.com/mezzio/mezzio-session/blob/1.15.x/src/SessionInterface.php
These libraries aim to replace $_SESSION with a more testable and flexible
alternative, and I think it's important to have an interface that decouples
frameworks, middleware, routers, etc. from the implementation - enabling
the use of session state without having to depend on a specific library.
Amanda, if you're still interested, I'd be happy to join a working group
and help out. :-)
On Tuesday, September 27, 2022 at 2:40:17 PM UTC+2 Amanda wrote:
|