Laravel 会话管理:自定义会话驱动
问题
我可以在 Laravel 中自定义会话驱动么?假如我想实现自己的 MongoDB 会话驱动,该怎么做?
回答
在 Laravel 中是允许自定义会话驱动的,下面我们讲解下实现一个 MongoDB 会话驱动的大致流程。
创建驱动
首先,自定义会话驱动须实现 SessionHandlerInterface
接口。这个接口包含几个我们需要实现的简单方法:
SessionHandlerInterface {
/* Methods */
abstract public close ( void ) : bool
abstract public destroy ( string $session_id ) : bool
abstract public gc ( int $maxlifetime ) : int
abstract public open ( string $save_path , string $session_name ) : bool
abstract public read ( string $session_id ) : string
abstract public write ( string $session_id , string $session_data ) : bool
}
因为 Laravel 默认并不包含用于存放扩展的目录,所以我们先在项目 app
目录下创建一个 Extensions
子目录用于存放我们的 MongoDB 会话驱动,然后在该目录下创建一个 MongoSessionHandler.php
文件,其内容如下:
app\Extensions\MongoSessionHandler.php
<?php
namespace App\Extensions;
class MongoSessionHandler implements \SessionHandlerInterface
{
public function open($savePath, $sessionName) {}
public function close() {}
public function read($sessionId) {}
public function write($sessionId, $data) {}
public function destroy($sessionId) {}
public function gc($lifetime) {}
}
我们简单介绍下每一个方法:
open方法
通常用于基于文件的 Session 存储系统。因为 Laravel 已经附带了一个 file
会话驱动。所以你不需要在该方法中放置任何代码。但 PHP 要求必须实现这个方法,所以你只需要把这个方法简单的置空就好了。
close
方法
跟 open
方法相似,通常也可以置空。对大多数的驱动而言,此方法不是必须的。
read
方法
应当返回字符串格式的与给定的 $sessionId
相匹配的会话数据。在你的自定义的驱动中读写会话数据时,不需要进行任何序列化或者其他编转码操作,Laravel 会自动为你执行序列化。
write
方法
将与 $sessionId
关联的给定的 $data
字符串写入到持久化存储系统中。同样,你不需要进行任何序列化或其他编转码操作,Laravel 会自动为你处理这些事情。
destroy
方法
从持久化存储中删除与 $sessionId
相关的数据。
gc
方法
销毁给定的 $lifetime
(UNIX 的时间戳)之前的所有数据。对本身拥有过期机制的系统如 Memcached 和 Redis 而言,该方法可以置空。
更详细的说明,请参阅 SessionHandlerInterface 接口的 PHP 文档。
注册驱动
当实现驱动后,还需要在框架中注册它。注册需要使用 Session
门面 的 extend
方法。通常应在 服务提供者 中的 boot
方法中调用 extend
方法。
我们在 app\Providers
目录中创建一个 SessionServiceProvider.php
文件,内容如下:
app\Providers\SessionServiceProvider.php
<?php
namespace App\Providers;
use App\Extensions\MongoSessionHandler;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\ServiceProvider;
class SessionServiceProvider extends ServiceProvider
{
/**
* 执行服务的注册后启动
*
* @return void
*/
public function boot()
{
Session::extend('mongo', function ($app) {
// 返回实现 SessionHandlerInterface 的对象
return new MongoSessionHandler;
});
}
/**
* 在容器中注册绑定关系
*
* @return void
*/
public function register()
{
//
}
}
可以看到,extend
方法的第一个参数指定驱动名,第二个参数接受一个回调函数,返回我们实现 SessionHandlerInterface
的对象。
如果不想新建服务提供者,也可以在已有的
AppServiceProvider
服务提供者(app\Providers\AppServiceProvider.php
)中注册驱动。
驱动注册完成后,最后在配置文件 config/session.php
设置会话使用自定义的 mongo
驱动读写数据就可以啦:
'driver' => env('SESSION_DRIVER', 'mongo'),