Session brick
Flash після redirect, CSRF-токен, «попередній URL» —
усе це потребує стану між запитами. Без session web-форма
лишається stateless: після POST з помилкою немає куди
покласти errors/old, а CSRF не має де жити.
addSession() на ConceptStack
вмикає Symfony session, flash bag і (opt-in) CSRF token manager.
Повертає SessionBuilder. Рецепт —
Session і CSRF.
Навіщо не підтягувати Session автоматично з Http:
API-треки часто мають лишатися без cookie. Capability явна —
немає «сюрпризу» у контейнері. CSRF — не
окремий top-level brick: withCsrf() на Session,
бо без session token manager не має сенсу. Middleware
(VerifyCsrfTokenMiddleware, …) лишаються в
routes/*.php — Stack їх не реєструє: порядок
pipeline — історія запиту.
Методи SessionBuilder:
| Метод | Параметри | Опис | Залежність |
|---|---|---|---|
setOptions() |
array<string, mixed> $options |
Native session options (cookie_*, use_strict_mode, …) | — |
setHandlerFactory() |
Closure(): SessionHandlerInterface |
Фабрика handler-а (glue передає шлях до storage явно) | — |
withCsrf() |
— | Opt-in: CsrfTokenManagerInterface у контейнері |
— (middleware — у routes) |
setOptions()
$stack->addSession()
->setOptions([
'cookie_lifetime' => 0,
'cookie_path' => '/',
'cookie_httponly' => true,
'cookie_samesite' => 'Lax',
]);
Cookie lifetime, SameSite, httponly — це політика безпеки й UX,
не «внутрішня деталь пакета». Опції йдуть у
NativeSessionStorage
(extension-session-symfony),
як у Symfony — без окремого config brick на ранніх кроках рецепта.
setHandlerFactory()
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler;
$stack->addSession()
->setHandlerFactory(function () use ($rootPath) {
return new NativeFileSessionHandler($rootPath . 'storage/sessions');
});
Stack навмисно не вгадує шлях до storage: у Docker, CLI і
shared hosting корені різні. Glue передає factory, що повертає
SessionHandlerInterface. Без
setHandlerFactory() — NativeFileSessionHandler()
з PHP defaults (часто незручно в контейнері). Каталог
storage/sessions має бути writable.
withCsrf()
$stack->addSession()
->setHandlerFactory(function () use ($rootPath) {
return new NativeFileSessionHandler($rootPath . 'storage/sessions');
})
->withCsrf();
Opt-in, коли є HTML-форми з POST: реєструє
CsrfServiceProvider, token у session
(extension-csrf).
Сам brick не перевіряє POST — це робота middleware
у route file, наприклад:
$router->lazyMiddlewares([
HandleCsrfExceptionMiddleware::class,
VerifyCsrfTokenMiddleware::class,
]);
Поле форми: _csrf_token (CsrfField::NAME).
Ключі flash і URL для redirect back — у
Concept\App\Http\SessionKey (див.
крок 5 і
крок 7).
На ранніх кроках рецепта token у view передають явно з
controller; пізніше (Обробка помилок)
централізуємо через ShareViewDataMiddleware →
VIEW_PAYLOAD, щоб не копіювати csrf/flashes/errors
у кожному action.
Що реєструє brick
SessionServiceProvider→SessionInterface,FlashBagInterface- З
withCsrf():CsrfServiceProvider→CsrfTokenManagerInterface
Session стартує при першому resolve SessionInterface
(lazy) — немає cookie на чистих API-маршрутах, якщо їх не
торкались. Flash і CSRF використовують той самий session store.
Рецепт — Session і CSRF. Каталог bricks — Bricks і addX().