使用 Zend_Form_Element 生成表单元素表单由元素组成,它一般对应于 HTML 表单输入。Zend_Form_Element 封装了单个表单元素,并完成下列工作:
基础类 插件加载器
下列加载器类型和各种各样的插件加载器方法一起使用:'validate'、 'filter' 和 'decorator'。类型名是大小写敏感的。 和插件加载器交互使用的方法如下:
定制的校验器、过滤器和装饰器是在表单和封装定制功能之间共享功能的简单的办法。 Example #1 定制标签 插件的一个普通用例是来为标准类提供替换。例如,如果想实现一个不同的 'Label' 装饰器 -- 如总要追加冒号 --你可以创建你自己的带有类前缀的 'Label' 装饰器,然后把它加到你的前缀路径。 让我们从定制标签装饰器来开始,给它一个类前缀 "My_Decorator",类文件就是 "My/Decorator/Label.php"。 <?php class My_Decorator_Label extends Zend_Form_Decorator_Abstract { protected $_placement = 'PREPEND'; public function render($content) { if (null === ($element = $this->getElement())) { return $content; } if (!method_exists($element, 'getLabel')) { return $content; } $label = $element->getLabel() . ':'; if (null === ($view = $element->getView())) { return $this->renderLabel($content, $label); } $label = $view->formLabel($element->getName(), $label); return $this->renderLabel($content, $label); } public function renderLabel($content, $label) { $placement = $this->getPlacement(); $separator = $this->getSeparator(); switch ($placement) { case 'APPEND': return $content . $separator . $label; case 'PREPEND': default: return $label . $separator . $content; } } } 现在,当元素寻找装饰器时,就使用这个插件路径: $element->addPrefixPath('My_Decorator', 'My/Decorator/', 'decorator'); 另外,我们可以在表单一级来做以确保所有的装饰器使用这个路径: $form->addElementPrefixPath('My_Decorator', 'My/Decorator/', 'decorator'); 用这个添加的路径,当添加一个装饰器,将首先搜索 'My/Decorator/' 路径来检查是否存在装饰器。结果,如果请求 'Label' 装饰器,'My_Decorator_Label' 将被使用。 过滤器
在校验之前对输入执行规范化常常是有用的并/或必需的 - 例如,你可能想要剥离所有 HTML,在剩下的东东上运行校验来确保提交有效。或者你可能想把输入的数据两边的空格都消掉,这样 StringLength 校验器就不会返回失败。这些操作使用 <?php $filtered = $element->getValue(); ?> 有两个办法添加过滤器:
看一些例子: <?php // 具体的过滤器实例: $element->addFilter(new Zend_Filter_Alnum()); // 合格的全类名: $element->addFilter('Zend_Filter_Alnum'); // 短过滤器名: $element->addFilter('Alnum'); $element->addFilter('alnum'); ?> 短名一般就是过滤器名去掉前缀,缺省就是去掉 'Zend_Filter_' 前缀。另外,首字母不需要大写。
任何时候需要非过滤的数据,使用 <?php $unfiltered = $element->getUnfilteredValue(); ?> 参见 Zend_Filter 文档 有更多关于过滤器的信息。 过滤器带有这些方法:
校验器
如果你赞同安全咒语“过滤输入,转义输出”,你将会校验(“过滤输入”)你的表单输入。 在 两个办法添加校验器到校验器链:
看一些例子: <?php // Concrete validator instance: $element->addValidator(new Zend_Validate_Alnum()); // Fully qualified class name: $element->addValidator('Zend_Validate_Alnum'); // Short validator name: $element->addValidator('Alnum'); $element->addValidator('alnum'); ?> 短名一般就是校验器名去掉前缀,缺省就是去掉 'Zend_Validate_' 前缀。另外,首字母不需要大写。
如果特定的校验失败,为阻止后面的校验工作,传递第二个参数 <?php $element->addValidator('alnum', true); ?>
如果你使用一个字符串名来添加一个校验器,并且这个校验器接受参数给构造器,你可以把这个第三个参数 <?php $element->addValidator('StringLength', false, array(6, 20)); ?>
这样传递参数应该按照它们在构造器里定义的顺序进行。上述例子将带参数 <?php $validator = new Zend_Validate_StringLength(6, 20); ?>
你也可以使用 <?php $element->addValidators(array( array('NotEmpty', true), array('alnum'), array('stringLength', false, array(6, 20)), )); ?> 如果你想做的更明确和更详细,可以使用数组键 'validator'、 'breakChainOnFailure' 和 'options': <?php $element->addValidators(array( array( 'validator' => 'NotEmpty', 'breakChainOnFailure' => true), array('validator' => 'alnum'), array( 'validator' => 'stringLength', 'options' => array(6, 20)), )); ?> 这个用法展示如何在配置文件中配置校验器: element.validators.notempty.validator = "NotEmpty" element.validators.notempty.breakChainOnFailure = true element.validators.alnum.validator = "Alnum" element.validators.strlen.validator = "StringLength" element.validators.strlen.options.min = 6 element.validators.strlen.options.max = 20 注意每个条目有一个键,不管是否需要,这是使用配置文件规定的 --但它也帮助清楚理解哪个参数用于什么。请记住任何校验器选项必需按顺序指定。
为校验一个元素,传递值给 <?php if ($element->isValid($value)) { // valid } else { // invalid } ?>
校验器按顺序处理,除非用 校验失败后,你可以从校验器链读取错误代码和消息: <?php $errors = $element->getErrors(); $messages = $element->getMessages(); ?> (注意:错误消息返回的是一个有错误代码/错误消息对的联合数组)
除了校验器外,你可以用
关于校验器的更多信息,参见 Zend_Validate 文档 。
校验相关的方法包括:
定制错误消息有时,你想定制一条或多条特定的错误消息来替代由附加到元素上的校验器所带的错误消息。 另外,有时候你想自己标记表单无效,从 1.6.0 版开始,通过下列方法来实现这个功能。
所有用这个方式设置的错误可以被翻译。 装饰器对许多 web 开发者来说一个特别的痛苦是 XHTML 表单自己的生成。对于每个元素,开发者需要为元素自己生成 markup,label 是一个典型,并且,如果他们对用户很好,需要为显示校验错误消息生成 markup。在页面元素越多,任务就越不琐碎。
因为装饰器注册顺序的原因 --先注册先执行--你需要确保按合适的顺序来注册装饰器,或者确保以健全的方式设置替换选项。这个是注册缺省装饰器的例子: <?php $this->addDecorators(array( array('ViewHelper'), array('Errors'), array('HtmlTag', array('tag' => 'dd')), array('Label', array('tag' => 'dt')), )); ?> 初始内容由 'ViewHelper' 装饰器生成,它生成表单元素自己。接着,'Errors' 装饰器从元素里抓取错误消息。如果有任何错误,就传递给 'FormErrors' 视图助手来解析。下一个装饰器 'HtmlTag' 在一个 HTML <dd> 标签里封装元素和错误。最后,'label' 装饰器读取元素的标签并传递给 'FormLabel' 视图助手,封装在一个 HTML <dt> 标签里。缺省地,数据预先准备给内容,输出结果基本上是这样的: <dt><label for="foo" class="optional">Foo</label></dt> <dd> <input type="text" name="foo" id="foo" value="123" /> <ul class="errors"> <li>"123" is not an alphanumeric value</li> </ul> </dd> 关于装饰器的更多信息,请阅读 Zend_Form_Decorator 一节。
装饰器带有的方法包括:
元数据和属性
表单元素可能要求另外的元数据。例如,对于 XHTML 表单元素,你可能想指定属性如类或 id,有一组访问器来完成它:
然而大多数时候,你可以把它们当作对象属性来访问,因为 <?php // Equivalent to $element->setAttrib('class', 'text'): $element->class = 'text; ?> 缺省地,在解析过程中所有属性传递给由元素使用的视图助手,并当作该元素标签的 HTML 属性来解析。 标准元素
Zend_Form_Element 方法
配置
该规则的例外包括如下:
这里是一个例子,为每个配置数据类型传递配置的配置文件: [element] name = "foo" value = "foobar" label = "Foo:" order = 10 required = true allowEmpty = false autoInsertNotEmptyValidator = true description = "Foo elements are for examples" ignore = false attribs.id = "foo" attribs.class = "element" onclick = "autoComplete(this, '/form/autocomplete/element')" ; sets 'onclick' attribute prefixPaths.decorator.prefix = "My_Decorator" prefixPaths.decorator.path = "My/Decorator/" disableTranslator = 0 validators.required.validator = "NotEmpty" validators.required.breakChainOnFailure = true validators.alpha.validator = "alpha" validators.regex.validator = "regex" validators.regex.options.pattern = "/^[A-F].*/$" filters.ucase.filter = "StringToUpper" decorators.element.decorator = "ViewHelper" decorators.element.options.helper = "FormText" decorators.label.decorator = "Label" 定制元素
通过继承
有两个方法一般用来扩展元素:
用例子来说明,你在一个表单里生成的所有文本元素需要用 <?php class My_Element_Text extends Zend_Form_Element { public function init() { $this->addPrefixPath('My_Decorator', 'My/Decorator/', 'decorator') ->addFilters('StringTrim') ->addValidator('Regex', false, array('/^[a-z0-9]{6,}$/i')) ->addDecorator('TextItem') ->setAttrib('size', 30) ->setAttrib('maxLength', 45) ->setAttrib('class', 'text'); } } ?> 你接着可以通知表单对象关于元素的前缀路径并开始生成元素: <?php $form->addPrefixPath('My_Element', 'My/Element/', 'element') ->addElement('foo', 'text'); ?>
'foo' 元素现在是
当继承 <?php class My_Element_Text extends Zend_Form_Element { public function loadDefaultDecorators() { $this->addDecorator('ViewHelper') ->addDecorator('DisplayError') ->addDecorator('Label') ->addDecorator('HtmlTag', array('tag' => 'div', 'class' => 'element')); } } ?>
有许多办法定制元素。别忘了阅读
|