Cессии

CakePHP предоставляет собственную оболочку и набор полезных функций поверх session расширения PHP. Cессии позволяют идентифицировать уникальных пользователей по запросам и хранить постоянные данные для определённых пользователей. В отличие от Cookies, данные сессии недоступны на стороне клиента. Использование $_SESSION вообще исключается в CakePHP, и вместо этого использование классов сеанса является предпочтительным.

Настройка сессии

Конфигурация сессии обычно определяется в /config/app.php. Доступны следующие варианты:

  • Session.timeout - Число минут до того, как истечёт время CakePHP обработчика сессии.
  • Session.defaults - Позволяет использовать встроенные конфигурации сессий по умолчанию в качестве базы для настройки сессии. Ниже приведены встроенные значения по умолчанию.
  • Session.handler - Позволяет определить пользовательский обработчик сессии. Это используют сore database и обработчики кеш-сессии. См. ниже дополнительную информацию о обработчиках сессий.
  • Session.ini - Позволяет вам установить дополнительные параметры сессии для вашей ini-конфигурации. Это в сочетании с Session.handler заменяет пользовательские функции обработки сеанса предыдущих версий.
  • Session.cookie - Имя используемого файла cookie. По умолчанию используется значение „CAKEPHP“.
  • Session.cookiePath - URL-адрес, для которого установлен сессионный файл cookie. Карты в конфигурацию session.cookie_path php.ini. По умолчанию используется базовый путь к приложению.

session.cookie_secure CakePHP по умолчанию установлено в true, когда ваше приложение находится по протоколу SSL. Если ваше приложение работает как с протоколами SSL, так и с протоколом, отличным от SSL, у вас могут возникнуть проблемы с потерями сеансов. Если вам нужен доступ к сеансу как для SSL, так и для доменов, не относящихся к SSL, вам необходимо отключить этот так:

Configure::write('Session', [
    'defaults' => 'php',
    'ini' => [
        'session.cookie_secure' => false
    ]
]);

В пути к cookie сессии по умолчанию используется базовый путь приложения. Чтобы изменить это, вы можете использовать ini-значение session.cookie_path. Например, если вы хотите, чтобы ваша сессия сохранялась во всех поддоменах, вы можете сделать так:

Configure::write('Session', [
    'defaults' => 'php',
    'ini' => [
        'session.cookie_path' => '/',
        'session.cookie_domain' => '.yourdomain.com'
    ]
]);

По умолчанию PHP устанавливает, что cookie сессии истекает, как только браузер закрывается, независимо от настроенного значения Session.timeout. Тайм-аут cookie контролируется значением session.cookie_lifetime и может быть сконфигурирован с его использованием:

Configure::write('Session', [
    'defaults' => 'php',
    'ini' => [
        // Выполните инвалидацию cookie файла через 30 минут,
        // если за это время не посещена ни одна страница на сайте.
        'session.cookie_lifetime' => 1800
    ]
]);

Разница между Session.timeout и значением session.cookie_lifetime заключается в том, что последний полагается на то, что клиент говорит правду о cookie. Если вам требуется более строгая проверка тайм-аута, не полагайтесь на то, что сообщает клиент, а используйте Session.timeout.

Обратите внимание, что Session.timeout соответствует общему времени бездействия для пользователя (т.е. времени без посещения любой страницы, где используется сессия), и не ограничивает общее количество минут, на которые пользователь может оставаться на сайт.

Встроенные обработчики сессий и конфигурации

CakePHP поставляется с несколькими встроенными конфигурациями сессий. Вы можете либо использовать их в качестве основы для своей конфигурации сессии, либо создать полностью настраиваемое решение. Чтобы использовать значения по умолчанию, просто установите ключ „defaults“ на имя используемого по умолчанию. Затем вы можете переопределить любой дополнительный параметр, объявив его в конфигурации вашей сессии:

Configure::write('Session', [
    'defaults' => 'php'
]);

Вышеизложенное будет использовать встроенную „php“ конфигурацию сессии. Вы можете изменить её часть или всё, выполнив следующие действия:

Configure::write('Session', [
    'defaults' => 'php',
    'cookie' => 'my_app',
    'timeout' => 4320 // 3 дня
]);

Вышеупомянутое переопределяет тайм-аут и имя файла cookie для конфигурации „php“ сессии. Встроенные конфигурации:

  • php - Сохраняет сессии со стандартными настройками в файле php.ini.
  • cake - Сохраняет сессии как файлы внутри tmp/sessions. Это хороший вариант, когда на хостах не разрешено писать за пределами собственного домашнего каталога.
  • database - Используйте встроенные сеансы базы данных. Смотрите ниже для получения дополнительной информации.
  • cache - Используйте встроенный кэш сессий. Смотрите ниже для получения дополнительной информации.

Обработчики сессий

Обработчики сессий также могут быть определены в массиве конфигурации сессии. Определив ключ конфигурации „handler.engine“, вы можете назвать имя класса или предоставить экземпляр обработчика. Класс/объект должен реализовывать собственный PHP SessionHandlerInterface. Внедрение этого интерфейса позволит Session автоматически отображать методы для обработчика. Оба основных обработчика кэша сессии и базы данных используют этот метод для сохранения сессий. Дополнительные настройки для обработчика должны быть помещены внутри массива обработчиков. Затем вы можете прочитать эти значения изнутри вашего обработчика:

'Session' => [
    'handler' => [
        'engine' => 'DatabaseSession',
        'model' => 'CustomSessions'
    ]
]

Вышеописанное показывает, как можно настроить обработчик сессии базы данных с помощью модели приложения. При использовании имён классов в качестве обработчика, CakePHP ожидает, что ваш класс будет найден в пространстве имён Network\Session. Например, если у вас есть класс AppSessionHandler, файл должен быть src/Network/Session/AppSessionHandler.php, а имя класса должно быть App\Network\Session\AppSessionHandler. Вы также можете использовать обработчики сессий изнутри плагинов, установив двигатель в MyPlugin.PluginSessionHandler.

База данных сессий

Если вам нужно использовать базу данных для хранения данных сессии, это можно настроить следующим образом:

'Session' => [
    'defaults' => 'database'
]

Для этой конфигурации требуется таблица базы данных, имеющая эту схему:

CREATE TABLE `sessions` (
  `id` char(40) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
  `created` datetime DEFAULT CURRENT_TIMESTAMP, -- Optional
  `modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- Optional
  `data` blob DEFAULT NULL, -- for PostgreSQL use bytea instead of blob
  `expires` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Копию схемы для таблицы сессий можно найти в скелете приложения в config/schema/sessions.sql.

Вы также можете использовать свой собственный класс Table для обработки сохранения сессий:

'Session' => [
    'defaults' => 'database',
    'handler' => [
        'engine' => 'DatabaseSession',
        'model' => 'CustomSessions'
    ]
]

Вышеприведённое будет означать, что Session использует встроенные значения „database“ по умолчанию и указывает, что таблица, называемая CustomSessions, будет делегатом для сохранения информации о сессии в базе данных.

Кеширование сессий

Класс Cache также может использоваться для хранения сессий. Это позволяет хранить сессии в кэше, таком как APC, Memcached или XCache. Есть некоторые оговорки, связанные с использованием кэша сессий, поскольку если вы исчерпаете пространство кэша, сессии начнут истекать по мере удаления записей из кэша.

Чтобы использовать сессии на основе кэша, вы можете настроить конфигурацию сессии так:

Configure::write('Session', [
    'defaults' => 'cache',
    'handler' => [
        'config' => 'session'
    ]
]);

Это позволит настроить Session для использования класса CacheSession в качестве делегата для сохранения сессий. Вы можете использовать ключ конфигурации, в котором используется конфигурация кэша. Конфигурация кэша по умолчанию - 'default'.

Настройка ini директив

Встроенные по умолчанию настройки пытаются обеспечить общую базу для настройки сессий. Возможно, вам потребуется также настроить определенные флаги ini. CakePHP предоставляет возможность настраивать параметры ini как для стандартных конфигураций, так и для пользовательских. Ключ ini в настройках сессии позволяет указать индивидуальные значения конфигурации. Например, вы можете использовать его для управления настройками типа session.gc_divisor:

Configure::write('Session', [
    'defaults' => 'php',
    'ini' => [
        'session.cookie_name' => 'MyCookie',
        'session.cookie_lifetime' => 1800, // Валидно 30 минут
        'session.gc_divisor' => 1000,
        'session.cookie_httponly' => true
    ]
]);

Создание пользовательского обработчика сессии

Создание пользовательского обработчика сессии прямо в CakePHP. В этом примере мы создадим обработчик сессии, который хранит сессии как в кэше (APC), так и в базе данных. Это даёт нам лучшее из быстрого ввода-вывода APC, не беспокоясь о том, что сессии испаряются, когда кэш заполняется.

Сначала нам нужно создать наш собственный класс и поместить его в src/Network/Session/ComboSession.php. Класс должен выглядеть примерно так:

namespace App\Network\Session;

use Cake\Cache\Cache;
use Cake\Core\Configure;
use Cake\Network\Session\DatabaseSession;

class ComboSession extends DatabaseSession
{
    public $cacheKey;

    public function __construct()
    {
        $this->cacheKey = Configure::read('Session.handler.cache');
        parent::__construct();
    }

    // Чтение данных сессии.
    public function read($id)
    {
        $result = Cache::read($id, $this->cacheKey);
        if ($result) {
            return $result;
        }
        return parent::read($id);
    }

    // Запись данных в сессию.
    public function write($id, $data)
    {
        Cache::write($id, $data, $this->cacheKey);
        return parent::write($id, $data);
    }

    // Уничтожение сессии.
    public function destroy($id)
    {
        Cache::delete($id, $this->cacheKey);
        return parent::destroy($id);
    }

    // Удаление истёкших сессий.
    public function gc($expires = null)
    {
        return Cache::gc($this->cacheKey) && parent::gc($expires);
    }
}

Наш класс расширяет встроенную DatabaseSession, поэтому нам не нужно дублировать всю её логику и поведение. Мы завершаем каждую операцию с помощью Cake\Cache\Cache. Это позволяет нам получать сессии из быстрого кэша и не беспокоиться о том, что происходит, когда мы заполняем кэш. Использование этого обработчика сессии также легко. В вашем config/app.php сделайте блок сессии следующим:

'Session' => [
    'defaults' => 'database',
    'handler' => [
        'engine' => 'ComboSession',
        'model' => 'Session',
        'cache' => 'apc'
    ]
],
// Не забудьте добавить конфигурацию кэша Apc
'Cache' => [
    'apc' => ['engine' => 'Apc']
]

Теперь наше приложение начнёт использовать наш специальный обработчик сессии для чтения и записи данных сессии.

class Session

Доступ к объекту сессии

Вы можете получить доступ к данным сессии в любом месте, где у вас есть доступ к объекту запроса. Это означает, что объект сессии доступен из:

  • Controllers
  • Views
  • Helpers
  • Cells
  • Components

В дополнение к основному объекту сессии вы также можете использовать Cake\View\Helper\SessionHelper для взаимодействия с сессией в ваших представлениях. Основным примером использования сессии будет:

$name = $this->request->session()->read('User.name');

// Если вы получаете доступ к сессии несколько раз, вам,
// вероятно, понадобится локальная переменная.
$session = $this->request->session();
$name = $session->read('User.name');

Чтение и запись данных сессии

Session::read($key)

Вы можете читать значения из сессии, используя Hash::extract() совместимый синтаксис:

$session->read('Config.language');
Session::write($key, $value)

$key должна быть разделенна точками пути, который вы хотите записать в $value:

$session->write('Config.language', 'en');

Вы также можете указать один или несколько хэшей, например:

$session->write([
  'Config.theme' => 'blue',
  'Config.language' => 'en',
]);
Session::delete($key)

Когда вам нужно удалить данные из сессии, вы можете использовать delete():

$session->delete('Some.value');
static Session::consume($key)

Когда вам нужно читать и удалять данные из сессии, вы можете использовать consume():

$session->consume('Some.value');
Session::check($key)

Если вы хотите увидеть, существуют ли определённые данные в сессии, вы можете использовать check():

if ($session->check('Config.language')) {
    // Config.language существует и не является нулевым.
}

Уничтожение сессии

Session::destroy()

Уничтожение сессии полезно, когда пользователи выходят из системы. Чтобы уничтожить сессию, используйте метод destroy():

$session->destroy();

Уничтожение сессии удалит все серверные данные из сессии, но не удалит куки-файл сессии.

Возобновление идентификаторов сессии

Session::renew()

В то время как AuthComponent автоматически обновляет идентификатор сессии при входе в систему и выходе из системы, вам может потребоваться возобновить идентификатор сессии вручную. Для этого используйте метод renew():

$session->renew();

Flash-сообщения

Flash-сообщения - это небольшие сообщения, отображаемые конечным пользователям один раз. Они часто используются для представления сообщений об ошибках или подтверждения того, что действия прошли успешно.

Чтобы установить и отобразить флэш-сообщения, вы должны использовать Флэш и Flash