Макеты (иногда их также называют Шаблонами) нужны, чтобы избежать повторения в коде каждого файла представления тех частей, которые являются общими для многих страниц на сайте, т.е. таких блоков как:
- хэдер
- футер
- меню
- и др.
Т.е. макет позволяет не дублировать код одинаковых частей, которые есть у разных страниц сайта.
Работа подсистемы Ядра отвечающей за использование макета в основном сосредоточена в реализации метода View->render() (см. исх. код класса View, ранее мы упоминали этот метод в разделе "Представления").
Т.е. в момент, когда в действии контроллера выполняется код вида:
$this->view->render('путь/к/файлу/предстваления');запускается реализация метода View->render():
public function render($viewFilePath, $layoutPath = '')
{
if($layoutPath) {
$layoutPath = $this->layoutsBasePath . $layoutPath;
} else {
$layoutPath = $this->layoutPath;
}
// Далее начинаем формировать представление
extract($this->vars); // распаковываем переменные, переданные в представление (VIEW)
ob_start(); // перехватываем поток вывода
include($this->templateBasepath . $viewFilePath);
$CONTENT_DATA = ob_get_contents(); // записываем перехваченное в переменную
ob_end_clean(); // отключаем перехват
include($layoutPath); // подключаем макет, куда и будет подставлено
}-- где фактически происходит следующее:
- Сначала определяется какой именно путь к файлу макета нужно использовать (путь по умолучанию устанавливается в конструктре данного класса и берется из конфига), после чего это путь записывается в переменную
$layoutPath. - Далее с помощью стандатрной функции extract() в область видимости разворачиваются переменные, ранее переданные в Представление вызовом addVar() в контроллере.
- После чего наступает наиболее интересная стадия, с помощью кода:
ob_start(); // перехватываем поток вывода
include($this->templateBasepath . $viewFilePath);
// записываем перехваченное в переменную
$CONTENT_DATA = ob_get_contents();
ob_end_clean(); // отключаем перехватмы складываем, все что направлялось в стадартный поток вывода -- т.е.:
- начиная с вызова ob_start(), весь html из файлов представления а также все результаты работы функции
echo()не выводятся сразу на экран, а накапливается в специальной области памяти (буфере). - Накопленные данные извлекаются из буфера вызовом ob_get_contents() и записываются в переменную
$CONTENT_DATA. - Буферизация вывода отлючается вызовом функции ob_end_clean();
- Затем делается включение файл макета:
include($layoutPath); Далее рассмотрим пример файла макете и увидим как именно файл макета должен использовать данные, накопленные в $CONTENT_DATA
В качестве пример рассмотрим код макета основного файла макета main.php (исх. код):
<!DOCTYPE html>
<html>
<?php include('includes/main/head.php'); ?>
<body>
<?php include('includes/main/nav.php'); ?>
<div class="container">
<?= $CONTENT_DATA ?>
</div>
<?php include('includes/main/footer.php'); ?>
</body>
</html>-- здесь мы фактически видим основу тела html страницы, куда подключаются разные части и в том числе выводятся данные полученные в Представлении:
<?= $CONTENT_DATA ?>Имя (путь к файлу) используемого макета определяется сразу для всех действий Контроллера в свойстве класса контроллера $layoutPath.
Чтобы создать собственный макет и подключить его к контроллеру, действуйте так:
- Где-нибудь внутри (можно в поддиректории) директории
application/views/layouts/(или иной, все зависит от того, что указано в конфиге) Создайте основной файл вашего макета (тот который будет выводить$CONTENT_DATAи подключать другие части страницы, по аналогии с тем как это делает стандатрный main.php. - Укажите путь к этому макету в
$layoutPathвашего контроллера. - Готово! Все действия контроллера будут при вызове
$this->view->render()использовать ваш новый макет.
- Система макетов позволяет переиспользовать общие части внешнего вида (такие как хэдер и футер) для разных файлов представлений.
- Файл макета должен (иначе какой смысл его описывать) обращаться к переменной
$CONTENT_DATAи также может делать включения (а может и не делать, если выхотите все описать прямо в нем же) других нужных ему частей. - Чтобы указать какой файл макета использовать контроллеру используется свойство контроллера
$layoutPath.