Скрипты макетов
В обоих случаях вам нужно создать скрипт макета.
Скрипты макета используют 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();
?>
</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_Layout с MVC Zend Framework-а
Zend_Controller
предлагает богатый набор
возможностей для расширения посредством
плагинов
фронт-контроллера и помощников действий.
Zend_View
тоже имеет своих
помощников.
Zend_Layout
использует возможности такого расширения
при использовании с компонентами MVC.
Zend_Layout::startMvc()
создает экземпляр
Zend_Layout
с любой предоставленной вами конфигурацией
(опционально). Затем он регистрирует плагин фронт-контроллера,
который производит рендеринг макета с любым содержимым приложения
сразу, как только завершается цикл диспетчеризации, регистрирует
помощник действия для доступа к объекту макета из ваших контроллеров
действий. Кроме этого, вы можете в любой момент времени извлечь
экземпляр макета внутри скрипта вида, используя помощник вида
layout
.
Для начала посмотрим, как производится инициализация Zend_Layout для
использования в MVC:
<?php
// В вашем файле загрузки:
Zend_Layout::startMvc();
?>
startMvc()
может принимать массив опций или объект
Zend_Config
для настойки экземпляра. Эти опции описаны
в Опции конфигурирования 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 как отдельной компоненты
Как отдельная компонента Zend_Layout не предоставляет столько
возможностей или такого удобства, как в случае использовании с MVC.
Тем не менее, и в таком использовании сохраняются два основных
преимущества:
При использовании Zend_Layout в качестве отдельной компоненты просто
инстанцируйте объект макета, используйте различные аксессоры для
установки состояния, устанавливайте переменные как свойства объекта
и производите рендеринг макета:
<?php
$layout = new Zend_Layout();
// Установка пути к скриптам макета:
$layout->setLayoutPath('/path/to/layouts');
// установка переменных:
$layout->content = $content;
$layout->nav = $nav;
// выбор другого скрипта вида:
$layout->setLayout('foo');
// рендеринг конечного макета
?>
Пример макета
Иногда одна картинка стоит тысячи слов. Ниже показан пример
скрипта макета, показывающий, как все это может быть объединено.
Действительный порядок элементов может быть иным в зависимости от
установленного CSS. Например, если вы используете абсолютное
позиционирование, то можете разместить навигацию в конце документа,
но она будет отображаться вверху, то же самое можно сказать о
боковой панели, заголовке. Реальный порядок извлечения
содержимого остается тем же.