Представления
Когда нужен серверный HTML — админка, SSR-страница, письмо — Winter рендерит его
из обычных PHP-шаблонов через ResponseView. Есть макеты, частичные шаблоны и
набор хелперов; данные передаются в шаблон как переменные.
Что такое представления и зачем
Представление (view) — шаблон, из которого рендерится HTML-страница ответа.
Проблема. Собирать HTML конкатенацией строк в контроллере — нечитаемо и опасно: разметка мешается с логикой, легко забыть экранирование, невозможно переиспользовать общий каркас страницы.
Решение. Держите разметку в отдельных PHP-шаблонах, а из контроллера
возвращайте ResponseView с именем шаблона и данными. Каркас страницы выносится в
макет, повторяющиеся куски — в частичные шаблоны. Об этом и раздел.
Winter — в первую очередь про API
Для JSON-API представления не нужны — там ResponseEntity (см.
Ответы). ResponseView пригодится, когда сервер отдаёт
готовый HTML.
Базовый путь
Каталог шаблонов задаётся один раз (по умолчанию — Kernel::$pathResource, то
есть resources/):
use Flytachi\Winter\K2\Http\Response\ResponseView;
ResponseView::setBasePath(__DIR__ . '/resources/views');Рендеринг
Два способа: отдать одиночный шаблон или обернуть его в макет.
use Flytachi\Winter\K2\Http\Response\ResponseView;
// Один шаблон
return ResponseView::view('user/profile', ['user' => $user]);
// Шаблон внутри макета
return ResponseView::render('layouts/main', 'user/profile', ['user' => $user]);Все ключи массива $data попадают в область шаблона как переменные (через
extract()), а ответ уходит с Content-Type: text/html; charset=utf-8.
Типичный контроллер, отдающий страницы:
#[RequestMapping('cabinet')]
class PageController extends Controller
{
#[GetMapping('profile')]
public function profile(): ResponseView
{
return ResponseView::render('layouts/main', 'user/profile', [
'title' => 'Профиль',
'user' => $this->service->current(),
]);
}
}Хелперы шаблонов
Внутри любого шаблона доступны глобальные функции:
| Функция | Что делает |
|---|---|
wrContent() |
Выводит отрендеренный шаблон-ресурс внутри макета |
wrImport('partial/name') |
Подключает другой шаблон в текущую область |
wrData(?string $key) |
Значение из $data по ключу (или весь массив при null) |
wrIsActiveLink($link, $success, $none) |
CSS-класс по текущему URI запроса |
Пример макета:
<!doctype html>
<html>
<head><title><?= wrData('title') ?></title></head>
<body>
<?php wrImport('partial/nav'); ?>
<?php wrContent(); ?>
</body>
</html>Внутри layouts/main вызов wrContent() подставляет отрендеренный ресурс
(например, user/profile), а wrImport() включает частичный шаблон навигации.
Свой код и заголовки
ResponseView тоже билдер — можно задать HTTP-код и заголовки:
use Flytachi\Winter\Base\HttpCode;
return ResponseView::view('errors/404', [], HttpCode::NOT_FOUND)
->header('Cache-Control', 'no-store');Debug-оверлей
В режиме разработки (DEBUG=true) к отрендеренному HTML добавляется отладочный
оверлей. В продакшене (DEBUG=false) его нет.
Дальше
- Ответы —
ResponseEntity, файлы, своиSendable - Контроллеры — что возвращает обработчик
- Обработка ошибок — HTML-страницы ошибок