Основы веб-разработки

Представления

Когда нужен серверный HTML — админка, SSR-страница, письмо — Winter рендерит его из обычных PHP-шаблонов через ResponseView. Есть макеты, частичные шаблоны и набор хелперов; данные передаются в шаблон как переменные.

Тип ResponseViewШаблоны .php в resources/Content-Type text/html

Что такое представления и зачем

Представление (view) — шаблон, из которого рендерится HTML-страница ответа.

Проблема. Собирать HTML конкатенацией строк в контроллере — нечитаемо и опасно: разметка мешается с логикой, легко забыть экранирование, невозможно переиспользовать общий каркас страницы.

Решение. Держите разметку в отдельных PHP-шаблонах, а из контроллера возвращайте ResponseView с именем шаблона и данными. Каркас страницы выносится в макет, повторяющиеся куски — в частичные шаблоны. Об этом и раздел.

Winter — в первую очередь про API

Для JSON-API представления не нужны — там ResponseEntity (см. Ответы). ResponseView пригодится, когда сервер отдаёт готовый HTML.

Базовый путь

Каталог шаблонов задаётся один раз (по умолчанию — Kernel::$pathResource, то есть resources/):

bootstrap.php
use Flytachi\Winter\K2\Http\Response\ResponseView;

ResponseView::setBasePath(__DIR__ . '/resources/views');

Рендеринг

Два способа: отдать одиночный шаблон или обернуть его в макет.

php
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.

Типичный контроллер, отдающий страницы:

main/PageController.php
#[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 запроса

Пример макета:

resources/layouts/main.php
<!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-код и заголовки:

php
use Flytachi\Winter\Base\HttpCode;

return ResponseView::view('errors/404', [], HttpCode::NOT_FOUND)
  ->header('Cache-Control', 'no-store');

Debug-оверлей

В режиме разработки (DEBUG=true) к отрендеренному HTML добавляется отладочный оверлей. В продакшене (DEBUG=false) его нет.

Дальше