При формирования представления, по моему мнению, удобно использовать шаблонизаторы. У них есть много удобных и полезных возможностей, например, наследование шаблонов, фильтрация, функции, виджеты, переопределение блоков и так далее. Два из рассматриваемых нами фреймворков, а именно: Symfony и Laravel для формирования представлений предоставляют шаблонизаторы «из коробки», а вот Yii по умолчанию для этих целей использует чистый php, хотя не запрещает нам подключить и использовать в рамках фреймворка подходящий шаблонизатор.
Рассмотрим сначала как формируются шаблоны в Yii, а затем перейдём к рассмотрению вопроса использования в представлениях шаблонизаторов в рамках фреймворков Symfony и Laravel.
Yii view & native PHP
Итак, как мы уже сказали, «из коробки» Yii предлагает в шаблонах использовать чистый PHP. Представления, которые мы будем использовать в контроллерах приложении располагаются в папке frontend/views. Для каждого контроллера в данной директории создаётся отдельная папка (например, для контроллера CompanyController нужно создать папку company), а внутри папки будут храниться шаблоны для экшенов, каждому экшену свой шаблон (для экшена actionShow создадим шаблон show.php, для actionIndex — index.php). Для базовых шаблонов существует папка frontend/views/layouts, по умолчанию ко всем шаблонам будет применяться базовый шаблон main.php. Чтобы задать другой базовый шаблон для контроллера, надо переопределить в нём свойство $layout, например:
public $layout = 'new_layout';
Чтобы задать иной базовый шаблон по умолчанию для всех контроллеров, надо добавить параметр в «корень» конфигурации frontend/config/main.php:
[
...
'layout' => 'my_new_layout',
...
]
Если вместо названия базового шаблона передать false, то базовый шаблон применять при формировании представления не будет.
Внесём изменения в CompanyController.php в методе actionIndex():
<?php
...
class CompanyController extends Controller {
public function actionIndex(): string
{
$companies = Company::find()->orderBy('name')->all();
$result = [];
foreach ($companies as $company) {
$result[] = 'ID: ' . $company->id . '. Company name: ' . $company->name;
}
return $this->render('index', [
'companies' => $result,
]);
}
...
}
И создадим файл frontend/views/company/index.php с содержимым:
<?php
/* @var $this yii\web\View */
/* @var $companies array */
use yii\helpers\Html;
$this->title = 'Список компаний';
$this->params['breadcrumbs'][] = $this->title;
?>
<div>
<h1><?= Html::encode($this->title) ?></h1>
<?php foreach ($companies as $company): ?>
<?= $company ?><br>
<?php endforeach; ?>
</div>
Хорошей практикой является указывать в начале view-файла в комментариях переменные, которые доступны для использования.
В базовом шаблоне main.php, который был у нас «из коробки», есть каркас html страницы, в котором используется поле title, а также реализованы breadcrumbs («хлебные крошки»). В нашем частном шаблоне index.php мы помимо вывода непосредственно списка компаний задаём также title и дополняем цепочку breadcrumbs ещё одним элементом (текущей страницей).
Теперь страница со списком компаний приобрела более благородный вид. Осталось создать подобные представления для остальных страниц нашего приложения.
Более подробно о представлениях в Yii можно узнать из документации: http://www.yiiframework.com/doc-2.0/guide-structure-views.html
Перейдём к рассмотрению шаблонизатора, используемого во фреймворке Symfony.
Шаблонизатор Twig в Symfony
Фреймворк Symfony «из коробки» предлагает нам использовать в приложении довольно мощный шаблонизатор Twig. Согласно документации, каждый шаблон компилируется в PHP класс и затем кешируется, что обеспечивает довольно высокую скорость отображения шаблона.
Шаблоны, общие для всего приложения, хранятся в директории app/Resources/views/, шаблоны бандлов сторонних библиотек хранятся в vendor/path/to/CoolBundle/Resources/views/, а шаблоны бандла FunnyAppBundle будут храниться в директории src/Funny/AppBundle/Resources/veiws/. Для каждого контроллера в данной папке создаётся подпапка с названием контроллера, например, Company, в которой для каждого экшена создаётся отдельный шаблон с расширением *.html.twig, например для экшена listAction мы создадим шаблон list.html.twig.
Расширение базового шаблона app/Resources/views/base.html.twig происходит не средствами фреймворка, как в Yii, а средствами самого шаблонизатора, то есть чтобы расширить (extends) базовый шаблон, нужно в шаблоне src/Funny/AppBundle/Resources/veiws/Company/list.html.twig в начале файла указать:
{% extends 'base.html.twig' %}
Полностью файл list.html.twig будет выглядеть следующим образом:
{% extends 'base.html.twig' %}
{% block title %}Список компаний{% endblock %}
{% block body %}
<h2>Список компаний</h2>
{% for company in companies %}
<p>ID: {{ company.getId() }}. Company name: {{ company.getName() }}</p>
{% endfor %}
{% endblock %}
Мы переопределяем два блока, определённые в базовом шаблоне: {% block title %} — текст из тега <title> и {% block body %} — основной контент страницы.
В данном примере, помимо возможности наследования шаблонов, продемонстрировано использование цикла {% for %}, который аналогичен циклу foreach в PHP. Для вывода значения переменной или функции используется конструкция {{ … }}.
Подобным образом нам необходимо создать шаблоны и для остальных экшенов.
О том, как работать с шаблонами в рамках Symfony, и базовую информацию о шаблонизаторе Twig можно узнать из официальной документации по Symfony: http://symfony.com/doc/current/templating.html
Более подробно с синтаксисом и возможностями шаблонизатора можно ознакомиться на сайте http://twig.sensiolabs.org/.
Рассмотрим теперь, как работает с шаблонами Laravel.
Laravel & шаблонизатор Blade
Laravel предлагает нам использовать шаблонизатор Blade, который поставляется вместе с фреймворком. Согласно документации в шаблонизаторе Blade есть два основных преимущества: наследование шаблонов и секции. Рассмотрим данные преимущества на примере базового шаблона (layout) и шаблона списка компаний, который будет «расширять» базовый шаблон.
Все шаблоны будут располагаться в папке resources/views/, базовый шаблон будет располагаться непосредственно в данной директории, а шаблоны экшенов в поддиректориях.
Создадим базовый шаблон layout.blade.php:
<html>
<head>
<title>FunnyApp - @yield('title')</title>
</head>
<body>
@section('header')
<h1>FunnyApp</h1>
@show
<div class="container">
@yield('content')
</div>
</body>
</html>
Отличие директивы @yield от @section в том, что @yield будет выводить контент из секции, которую получит из шаблона наследника, а директива @section сразу задаёт некоторый контент, который в шаблоне-наследнике может быть переопределён или дополнен.
Шаблон для экшена CompanyController@index, который будет располагаться в директории resources/views/company/, мы назовём index.blade.php и поместим туда следующий код:
@extends('layout')
@section('title', 'Список компаний')
@section('header')
@parent
<h2>Список компаний</h2>
@endsection
@section('content')
@foreach ($companies as $company)
ID: {{ $company->id }} Company name: {{ $company->name }} <br>
@endforeach
@endsection
Директивой @extends мы задаём от какого шаблоны мы наследуемся, а дерективы @section задают контент для тех мест, где базовый шаблон будет запрашивать данные от шаблона наследника, а также расширяют контент в том месте, где он уже задан в базовом шаблоне. Чтобы получить данные из секции базового шаблона используется директива @parent.
Также в данном шаблоне продемонстрирована возможность использования циклов, в данном случае мы проходим по массиву, используя директиву @foreach. Для вывода значения переменных используется конструкция {{ … }}.
Осталось поправить экшен index в контроллере CompanyController:
<?php
namespace App\Http\Controllers;
use App\Models\Company;
use Illuminate\Contracts\View\View;
use Illuminate\Routing\Controller;
class CompanyController extends Controller
{
/**
* Displays list of companies.
*
* @return View
*/
public function index(): View
{
$companies = Company::all();
return view('company.index', ['companies' => $companies]);
}
}
Для вывода данных с помощью шаблона используется глобальная функция (хелпер) view(), которая принимает в качестве первого параметра идентификатор шаблона, а вторым параметром при необходимости можно передать массив переменных, которые будут доступны в данном шаблоне.
Идентификатор шаблона состоит из двух частей: названия директории (относительно resources/views), в которой находится данный шаблон, и названия самого шаблона (без суффикса blade.php). Разделяются данные части точкой. В случае, если шаблон имеет более одного уровня вложенности, то названия директорий, составляющих путь до шаблона, также разделяются с помощью точки.