Сессии в Laravel: настройка и работа без лишнего
Как включить сессии в Laravel 11, выбрать драйвер, положить и достать данные, настроить flash-сообщения и не потерять сессию после логина. Пошагово, с проверками на каждом шаге.

За 20–30 минут вы настроите сессии в проекте на Laravel 11.x: выберете драйвер (файлы, база или Redis), научитесь класть и читать данные, показывать одноразовые flash-сообщения после редиректа и защищать сессию при входе пользователя. В конце — разбор частых ошибок, из-за которых данные «пропадают» между запросами.
Что нужно иметь до начала
Проверьте, что у вас уже есть, иначе застрянете на середине.
- Laravel 11.x (проверьте командой
php artisan --version). Для 10.x всё описанное тоже работает, отличается только расположение конфигов. - PHP 8.2 или новее — минимум для Laravel 11.
- Файл
.envв корне проекта и права на запись в каталогstorage/framework/sessions(для драйвера по умолчанию). - Если планируете хранить сессии в базе — доступ к БД и выполненные миграции.
Одно важное отличие свежих версий: в Laravel 11 драйвер сессии по умолчанию — database, а не file, как было в старых проектах. Это меняет порядок первого запуска, о чём ниже.
Шаг 1. Выберите и включите драйвер
Драйвер задаётся переменной SESSION_DRIVER в файле .env. Открывать config/session.php ради этого не нужно — конфиг читает значение оттуда.
# .env
SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=falseSESSION_LIFETIME — время жизни сессии в минутах. SESSION_ENCRYPT=true включает шифрование содержимого сессии на диске; ценой становится небольшая нагрузка на CPU.
Если выбрали database, создайте таблицу для сессий. В Laravel 11 миграцию генерирует отдельная команда:
php artisan make:session-table
php artisan migrateПроверка: после migrate в базе появится таблица sessions с колонками id, user_id, payload, last_activity. Если её нет — миграция не выполнилась, смотрите вывод команды.
Для драйвера file ничего создавать не надо: файлы лягут в storage/framework/sessions. Убедитесь, что каталог доступен на запись веб-серверу.
Шаг 2. Положите и прочитайте данные
Сессия доступна через объект Request либо через хелпер session(). В контроллере предпочтительнее внедрять Request — так проще тестировать.
use Illuminate\Http\Request;
class CartController
{
public function add(Request $request)
{
// Записываем значение
$request->session()->put('cart.count', 3);
// Читаем со значением по умолчанию, если ключа нет
$count = $request->session()->get('cart.count', 0);
// Проверяем наличие ключа
if ($request->session()->has('cart.count')) {
// ...
}
// Удаляем один ключ
$request->session()->forget('cart.count');
return response()->json(['count' => $count]);
}
}Точка в ключе cart.count — это доступ к вложенному массиву, а не буквальный ключ с точкой. Так Laravel читает и пишет вложенную структуру.
Проверка: сделайте два запроса подряд с одной cookie сессии. Во втором запросе get('cart.count') должен вернуть то, что вы положили в первом. Если возвращается значение по умолчанию — сессия не сохраняется между запросами, к этому вернёмся в разделе ошибок.
Шаг 3. Настройте flash-сообщения
Flash-данные живут ровно один следующий запрос — это классический паттерн «сохранили, сделали редирект, показали сообщение».
// В контроллере после успешного действия
return redirect()
->route('orders.index')
->with('status', 'Заказ оформлен');Метод with() у редиректа кладёт данные во flash. В шаблоне Blade читаете так:
@if (session('status'))
<div class="alert">{{ session('status') }}</div>
@endifЕсли нужно записать flash вручную, без редиректа, есть flash():
$request->session()->flash('status', 'Готово');Проверка: после редиректа сообщение показывается один раз. Обновите страницу — оно исчезнет. Если сообщение висит на каждом обновлении, вы использовали put() вместо flash().
Шаг 4. Защитите сессию при входе пользователя
При смене прав доступа (логин, логаут) идентификатор сессии нужно пересоздавать — иначе открывается дыра для fixation-атаки1. Стандартный Auth::login() и стартовый scaffolding делают это сами, но если пишете авторизацию руками — вызывайте регенерацию явно.
if (Auth::attempt(['email' => $email, 'password' => $password])) {
// Пересоздаём идентификатор сессии после входа
$request->session()->regenerate();
return redirect()->intended('dashboard');
}При выходе очищайте и инвалидируйте сессию:
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();regenerateToken() обновляет CSRF-токен, чтобы старые формы не сработали от имени нового состояния.
Регенерация идентификатора после логина — не опциональная гигиена, а условие, без которого перехваченная до входа cookie останется валидной и после него.
Если не получилось
Пять симптомов, которые встречаются чаще всего.
- Данные не сохраняются между запросами. Скорее всего маршрут не проходит через middleware сессий. В Laravel 11 сессии подключены к группе
web. Проверьте, что маршрут объявлен вroutes/web.php, а не вroutes/api.php, где сессий по умолчанию нет. - Ошибка
Table 'sessions' doesn't exist. Выбран драйверdatabase, но миграция не выполнена. Запуститеphp artisan make:session-tableиphp artisan migrate. - Ошибка
failed to open stream: Permission deniedпри драйвере file. Веб-серверу не хватает прав наstorage/framework/sessions. Выдайте права владельцу процесса PHP-FPM или веб-сервера. - 419 Page Expired при отправке форм. Это не про хранилище сессии, а про CSRF: в форме нет
@csrf, либо сессия не создалась (см. первый пункт). Токен и сессия связаны. - Разные пользователи видят чужую сессию за балансировщиком. При драйвере
fileи нескольких серверах файлы лежат на разных машинах. Переключитесь наdatabaseилиredis— общее хранилище для всех нод.
Что делать дальше
Базовая настройка закончена. Дальше смотрите в сторону трёх вещей.
- Под нагрузкой переведите драйвер на
redis: он быстрее файлов и базы на чтении и записи, и это общее хранилище для кластера. Настройка подключения — вconfig/database.php, секцияredis. - Для продакшена задайте
SESSION_SECURE_COOKIE=true, чтобы cookie сессии не уходила по HTTP, и проверьтеSESSION_SAME_SITEвconfig/session.php. - Следите за ростом таблицы
sessionsпри драйвере database — устаревшие записи Laravel чистит вероятностно (параметрlotteryв конфиге), но на больших объёмах имеет смысл добавить регулярную очистку.
Инвалидация конкретных пользовательских сессий (разлогинить всех на всех устройствах) — отдельная тема, здесь её не разбираем.
1 Session fixation — атака, при которой злоумышленник заранее навязывает жертве известный ему идентификатор сессии и получает доступ к аккаунту после того, как жертва войдёт под этим идентификатором. Регенерация ID при логине обнуляет этот сценарий.
Проверка грамотности: Орфография, пунктуация, стиль — с объяснением каждой правки
Спросить за 10 ₽Источники: Laravel 11.x — HTTP Session (официальная документация), Laravel 11.x — Authentication
Частые вопросы
А если у меня Laravel 10, а не 11 — всё будет работать?
Почему данные не сохраняются, хотя я вызываю put()?
Какой драйвер выбрать — file, database или redis?
Чем flash отличается от обычной записи в сессию?
Нужно ли вызывать regenerate() вручную, если использую стандартную авторизацию Laravel?
Как быстро растёт таблица sessions и надо ли её чистить?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.