Формирование HTML во фреймворках — отдельная нетривиальная тема. Конечно, никто не запрещает создавать HTML напрямую в виде строки, но такой способ просто перестает работать на реальных сайтах, где HTML одной страницы — это сотни, а то и тысячи строк.
<?php
$app->get('/courses/{name}', function ($request, $response, array $args) use ($courses) {
$slug = $args['name'];
$course = $courses[$slug];
return $response->write("<h1>{$course->name}</h1>")
->write("<div>{$course->body}</div>");
});
У такого подхода масса недостатков:
Для решения подобных задач придумали шаблонизаторы — специализированные библиотеки, позволяющие описывать шаблон отдельно от остальной части кода.
Для начала необходимо установить пакет slim/php-view. Выполните соответствующую команду в корне проекта:
$ composer require slim/php-view php-di/php-di
Измените настройку Slim в начале файла public/index.php так как показано в примере:
<?php
// Контейнеры в этом курсе не рассматриваются (это тема связанная с самим ООП), но если вам интересно, то посмотрите DI Container
use Slim\Factory\AppFactory;
use DI\Container;
$container = new Container();
$container->set('renderer', function () {
// Параметром передается базовая директория, в которой будут храниться шаблоны
return new \Slim\Views\PhpRenderer(__DIR__ . '/../templates');
});
$app = AppFactory::createFromContainer($container);
$app->addErrorMiddleware(true, true, true);
В этих строчках происходит подключение шаблонизатора к Слиму, используя DI Container. Наши шаблоны будут храниться в директории templates в корне проекта.
Далее добавьте еще один обработчик:
<?php
$app->get('/users/{id}', function ($request, $response, $args) {
$params = ['id' => $args['id'], 'nickname' => 'user-' . $args['id']];
// Указанный путь считается относительно базовой директории для шаблонов, заданной на этапе конфигурации
// $this доступен внутри анонимной функции благодаря https://php.net/manual/ru/closure.bindto.php
// $this в Slim это контейнер зависимостей
return $this->get('renderer')->render($response, 'users/show.phtml', $params);
});
Метод render()
выполняет рендеринг указанного шаблона и добавляет результат в ответ.
Сама функция принимает на вход три параметра:
И последний шаг, добавьте файл templates/users/show.phtml со следующим содержимым:
<h1>Hello, <?= $id ?></h1>
Расширение phtml используют тогда, когда хотят показать что внутри файла содержится шаблон на PHP, в остальном файл рассматривается как обычный файл с кодом на PHP.
Теперь откройте браузер и попробуйте загрузить страницу http://localhost:8080/users/nick.
$ curl localhost:8080/users/nick
<h1>Hello, nick</h1>
Вместо кода <?= $id ?>
на экране появилось значение переменной
$id
. Откуда она взялась в шаблоне? Наш шаблонизатор берет массив
$params
, который передается третьим параметром в метод render()
и
создает внутри шаблона локальную переменную на каждый ключ этого массива. Причем имя переменной и
ключа совпадают. Этот принцип работает всегда. Если вам нужно вывести данные на странице, то
добавляйте их в массив $params
и обращайтесь к ним в шаблоне через переменные.
Этой тактики следует придерживаться и для суперглобальных массивов. По понятным причинам их можно использовать напрямую:
<h1><?= $_GET['name'] ?></h1>
Но делать так ни в коем случае нельзя. Такой код значительно сложнее в отладке и потенциально очень опасен (подробнее об этом дальше по курсу).
Теперь, когда мы добавили поддержку шаблонов во фреймворк, появляется способ создавать нетривиальные сайты. Ниже пример обработчика и шаблона для вывода курсов:
Обработчик
<?php
$app->get('/courses', function ($request, $response) use ($courses) {
$params = [
'courses' => $courses
];
return $this->get('renderer')->render($response, 'courses/index.phtml', $params);
});
Шаблон
<table>
<?php foreach ($courses as $course): ?>
<tr>
<td>
<?= $course['id'] ?>
</td>
<td>
<?= $course['name'] ?>
</td>
</tr>
<?php endforeach ?>
</table>
<!-- END -->