yii2 шаблон в шаблоне
  • 968

Как в yii2 разместить шаблон в шаблоне.

Автор: admin | 24 октября (Ср.) 2018г. в 19ч.47м.

Рассмотрим возможность создания вложенных шаблонов, реализованную в yii2 для возможности установки своих шаблонов для каждого контроллера или экшена.
Шаблон layout в yii2 - это контейнер для вывода контента, который передается из экшена и рендерится в файл вида. Таким образом получается, что файл вида view вложен в шаблон вида layout и содержится он в переменной $content

В layout:
<?php

/* @var $this \yii\web\View */
/* @var $content string */

use yii\helpers\Html;
use yii\bootstrap\Nav;
use yii\bootstrap\NavBar;
use yii\widgets\Breadcrumbs;
use frontend\assets\AppAsset;
use common\widgets\Alert;

AppAsset::register($this);
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang="<?= Yii::$app->language ?>">
<head>
    <meta charset="<?= Yii::$app->charset ?>">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <?= Html::csrfMetaTags() ?>
    <?php $this->head() ?>
</head>
<body>
<?php $this->beginBody() ?>

    <?php echo $this->render('//layouts/_header') ?>    

    <div id="mainContent">
         <?= $content ?>
         <?php echo $this->render('//layouts/_sideBar') ?>
    </div>

    <?= $this->render('//layouts/_footer') ?>

<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage() ?>
​

Файл вида (для примера index.php):

<?php
use yii\helpers\Html;
use yii\helpers\Url;

/* @var $this \yii\web\View */
?>

<div>
    <?= $page; ?>
</div>

В качестве шаблона в yii2 используется по умолчанию файл views/layouts/main.php. И весь этот шаблон будет всегда служить оберткой для контента из экшена.

Но что если нужно, чтобы часть layout все же менялась в разных контроллерах. Например, для страниц, генерируемых контроллером SiteController в шаблоне был сайдбар, а для страниц из PageController сайдбар не нужен, и при этом все остальные детали шаблона будут в двух версиях контроллеров. Очевидно, нужно создать общий шаблон для всех контроллеров с разметкой, которая будет общей. И нужен шаблон отдельно для каждого контроллера, в котором будет центральный блок с сайдбаром для SiteController и без него для PageController:

Сделаем для примера такую структуру папок видов:

views
    -layouts
           _siteLayout.php
           _pageLayout.php
           main.php

    -site
           index.php
    -page
           index.php
Родительским для всех шаблонов будет main.php. В него будет вложен уникальный для каждого контроллера шаблон, содержащийся в $content. А внутри уникального шаблона выводится в  $content его дочерний вид, что рендерится в экшене контроллера - index.php Таким образом дочерний шаблон в родительском всегда содержится в переменной $content. И будь у нас многослойная вложенность шаблонов, именно в $content содержится рендеринг дочернего вида. 

Вот так это выглядет на схеме:
Вложенные шаблоны видов в yii2.

Реализация вложенных шаблонов.

Итак, изменим наш код примера, чтобы был общий шаблон и два шаблона-наследника, каждый для своего контроллера (один с сайдбаром, другой без). Опишем main.php:

...
<?php $this->beginBody() ?>

    <?php echo $this->render('//layouts/_header') ?>    

    <?php //тут выводим дочерний вид ?>
    <?= $content ?>
     

    <?= $this->render('//layouts/_footer') ?>

<?php $this->endBody() ?>
</body>
...
​​

Создаем два дочерних шаблона _siteLayout.php и _pageLayout.php. Для того, чтобы они выводились в родительском шаблоне, помещаем весь код между $this->beginContent('путь к родительскому шаблону', $params = [])  и $this->endContent .

В переменной params можно передать массив переменных, которые будут видны в родительском шаблоне, по типу, как передается массив переменных при рендеринге вида из экшена контроллера.

<?
_siteLayout.php с сайдбаром

?>

<?php $this->beginContent('@frontend/views/layouts/main.php'); ?>

<div id="mainContent">
     <?= $content ?>
     <?php echo $this->render('//layouts/_sideBar') ?>
</div>

<?php $this->endContent(); ?>
<?
_pageLayout.php без сайдбара

?>

<?php $this->beginContent('@frontend/views/layouts/main.php'); ?>

<div id="mainContent">
     <?= $content ?>
</div>

<?php $this->endContent(); ?>

Теперь в соответствующих контроллерах устанавливаем layout-ы:

class SiteController extends Controller
{
    // шаблон с сайдбаром
    public $layout = '@app/views/layouts/_siteLayout';
class PageController extends Controller
{
    // шаблон без сайдбара
    public $layout = '@app/views/layouts/_pageLayout';

Теперь файлы видов из экшена будут попадать в нужный шаблон, а он в свою очередь будет вложен в main.php шаблон. 
Таким образом можно сделать многослойную вложенность шаблона в шаблон, изменяя внешний вид и вывод данных на сайте в зависимости от потребностей.

P.S.

В некоторых случаях для изменения структуры шаблона будет полезна другая возможность, реализованная в yii2, о которой я писал в статье про создание динамических блоков видов в yii2.

Приветствую!

Меня зовут Сергей. Я - автор этого блога.

Если Вам был полезен материал на моем сайте, поддержите пожалуйста мой проект, чтобы о нем узнали другие люди - кликните plizz :) на иконку в соц. сети, чтобы поделиться материалом с другими.