В этом разделе представлены два основных способа использования
Zend_Layout
: с MVC и без.
В обоих случаях вам нужно создать скрипт макета.
Скрипты макета используют Zend_View (или другую
реализацию интерфейса Zend_View_Interface, используемую вами).
Переменные макета регистрируются с помощью
метки
заполнения Zend_Layout
-а,
и доступ к ним может быть произведен через
помощника
меток заполнения, либо путем извлечения их как свойств
объекта макета посредством помощника макета.
Пример:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>My Site</title> </head> <body> <?php // извлечение содержимого ключа 'content' // с использованием помощника макета: echo $this->layout()->content; // извлечение содержимого ключа 'foo' // с использованием помощника меток заполнения: echo $this->placeholder('Zend_Layout')->foo; // извлечение объекта макета и получение различных переменных из него $layout = $this->layout(); echo $layout->bar; echo $layout->baz; ?> </body> </html>
Поскольку Zend_Layout
использует Zend_View
для рендеринга, то вы можете использовать любые зарегистрированные
помощники видов, а также обращаться к любым установленным ранее
переменным вида.
Особенно полезны различные помощники меток
заполнения, так как они позволяют извлекать содержимое
таких областей, как раздел <head>, навигация и т.п.:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <?= $this->headTitle() ?> <?= $this->headScript() ?> <?= $this->headStyle() ?> </head> <body> <?= $this->render('header.phtml') ?> <div id="nav"><?= $this->placeholder('nav') ?></div> <div id="content"><?= $this->layout()->content ?></div> <?= $this->render('footer.phtml') ?> </body> </html>
Zend_Controller
предлагает богатый набор
возможностей для расширения посредством
плагинов
фронт-контроллера и помощников действий.
Zend_View
тоже имеет своих
помощников.
Zend_Layout
использует возможности такого расширения
при использовании с компонентами MVC.
Zend_Layout::startMvc()
создает экземпляр
Zend_Layout
с любой предоставленной вами конфигурацией
(опционально). Затем он регистрирует плагин фронт-контроллера,
который производит рендеринг макета с любым содержимым приложения
сразу, как только завершается цикл диспетчеризации, регистрирует
помощник действия для доступа к объекту макета из ваших контроллеров
действий. Кроме этого, вы можете в любой момент времени извлечь
экземпляр макета внутри скрипта вида, используя помощник вида
layout
.
Для начала посмотрим, как производится инициализация Zend_Layout для использования в MVC:
<?php // В вашем файле загрузки: Zend_Layout::startMvc(); ?>
startMvc()
может принимать массив опций или объект
Zend_Config
для настойки экземпляра. Эти опции описаны
в Раздел 20.3, «Опции конфигурирования Zend_Layout».
В контроллере действий вы можете обращаться к экземпляру макета как к помощнику действий:
<?php class FooController extends Zend_Controller_Action { public function barAction() { // отключение макета для данного действия $this->_helper->layout->disableLayout(); } public function bazAction() { // использование другого скрипта макета с этим действием $this->_helper->layout->setLayout('foobaz'); }; } ?>
В своих скриптах вида вы можете обращаться к объекту вида через
помощник вида layout
. Этот помощник вида немного
отличается от остальных тем, что не принимает аргументов и
возвращает объект вместо строкового значения. Это позволяет сразу
вызывать методы объекта макета:
<?php $this->layout()->setLayout('foo'); // установка другого макета ?>
Вы можете в любой момент времени извлечь зарегистрированный с MVC
экземпляр Zend_Layout
, используя статический метод
getMvcInstance()
:
<?php // Возвращает null, если до этого не был вызван startMvc() $layout = Zend_Layout::getMvcInstance(); ?>
Наконец, плагин фронт-контроллера для Zend_Layout
-а
имеет одну ценную возможность в дополнение к рендерингу самого
макета: он извлекает все именованные сегменты из объекта ответа и
устанавливает их как переменные макета, при этом сегмент 'default'
присваивается переменной 'content'. Это позволяет иметь доступ к
содержимому приложения и производить его рендеринг в вашем скрипте
вида.
Для примера предположим, что в вашем приложении вызывается
FooController::indexAction()
, который производит
рендеринг некоторого содержимого в используемый по умолчанию сегмент
ответа и затем производит переход к действию
NavController::menuAction()
, который рендерит
содержимое в сегмент 'nav' объекта ответа. Наконец, вы производите
переход к действию CommentController::fetchAction()
и
извлекаете комментарии, но их рендеринг производится в
используемый по умолчанию сегмент (комментарии добавляются в конец
уже имеющегося содержимого). Ваш скрипт вида может затем произвести
их рендеринг по отдельности:
<body> <!-- рендеринг /nav/menu --> <div id="nav"><?= $this->layout()->nav ?></div> <!-- рендеринг /foo/index + /comment/fetch --> <div id="content"><?= $this->layout()->content ?></div> </body>
Эта возможность особенно полезна, если используется вместе с помощником действий и плагином ActionStack, с помощью которых вы можете создавать стек действий для обхода в цикле диспетчеризации и таким образом создавать страницы с различными "виджетами".
Как отдельная компонента Zend_Layout не предоставляет столько возможностей или такого удобства, как в случае использовании с MVC. Тем не менее, и в таком использовании сохраняются два основных преимущества:
Область видимости переменных макета.
Отделение скрипта макета от других скриптов видов.
При использовании Zend_Layout в качестве отдельной компоненты просто инстанцируйте объект макета, используйте различные аксессоры для установки состояния, устанавливайте переменные как свойства объекта и производите рендеринг макета:
<?php $layout = new Zend_Layout(); // Установка пути к скриптам макета: $layout->setLayoutPath('/path/to/layouts'); // установка переменных: $layout->content = $content; $layout->nav = $nav; // выбор другого скрипта вида: $layout->setLayout('foo'); // рендеринг конечного макета echo $layout->render(); ?>
Иногда одна картинка стоит тысячи слов. Ниже показан пример скрипта макета, показывающий, как все это может быть объединено.
Действительный порядок элементов может быть иным в зависимости от установленного CSS. Например, если вы используете абсолютное позиционирование, то можете разместить навигацию в конце документа, но она будет отображаться вверху, то же самое можно сказать о боковой панели, заголовке. Реальный порядок извлечения содержимого остается тем же.