Everything is working as expected. There is no name clash because when you use $this->createElement(), the element you create is not actually kept anywhere. With this approach, you must explicitly keep the element in some variable (like a member variable), and then add it to the form element set using $this->addElement().
If you take a look at Zend_Form source code you will notice that:
1- When calling createElement(), the element is created and immediately returned; in other words, the element is not internally kept anywhere, so you must keep it yourself and add it to the form latter:
public function createElement($type, $name, $options = null)
{
...
$element = new $class($name, $options);
return $element;
}
2- When you call addElement(), the element is then added to the form, and internally kept in a protected member array called _elements. This is the same thing as doing:
$this->id = $this->createElement('text', 'id', array(...));
which magically calls addElement() (as pointed by user user594791 in his comment). You could also directly put the element in the _elements array, but I advise against this, because addElement() does some further processing. There are no name clashes because you are doing the same action twice (as pointed by Marcin in the other answer), and in the second time you are overwriting the element with itself.
Finally, I also advise against instantiating elements which you will not use (waste of resources and not very good programming practice). It is preferable to keep an associative array of configurations for possibly necessary elements in your parent class; then, in your sub-classes, you only instantiate the elements you really require, using the respective configuration arrays which were pre-stored in the parent class. An example:
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
);
}
}
If you have many elements, and do not wish to pollute the parent init() method very much, I suggest you place the complete element definitions in an external file, which can be either a PHP file which returns a PHP array with the full configuration, a XML file, INI file, or any other format supported by Zend_Config (you can define the elements without a piece of actual PHP code - here -at the bottom of the page- is an example of defining an element with an INI file).