过去几周我一直在研究Zend_Form,它即将发布。我想展示一些Cal在他的DevZone报道中没有涵盖的功能(部分原因是其中一些尚未完成),包括:
- 国际化
- 用于显示和逻辑目的的元素分组
- 数组支持
这篇文章将主要作为对其中一些功能的高级概述;如果您正在寻找更深入的报道,请查看单元测试。:-)
国际化
在许多库中使用表单组件时,国际化(i18n)通常很难实现。有许多潜在的翻译目标:标签、提交和重置按钮以及错误消息都可能需要处理。
Zend_Form
允许在元素和表单级别设置翻译对象,还允许为所有表单和元素设置默认翻译对象。我个人觉得后者是最灵活的;在大多数项目中,您只有一组翻译文件,那么为什么不简单地重复使用相同的对象呢?
// Create your translation object $translate = new Zend_Translate(...); // Set it as the default object for all forms and elements: Zend_Form::setDefaultTranslator($translate);
你得到了什么?
- 传说。如果字段集图例有可用的翻译,它将被翻译。
- 标签。如果您提供的标签有可用的翻译,将使用它。
- 按钮。提交、重置和常规表单按钮值将被翻译。
- 错误消息。验证错误消息将被翻译,
Zend_Validate
提供的任何值替换。
换句话说,Zend_Form
中的翻译集成得很好。
元素分组
在Zend_Form
中,我们区分两种类型的元素分组:用于显示目的的分组(DisplayGroups)和用于逻辑目的的分组(SubForms)
使用DisplayGroups,您基本上是在说您希望在视觉上或语义上将页面上的元素组合在一起。通常(默认情况下)这是通过字段集完成的。DisplayGroups提供了一种简单的机制来执行此操作。元素仍然是父表单对象的子对象,但在显示组中呈现。
其他时候,您希望对元素进行逻辑分组。例如,您可能希望将账单地址与送货地址分开分组。这种分组可能是数组键下的简单命名空间(稍后我将详细介绍)、共享过滤器或装饰器,或者在高级用例中,多页表单的单独页面。
Zend_Form
对这些情况的回答是“子表单”。它们实际上是Zend_Form
的子类,唯一真正的区别是类和使用的默认装饰器(默认情况下,它们呈现在字段集中)。由于它们与常规表单共享相同的功能,这意味着它们可以验证其元素、呈现它们自己等。但是,Zend_Form
本身不能迭代或呈现子表单元素;只有子表单可以做到这一点。
子表单的一个潜在强大用例是多页表单。您可以轻松地创建一个由多个子表单组成的表单,并在每页显示一个子表单,在表单提交之间的会话中持久保存数据;只有当所有页面都收到它们的数据时,父表单才有效,允许您最终将数据传递给模型。
显示和逻辑级别的表单分组都是强大的工具,而此功能对于Zend_Form
来说是微不足道的。
数组支持
许多开发人员喜欢在嵌套数组下命名他们的表单元素。这允许对相关数据进行分组,以及在同一页面上具有多个具有相似数据的组。举个例子,想象一个同时显示发货地址和账单地址的表单:
<form action="/foo/bar" method="post"> <fieldset> <legend>Shipping Address</legend> <dl> <dt>Address:</dt> <dd><input name="shipping[address]" type="text" value="" /></dd> <dt>City:</dt> <dd><input name="shipping[city]" type="text" value="" /></dd> <dt>Postal:</dt> <dd><input name="shipping[postal]" type="text" value="" /></dd> </dl> </fieldset> <fieldset> <legend>Billing Address</legend> <dl> <dt>Address:</dt> <dd><input name="billing[address]" type="text" value="" /></dd> <dt>City:</dt> <dd><input name="billing[city]" type="text" value="" /></dd> <dt>Postal:</dt> <dd><input name="billing[postal]" type="text" value="" /></dd> </dl> </fieldset> </form>
PHP将从提交的表单中接收两个数组,’shipping’和’billing’。
Zend_Form
现在允许这样做(从今天开始)。要保留所有现有功能,并允许元素和子表单与其父表单保持分离,您需要进行一些配置:
$shipping = new Zend_Form_SubForm('shipping'); // This next line tells the elements, validators, and decorators that they are // part of an array; by default, the sub form name is used: $shipping->setIsArray(true); // This can also be accomplished by explicitly setting the array name: $shipping->setElementsBelongTo('shipping');
有趣的是,这可以任意深,通过指定数组键,因为它会出现在表单中。因此,举个例子,如果我们想要在“人口统计”数组中返回整个表单,并且“运输”和“账单”是该数组中的键,我们可以执行以下操作:
// Set base key for entire form: $form->setElementsBelongTo('demographics'); // Set subkey for shipping sub form: $shipping->setElementsBelongTo('demographics[shipping]'); // Set subkey for billing sub form: $billing->setElementsBelongTo('demographics[billing]');
当您设置或检索值或验证时,这些数组键会受到尊重。更重要的是,由于它们是可配置的,您可以将它们排除在通用形式之外,只在具体实例中设置它们——允许重复使用和重新使用-目的。
结论
这篇文章主要是作为对Zend_Form
的一些更高级特性的高级概述。在接下来的几周内,更详尽的文档将出现在ZendFramework存储库中,使开发人员能够更深入地了解其功能。希望我已经激起了一些人的胃口,我们会让更多的人尝试当前的代码库。
更新:修复了数组表示法HTML示例以显示单独的帐单地址和送货地址。