Markus,这是我使用的一个似乎效果不错的解决方案,希望它适合你。
首先,为了呈现没有<dl> 标签的表单,我们需要在表单对象本身上设置装饰器。在扩展 Zend_Form 的类内部,您可以调用 Zend_Form->setDecorators() 并传递一个表单装饰器数组。
来自参考指南:
The default decorators for Zend_Form are FormElements, HtmlTag (wraps in a definition list), and Form; the equivalent code for creating them is as follows:
$form->setDecorators(array(
'FormElements',
array('HtmlTag', array('tag' => 'dl')),
'Form'
));
要将表单包装在 dl 以外的其他东西中,我们使用上述装饰器,但将 dl 更改为您使用的任何标签,我通常使用 form 类的 div,我们稍后会看到。
接下来,需要处理元素。 Zend_Form 元素对不同类型的元素有不同的装饰器。以下每组元素类型都有自己独特的一组装饰器:[Submit & Button]、[Captcha]、[File]、[Image] 和 [Radio*]。 radio 的装饰器与标准元素非常相似,只是它没有在标签内指定for 属性。
所有其他表单元素、文本、密码、选择、复选框等都使用同一组默认装饰器。
要从单个表单元素中删除 dd/dt 标签,我们需要对其应用我们自己的一组装饰器。下面是一个不使用 dd/dt 标签的例子:
array(
'ViewHelper',
'Errors',
array('Description', array('tag' => 'p', 'class' => 'description')),
array('HtmlTag', array('class' => 'form-div')),
array('Label', array('class' => 'form-label'))
);
这会将每个表单元素包装在一个带有form-div 类的div 标记中。问题是,您必须将这组装饰器应用于您不想被包装在 dd/dt 标签中的每个元素,这可能有点问题。
为了解决这个问题,我创建了一个从 Zend_Form 扩展的类,并为其提供一些默认行为和与 Zend_Form 的默认装饰器不同的装饰器。
虽然我们不能让 Zend_Form 自动将正确的装饰器分配给特定的元素类型(您可以将它们分配给特定的元素 names),但我们可以设置一个默认值,让自己轻松访问装饰器来自一个地方,因此如果需要更改,可以轻松更改所有表单。
这是基类:
<?php
class Application_Form_Base extends Zend_Form
{
/** @var array Decorators to use for standard form elements */
// these will be applied to our text, password, select, checkbox and radio elements by default
public $elementDecorators = array(
'ViewHelper',
'Errors',
array('Description', array('tag' => 'p', 'class' => 'description')),
array('HtmlTag', array('class' => 'form-div')),
array('Label', array('class' => 'form-label', 'requiredSuffix' => '*'))
);
/** @var array Decorators for File input elements */
// these will be used for file elements
public $fileDecorators = array(
'File',
'Errors',
array('Description', array('tag' => 'p', 'class' => 'description')),
array('HtmlTag', array('class' => 'form-div')),
array('Label', array('class' => 'form-label', 'requiredSuffix' => '*'))
);
/** @var array Decorator to use for standard for elements except do not wrap in HtmlTag */
// this array gets set up in the constructor
// this can be used if you do not want an element wrapped in a div tag at all
public $elementDecoratorsNoTag = array();
/** @var array Decorators for button and submit elements */
// decorators that will be used for submit and button elements
public $buttonDecorators = array(
'ViewHelper',
array('HtmlTag', array('tag' => 'div', 'class' => 'form-button'))
);
public function __construct()
{
// first set up the $elementDecoratorsNoTag decorator, this is a copy of our regular element decorators, but do not get wrapped in a div tag
foreach($this->elementDecorators as $decorator) {
if (is_array($decorator) && $decorator[0] == 'HtmlTag') {
continue; // skip copying this value to the decorator
}
$this->elementDecoratorsNoTag[] = $decorator;
}
// set the decorator for the form itself, this wraps the <form> elements in a div tag instead of a dl tag
$this->setDecorators(array(
'FormElements',
array('HtmlTag', array('tag' => 'div', 'class' => 'form')),
'Form'));
// set the default decorators to our element decorators, any elements added to the form
// will use these decorators
$this->setElementDecorators($this->elementDecorators);
parent::__construct();
// parent::__construct must be called last because it calls $form->init()
// and anything after it is not executed
}
}
/*
Zend_Form_Element default decorators:
$this->addDecorator('ViewHelper')
->addDecorator('Errors')
->addDecorator('Description', array('tag' => 'p', 'class' => 'description'))
->addDecorator('HtmlTag', array('tag' => 'dd',
'id' => array('callback' => $getId)))
->addDecorator('Label', array('tag' => 'dt'));
*/
现在要使用这个类,从这个基类扩展你的所有表单,然后像往常一样分配元素。如果您使用Zend_Form_Element_XXX 而不是addElement(),那么您需要将装饰器之一作为选项传递给元素构造函数,如果您使用 Zend_Form->addElement,那么它将使用我们分配的默认装饰器$elementDecorators在课堂上。
这是一个展示如何从该类扩展的示例:
<?php
class Application_Form_Test extends Application_Form_Base
{
public function init()
{
// Add a text element, this will automatically use Application_Form_Base->elementDecorators for its decorators
$this->addElement('text', 'username', array(
'label' => 'User Name:',
'required' => false,
'filters' => array('StringTrim'),
));
// This will not use the correct decorators unless we specify them directly
$text2 = new Zend_Form_Element_Text(
'text2',
array(
'decorators' => $this->elementDecorators, // must give the right decorator
'label' => 'Text 2'
)
);
$this->addElement($text2);
// add another element, this also uses $elementDecorators
$this->addElement('text', 'email', array(
'label' => 'Email:',
'required' => false,
'filters' => array('StringTrim', 'StringToLower'),
));
// add a submit button, we don't want to use $elementDecorators, so pass the button decorators instead
$this->addElement('submit', 'submit', array(
'label' => 'Continue',
'decorators' => $this->buttonDecorators // specify the button decorators
));
}
}
这显示了一种非常有效的方法来摆脱 dd/dt 和 dl 元素并用您自己的元素替换它们。必须为每个元素指定装饰器有点不方便,而不是能够将装饰器分配给特定元素,但这似乎运作良好。
要添加一个我认为您想要做的解决方案,如果您想渲染一个没有标签的元素,只需创建一个新的装饰器并从中省略标签装饰器,如下所示:
$elementDecorators = array(
'ViewHelper',
'Errors',
array('Description', array('tag' => 'p', 'class' => 'description')),
array('HtmlTag', array('class' => 'form-div')),
// array('Label', array('class' => 'form-label', 'requiredSuffix' => '*'))
// comment out or remove the Label decorator from the element in question
// you can do the same for any of the decorators if you don't want them rendered
);
如有任何问题,请随时要求澄清,希望这会对您有所帮助。