一切都按预期工作。没有名称冲突,因为当您使用 $this->createElement() 时,您创建的元素实际上并没有保存在任何地方。使用这种方法,您必须将元素显式保存在某个变量(如成员变量)中,然后使用 $this->addElement() 将其添加到表单元素集。
如果您查看 Zend_Form 源代码,您会注意到:
1- 调用createElement()时,元素被创建并立即返回;换句话说,该元素没有在内部保存在任何地方,因此您必须自己保存它并将其添加到后者的表单中:
public function createElement($type, $name, $options = null)
{
...
$element = new $class($name, $options);
return $element;
}
2- 当您调用 addElement() 时,该元素随后被添加到表单中,并在内部保存在名为 _elements 的受保护成员数组中。这和做的一样:
$this->id = $this->createElement('text', 'id', array(...));
它神奇地调用了 addElement() (正如用户 user594791 在他的评论中指出的那样)。您也可以直接将元素放入 _elements 数组中,但我建议不要这样做,因为 addElement() 会进行一些进一步的处理。没有名称冲突,因为您两次执行相同的操作(正如 Marcin 在另一个答案中指出的那样),第二次您正在用自身覆盖元素。
最后,我还建议不要实例化您不会使用的元素(浪费资源并且不是很好的编程习惯)。最好为父类中可能需要的元素保留一个关联的配置数组;然后,在您的子类中,您只需使用预先存储在父类中的相应配置数组来实例化您真正需要的元素。一个例子:
class ParentForm extends Zend_Form {
...
protected $_elementConfig;
...
public function init() {
...
// Add element configuration, but don't instantiate element right now
$this->_elementConfig = array();
// Element 1, a text input
$this->elementConfig['myTextInput'] = array(
'Text',
array(
'label' => 'Theme',
'description' => 'Main application theme',
'maxLength' => 128,
'validators' => array(
array('StringLength', false, array('max' => 128))
),
'filters' => array(
array('HtmlEntities')
)
)
);
// Element 2, a submit button
$this->elementConfig['mySubmitButton'] = array(
'Submit',
array(
'label' => 'Save'
)
);
// Element 3, something else
...
}
...
}
class ChildForm extends ParentForm {
public function init() {
parent::__construct(); // Parent init() is called by the parent constructor
...
// Will use the submit button
$this->addElement(
$this->_elementConfig['mySubmitButton'][0], // Type of element
'mySubmitButton', // Name of element
$this->_elementConfig['mySubmitButton'][1] // Config of element
);
}
}
如果你有很多元素,并且不希望过多地污染父 init() 方法,我建议你将完整的元素定义放在一个外部文件中,该文件可以是一个 PHP 文件,它返回一个 PHP 数组完整配置、XML 文件、INI 文件或 Zend_Config 支持的任何其他格式(您可以在没有实际 PHP 代码的情况下定义元素 - here -在页面底部 - 是定义元素的示例使用 INI 文件)。