Добавить историю посещений страниц в сессию и выводить список последних 10 посещенных страниц в отдельный блок. Примерно так:
Production / Работа с Сессией
Теперь рассмотрим более прогрессивный способ работы с авторизацией, да и не только с ней: так называемую сессию.
Сессия это такие данные которые фиксируются за пользователем который заходит на наш сайт, и могут оставаться привязанными к нему даже после закрытия браузера. Могут, но как правило не остаются, и пропадают сразу после закрытия бразуера.
Ну то есть, например, когда вы на каком-то сайте логинитесь, и потом, например, через несколько дней заходите на тот же сайт и вам не приходится по новой вводить данные для входа. То есть каким-то образом факт вашей авторизации остается зафиксированным.
Как же это работает?
На самом деле достаточно просто. В PHP при активации механизма сессии создается специальный файлик с уникальным именем, в который можно сохранять разные данные.
Это имя передается браузеру и браузер начинает это имя хранить. Хранит он его в тех самых куках про которые пишет каждый первый сайт:
Мы их еще разберем подробнее, но попозже.
Как только браузер получает это уникальное имя, он его теперь сам при каждом запросе начинает передавать серверу. И когда сервер видит, что браузер прислал это самое уникальное имя, он понимает, что надо взять файлик по этому уникальному имени открыть его и достать из него данные.
Пробрасываем данные между страницами
Чтобы не сразу кидаться во все тяжкие и реализовывать авторизацию. Попробуем просто добавить поле для ввода, в которое можно будет что-то написать, и чтобы оно стало доступно на всех страницах.
Создадим сначала SetWelcomeController, которые пока просто будет перенаправлять пользователя на страницу с которой будет отправляться запрос
вот этот $_SERVER['HTTP_REFERER']
как раз хранит адрес такой страницы.
Теперь привяжем контроллер к роутеру:
$router->add("/set-welcome/", SetWelcomeController::class);
и добавим поле для ввода в навигацию
получится такое:
теперь у меня такая идея, я хочу туда что-то написать, и чтобы это что-то стало доступно сразу на всех страницах. Причем мне не надо будет ничего фиксировать в БД.
И так, активируем механизм сессии. Так как нам надо чтобы сессия была доступна с любой страницы, то править будем BaseController, на самом деле конечно это не очень хорошо. И сессию лучше делать через middleware, но и наш подход допустим.
Правим функцию process_response, добавляем строчку
в принципе все, механизм сессии активировался! =)
Как это проверить?
Открываем консольку и идем сюда
То есть в куках (а куки это просто встроенное в бразуер хранилище в виде словарика, где есть ключ и привязанное к нему значение), под ключем PHPSESSID лежит уникальный номер вашей сессии. Вы можете удалить эту строчку через Delete перегрузить страницу и там появится уже новый номер.
А как посмотреть файлик который привязывается к этой сессии? Сначала надо найти папку куда PHP сохраняет сессии. Для этого в laragon надо зайти в настройки php
и найти там ключ session.save_path
тут и будет указано где хранятся файлики с сессиями. Давайте зайдем в папку и найдем файлик, соответствующий нашей сессии:
если его открыть он будет пустой. Давайте в него что-нибудь запишем. Идем в SetWelcomeController и добавляем строчку:
<?php
class SetWelcomeController extends BaseController {
public function get(array $context) {
$_SESSION['welcome_message'] = $_GET['message']; // добавил
$url = $_SERVER['HTTP_REFERER'];
header("Location: $url");
exit;
}
}
а теперь попробуем чего-нибудь написать в наше новое поле для ввода и тыкнуть Enter
вроде ничего не произошло, но теперь если открыть файл сессии, то увидим в нем
то есть наше сообщение зафиксировалось и теперь доступно с любой страницы.
Давайте, например, будем выводить его на странице объектов. Идем в ObjectController добавляем переменную в контекст со значением из сессии
правим шаблон:
открываем любой объект и пробуем что-то писать:
Но всегда надо помнить, что сессия привязана к одному браузеру.
Например, если открыть эту же страницу в режиме инкогнито, то мы и вовсе получим ошибку
почему так? Потому что открытие страницы в режиме инкогнито равносильно запуску одноразового браузера, у которого чистая история и чистые куки.
То есть инкогнито браузер запрашивает уже новую сессию в которой значение $_SESSION['welcome_message']
еще не определено. А поэтому ключ не доступен.
Поэтому во избежание такой ошибки надо добавить проверку на существование ключа, вот так
$context["my_session_message"] = isset($_SESSION['welcome_message']) ? $_SESSION['welcome_message'] : "";
вот теперь ошибки нет
можно глянуть их куки:
и увидеть, что у них разные значения ключей.
В принципе мы можем подделать сессию если скопируем значения ключа
вообще, такой прием называется подделкой сессии и является одной из возможных атак на сайт =)
Хранение массивов в сессии
Кстати в сессии можно хранить не обязательно простые типы, навроде строк или цифр. Можно, например, хранить массивы. Для этого нам надо просто изначально ключ в сессии инициализировать пустым списком, как-то так:
подключаем в контроллере:
class ObjectController extends BaseSpaceTwigController {
public $template = "__object.twig";
public function getContext(): array
{
// ...
// передаем в контекст список messages
$context["messages"] = isset($_SESSION['messages']) ? $_SESSION['messages'] : "";
return $context;
}
}
и теперь можно выводить в шаблоне
тестим:
Сохранение сессии после закрытия браузера
Кстати вы возможно заметили, что если закрыть и открыть браузер, то все что мы тут вводили теряется.
Почему так происходит? Потому что стандартное поведение сессии — это забыться по закрытию браузера. И на самом деле забывает сессию именно бразуер. Помните вот эту картинку
вот это идентификатор сессии который можно посмотреть в бразуере в куках, имеет определенное время жизни. Увидеть его можно в cтолбике Expire
значение Session означает что эта кука удалится по закрытию браузера. Но можно тыкнуть по значению два раза и ввести туда какую-нибудь дату в формате YYYY-MM-DD (например, 2021-12-31)
попробовать закрыть и открыть браузер, и убедиться, что значения теперь сохранились.
Но тут есть две проблемы, первая – не будем же мы заставлять пользователя лазить в куки и прописывать значения вручную. И вторая – хотя мы и установили время жизни куки с идентификатором сессии на конкретную дату, на сервере все равно стоит другое значение. Можно зайти в настройки
и найти там такое значение
которое означает что сессия будет считаться просроченной через 36000 секунд, то есть примерно через 10 часов. То есть это означает, что файлик с сессией будет удален на сервер не раньше, чем через 10 часов.
Но мы ж вроде в браузере посидели всего несколько минут закрыли-открыли, и данных уже нет. Как сделать так чтобы данные сохранились хотя бы на ближайшие 10 часов.
Для этого есть еще одна функция которая называется session_set_cookie_params
с помощью него можно указать как долго браузер будет хранить идентификатор сессии. Давайте загоним туда эти самые 10 часов.
Идем в BaseController
и добавляем перед session_start
:
проверяем, только не забудьте открыть и закрыть браузер, чтобы старое значение PHPSESSID сбросилось. Получается так:
Можно теперь смело закрывать браузер и не бояться потерять значение