HTTP сессии
11.x
.
Почему это важно?
Введение
HTTP-приложения не имеют своего внутреннего состояния. Сессии — способ сохранения информации о пользователе между отдельными запросами. Laravel поставляется со множеством различных механизмов сессий, доступных через единый выразительный API. Из коробки поддерживаются такие популярные системы, как Memcached, Redis и СУБД.
Настройка
Настройки сессии содержатся в файле config/session.php
. Обязательно просмотрите параметры, доступные вам в этом файле. По умолчанию Laravel использует драйвер сессий file
, который подходит для большинства приложений. Для увеличения производительности сессий в продакшне вы можете использовать драйверы memcached
или redis
.
Настройки драйвера driver
сессии определяют где будут храниться данные сессии для каждого запроса. Laravel поставляется с целым набором замечательных драйверов:
Драйвер массива используется во время тестирования и не сохраняет данные для последующих запросов.
Требования для драйверов
Database
При использовании драйвера сессий 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, необходимо установить пакет predis/predis
(~1.0) с помощью Composer. Вы можете настроить подключения Redis в конфиге database
. А в конфиге session
в параметре connection
можно указать конкретное подключение Redis для сессии.
Использование сессий
Получение данных
В Laravel есть два основных способа работы с данными сессии: с помощью глобального хелпера session
и через экземпляр Request
. Сначала давайте обратимся сессии через экземпляр Request
, который может быть указан в качестве зависимости в методе контроллера. Учтите, зависимости метода контроллера автоматически внедряются при помощи сервис-контейнера Laravel:
<?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 show(Request $request, $id)
{
$value = $request->session()->get('key');
//
}
}
При получении значения из сессии, вы можете передать значение по умолчанию вторым аргументом метода get
. Это значение будет возвращено, если указанного ключа нет в сессии. Если вы передадите в метод функцию Closure
в качестве значения по умолчанию, и запрашиваемого ключа не существует, то будет выполняться это замыкание и возвращаться его результат:
$value = $request->session()->get('key', 'default');
$value = $request->session()->get('key', function () {
return 'default';
});
Глобальный хелпер Session
Также вы можете использовать глобальную PHP-функцию session
для извлечения и помещения данных в сессию. При вызове session
с одним строковым аргументом, метод вернёт значение ключа этой сессии. При вызове хелпера с массивом пар ключ/значение, эти значения будут сохранены в сессии:
Route::get('home', function () {
// Получить часть данных из сессии...
$value = session('key');
// Указать значение по умолчанию...
$value = session('key', 'default');
// Хранить часть данных в сессии...
session(['key' => 'value']);
});
Есть небольшое практическое отличие между использованием сессий через экземпляр HTTP-запроса и использованием глобального хелпера
session
. Оба способа тестируются методомassertSessionHas
, доступным во всех ваших тест-кейсах.
Получение всех данных сессии
Если вы хотите получить все данные из сессии, используйте метод all
:
$data = $request->session()->all();
Определение наличия элемента в сессии
Для проверки существования значения в сессии можно использовать метод has
. Этот метод вернёт true
, если значение существует и не равно null
:
if ($request->session()->has('users')) {
//
}
Для проверки существования значения в сессии, даже если оно равно null
, можно использовать метод exists
. Этот метод вернёт true
, если значение существует:
if ($request->session()->exists('users')) {
//
}
Хранение данных
Для сохранения данных в сессии обычно используются метод put
или хелпер session
:
// Через экземпляр запроса...
$request->session()->put('key', 'value');
// Через глобальный хелпер...
session(['key' => 'value']);
Запись данных в массивы сессии
Метод push
служит для записи нового значения в элемент сессии, который является массивом. Например, если ключ user.teams
содержит массив с именами команд, вы можете записать новое значение в массив вот так:
$request->session()->push('user.teams', 'developers');
Чтение и удаление элемента
Метод pull
прочитает и удалит элемент из сессии за одно действие:
$value = $request->session()->pull('key', 'default');
Флеш-данные
Иногда вам нужно сохранить переменную в сессии только для следующего запроса. Вы можете сделать это методом flash
. Сохранённые этим методом данные будут доступны только во время следующего HTTP-запроса, а затем будут удалены. В основном такие данные полезны для кратковременных сообщений о состоянии:
$request->session()->flash('status', 'Task was successful!');
Для сохранения одноразовых данных в течение большего числа запросов используйте метод reflash
, который оставит все эти данные для следующего запроса. А если вам надо хранить только определённые данные, то используйте метод keep
:
$request->session()->reflash();
$request->session()->keep(['username', 'email']);
Удаление данных
Метод forget
удалит куски данных из сессии. Для удаления из сессии всех данных используйте метод flush
:
$request->session()->forget('key');
$request->session()->flush();
Обновление ID сессии
Обновление ID сессии часто используется для защиты приложения от злоумышленников, применяющих атаку фиксации сессии на ваше приложение.
Laravel автоматически обновляет ID сессии во время аутентификации, если вы используете встроенный LoginController
; но если вы хотите обновлять ID сессии вручную, используйте метод regenerate
.
$request->session()->regenerate();
Добавление своих драйверов сессий
Реализация драйвера
Ваш драйвер сессий должен реализовывать 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
.
Поскольку задачи этих методов не так очевидны, давайте коротко рассмотрим каждый из них:
Регистрация драйвера
После реализации драйвера его можно зарегистрировать в фреймворке. Для добавления дополнительных драйверов для работы с сессиями в Laravel используйте метод extend
фасада Session
. Вам надо вызвать метод extend
из метода boot
сервис-провайдера. Это можно сделать в имеющемся AppServiceProvider или создать абсолютно новый провайдер:
<?php
namespace App\Providers;
use App\Extensions\MongoSessionStore;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\ServiceProvider;
class SessionServiceProvider extends ServiceProvider
{
/**
* Выполнение пост-регистрационной загрузки сервисов.
*
* @return void
*/
public function boot()
{
Session::extend('mongo', function ($app) {
// Return implementation of SessionHandlerInterface...
return new MongoSessionStore;
});
}
/**
* Регистрация привязок в контейнере.
*
* @return void
*/
public function register()
{
//
}
}
Когда драйвер сессий зарегистрирован, вы можете использовать драйвер mongo
в своём конфиге config/session.php
.