<sect1 id="zend.form.standardDecorators">
    <title> Zend Framework 带有的标准表单装饰器（Decorators） </title>

    <para>
        <code>Zend_Form</code> 带有若干标准装饰器，更多关于装饰器的一般用法，参见 <link linkend="zend.form.decorators">the Decorators section</link>。
    </para>

    <sect2 id="zend.form.standardDecorators.callback">
        <title>Zend_Form_Decorator_Callback</title>

        <para>
            回调（callback）装饰器可以对解析内容执行任意回调。回调应当通过传递给装饰器配置的 'callback' 选项来指定，可以是任何有效的 PHP 回调类型。回调接受三个参数 <code>$content</code> （传递给装饰器的原始内容）、<code>$element</code> （被装饰的条目）和 一个 <code>$options</code> 数组。这是个回调的例子：
        </para>

        <programlisting role="php"><![CDATA[<?php
class Util
{
    public static function label($content, $element, array $options)
    {
        return '<span class="label">' . $element->getLabel() . "</span>";
    }
}
?>]]></programlisting>

        <para>
            这个回调被指定为 <code>array('Util','label')</code>，并为标签（label）产生一些（坏的） HTML markup。回调装饰器将替换追加或用这个返回值预先准备原始内容。
        </para>

        <para>
            回调装饰器允许为替换选项指定一个 null 值，它将用回调返回值来替换原始内容，'prepend' 和 'append' 仍然有效。
        </para>
    </sect2>
    <sect2 id="zend.form.standardDecorators.captcha">
        <title>Zend_Form_Decorator_Captcha</title>

        <para>
            Captcha 装饰器用于 <link linkend="zend.form.standardElements.captcha">Captcha 表单元素 </link>。
            它利用 captcha 适配器的 <code>render()</code> 方法来生成输出。
        </para>

        <para>
            Captcha 装饰器的一个变量，'Captcha_Word'，也常用，并生成两个元素，id 和 input。
            id 表示比较依靠的会话识别符，input 用于 captcha 的校验。这些作为单个的元素被校验。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.description">
        <title>Zend_Form_Decorator_Description</title>

        <para>
            描述装饰器用来显示设置在 <code>Zend_Form</code>、 <code>Zend_Form_Element</code> 或 <code>Zend_Form_DisplayGroup</code> 条目上的描述。它使用对象的 <code>getDescription()</code> 方法来取出描述。普通的用例用来为元素提供用户接口（UI）提示。
        </para>

        <para>
            缺省地，如果没有描述，就不会生成输出。如果有描述，它将缺省地封装在 <code>p</code> 标签里，当生成装饰器时你可以通过传递一个 <code>tag</code>选项或调用 <code>setTag()</code> 来指定一个标签。你也可以使用 <code>class</code> 选项或调用 <code>setClass()</code> 来指定一个类，缺省使用 'hint' 类。
        </para>

        <para>
            缺省描述使用视图对象的转义机制来转义。你可以传递 <code>false</code> 值给装饰器的 'escape' 选项或 <code>setEscape()</code> 方法来关闭（disable）它。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.dtDdWrapper">
        <title>Zend_Form_Decorator_DtDdWrapper</title>

        <para>
            缺省装饰器使用定义列表 (<code>&lt;dl&gt;</code>) 来解析表单元素。因为表单条目可以以任何顺序出现，显示组和子表单可以用其它表单条目点缀。为在定义列表里保持这些特定的题目类型，DtDdWrapper 生成一个新的、空定义 term (<code>&lt;dt&gt;</code>) 并在新定义数据（<code>&lt;dd&gt;</code>）里封装它的内容 。输出看起来是这样的：
        </para>

        <programlisting role="html"><![CDATA[
<dt></dt>
<dd><fieldset id="subform">
    <legend>User Information</legend>
    ...
</fieldset></dd>
]]></programlisting>

        <para>
            装饰器通过把提供给它的内容封装在 <code>&lt;dd&gt;</code> 元素里来替换它。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.errors">
        <title>Zend_Form_Decorator_Errors</title>

        <para>
            元素错误用错误装饰器来获得它们自己的装饰器。这个装饰器代理 FormErrors 视图助手，它在无序的列表里 (<code>&lt;ul&gt;</code>) 解析错误消息作为列表条目。<code>&lt;ul&gt;</code> 元素接收 "errors" 类。
        </para>

        <para>
            错误装饰器可以预先准备或追加提供给它的内容。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.fieldset">
        <title>Zend_Form_Decorator_Fieldset</title>

        <para>
            显示组和子表单缺省地在字段（fieldsets）里解析内容。字段装饰器在注册的元素里检查 'legend' 选项或 <code>getLegend()</code> 方法，如果非空，就用它作为 legend。任何传递进来的内容被封装在 HTML 字段里，替换原先的内容。任何在装饰器条目里的属性设置都作为 HTML 属性传递给字段。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.form">
        <title>Zend_Form_Decorator_Form</title>

        <para>
            <code>Zend_Form</code> 对象一般需要解析 HTML 表单标签（tag）。表单装饰器代理表单视图助手。它使用 <code>Zend_Form</code> 对象的动作和方法，封装任何提供给它的内容到 HTML 表单元素，和任何属性作为 HTML 属性。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.formElements">
        <title>Zend_Form_Decorator_FormElements</title>

        <para>
            表单、显示组和子表单是元素的集合。为了解析这些元素，它们使用 FormElements 装饰器（它迭代所有条目，在每个条目调用 <code>render()</code> 并用注册的分隔符连接它们）。它可以追加或预先准备传递给它的内容。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.htmlTag">
        <title>Zend_Form_Decorator_HtmlTag</title>

        <para>
            HtmlTag  装饰器让你用 HTML 标签来装饰内容。通过传递 'tag' 选项和任何其它用作 HTML 属性的选项来使用标签。标签缺省地假定为 block 一级，通过封装在给定的标签里来替换内容。然而，你也可以指定一个追加或者预先准备的替换。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.image">
        <title>Zend_Form_Decorator_Image</title>

        <para>
            图像装饰器让你生成一个 HTML 图像输入（<code>&lt;input type="image" ... /&gt;</code>），并在另一个 HTML 标签里可选地解析它。
        </para>

        <para>
            缺省地，（图像）装饰器使用元素的 src 属性，它可以用 <code>setImage()</code> 方法来设置图像源。另外，元素的标签（label）将用做 alt 标签（tag），并且 <code>imageValue</code>（用图像元素的 <code>setImageValue()</code> 和 <code>getImageValue()</code> 访问器来处理）将用于值的设置。
        </para>

        <para>
            为指定一个封装元素的 HTML 标签，或者传递 'tag' 选项给装饰器，或者显式地调用 <code>setTag()</code>。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.label">
        <title>Zend_Form_Decorator_Label</title>

        <para>
            表单元素一般都有标签，标签装饰器用来解析这些标签。它代理 FormLabel 视图助手，用这个元素的 <code>getLabel()</code> 方法把元素标签读出来。如果没有标签，就不解析。缺省地，如果有翻译适配器和这个标签的翻译，标签就被翻译。
        </para>

        <para>
            你可以可选地指定一个 'tag' 选项，如果提供了，它封装在 block 一级标签（tag）封装这个标签（label）。如果有 'tag' 选项而没有标签（label）存在，那么标签（tag）就被不带内容解析。你可以用 'class' 选项或调用 <code>setClass()</code> 来指定和标签（tag）一起使用的类。
        </para>

        <para>
            另外，当显示元素（基于标签（label）是否用于可选的或必需的元素）时，你可以指定前缀和后缀来用。普通的用例是追加 ':' 给标签（label），或者一个 '*' 来表明元素是必需的。可以用下列选项和方法来做：
        </para>

        <itemizedlist>
            <listitem><para>
                    <code>optionalPrefix</code>: 当元素是可选的时候，设置文本给标签带有的前缀。使用 <code>setOptionalPrefix()</code> 和 <code>getOptionalPrefix()</code> 访问器来处理。
            </para></listitem>

            <listitem><para>
                    <code>optionalSuffix</code>: 当元素是可选的时候，设置追加给标签的文本。使用 <code>setOptionalSuffix()</code> 和 <code>getOptionalSuffix()</code> 访问器来处理。
            </para></listitem>

            <listitem><para>
                    <code>requiredPrefix</code>: 当元素必需的时候，设置文本给标签带有的前缀。使用 <code>setRequiredPrefix()</code> 和 <code>getRequiredPrefix()</code> 访问器来处理。
            </para></listitem>

            <listitem><para>
                    <code>requiredSuffix</code>: 当元素是必需的时候，设置追加给标签的文本。使用 <code>setRequiredSuffix()</code> 和 <code>getRequiredSuffix()</code> 访问器来处理。
            </para></listitem>
        </itemizedlist>

        <para>
            缺省地，标签装饰器预先准备给要提供的内容，指定一个 'append' 的 'placement' 选项来把它放在内容的后面。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.viewHelper">
        <title>Zend_Form_Decorator_ViewHelper</title>

        <para>
            大部分元素使用 <code>Zend_View</code> 助手来解析，这是通过 ViewHelper 装饰器来完成的。这样，你可以指定一个 'helper' 标签（tag）来显式地设置视图助手来使用。如果什么也没有提供，它使用元素类名的最后一节来确定助手，用字符串 'form'来预先准备：例如，'Zend_Form_Element_Text' 寻找一个叫 'formText' 的视图助手。
        </para>

        <para>
            任何提供的元素的属性被当作元素属性来传递给视图助手。
        </para>

        <para>
            缺省地，这个装饰器追加内容，使用 'placement' 选项类指定另外的布置（placement）。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.viewScript">
        <title>Zend_Form_Decorator_ViewScript</title>

        <para>
            有时候你可能想用视图脚本来生成元素，这样你可以对元素有精细的控制，把视图脚本交给（页面）设计者，或者基于你所使用的模块来构造一个简便地覆盖（override）设置的办法（每个模块可以可选地覆盖元素视图脚本来符合它们的需求）。ViewScript 装饰器解决了这个问题。
        </para>

        <para>
            ViewScript 装饰器要求一个 'viewScript' 选项，或者提供给装饰器，或者作为元素的属性。它接着解析哪个视图脚本为部分脚本，意思是每次调用它有自己的变量范围。没有从视图来的变量将注入除非元素它自己。若干变量如下：
        </para>

        <itemizedlist>
            <listitem><para>
                    <code>element</code>: 被装饰的元素
            </para></listitem>

            <listitem><para>
                    <code>content</code>: 传递给装饰器的内容
            </para></listitem>

            <listitem><para>
                    <code>decorator</code>: 装饰器对象自己
            </para></listitem>

            <listitem><para>
                    另外，所有通过 <code>setOptions()</code> 传递给装饰器的不用于内部（如 placement、 separator 等）的选项作为视图变量传递给视图脚本。
            </para></listitem>
        </itemizedlist>

        <para>
            作为例子，你可以有下列元素：
        </para>

        <programlisting role="php"><![CDATA[<?php
// Setting the decorator for the element to a single, ViewScript, decorator,
// specifying the viewScript as an option, and some extra options:
$element->setDecorators(array(array('ViewScript', array(
    'viewScript' => '_element.phtml',
    'class'      => 'form element'
))));

// OR specifying the viewScript as an element attribute:
$element->viewScript = '_element.phtml';
$element->setDecorators(array(array('ViewScript', array('class' => 'form element'))));
?>]]></programlisting>

        <para>
            你可以接着有一个如下的视图脚本：
        </para>

        <programlisting role="php"><![CDATA[
<div class="<?= $this->class ?>">
    <?= $this->formLabel($this->element->getName(), $this->element->getLabel()) ?>
    <?= $this->{$this->element->helper}(
        $this->element->getName(),
        $this->element->getValue(),
        $this->element->getAttribs()
    ) ?>
    <?= $this->formErrors($this->element->getMessages()) ?>
    <div class="hint"><?= $this->element->getDescription() ?></div>
</div>
]]></programlisting>

        <note>
            <title> 用视图脚本替换内容 </title>

            <para>
                你可能发现用视图脚本来替换提供给装饰器的内容很有用 －－ 例如，如果你想封装它。你可以通过指定一个布尔 false 值给装饰器的 'placement' 选项来做：
            </para>

            <programlisting role="php"><![CDATA[<?php
// At decorator creation:
$element->addDecorator('ViewScript', array('placement' => false));

// Applying to an existing decorator instance:
$decorator->setOption('placement', false);

// Applying to a decorator already attached to an element:
$element->getDecorator('ViewScript')->setOption('placement', false);

// Within a view script used by a decorator:
$this->decorator->setOption('placement', false);
?>]]></programlisting>
        </note>

        <para>
            当你想对元素的解析有个非常精细的控制，建议使用 ViewScript 装饰器。
        </para>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 tw=80 et:
-->
