Skip to content
虚位以待
虚位以待
赞助商
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待

会话

介绍

由于 HTTP 驱动的应用程序是无状态的,会话提供了一种在请求之间存储用户信息的方法。Laravel 提供了多种会话后端,通过一个干净、统一的 API 可供使用。支持流行的后端如 MemcachedRedis 和数据库的支持是开箱即用的。

配置

会话配置文件存储在 config/session.php。请务必查看此文件中提供的详细文档选项。默认情况下,Laravel 配置为使用 file 会话驱动,这对于许多应用程序来说都能很好地工作。在生产应用程序中,您可以考虑使用 memcachedredis 驱动以获得更快的会话性能。

会话 driver 定义了每个请求的会话数据将存储在哪里。Laravel 开箱即用地提供了几个很好的驱动:

  • file - 会话存储在 storage/framework/sessions
  • cookie - 会话存储在安全、加密的 cookie 中。
  • database - 会话存储在应用程序使用的数据库中。
  • memcached / redis - 会话存储在这些快速的基于缓存的存储中。
  • array - 会话存储在一个简单的 PHP 数组中,不会在请求之间持久化。

NOTE

数组驱动通常用于运行测试,以防止会话数据持久化。

驱动前提条件

数据库

使用 database 会话驱动时,您需要设置一个表来包含会话项。以下是表的 Schema 声明示例:

php
Schema::create('sessions', function ($table) {
    $table->string('id')->unique();
    $table->text('payload');
    $table->integer('last_activity');
});

您可以使用 session:table Artisan 命令为您生成此迁移!

php
php artisan session:table

composer dump-autoload

php artisan migrate

Redis

在使用 Laravel 的 Redis 会话之前,您需要通过 Composer 安装 predis/predis 包 (~1.0)。

其他会话注意事项

Laravel 框架内部使用 flash 会话键,因此您不应通过该名称向会话添加项。

如果您需要加密所有存储的会话数据,请将 encrypt 配置选项设置为 true

基本用法

访问会话

首先,让我们访问会话。我们可以通过 HTTP 请求访问会话实例,可以在控制器方法中进行类型提示。请记住,控制器方法依赖项是通过 Laravel 服务容器注入的:

php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * 显示给定用户的个人资料。
     *
     * @param  Request  $request
     * @param  int  $id
     * @return Response
     */
    public function showProfile(Request $request, $id)
    {
        $value = $request->session()->get('key');

        //
    }
}

当您从会话中检索值时,您还可以将默认值作为 get 方法的第二个参数传递。如果指定的键不存在于会话中,将返回此默认值。如果您将 Closure 作为默认值传递给 get 方法,则将执行 Closure 并返回其结果:

php
$value = $request->session()->get('key', 'default');

$value = $request->session()->get('key', function() {
    return 'default';
});

如果您想从会话中检索所有数据,可以使用 all 方法:

php
$data = $request->session()->all();

您还可以使用全局 session PHP 函数在会话中检索和存储数据:

php
Route::get('home', function () {
    // 从会话中检索一条数据...
    $value = session('key');

    // 在会话中存储一条数据...
    session(['key' => 'value']);
});

确定会话中是否存在某项

has 方法可用于检查会话中是否存在某项。如果该项存在,此方法将返回 true

php
if ($request->session()->has('users')) {
    //
}

在会话中存储数据

一旦您可以访问会话实例,您可以调用各种函数来与底层数据进行交互。例如,put 方法在会话中存储一条新数据:

php
$request->session()->put('key', 'value');

推送到数组会话值

push 方法可用于将新值推送到会话值的数组中。例如,如果 user.teams 键包含一个团队名称数组,您可以像这样将新值推送到数组中:

php
$request->session()->push('user.teams', 'developers');

检索并删除一项

pull 方法将从会话中检索并删除一项:

php
$value = $request->session()->pull('key', 'default');

从会话中删除项

forget 方法将从会话中删除一条数据。如果您想删除会话中的所有数据,可以使用 flush 方法:

php
$request->session()->forget('key');

$request->session()->flush();

重新生成会话 ID

如果您需要重新生成会话 ID,可以使用 regenerate 方法:

php
$request->session()->regenerate();

闪存数据

有时您可能希望仅在下一个请求中存储会话中的项。您可以使用 flash 方法来实现。使用此方法存储在会话中的数据仅在后续的 HTTP 请求中可用,然后将被删除。闪存数据主要用于短期状态消息:

php
$request->session()->flash('status', '任务成功完成!');

如果您需要在更多请求中保留闪存数据,可以使用 reflash 方法,这将使所有闪存数据在额外的请求中保留。如果您只需要保留特定的闪存数据,可以使用 keep 方法:

php
$request->session()->reflash();

$request->session()->keep(['username', 'email']);

添加自定义会话驱动

要向 Laravel 的会话后端添加其他驱动,您可以在 Session facade 上使用 extend 方法。您可以从服务提供者boot 方法中调用 extend 方法:

php
<?php

namespace App\Providers;

use Session;
use App\Extensions\MongoSessionStore;
use Illuminate\Support\ServiceProvider;

class SessionServiceProvider extends ServiceProvider
{
    /**
     * 执行服务的注册后引导。
     *
     * @return void
     */
    public function boot()
    {
        Session::extend('mongo', function($app) {
            // 返回 SessionHandlerInterface 的实现...
            return new MongoSessionStore;
        });
    }

    /**
     * 在容器中注册绑定。
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

请注意,您的自定义会话驱动应实现 SessionHandlerInterface。此接口仅包含几个简单的方法需要我们实现。一个存根的 MongoDB 实现看起来像这样:

php
<?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) {}
}

由于这些方法不像缓存 StoreInterface 那样容易理解,让我们快速了解每个方法的作用:

  • open 方法通常用于基于文件的会话存储系统。由于 Laravel 附带了一个 file 会话驱动,您几乎不需要在此方法中放置任何内容。您可以将其留为空存根。这只是 PHP 需要我们实现此方法的糟糕接口设计的一个事实(我们稍后会讨论)。
  • close 方法,像 open 方法一样,通常也可以忽略。对于大多数驱动,它是不需要的。
  • read 方法应返回与给定 $sessionId 关联的会话数据的字符串版本。检索或存储会话数据时,无需在驱动中进行任何序列化或其他编码,因为 Laravel 会为您执行序列化。
  • write 方法应将与 $sessionId 关联的给定 $data 字符串写入某个持久存储系统,例如 MongoDB、Dynamo 等。
  • destroy 方法应从持久存储中删除与 $sessionId 关联的数据。
  • gc 方法应销毁所有比给定 $lifetime(UNIX 时间戳)更旧的会话数据。对于自我过期系统如 Memcached 和 Redis,此方法可以留空。

一旦会话驱动注册,您可以在 config/session.php 配置文件中使用 mongo 驱动。