<sect1 id="zend.layout.advanced">
    <title>Использование Zend_Layout для опытных разработчиков</title>

    <para>
        Имеются различные варианты использования <code>Zend_Layout</code> для
        опытных разработчиков, которые хотят адаптировать его для других
        реализаций вида, другой файловой структуры и т.д.
    </para>

    <para>
        Основные возможности расширения:
    </para>

    <itemizedlist>
        <listitem><para>
                <emphasis>Собственные объекты вида.</emphasis>
                <code>Zend_Layout</code> позволяет использовать любые классы,
                реализущие интерфейс <code>Zend_View_Interface</code>.
        </para></listitem>

        <listitem><para>
                <emphasis>Собственные плагины фронт-контроллера.</emphasis>
                <code>Zend_Layout</code> поставляется со стандартным плагином
                фронт-контроллера, который автоматизирует рендеринг макетов,
                производимый до возвращения ответа. Вы можете заменить
                его на собственный плагин.
        </para></listitem>

        <listitem><para>
                <emphasis>Собственные помощники действий.</emphasis>
                <code>Zend_Layout</code> поставляется со стандартным помощником
                действий, который должен подходить для большинства нужд, т.к. он
                является простым посредником к объекту макета.
        </para></listitem>

        <listitem><para>
                <emphasis>Собственное определение пути к скрипту
                макета</emphasis>.
                <code>Zend_Layout</code> позволяет использовать собственный
                вариант <link linkend="zend.filter.inflector">инфлекции</link>
                для определения пути к скрипту макета или просто изменить
                прикрепленный инфлектор для указания собственных правил
                инфлекции.
        </para></listitem>
    </itemizedlist>

    <sect2 id="zend.layout.advanced.view">
        <title>Собственные объекты вида</title>

        <para>
            <code>Zend_Layout</code> позволяет использовать любые классы,
            реализующие интерфейс <code>Zend_View_Interface</code> или
            наследующие от <code>Zend_View_Abstract</code> для рендеринга
            скриптов макета. Просто передайте свой объект вида в качестве
            параметра конструктору/<code>startMvc()</code> или установите его,
            используя аксессор <code>setView()</code>:
        </para>

        <programlisting language="php"><![CDATA[<?php
$view = new My_Custom_View();
$layout->setView($view);
?>]]></programlisting>

        <note>
            <title>Не все реализации Zend_View одинаковы</title>

            <para>
                Хотя <code>Zend_Layout</code> позволяет использовать любые
                классы, реализующие <code>Zend_View_Interface</code>, вы можете
                столкнуться с проблемами, если они не используют помощники <code>Zend_View</code>-а, в частности, помощников макета и <link linkend="zend.view.helpers.initial.placeholder">меток заполнения</link>. Это потому, что <code>Zend_Layout</code> делает набор переменных в объекте доступным через себя или через <link linkend="zend.view.helpers.initial.placeholder">метки заполнения</link>.
            </para>

            <para>
                Если требуется использовать свою реализацию
                <code>Zend_View</code>, которая не поддерживает этих помощников,
                то нужно найти способ для получения переменных внутри вида. Это
                может быть реализовано путем расширения объекта
                <code>Zend_Layout</code> и изменения метода
                <code>render()</code> для передачи переменных виду, либо путем
                создания своего собственного класса плагина, который передает их
                до рендеринга макета.
            </para>

            <para>
                Также если ваша реализация вида поддерживает возможность
                использования плагинов, то вы можете обращаться к переменным
                через метку заполнения 'Zend_Layout', используя
                <link linkend="zend.view.helpers.initial.placeholder">помощника
                меток заполнения</link>:
            </para>

            <programlisting language="php"><![CDATA[<?php
$placeholders = new Zend_View_Helper_Placeholder();
$layoutVars   = $placeholders->placeholder('Zend_Layout')->getArrayCopy();
?>]]></programlisting>
        </note>
    </sect2>

    <sect2 id="zend.layout.advanced.plugin">
        <title>Собственные плагины фронт-контроллера</title>

        <para>
            Если используются компоненты MVC, <code>Zend_Layout</code>
            регистрирует плагин фронт-контроллера, который производит рендеринг
            макета до того, как будет произведен выход из цикла диспетчеризации.
            Для большинства случаев подходит плагин по умолчанию, но если вы
            хотите написать собственный, то можете указать имя класса плагина
            для загрузки путем передачи опции <code>pluginClass</code> методу
            <code>startMvc()</code>.
        </para>

        <para>
            Плагин, написанный вами для этой цели, должен наследовать от класса
            <code>Zend_Controller_Plugin_Abstract</code> и принимать объект
            макета в качестве аргумент конструктора. Иначе вы должны
            продумать детали своей реализации плагина.
        </para>

        <para>
            По умолчанию используется плагин
            <code>Zend_Layout_Controller_Plugin_Layout</code>.
        </para>
    </sect2>

    <sect2 id="zend.layout.advanced.helper">
        <title>Собственные помощники действий</title>

        <para>
            При использовании с компонентами MVC <code>Zend_Layout</code>
            регистрирует помощника действий с помощью брокера помощников.
            Используемый по умолчанию
            <code>Zend_Layout_Controller_Action_Helper_Layout</code> действует
            как простой посредник к объекту макета и должен подходить в
            большинстве случаев.
        </para>

        <para>
            Если понадобится написать дополнительный функционал, то просто
            напишите класс помощника действий, наследующий от
            <code>Zend_Controller_Action_Helper_Abstract</code>, и передайте его
            имя в качестве опции <code>helperClass</code> методу
            <code>startMvc()</code>.
        </para>
    </sect2>

    <sect2 id="zend.layout.advanced.inflector">
        <title>Собственное определение пути к скрипту макета: использование инфлектора</title>

        <para>
            <code>Zend_Layout</code> использует
            <code>Zend_Filter_Inflector</code> для установки цепочки фильтров,
            преобразующей имя макета в путь к скрипту макета. По умолчанию он
            использует правила 'CamelCaseToDash', 'StringToLower' и
            суффикс 'phtml' для преобразования имени макета в путь. Например:
        </para>

        <itemizedlist>
            <listitem><para>
                    'foo' будет преобразован в 'foo.phtml'.
            </para></listitem>

            <listitem><para>
                    'FooBarBaz' будет преобразован в 'foo-bar-baz.phtml'.
            </para></listitem>
        </itemizedlist>

        <para>
            Есть три способа изменить инфлекцию - модификация шаблона инфлекции
            и/или суффикса скрипта вида через аксессоры
            <code>Zend_Layout</code>, изменение правил инфлекции и шаблона,
            связанных с экземпляром <code>Zend_Layout</code> инфлектора,
            создание своего собственного экземпляра инфлектора и передача его
            <code>Zend_Layout::setInflector()</code>.
        </para>

        <example id="zend.layout.advanced.inflector.accessors">
            <title>Использование аксессоров Zend_Layout для модификации инфлектора</title>

            <para>
                Используемый по умолчанию инфлектор <code>Zend_Layout</code>
                использует статические ссылки для цели и суффикса скрипта вида,
                и имеет аксессоры для установки этих значений.
            </para>

            <programlisting language="php"><![CDATA[<?php
// Установка шаблона:
$layout->setInflectorTarget('layouts/:script.:suffix');

// Установка суффикса скрипта макета:
$layout->setViewSuffix('php');
?>]]></programlisting>
        </example>

        <example id="zend.layout.advanced.inflector.directmodification">
            <title>Непосредственное изменение инфлектора Zend_Layout</title>

            <para>
                Инфлекторы имеют шаблон и одно или более правил. По умолчанию с
                <code>Zend_Layout</code> используется шаблон ':script.:suffix';
                ':script' передает зарегистрированное имя макета, в то же время
                как ':suffix' является статическим правилом для инфлектора.
            </para>

            <para>
                Предположим, вы хотите, чтобы скрипт макета заканчивался
                суффиксом 'html', и что вы хотите разделить исходные слова в
                формате CamelCased символами подчеркивания всесто тире и не
                приводить их к нижнему регистру. Кроме этого, вы хотите искать
                скрипт в поддиректории 'layouts'.
            </para>

            <programlisting language="php"><![CDATA[<?php
$layout->getInflector()->setTarget('layouts/:script.:suffix')
                       ->setStaticRule('suffix', 'html')
                       ->setFilterRule(array('CamelCaseToUnderscore'));
?>]]></programlisting>
        </example>

        <example id="zend.layout.advanced.inflector.custom">
            <title>Собственные инфлекторы</title>

            <para>
                В большинстве случаев модификации существующего инфлектора будет
                достаточно. Тем не менее, у вас может быть инфлектор, который вы
                хотите использовать в разных местах и с объектами
                различных типов. <code>Zend_Layout</code> поддерживает это.
            </para>

            <programlisting language="php"><![CDATA[<?php
$inflector = new Zend_Filter_Inflector('layouts/:script.:suffix');
$inflector->addRules(array(
    ':script' => array('CamelCaseToUnderscore'),
    'suffix'  => 'html'
));
$layout->setInflector($inflector);
?>]]></programlisting>
        </example>

        <note>
            <title>Инфлекция может быть отключена</title>

            <para>
                Инфлекция может быть отключена или включена с использованием
                аксессоров объекта <code>Zend_Layout</code>. Это может быть
                полезным, если вы хотите указывать абсолютный путь к скрипту
                макета или знаете, что механизм, который вы будете использовать
                для указания скрипта макета, не требует инфлекции. Используйте
                методы <code>enableInflection()</code> и
                <code>disableInflection()</code>.
            </para>
        </note>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
