Сессии и flash-сообщения
Сессия — хранилище данных одного посетителя, которое сохраняется между его запросами: сайт помнит, что лежит в корзине или какой язык выбран. Flash-сообщение — запись в сессии, которая живёт до следующей страницы: с её помощью показывают «Статья сохранена» после перенаправления.
Где находится сессия
Сессия — компонент Yii::$app->session. Настраивать и открывать её не нужно: она запускается сама при первом обращении. Файлов для неё создавать не требуется — её используют в действиях и шаблонах.
Запись и чтение
// controllers/PostController.php
public function actionView(int $id): string
{
$session = Yii::$app->session;
$session->set('lastPostId', $id);
$views = $session->get('views', 0) + 1;
$session->set('views', $views);
return "Вы открыли статей: $views";
}Обновляйте страницу — число будет расти: значение хранится на сервере и привязано к браузеру посетителя. Второй аргумент get() — значение по умолчанию.
| Вызов | Что делает |
|---|---|
$session->set('key', $value) | Записывает значение |
$session->get('key', $default) | Читает значение |
$session->has('key') | Проверяет, есть ли значение |
$session->remove('key') | Удаляет значение |
$session->destroy() | Удаляет все данные сессии |
Flash-сообщение
После сохранения статьи действие перенаправляет посетителя, поэтому вывести сообщение сразу нельзя. Его записывают в сессию:
public function actionCreate()
{
$post = new Post();
if ($post->load(Yii::$app->request->post()) && $post->save()) {
Yii::$app->session->setFlash('success', 'Статья сохранена.');
return $this->redirect(['post/view', 'id' => $post->id]);
}
return $this->render('create', ['post' => $post]);
}Первый аргумент — ключ сообщения, второй — текст.
Показ сообщения
В стандартном проекте макет views/layouts/main.php уже содержит строку <?= Alert::widget() ?>. Этот виджет (файл widgets/Alert.php) выводит сообщения с ключами success, error, danger, info и warning цветными блоками Bootstrap. Поэтому после сохранения статьи над содержимым страницы появится зелёная полоса «Статья сохранена.», а после обновления страницы она исчезнет.
В собственном макете без этого виджета сообщение выводят вручную:
<?php
// views/layouts/main.php
use yii\helpers\Html;
?>
<?php if (Yii::$app->session->hasFlash('success')): ?>
<div class="alert alert-success">
<?= Html::encode(Yii::$app->session->getFlash('success')) ?>
</div>
<?php endif; ?>getFlash() возвращает текст и помечает сообщение прочитанным — на следующей странице его уже не будет.
Cookie
Сессию браузер находит по cookie — небольшому значению, которое он хранит и присылает с каждым запросом. Свои cookie записывают через ответ, а читают через запрос:
Yii::$app->response->cookies->add(new \yii\web\Cookie([
'name' => 'theme',
'value' => 'dark',
]));
$theme = Yii::$app->request->cookies->getValue('theme', 'light');Yii подписывает cookie ключом cookieValidationKey из config/web.php, поэтому посетитель не может подделать значение.
Частая ошибка
Flash-сообщение записывают перед перенаправлением, а не перед render(). Если после setFlash() сразу вывести шаблон, сообщение появится и на этой странице, и ещё раз на следующей. Правило простое: успешное действие заканчивается парой setFlash() и redirect().