#9 php Сессии: session_start и массив $_SESSION — счётчик на сервере

Куки научили сервер «узнавать» посетителя, но у них есть слабость: данные хранятся в браузере, где их видно и можно подменить.

Сессии решают эту задачу по-другому: данные лежат на сервере, а у браузера остаётся только «номерок» — идентификатор сессии. Сделаем тот же счётчик, но «по-взрослому».

Немного теории

Механика такая (документация session_start()): при вызове session_start() PHP либо находит существующую сессию, либо заводит новую. Данные сессии он хранит у себя на сервере, а браузеру просит запомнить только идентификатор — специальную куку PHPSESSID. В дальнейшем браузер прикладывает эту куку к запросам, PHP по ней находит «ту самую» сессию — и наш скрипт снова видит сохранённые данные.

Как это работает

  1. браузер впервые открывает страницу;
  2. PHP заводит сессию: место под данные — на сервере, а в ответе просит браузер запомнить куку PHPSESSID;
  3. мы записываем счётчик в массив $_SESSION;
  4. при следующем запросе браузер прикладывает PHPSESSID, PHP восстанавливает сессию — и в $_SESSION снова лежит наш счётчик.

Код страницы

<?php
session_start();

if (isset($_SESSION['visits'])) {
    $_SESSION['visits'] = $_SESSION['visits'] + 1;
} else {
    $_SESSION['visits'] = 1;
}
$visits = $_SESSION['visits'];
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Счётчик в сессии</title>
</head>
<body>
  <h1>Счётчик в сессии</h1>
  <p>Вы открыли страниц в этой сессии: <?php echo $visits; ?></p>
</body>
</html>

Разберём новые моменты:

  • session_start() стоит до <!DOCTYPE html> — по той же причине, что setcookie() в уроке про куки: идентификатор отправляется заголовком, а заголовки уходят до вывода;
  • $_SESSION — обычный ассоциативный массив: что записали в одном запросе, то прочитаете в следующем — PHP сам сохраняет его содержимое и сам восстанавливает;
  • никаких setcookie() мы не вызывали — куку PHPSESSID PHP ставит сам.

Проверяем

Откройте http://localhost:19791/lessons/lesson09-sessions/ и обновляйте страницу — счётчик растёт: 1, 2, 3... А теперь самое интересное, откройте в DevTools (Application → Cookies): там есть PHPSESSID, но нет никакого visits. Значение счётчика в браузер вообще не уходит — оно лежит на сервере.

Удалите куку PHPSESSID и обновите страницу — счётчик начнётся заново: без «номерка» сервер не узнает вашу сессию. То же произойдёт в режиме инкогнито.

Сессии и куки: в чём разница

  • где данные: куки — в браузере посетителя, сессии — на сервере (в браузере только PHPSESSID);
  • объём: куки маленькие (килобайты), в сессии можно хранить заметно больше;
  • доверие: значение куки посетитель может подменить; данные сессии из браузера не видны — их можно только «забыть», удалив куку-номерок;
  • срок: по умолчанию сессия живёт, пока открыт браузер — как сессионная кука.

Попробуйте сами

  • создайте в той же папке вторую страницу (например, page2.php) с тем же PHP-кодом и ссылкой на первую — счётчик окажется общим: сессия одна на весь сайт, а не на одну страницу;
  • поэкспериментируйте с удалением PHPSESSID в DevTools и режимом инкогнито;
  • посложнее: сохраните в сессию время последнего захода (вспомните урок про дату) и покажите «вы были здесь в ...».

Итоги

  • сессия хранит данные о посетителе на сервере; у браузера — только идентификатор в куке PHPSESSID;
  • session_start() нужен на каждой странице, до любого вывода;
  • $_SESSION — массив, который живёт между запросами в рамках одной сессии;
  • подделать данные сессии из браузера нельзя — можно лишь «забыть» её, удалив куку.

В следующем уроке соберём всё вместе: простейшая авторизация — форма входа, проверка пароля и «запоминание» вошедшего в сессии.