Description

Workerman has enhanced support for HTTP services since version 4.x. It introduces request classes, response classes, session classes, and SSE. If you want to use Workerman's HTTP services, it is strongly recommended to use Workerman 4.x or later versions.

Note that the following are usages for Workerman 4.x and are not compatible with Workerman 3.x.

Change the Session Storage Engine

Workerman provides file storage engine and redis storage engine for sessions. The default is to use the file storage engine. If you want to change to the redis storage engine, please refer to the following code.

<?php
use Workerman\Worker;
use Workerman\Protocols\Http\Session;
use Workerman\Protocols\Http\Session\RedisSessionHandler;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('http://0.0.0.0:8080');

// redis configuration
$config = [
    'host'     => '127.0.0.1', // required parameter
    'port'     => 6379,        // required parameter
    'timeout'  => 2,           // optional parameter
    'auth'     => '******',    // optional parameter
    'database' => 1,           // optional parameter
    'prefix'   => 'session_'   // optional parameter
];
// Use Workerman\Protocols\Http\Session::handlerClass method to change the underlying session handler class
Session::handlerClass(RedisSessionHandler::class, $config);

$worker->onMessage = function(TcpConnection $connection, Request $request)
{
    $session = $request->session();
    $session->set('somekey', rand());
    $connection->send($session->get('somekey'));
};

Worker::runAll();

Set Session Storage Location

When using the default storage engine, session data is stored on disk, with the default location being the return value of session_save_path().
You can use the following method to change the storage location.

use Workerman\Worker;
use \Workerman\Protocols\Http\Session\FileSessionHandler;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
require_once __DIR__ . '/vendor/autoload.php';

// Set session file storage location
FileSessionHandler::sessionSavePath('/tmp/session');

$worker = new Worker('http://0.0.0.0:8080');

$worker->onMessage = function(TcpConnection $connection, Request $request)
{
    $session = $request->session();
    $session->set('name', 'tome');
    $connection->send($session->get('name'));
};

// Run worker
Worker::runAll();

Session File Cleanup

When using the default session storage engine, there will be multiple session files on the disk.
Workerman will clean up expired session files based on the session.gc_probability, session.gc_divisor, and session.gc_maxlifetime options set in php.ini. For explanations of these three options, refer to the PHP manual.

Change Storage Driver

In addition to the file session storage engine and redis session storage engine, Workerman allows you to add new session storage engines through the standard SessionHandlerInterface interface, such as mongoDB session storage engine, MySQL session storage engine, etc.

Steps to add a new session storage engine

  1. Implement the SessionHandlerInterface interface
  2. Use Workerman\Protocols\Http\Session::handlerClass($class_name, $config) method to replace the underlying SessionHandler interface

Implementing SessionHandlerInterface Interface

Custom session storage drivers must implement the SessionHandlerInterface interface. This interface contains the following methods:

SessionHandlerInterface {
    /* Methods */
    abstract public read ( string $session_id ) : string
    abstract public write ( string $session_id , string $session_data ) : bool
    abstract public destroy ( string $session_id ) : bool
    abstract public gc ( int $maxlifetime ) : int
    abstract public close ( void ) : bool
    abstract public open ( string $save_path , string $session_name ) : bool
}

Explanation of SessionHandlerInterface

  • The read method is used to read all session data corresponding to the session_id from storage. Please do not perform deserialization operations on the data; the framework will do this automatically.
  • The write method is used to write session data corresponding to the session_id into storage. Please do not perform serialization operations on the data; the framework has already done this automatically.
  • The destroy method is used to destroy session data corresponding to the session_id.
  • The gc method is used to delete expired session data; storage should delete all sessions with a last modified time greater than maxlifetime.
  • The close method requires no operations; simply return true.
  • The open method requires no operations; simply return true.

Replacing the Underlying Driver

After implementing the SessionHandlerInterface, use the following method to change the underlying session driver.

Workerman\Protocols\Http\Session::handlerClass($class_name, $config);
  • $class_name is the name of the SessionHandler class that implements the SessionHandlerInterface. If there is a namespace, it must include the full namespace.
  • $config is the parameters for the constructor of the SessionHandler class.

Specific Implementation

Note that this MySessionHandler class is only for illustrating the process of changing the underlying session driver, and MySessionHandler cannot be used in production environments.

<?php
use Workerman\Worker;
use Workerman\Protocols\Http\Session;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('http://0.0.0.0:8080');

class MySessionHandler implements SessionHandlerInterface
{
    protected static $store = [];

    public function __construct($config) {
        // ['host' => 'localhost']
        var_dump($config);
    }

    public function open($save_path, $name)
    {
        return true;
    }

    public function read($session_id)
    {
        return isset(static::$store[$session_id]) ? static::$store[$session_id]['content'] : '';
    }

    public function write($session_id, $session_data)
    {
        static::$store[$session_id] = ['content' => $session_data, 'timestamp' => time()];
    }

    public function close()
    {
        return true;
    }

    public function destroy($session_id)
    {
        unset(static::$store[$session_id]);
        return true;
    }

    public function gc($maxlifetime) {
        $time_now = time();
        foreach (static::$store as $session_id => $info) {
            if ($time_now - $info['timestamp'] > $maxlifetime) {
                unset(static::$store[$session_id]);
            }
        }
    }
}

// Suppose the newly implemented SessionHandler class needs some configuration passed in
$config = ['host' => 'localhost'];
// Use Workerman\Protocols\Http\Session::handlerClass($class_name, $config) to change the underlying session driver class
Session::handlerClass(MySessionHandler::class, $config);

$worker->onMessage = function(TcpConnection $connection, Request $request)
{
    $session = $request->session();
    $session->set('somekey', rand());
    $connection->send($session->get('somekey'));
};

Worker::runAll();