Laravel 会话管理:自定义会话驱动 1 个改进

问题

我可以在 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'),

参考

本文为 Wiki 文章,邀您参与纠错、纰漏和优化
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!