Документация Laravel 10.x
Здесь ты найдешь сниппеты по Laravel и полезные советы по веб-разработке.
Поскольку приложения, управляемые HTTP, являются состоянием, сеансы предоставляют способ сохранения информации о пользователе через несколько запросов. Эта информация о пользователе обычно помещается в постоянное хранилище / фон, к которому можно получить доступ из последующих запросов.
Laravel поставляется с различными механизмами сеансов, к которым можно получить доступ через выразительный, унифицированный API. Поддержка популярных механизмов, таких как Memcached, Redis и базы данных, включена.
Файл конфигурации сессии вашего приложения хранится в config/session.php
. Обязательно просмотрите доступные вам опции в этом файле. По умолчанию Laravel настроен на использование драйвера сеанса file
, который подходит для многих приложений. Если ваше приложение будет балансироваться между несколькими веб-серверами, вы должны выбрать централизованное хранилище, к которому все серверы могут получить доступ, такое как Redis или база данных.
Опция конфигурации driver
сеанса определяет, где будут храниться данные сеанса для каждого запроса. Laravel поставляется с несколькими отличными драйверами из коробки:
file
- сеансы хранятся в storage/framework/sessions
.cookie
- сеансы хранятся в защищенных, зашифрованных куках.database
- сеансы хранятся в реляционной базе данных.memcached
/ redis
- сеансы хранятся в одном из этих быстрых кэш-хранилищ.dynamodb
- сеансы хранятся в AWS DynamoDB.array
- сеансы хранятся в массиве PHP и не сохраняются.Примечание Драйвер массива в основном используется во время тестирования и предотвращает сохранение данных в сеансе.
При использовании драйвера сеанса database
вам нужно создать таблицу для хранения записей сеанса. Пример объявления схемы для таблицы приведен ниже:
use Illuminate\Database\Schema\Blueprint;use Illuminate\Support\Facades\Schema; Schema::create('sessions', function (Blueprint $table) { $table->string('id')->primary(); $table->foreignId('user_id')->nullable()->index(); $table->string('ip_address', 45)->nullable(); $table->text('user_agent')->nullable(); $table->text('payload'); $table->integer('last_activity')->index();});
Вы можете использовать команду Artisan session:table
, чтобы сгенерировать этот миграцию. Для получения дополнительной информации о миграциях базы данных вы можете ознакомиться с полным руководством по миграциям:
php artisan session:table php artisan migrate
Прежде чем использовать сеансы Redis с Laravel, вам нужно установить расширение PhpRedis для PHP через PECL или установить пакет predis/predis
(~1.0) через Composer. Для получения дополнительной информации о настройке Redis, прочтите документацию по Redis в Laravel.
Примечание В файле конфигурации
session
опцияconnection
может использоваться для указания, какое соединение Redis используется сеансом.
Существует два основных способа работы с данными сеанса в Laravel: глобальный помощник session
и через экземпляр Request
. Сначала давайте рассмотрим доступ к сеансу через экземпляр Request
, который может быть указан в типе замыкания маршрута или метода контроллера. Помните, что зависимости метода контроллера автоматически внедряются через сервис-контейнер Laravel:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request;use Illuminate\View\View; class UserController extends Controller{ /** * Показать профиль для указанного пользователя. */ public function show(Request $request, string $id): View { $value = $request->session()->get('key'); // ... $user = $this->users->find($id); return view('user.profile', ['user' => $user]); }}
При извлечении элемента из сеанса вы также можете передать значение по умолчанию вторым аргументом метода get
. Это значение по умолчанию будет возвращено, если указанный ключ не существует в сеансе. Если вы передаете замыкание в качестве значения по умолчанию методу get
, и запрошенного ключа не существует, выполнится это замыкание, и его результат будет возвращен:
$value = $request->session()->get('key', 'default'); $value = $request->session()->get('key', function () { return 'default';});
Вы также можете использовать глобальную функцию session
PHP для извлечения и сохранения данных в сеансе. Когда помощник session
вызывается с одним строковым аргументом, он вернет значение этого ключа сеанса. Когда помощник вызывается с массивом пар ключ / значение, эти значения будут сохранены в сеансе:
Route::get('/home', function () { // Получение данных из сессии... $value = session('key'); // Указание значения по умолчанию... $value = session('key', 'default'); // Сохранение данных в сессии... session(['key' => 'value']);});
Примечание Практически нет разницы между использованием сеанса через экземпляр HTTP-запроса и использованием глобального помощника
session
. Оба метода поддерживают тестирование с использованием методаassertSessionHas
, который доступен во всех ваших тестовых случаях.
Если вы хотите извлечь все данные из сеанса, вы можете использовать метод all
:
$data = $request->session()->all();
Чтобы определить, присутствует ли элемент в сеансе, вы можете использовать метод has
. Метод has
возвращает true
, если элемент присутствует и не равен null
:
if ($request->session()->has('users')) { // ...}
Чтобы определить, присутствует ли элемент в сеансе, даже если его значение null
, вы можете использовать метод exists
:
if ($request->session()->exists('users')) { // ...}
Чтобы определить, отсутствует ли элемент в сеансе, вы можете использовать метод missing
. Метод missing
возвращает true
, если элемент отсутствует:
if ($request->session()->missing('users')) { // ...}
Для сохранения данных в сеансе обычно используется метод put
экземпляра запроса или глобального помощника session
:
// Через экземпляр запроса...$request->session()->put('key', 'value'); // Через глобальный помощник "session"...session(['key' => 'value']);
Метод push
может использоваться для добавления нового значения в значение сеанса, которое является массивом. Например, если ключ user.teams
содержит массив названий команд, вы можете добавить новое значение в массив так:
$request->session()->push('user.teams', 'developers');
Метод pull
извлечет и удалит элемент из сеанса в одном операторе:
$value = $request->session()->pull('key', 'default');
Если в ваших данных сеанса содержится целое число, которое вы хотите увеличить или уменьшить, вы можете использовать методы increment
и decrement
:
$request->session()->increment('count'); $request->session()->increment('count', $incrementBy = 2); $request->session()->decrement('count'); $request->session()->decrement('count', $decrementBy = 2);
Иногда вам может потребоваться хранить элементы в сеансе для следующего запроса. Вы можете сделать это, используя метод flash
. Данные, сохраненные в сеансе с использованием этого метода, будут доступны сразу и в течение последующего HTTP-запроса. После последующего HTTP-запроса мигрированные данные будут удалены. Flash-данные в основном полезны для краткосрочных сообщений о статусе:
$request->session()->flash('status', 'Task was successful!');
Если вам нужно сохранить свои мигрированные данные на несколько запросов, вы можете использовать метод reflash
, который сохранит все мигрированные данные для дополнительного запроса. Если вам нужно сохранить только определенные мигрированные данные, вы можете использовать метод keep
:
$request->session()->reflash(); $request->session()->keep(['username', 'email']);
Чтобы сохранить свои мигрированные данные только для текущего запроса, вы можете использовать метод now
:
$request->session()->now('status', 'Task was successful!');
Метод forget
удалит кусок данных из сеанса. Если вы хотите удалить все данные из сеанса, вы можете использовать метод flush
:
// Забыть один ключ...$request->session()->forget('name'); // Забыть несколько ключей...$request->session()->forget(['name', 'status']); $request->session()->flush();
Часто пересоздание идентификатора сеанса выполняется для предотвращения злоумышленников от использования атаки фиксации сеанса в вашем приложении.
Laravel автоматически пересоздает идентификатор сеанса во время аутентификации, если вы используете один из стартовых комплектов Laravel application starter kits или Laravel Fortify; однако, если вам нужно вручную пересоздать идентификатор сеанса, вы можете использовать метод regenerate
:
$request->session()->regenerate();
Если вам нужно пересоздать идентификатор сеанса и удалить все данные из сеанса в одном операторе, вы можете использовать метод invalidate
:
$request->session()->invalidate();
Внимание Для использования блокировки сеанса ваше приложение должно использовать драйвер кэша, который поддерживает атомарные блокировки. В настоящее время такие драйверы кэша включают драйверы
memcached
,dynamodb
,redis
иdatabase
. Кроме того, вы не можете использовать драйвер сеансаcookie
.
По умолчанию Laravel позволяет одновременно выполнять запросы с использованием одной сессии. Так, например, если вы используете библиотеку JavaScript HTTP для выполнения двух HTTP-запросов к вашему приложению, они будут выполняться одновременно. Для многих приложений это не проблема; однако потеря данных сеанса может произойти в небольшом подмножестве приложений, которые делают одновременные запросы к двум разным конечным точкам приложения, записывающим данные в сеанс.
Для устранения этой проблемы Laravel предоставляет функциональность, позволяющую ограничивать одновременные запросы для определенной сессии. Для начала вы можете просто добавить метод block
к определению вашего маршрута. В этом примере входящий запрос к конечной точке /profile
получит блокировку сеанса. Пока эта блокировка удерживается, все входящие запросы к конечным точкам /profile
или /order
, которые используют тот же идентификатор сеанса, будут ждать завершения выполнения первого запроса, прежде чем продолжить выполнение:
Route::post('/profile', function () { // ...})->block($lockSeconds = 10, $waitSeconds = 10) Route::post('/order', function () { // ...})->block($lockSeconds = 10, $waitSeconds = 10)
Метод block
принимает два необязательных аргумента. Первый аргумент, принимаемый методом block
, - это максимальное количество секунд, в течение которых блокировка сеанса должна быть удержана, прежде чем она будет освобождена. Конечно же, если запрос завершится выполнением раньше этого времени, блокировка будет освобождена раньше.
Второй аргумент, принимаемый методом block
, - это количество секунд, в течение которых запрос должен ждать при попытке получить блокировку сеанса. Исключение Illuminate\Contracts\Cache\LockTimeoutException
будет сгенерировано, если запрос не сможет получить блокировку сеанса в течение указанного количества секунд.
Если ни один из этих аргументов не передан, блокировка будет получена максимум на 10 секунд, а запросы будут ждать максимум 10 секунд при попытке получить блокировку:
Route::post('/profile', function () { // ...})->block()
Если ни один из существующих драйверов сеанса не соответствует потребностям вашего приложения, Laravel позволяет написать свой собственный обработчик сеанса. Ваш собственный драйвер сеанса должен реализовывать встроенный интерфейс SessionHandlerInterface
PHP. Этот интерфейс содержит всего несколько простых методов. Заготовленная реализация 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
, вам редко придется что-то добавлять в этот метод. Вы можете просто оставить этот метод пустым.close
, как и метод open
, также обычно может быть пропущен. Для большинства драйверов он не требуется.read
должен возвращать строковую версию данных сеанса, связанных с данным $sessionId
. Нет необходимости выполнять какую-либо сериализацию или другое кодирование при извлечении или сохранении данных сеанса в вашем драйвере, поскольку Laravel выполнит сериализацию за вас.write
должен записать предоставленную строку $data
, связанную с $sessionId
, в некоторую постоянную систему хранения, такую как MongoDB или другая система хранения по вашему выбору. Опять же, вам не следует выполнять какую-либо сериализацию - Laravel уже обработает это за вас.destroy
должен удалить данные, связанные с $sessionId
, из постоянного хранилища.gc
должен уничтожить все данные сеанса, старше заданного $lifetime
, который представляет собой временную метку UNIX. Для самоочищающихся систем, таких как Memcached и Redis, этот метод может быть оставлен пустым.После того как ваш драйвер реализован, вы готовы зарегистрировать его в Laravel. Чтобы добавить дополнительные драйверы в сеансовый бекенд Laravel, вы можете использовать метод extend
, предоставленный фасадом Session
. Вы должны вызвать метод extend
из метода boot
поставщика услуг. Вы можете сделать это из существующего App\Providers\AppServiceProvider
или создать совершенно новый поставщик:
<?php namespace App\Providers; use App\Extensions\MongoSessionHandler;use Illuminate\Contracts\Foundation\Application;use Illuminate\Support\Facades\Session;use Illuminate\Support\ServiceProvider; class SessionServiceProvider extends ServiceProvider{ /** * Зарегистрировать любые службы приложения. */ public function register(): void { // ... } /** * Загрузить любые службы приложения. */ public function boot(): void { Session::extend('mongo', function (Application $app) { // Вернуть реализацию SessionHandlerInterface... return new MongoSessionHandler; }); }}
После того как драйвер сессии зарегистрирован, вы можете использовать драйвер mongo
в файле конфигурации config/session.php
.