Sessions

Introduction

HTTP is a stateless protocol. What that means is that each request has no memory of previous requests. If you've ever used the web, though, you've probably noticed that websites are able to remember information across requests. For example, a "shopping cart" on an e-commerce website remembers what items you've added to your cart. How'd they do that? Sessions.

Note: Although similar in concept, Aphiria's sessions do not use PHP's built-in $_SESSION functionality because it is awful.

Basic Usage

Aphiria sessions must implement ISession (Session comes built-in).

Setting Data

Any kind of serializable data can be written to sessions:

use Aphiria\Sessions\Session;

$session = new Session();
$session->set('someString', 'foo');
$session->set('someArray', ['bar', 'baz']);

Getting Data

$session->set('someKey', 'myValue');
echo $session->get('someKey'); // "myValue"

Getting All Data

$session->set('foo', 'bar');
$session->set('baz', 'blah');
$data = $session->getAll();
echo $data['foo']; // "bar"
echo $data['baz']; // "blah"

Checking if a Session Has a Key

echo $session->containsKey('foo'); // 0
$session->set('foo', 'bar');
echo $session->containsKey('foo'); // 1

Deleting Data

$session->delete('someKey');

Flushing All Data

$session->flush();

Flashing Data

If you want to only keep data in a session only for the next request, you can use flash():

$session->flash('validationErrors', ['Invalid username']);

On the next request, the data in validationErrors will be deleted. Use reflash() if you need to extend the lifetime of the flash data by one more request.

Regenerating the ID

$session->regenerateId();

Session Handlers

Session handlers are what actually read and write session data from some form of storage, eg text files, cache, or cookies, and are typically invoked in middleware. All Aphiria handlers implement \SessionHandlerInterface (built into PHP). Aphiria has the concept of session "drivers", which represent the storage that powers the handlers. For example, FileSessionDriver stores session data to plain-text files, and ArraySessionDriver writes to an in-memory array, which can be useful for development environments. Aphiria contains a session handler already set up to use a driver:

use Aphiria\Sessions\Handlers\{DriverSessionHandler, FileSessionDriver};

$driver = new FileSessionDriver('/tmp/sessions');
$handler = new DriverSessionHandler($driver);

Using Sessions in Controllers

To use sessions in your controllers, simply inject it into the controller's constructor:

namespace App\Authentication\Api\Controllers;

use Aphiria\Sessions\ISession;

final class AuthController extends Controller
{
    public function __construct(private ISession $session) {}

    #[Post('login')]
    public function logIn(LoginDto $loginDto): IResponse
    {
        // Do the login...

        $this->session->set('user', (string)$user);
 
        // Create the response...
    }
}

Middleware

Middleware is the best way to handle reading session data from storage and persisting it back to storage at the end of a request. For convenience, Aphiria provides the Session middleware to handle reading and writing session data to cookies. Let's look at how to configure it:

use Aphiria\Sessions\Middleware\Session as SessionMiddleware;

// Assume our session and handler are already created...
$sessionMiddleware = new SessionMiddleware(
    session: $session,
    sessionHandler: $sessionHandler,
    sessionTtl: 3600,
    sessionCookieName: 'sessionid',
    sessionCookiePath: '/', // Defaults to null
    sessionCookieDomain: 'example.com', // Defaults to null
    sessionCookieIsSecure: true, // Defaults to false
    sessionCookieIsHttpOnly: true, // Defaults to true
    gcChance: 0.01 // Defaults to 0.01
);

Refer to the application builder library for more information on how to register the middleware.

ID Generators

If your session has just started or if its data has been invalidated, a new session ID will need to be generated. These IDs must be cryptographically secure to prevent session hijacking. If you're using Session, you can either pass in your own ID generator (must implement IIdGenerator) or use the default UuidV4IdGenerator.

Note: It's recommended you use Aphiria's UuidV4IdGenerator unless you know what you're doing.

Encrypting Session Data

You might find yourself storing sensitive data in sessions, in which case you'll want to encrypt it. To do this, pass in an instance of ISessionEncrypter to DriverSessionHandler (passing in null will cause your data to be unencrypted).

use Aphiria\Sessions\Handlers\DriverSessionHandler;
use Aphiria\Sessions\Handlers\ISessionEncrypter;

$driver = new FileSessionDriver('/tmp/sessions');
$encrypter = new class () implements ISessionEncrypter {
    // Implement ISessionEncrypter...
};
$handler = new DriverSessionHandler($driver, $encrypter);

Note: Aphiria does not provide native support for encryption. You must use another library to encrypt and decrypt data.

Now, all your session data will be encrypted before being written and decrypted after being read.