Session
A session handler repository for maintaining user state across multiple requests.
- Installation
-
Session
- Create a session
- Start session
- Session token
- Session ID
- Session name
- Retrieve session data
- Store session data
- Determine if session data exists
- Remove session data
- Migrate session
- Regenerate session
- Invalidate session
- Save session
- Flash session data
- Flash input data
- Session handler
- Encrypt session data
- Session handlers
- Session manager
Installation
To get started, install the session repository via the Composer package manager:
composer require zaphyr-org/session
Session
HTTP is a stateless protocol, which means that the server does not keep any information (state) between two requests.
This is a problem when you want to keep track of a user's activity on your website. For example, if you want to check
if a user is logged in, you need to keep track of that somehow. This is, where the session repository comes into play.
The session repository does not store session data in the $_SESSION
super global. Instead, the session repository uses
custom session handlers to store the session data.
Create a session
To start a session, you need to create a new Zaphyr\Session\Session
instance and pass a session name and session
handler to it. The session name is used to identify the session cookie. The session handler is responsible for storing
the session data. The session handler must implement
PHP's built in SessionHandlerInterface
. In our
example we will use the Zaphyr\Session\Handler\FileSessionHandler
which stores the session data in files. We will
learn about session handlers in more detail in the session handlers section.
$handler = new Zaphyr\Session\Handler\FileSessionHandler('/path/to/storage');
$session = new Zaphyr\Session\Session('session_name', $handler);
Start session
To start a new session, you need to call the start
method:
$session->start();
If you want to check if a session is already started, you can use the isStarted
method:
$session->isStarted();
Session token
The session token is used to prevent XSS attacks. The session token is generated automatically when the session is
started. You can retrieve the session token with the getToken
method:
$session->getToken();
You can also set a custom session token with the setToken
method. The provided token must be a string of 40
alphanumeric
characters. If the provided string does not fit the criteria, the setToken
method will create a new random token:
$session->setToken('oRILZgj1i94DNaAUotusSOCR7WvymbaLSMOxYhNF');
The session token is stored in the session data under the _token
key. The _token
key is reserved and should not be
used for other session data!
Session ID
The session ID is used to identify the session. The session ID is generated automatically when the session is
instantiated.
You can retrieve the session ID with the getId
method:
$session->getId();
You can also set a custom session ID with the setId
method. The provided ID must be a string of 40 alphanumeric
characters. If the provided string does not fit the criteria, the setId
method will create a new random ID:
$session->setId('oRILZgj1i94DNaAUotusSOCR7WvymbaLSMOxYhNF');
Session name
The session name is used to identify the session cookie. You can retrieve the session name with the getName
method:
$session->getName();
You can also set a custom session name with the setName
method:
$session->setName('oRILZgj1i94DNaAUotusSOCR7WvymbaLSMOxYhNF');
Retrieve session data
To get a single session value, you may use the get
method. This method will return the value of the session data
element, or null
by default if the value is not present:
$session->get('key');
You may pass a default value as the second argument to the get
method. This value will be returned if the session
value does not exist:
$session->get('key', 'default');
If you would like to get all the session data, you can use the all
method:
$session->all();
Store session data
To store a session value, you may use the set
method:
$session->set('key', 'value');
If you want to push a value onto an array session value, you may use the add
method:
$session->add('data.key', 'value');
Determine if session data exists
To determine if a session value is present, you may use the has
method. The has
method will return true
if the
session value exists:
$session->has('key');
Remove session data
If you would like to remove a session value, you may use the remove
method. The remove
method will remove the value
of the session data element if it exists:
$session->remove('key');
You may also delete multiple session values at once by passing an array of keys to the removeMultiple
method:
$session->removeMultiple(['key', 'anotherKey']);
To remove all session values, you may use the flush
method:
$session->flush();
Migrate session
If you want to generate a new session ID, you may use the migrate
method:
$session->migrate();
If you also want to destroy the existing session data, pass true
as an argument to the migrate
method:
$session->migrate(true);
Regenerate session
To regenerate the session token, you may use the regenerate
method:
$session->regenerate();
If you also want to destroy the existing session data, pass true
as an argument to the regenerate
method:
$session->regenerate(true);
Invalidate session
The invalidate
method will flush all session data and regenerates the session ID:
$session->invalidate();
Save session
The save
method will clear all flash data, serialize the session data, and write them to the session storage:
$session->save();
Flash session data
The session repository comes with a flash data feature. Flash data are session values that will be available for the next request only. After the next request, the flash data will be deleted automatically. Flash data are useful for short-lived messages like "Item has been successfully deleted".
To store a flash value, you may use the flash
method:
$session->flash('success', 'Item has been successfully deleted');
If you want to persist the flash data only for the current request, you may use the now
method:
$session->now('success', 'Item has been successfully deleted');
To store your flash data for an additional request, you may use the reflash
method:
$session->reflash();
To keep specific flash data for an additional request, you may use the keep
method:
$session->keep(['success']);
To clear all flash data, you may use the clearFlashData
method. This method will also be called when you are using
the save
method:
$session->clearFlashData();
The flash session data are stored in the session data under the _flash
key. The _flash
key is reserved and should
not be used for other session data!
Flash input data
The session repository also provides some handy methods to store input data. Input data are session values that will be available for the next request only. After the next request, the input data will be deleted automatically. Input data are useful for short-lived input data like form data.
To store the input data for the next request, you may use the flashInput
method:
$session->flashInput(['username' => 'JohnDoe']);
If you want to get the old input data for a specific key, you may use the getOldInput
method. If the old input data
for the given key does not exist, the getOldInput
method will return null
as the default value:
$session->getOldInput('username');
You may pass a default value as the second argument to the getOldInput
method. This value will be returned if the old
input data for the given key does not exist:
$session->getOldInput('username', 'default');
To determine if the session has old input data, you may use the hasOldInput
method:
$session->hasOldInput('username');
The flash input data are stored in the session data under the _input
key. The _input
key is reserved and should
not be used for other session data!
Session handler
To get the instance of the provided session handler, you may use the getHandler
method:
$session->getHandler();
Encrypt session data
The session repository also allows you to encrypt the session data. To encrypt the session data, you have to pass an
instance of the Zaphyr\Encrypt\Encrypt
class to the constructor of the Zaphyr\Session\EncryptedSession
instance.
The constructor of the Zaphyr\Encrypt\Encrypt
class expects the encryption key and the encryption algorithm as
arguments.
You can read more about the encryption in the encryption repository. After you
have configured the encryption, you can use the Zaphyr\Session\EncryptedSession
instance as usual:
$encryptor = new Zaphyr\Encrypt\Encrypt('OOQPAgC4tA7NanCiVCa1QN5BiRDpdQZR', 'AES-256-CBC');
$handler = new Zaphyr\Session\Handler\FileHandler('/path/to/storage');
$session = new Zaphyr\Session\EncryptedSession('encrypted_session', $handler, $encryptor);
Session handlers
The session handlers define how the session data is stored and retrieved. The session repository comes shipped with a file and database session handler. You can also create your custom session handler if you want to store the session data in a custom way.
File session handler
The Zaphyr\Session\Handler\FileHandler
stores the session data in a file on the server. Pass the path to the storage,
where the session data should be stored to the constructor, and you're good to go:
$handler = new Zaphyr\Session\Handler\FileHandler('/path/to/storage');
The file handler does not create the storage directory automatically. You have to create the directory manually. Also, the storage directory must be writable by the web server!
Configuring the file handler session lifetime
By default, the file handler will set the lifetime of the session to 60 minutes. However, you can set the lifetime
to a different value by passing the minutes
parameter to the constructor:
$handler = new Zaphyr\Session\Handler\FileHandler('/path/to/storage', minutes: 120);
Database session handler
The Zaphyr\Session\Handler\DatabaseHandler
stores the session data in a database. The database handler fits perfect,
if you serve your application on multiple servers, and want to share the session data between the servers.
When using the database handler, you will need to create a table to store the session data. Below is an example of a table that can be used to store the session data in a MySQL database:
CREATE TABLE `sessions`
(
`id` VARBINARY(128) NOT NULL PRIMARY KEY,
`data` TEXT NOT NULL,
`time` INTEGER UNSIGNED NOT NULL
) COLLATE utf8mb4_bin, ENGINE = InnoDB;
The database handler requires a Doctrine\DBAL\Connection
instance, which is used to store and retrieve the session
data. You can create a connection instance by using the Doctrine\DBAL\DriverManager
class:
$connectionParams = [
'dbname' => 'mydb',
'user' => 'user',
'password' => 'secret',
'host' => 'localhost',
'driver' => 'pdo_mysql',
];
$connection = Doctrine\DBAL\DriverManager::getConnection($connectionParams);
$handler = new Zaphyr\Session\Handler\DatabaseHandler($connection);
You can read more about doctrine database connections in the Doctrine documentation.
Configuring the database table and column names
The table used to store the session data is called sessions
by default and defines certain column names. However, you
can change the table and column names by passing an dbOptions
array parameter to the constructor:
$dbOptions = [
'timeColumn' => 'lifetime',
];
$handler = new Zaphyr\Session\Handler\DatabaseHandler($connection, dbOptions: $dbOptions);
These are the parameters that you can configure:
-
table
: The name of the table where to store the session data (default issessions
). -
idColumn
: The name of the field where to store the session ID (default isid
). -
dataColumn
: The name of the field where to store the session data (default isdata
). -
timeColumn
: The name of the field where to store the session lifetime (default istime
).
Configuring the database handler session lifetime
By default, the database handler will set the lifetime of the session to 60 minutes. However, you can set the
lifetime to a different value by passing the minutes
parameter to the constructor:
$handler = new Zaphyr\Session\Handler\DatabaseHandler($connection, minutes: 120);
Array session handler
Available since v1.1.0
The session repository also comes shipped with an array session handler, which stores the session data in an array and prevent the session data from being persisted. The array session handler is useful for testing purposes:
$handler = new Zaphyr\Session\Handler\ArrayHandler(minutes: 120);
Custom session handler
If none of the provided session handlers fits your needs, you can create your own custom session handler. To create a
custom session handler, you will need to implement PHP's built in SessionHandlerInterface
. You do not need to do any
serialization when retrieving or storing session data, as the session repository will perform the serialization for you.
class MyCustomHandler implements SessionHandlerInterface
{
/**
* {@inheritdoc}
*/
public function open(string $path, string $name): bool
{
// …
}
/**
* {@inheritdoc}
*/
public function close(): bool
{
// …
}
/**
* {@inheritdoc}
*/
public function read(string $id): string|false
{
// …
}
/**
* {@inheritdoc}
*/
public function write(string $id, string $data): bool
{
// …
}
/**
* {@inheritdoc}
*/
public function destroy(string $id): bool
{
// …
}
/**
* {@inheritdoc}
*/
public function gc(int $max_lifetime): int|false
{
// …
}
}
Session manager
The session repository comes shipped with a session manager, which makes it easy to create and manage sessions. Instead of creating a session instance manually, you can use the session manager to create sessions. The session manager also makes it easy to change the session handler, and to set the session lifetime. The session manager requires a session name and an array of session handler options. The session name is used to identify the session, and the session handler options are used to create the session handler. Below is an example of how to create a session manager:
$sessionName = 'my_session';
$handlerOptions = [
Zaphyr\Session\SessionManager::DATABASE_HANDLER => [
'connection' => [
'dbname' => 'mydb',
'user' => 'user',
'password' => 'secret',
'host' => 'localhost',
'driver' => 'pdo_mysql',
],
//'options' => [
// 'table' => 'sessions',
// 'idColumn' => 'id',
// 'dataColumn' => 'data',
// 'timeColumn' => 'time',
//],
],
Zaphyr\Session\SessionManager::FILE_HANDLER => [
'path' => __DIR__ . '/storage',
],
]
$sessionManager = new Zaphyr\Session\SessionManager($sessionName, $handlerOptions);
The database handler requires a connection
configuration, which is used to create
a database connection. Optionally, you can pass an options
array to the database handler configuration, which is used
to configure the database table and column names.
The file handler requires a path
configuration, which is used to store the session
data. You can read more about the session handler options in the session handler section.
Start a session
After you have created the session manager, you can start a session by calling the session()
method. The session()
method accepts an optional parameter, which specifies the session handler to use. If no session handler is specified,
the session manager will use the default session handler (Zaphyr\Session\Handler\FileHandler
by default).
The session()
method will return an instance of Zaphyr\Session\Contracts\SessionInterface
.
$session = $sessionManager->session();
To get a specific session handler, you can pass the session handler name to the session()
method:
$session = $sessionManager->session(Zaphyr\Session\SessionManager::DATABASE_HANDLER);
Change the default session expiration time
By default, the session manager will set the expiration time to 60 minutes. If you want to set a different expiration
time, you can pass the sessionExpireMinutes
parameter to the constructor:
$sessionManager = new Zaphyr\Session\SessionManager($sessionName, $handlerOptions, sessionExpireMinutes: 120);
Change the default session handler
The default session handler is the Zaphyr\Session\Handler\FileHandler
. However, you can change the default session
handler by passing the defaultHandler
parameter to the constructor:
$sessionManager = new Zaphyr\Session\SessionManager(
$sessionName,
$handlerOptions,
defaultHandler: Zaphyr\Session\SessionManager::DATABASE_HANDLER
);
Encrypt the session data
To encrypt the session data, you will need to pass an instance of the Zaphyr\Encrypt\Encrypt
class to the constructor.
Now the session data will be encrypted before it is stored in the session, and decrypted when it is retrieved:
$encryptor = new Zaphyr\Encrypt\Encrypt('OOQPAgC4tA7NanCiVCa1QN5BiRDpdQZR', 'AES-256-CBC');
$sessionManager = new Zaphyr\Session\SessionManager($sessionName, $handlerOptions, encryptor: $encryptor);
Add custom session handler
We already learned how to create a custom session handler. To use the custom session
handler on the session manager, you will need to add it to the session manager. You can add a custom session handler by
using the addHandler
. The first parameter is the name of the handler, and the second parameter is a callback that
returns an instance of the custom session handler:
$sessionManager->addHandler('custom_handler', fn () => new MyCustomHandler());
After you have added the custom session handler, you can use it by passing the name of the handler to the session
method:
$sessionManager->session('custom_handler');