Вступление

Поскольку приложения, управляемые HTTP, не сохраняют состояния, сеансы предоставляют способ хранения информации о пользователе по нескольким запросам. Laravel поставляется с различными сессиями, доступ к которым осуществляется через выразительный унифицированный API. Поддержка популярных бэкэндов, таких как Memcached , Redis и базы данных, включена в комплект поставки.

 

Конфигурация

Файл конфигурации сеанса хранится в . Обязательно ознакомьтесь с опциями, доступными вам в этом файле. По умолчанию Laravel настроен на использование драйвера сеанса, который будет хорошо работать для многих приложений. В производственных приложениях вы можете рассмотреть возможность использования драйверов или для еще большей производительности сеанса.config/session.phpfilememcachedredis

Параметр driverконфигурации сеанса определяет, где будут храниться данные сеанса для каждого запроса. Laravel поставляется с несколькими отличными водителями из коробки:

  • file- сеансы хранятся в .storage/framework/sessions
  • cookie - сеансы хранятся в безопасных, зашифрованных куки.
  • database - сеансы хранятся в реляционной базе данных.
  • memcachedredis- сессии хранятся в одном из этих быстрых хранилищ на основе кэша.
  • array - сеансы хранятся в массиве PHP и не будут сохраняться.

Драйвер массива используется во время тестирования и предотвращает сохранение данных, хранящихся в сеансе.

 

Необходимые условия для водителя

База данных

При использовании databaseдрайвера сеанса вам нужно будет создать таблицу, содержащую элементы сеанса. Ниже приведен пример Schemaобъявления для таблицы:

Schema::create('sessions', function ($table) {
    $table->string('id')->unique();
    $table->unsignedInteger('user_id')->nullable();
    $table->string('ip_address', 45)->nullable();
    $table->text('user_agent')->nullable();
    $table->text('payload');
    $table->integer('last_activity');
});

Вы можете использовать команду Artisan для генерации этой миграции:session:table

php artisan session:table

php artisan migrate

Redis

Перед использованием сеансов Redis с Laravel вам необходимо установить пакет (~ 1.0) через Composer. Вы можете настроить подключения Redis в файле конфигурации. В файле конфигурации эта опция может использоваться, чтобы указать, какое соединение Redis используется сеансом.predis/predisdatabasesessionconnection

 

Использование сессии

Извлечение данных

Существует два основных способа работы с данными сеанса в Laravel: глобальный sessionпомощник и Requestэкземпляр. Во-первых, давайте посмотрим на доступ к сеансу через Requestэкземпляр, который может быть подсказан типом в методе контроллера. Помните, зависимости метода контроллера автоматически вводятся через сервисный контейнер 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');

        //
    }
}

Когда вы извлекаете элемент из сеанса, вы также можете передать значение по умолчанию в качестве второго аргумента getметода. Это значение по умолчанию будет возвращено, если указанный ключ не существует в сеансе. Если вы передадите a Closureв качестве значения по умолчанию getметоду, а запрошенный ключ не существует, Closureон будет выполнен и его результат будет возвращен:

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

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

Глобальный Помощник Сессии

Вы также можете использовать глобальную sessionфункцию PHP для извлечения и хранения данных в сеансе. Когда 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']);
});

Существует небольшая практическая разница между использованием сеанса через экземпляр HTTP-запроса и использованием глобального sessionпомощника. Оба метода тестируются с помощью assertSessionHasметода, который доступен во всех ваших тестовых случаях.

Получение всех данных сеанса

Если вы хотите получить все данные в сеансе, вы можете использовать allметод:

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

Определение, существует ли элемент в сеансе

Чтобы определить, присутствует ли элемент в сеансе, вы можете использовать hasметод. hasМетод возвращает , trueесли элемент присутствует и не null:

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

Чтобы определить, присутствует ли элемент в сеансе, даже если его значение равно null, вы можете использовать existsметод. existsМетод возвращает , trueесли элемент присутствует:

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

 

Хранение данных

Для хранения данных в сеансе вы обычно будете использовать putметод или sessionпомощника:

// Via a request instance...
$request->session()->put('key', 'value');

// Via the global helper...
session(['key' => 'value']);

Нажатие на массив значений сеанса

Этот pushметод может использоваться для помещения нового значения в значение сеанса, которое является массивом. Например, если ключ содержит массив имен команд, вы можете вставить новое значение в массив следующим образом:user.teams

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

Извлечение и удаление предмета

pullМетод извлечения и удаления элемента из сессии в одном заявлении:

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

 

Flash-данные

Иногда вы можете захотеть хранить элементы в сеансе только для следующего запроса. Вы можете сделать это, используя flashметод. Данные, сохраненные в сеансе с использованием этого метода, будут доступны только во время последующего HTTP-запроса, а затем будут удалены. Данные Flash в первую очередь полезны для кратковременных сообщений о состоянии:

$request->session()->flash('status', 'Task was successful!');

Если вам необходимо хранить данные флэш-памяти для нескольких запросов, вы можете использовать reflashметод, который сохранит все данные флэш-памяти для дополнительного запроса. Если вам нужно только сохранить определенные данные флэш-памяти, вы можете использовать keepметод:

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

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

 

Удаление данных

forgetМетод будет удалить часть данных из сеанса. Если вы хотите удалить все данные из сеанса, вы можете использовать flushметод:

// Forget a single key...
$request->session()->forget('key');

// Forget multiple keys...
$request->session()->forget(['key1', 'key2']);

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

 

Восстановление идентификатора сеанса

Регенерация идентификатора сеанса часто выполняется для того, чтобы предотвратить использование атакой фиксации сеанса в вашем приложении злонамеренными пользователями .

Laravel автоматически восстанавливает идентификатор сеанса во время аутентификации, если вы используете встроенный LoginController; однако, если вам нужно вручную восстановить идентификатор сеанса, вы можете использовать этот regenerateметод.

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

 

Добавление пользовательских драйверов сеансов

Реализация драйвера

Ваш пользовательский драйвер сеанса должен реализовать SessionHandlerInterface. Этот интерфейс содержит всего несколько простых методов, которые нам нужно реализовать. Описанная реализация MongoDB выглядит примерно так:

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

Laravel не поставляется с каталогом, содержащим ваши расширения. Вы можете разместить их где угодно. В этом примере мы создали Extensionsкаталог для размещения MongoSessionHandler.

Поскольку цель этих методов не совсем понятна, давайте быстро рассмотрим, что делает каждый из методов:

  • Этот openметод обычно используется в файловых системах хранения сеансов. Поскольку Laravel поставляется с fileдрайвером сеанса, вам почти никогда не нужно ничего добавлять в этот метод. Вы можете оставить это как пустую заглушку. Фактом плохого дизайна интерфейса (о котором мы поговорим позже) является то, что PHP требует от нас реализации этого метода.
  • closeМетод, как openметод, можно также , как правило , можно пренебречь. Для большинства водителей это не нужно.
  • readМетод должен возвращать версию строки данных сеанса , связанные с данными $sessionId. При извлечении или сохранении данных сеанса в вашем драйвере нет необходимости выполнять сериализацию или другую кодировку, поскольку Laravel выполнит сериализацию за вас.
  • writeМетод должен написать данную $dataстроку , связанную с $sessionIdкакой - то постоянной системой хранения, такими как MongoDB, Динамо и т.д. Опять же , вы не должны выполнять какую - либо сериализации - Laravel будет уже обработан , что для вас.
  • destroyМетод должен удалить данные , связанные с $sessionIdот постоянного хранения.
  • gcМетод должен уничтожить все данные сеанса, которое старше , чем данные $lifetime, который является меткой времени UNIX. Для самодействующих систем, таких как Memcached и Redis, этот метод можно оставить пустым.

 

Регистрация водителя

Как только ваш драйвер был реализован, вы готовы зарегистрировать его в фреймворке. Чтобы добавить дополнительные драйверы в бэкэнд сессии Laravel, вы можете использовать extendметод на Session фасаде . Вы должны вызывать extendметод из bootметода поставщика услуг . Вы можете сделать это из существующего AppServiceProviderили создать совершенно нового поставщика:

<?php

namespace App\Providers;

use App\Extensions\MongoSessionHandler;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\ServiceProvider;

class SessionServiceProvider extends ServiceProvider
{
    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Session::extend('mongo', function ($app) {
            // Return implementation of SessionHandlerInterface...
            return new MongoSessionHandler;
        });
    }
}

После того, как драйвер сеанса был зарегистрирован, вы можете использовать mongoдрайвер в вашем файле конфигурации.config/session.php