jasny/session-middleware

PSR-15 session middleware with support for mock sessions

v1.1.0 2020-04-16 00:00 UTC

This package is auto-updated.

Last update: 2022-01-17 05:04:49 UTC


README

Build Status Scrutinizer Code Quality Code Coverage Packagist Stable Version Packagist License

Using superglobals like $_SESSION object makes it difficult to test an application as global variables can have unexpected side effects. Using superglobals undermines the effort of using dependency injection and using containers.

The middleware creates an object that wraps $_SESSION, which is available for dependency injection and as attribute of the PSR-7 ServerRequest. The middleware complies with PSR-15. It will also work as double pass middleware.

Installation

composer require jasny/session-middleware

Usage

use Jasny\Session\SessionMiddleware;

$router->add(new SessionMiddleware());
$response = $router->handle($request);

Get the session object from the PSR-7 ServerRequest object and use it as array

$session = $request->getAttribute('session');
$session['foo.bar'] = 10;

if (isset($session['foo.user'])) {
  // ...
}

The session is started by the middleware.

Methods

The session object implements SessionInterface and has the following methods;

  • start() - Start the session.
  • status() - Get the session status.
  • stop() - Write session data and end session.
  • abort() - Discard session array changes and finish session.
  • clear() - Clear all data from the session.
  • kill() - Destroy the session and remove the session cookie.
  • rotate() - Delete the current session and start a new one.

When rotating a session, it's possible to copy some of the data by supplying a callback.

$session->rotate(fn(array $oldSessionData) => ['tid' => $oldSessionData['tid'] ?? null]);

Session options

By default, the middleware will create a GlobalSession object. This object is linked to PHPs session management including $_SESSION. You can manually instantiate this object, supplying session options. These options are passed to session_start().

use Jasny\Session\GlobalSession;
use Jasny\Session\SessionMiddleware;

$session = new GlobalSession([
    'cookie_lifetime' => 0,
    'cookie_httponly' => 1,
    'use_only_cookies' => 1,
    'use_trans_sid' => 0,
    'cookie_secure' => (bool)($_SERVER['HTTPS'] ?? false),
    'cookie_samesite' => 'Lax',
]);

$router->add(new SessionMiddleware($session));
$response = $router->handle($request);

Flash

The session flash object can be used to pass a message to the next request. It is automatically removed from the session after it is used. A typical use case is to store information in a database, than redirect to a page and showing a success message. Or if the information could not be saved, to show an error message.

The flash information contains a type (e.g. success, error, info, warning) and a message. Optionally a content type can be specified for the message. This defaults to text/plain.

$session->flash('success', 'The information has been saved');

In the next request

{% for flash in app.flashes() %}
    <div class="flash-{{ flash.type }}">
        {{ flash.message }}
    </div>
{% endfor %}

If flash() or flashes() is called, the flash messages are cleared from the session. To prevent this call reissue()

$session->flashes()
    ->reissue()
    ->add('warning', "Could not display the page");

header('Location: /other-page');
exit();

Call $session->flashes()->clear() to explicly clear all flash messages, both newly added (to the session) and those available for the current request.

Testing

When running tests, you can injecting a MockSession object in the server request before passing it to the middleware.

use Jasny\Session\MockSession;

$session = new MockSession([
  'foo.user' => 'john@example.com'
]);

$requestWithSession = $request->withAttribute('session', $session);
$response = $router->handle($requestWithSession);

Alternatively you can pass a session object when creating the SessionMiddleware. This session object will be used instead of the global session.

use Jasny\Session\SessionMiddleware;
use Jasny\Session\MockSession;

$mockSession = new MockSession();

$router->add(new SessionMiddleware($mockSession));
$response = $router->handle($request);