简介
由于 HTTP 驱动的应用是无状态的,session 提供了一种在多个请求中保存用户信息的方式。Laravel 提供的多种后端可以通过丰富、统一的 API 进行调用。默认支持像 Memcached、Redis、以及数据库等流行的后端驱动。
配置
Session 配置文件存储在 config/session.php。记得查看一下该配置文件中对你可用的选项。默认情况下,Laravel 使用 file session 驱动,它对于大多数应用来说都是可用的。在生产环境的应用中,你可以考虑使用性能更好的 memcached 或 redis 驱动。
Session 的 driver 配置项定义了在哪里存储每个请求的 session 数据。Laravel 提供了几个开机即用的非常棒的驱动:
file– session 存储在storage/framework/sessions。cookie– session 存储在安全、加密的 cookie 中。database– session 存储在关系型数据库中。memcached / redis– sessions 保存在其中一个快速且基于缓存的存储系统中。array– session 存储在 PHP 数组中,但不是持久化的。
array 驱动一般用于测试,阻止数据被持久化的存储在 session 中。
驱动先决条件
数据库
当使用 database session 驱动时,你需要创建一个包含 session 元素的数据表,下面是对这个表的 Schema 声明的例子:
Schema::create('sessions', function ($table) {
$table->string('id')->unique();
$table->integer('user_id')->nullable();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->text('payload');
$table->integer('last_activity');
});你可以使用 session:table Artisan 命令来生成这个迁移:
php artisan session:table php artisan migrate
Redis
在 Laravel 中使用 Redis 驱动前,你需要通过 Composer 安装 predis/predis 包(~1.0)。你可以在 database 配置文件中配置你的 redis 连接项。在 session 配置文件中,connection 配置项可以用来指定使用哪个 redis 链接存储 session。
使用 Session
获取数据
Laravel 中有两种主要的方式来操作 session 数据:通过 session 全局辅助函数及 Request 实例。首先我们来看下使用 Request 实例来访问 session 数据,它可以通过数据库方法进行类型提示。控制器方法依赖会通过 Laravel 的服务容器自动注入:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* Show the profile for the given user.
*
* @param Request $request
* @param int $id
* @return Response
*/
public function show(Request $request, $id)
{
$value = $request->session()->get('key');
//
}
}当你从 session 中获取值的时候,你还可以给 get 方法传递第二个参数作为默认值。当指定的 key 在 session 中不存在时会返回默认值。如果你给 get 方法传递一个 Closure 作为默认值,并且请求的 key 不存在,Closure 将会被执行并返回其结果:
$value = $request->session()->get('key', 'default');
$value = $request->session()->get('key', function() {
return 'default';
});全局 session 辅助函数
你还可以使用全局的 session 辅助函数在 session 中获取及存储数据。当只给 session 辅助函数传递一个字符串参数时,当给其传递一个 key / value 键值对进行调用时,那些值将会被被存储到 session 中:
Route::get('home', function () {
// Retrieve a piece of data from the session...
$value = session('key');
// Specifying a default value...
$value = session('key', 'default');
// Store a piece of data in the session...
session(['key' => 'value']);
});session 辅助函数之间几乎没有任何不同。两个方法都是可以通过assertSessionHas 测试的,它在任何测试案例中都可用。获取所有 session 数据
如果你想获取 session 中的所有数据,你可以使用 all 方法:
$data = $request->session()->all();
判断一个项是否在 session 中存在
要判断一个值是否在 session 中设置了,你可以使用 has 方法。如果值存在则 has 方法会返回 true,否则会返回 false:
if ($request->session()->has('users')) {
//
}要判断一个值是否在 session 设置了,甚至它的值是 null,你可以使用 exist 方法,当值设置了时,exist 方法会返回 true:
if ($request->session()->exists('users')) {
//
}存储数据
要在 session 中存储数据,一般可以使用 put 方法或全局的 session 辅助方法:
// 通过请求实例
$request->session()->put('key', 'value');
// 通过全局辅助方法
session(['key' => 'value']);向 session 数组中添加数据
push 方法可以向数组 session 值中添加数据。例如,如果 user.teams 键中包含了一个团队名称的数组,你可以这样向数组中添加新的值:
$request->session()->push('user.teams', 'developers');取出并删除一项
使用 pull 方法可以从 session 中取出一项并删除:
$value = $request->session()->pull('key', 'default');闪存数据
有时你可能希望向 session 中存储一些只在下个请求中可用的数据,你可以使用 flash 方法来实现。使用该方法存储在 session 中的数据只在下个 HTTP 请求中有效,之后将被删除。闪存数据主要用来存储一些短期内有效的状态信息:
$request->session()->flash('status', 'Task was successful!');如果你需要在几个请求内保持闪存数据,你可以使用 reflush 方法,它将为一个额外的请求保存所有的闪存数据。如果你只想保持指定的闪存数据,你可以使用 keep 方法:
$request->session()->reflash(); $request->session()->keep(['username', 'email']);
删除数据
forget 方法可以从 session 中删除一条数据。如果你想删除 session 中的所有数据,你可以使用 flush 方法:
$request->session()->forget('key');
$request->session()->flush();重新生成 session ID
重新生成 Session ID 可以阻止恶意用户利用 session fixation 对你的应用进行攻击。
如果你使用内置 LoginController 的话,Laravel 会在用户认证时自动重新生成 Session ID。然而,如果你需要手动重新生成 Session ID,你可以使用 regenerate 方法:
$request->session()->regenerate();
添加自定义 Session 驱动
实现驱动
你的自定义 session 驱动需要实现 SessionHandlerInterface。这个接口包含了一些我们需要实现的简单的方法。MongoDB 的实现差不多是这样的:
<?php
namespace App\Extensions;
class MongoHandler 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) {}
}Laravel 没有提供包含扩展的文件夹。你可以根据自己的喜好来存放它们。在这个例子中,我们创建一个 Extensions 文件夹来存放 MongoHandler。
由于这些方法的意图并不是很容易理解,我们来快速看一下每个方法的作用:
open方法一般用于基于文件的 session 存储系统。由于 Laravel 提供了file驱动,所以你不需要在这个方法中做任何操作。你可以让它保持是空的。这是一个弱的接口设计(我们后面会讨论),PHP 要求我们实现该方法。close方法,同open方法一样,一般不需要理会。对于大多数驱动,它都是不需要的。read方法需要返回与给定的$sessionId相关的 session 数据的字符串版本。不需要做序列化或任何其他编码,因为 Laravel 已经为我们执行了序列化。write方法应该把给定的$data字符串与$sessionId关联持续化到存储系统,例如 MongoDB、Dynamo 等。再次强调,你不需要执行任何序列化 – Laravel 已经为我们处理了。destroy方法需要从存储系统删除所有与$sessionId相关的数据。gc方法需要删除所有比给定的$lifetime(Unix 时间戳)早的数据。对于自动过期的系统,如 Memcached 和 Redis,这个方法可以留空。
注册驱动
当你的驱动实现后,你就可以在框架中注册它了。要向 Laravel 的 session 后端添加额外的驱动,你可以使用 Session facade 的 extend 方法。你需要在服务提供者的 boot 方法中调用 extend 方法,你可以在已存在的 AppServiceProvider 中或创建一个新的提供者:
<?php
namespace App\Providers;
use App\Extensions\MongoSessionStore;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\ServiceProvider;
class SessionServiceProvider extends ServiceProvider
{
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot()
{
Session::extend('mongo', function($app) {
// Return implementation of SessionHandlerInterface...
return new MongoSessionStore;
});
}
/**
* Register bindings in the container.
*
* @return void
*/
public function register()
{
//
}
}当 session 驱动注册后,你可以在 config/session.php 中使用 mongo 驱动。
该篇属于专题:《Laravel 5.3 中文文档》