use Zend\Form\Factory;
use Zend\Form\Element;
use Zend\Form\FormElementManager\FormElementManagerV3Polyfill;
use Zend\ServiceManager\ServiceManager;
class MyElement extends Element
{
public function init()
{
echo "init\n";
}
public function setOptions($options)
{
echo "setOptions\n"
}
}
// scenario 1, incorrect
// same as calling $this->add() inside a fieldset
$factory = new Factory();
$factory->create([
'type' => MyElement::class,
'options' => [
'my_option' => true
]
]);
echo "\n";
// scenario 2, correct
$formElementManager = new FormElementManagerV3Polyfill(new ServiceManager());
$countrySelect = $formElementManager->get(MyElement::class, [
'my_option' => true
]);
Expected results
setOptions
init
setOptions
init
Actual results
init
setOptions
setOptions
init
Workaround
There are several different workarounds:
Don't use Zend\Form\Factory. This means don't use $this->add() in a fieldset. Write factories which initialize elements and fieldsets.
Manually call ->init() again on the element after it's been created
Implement ElementPrepareAwareInterface instead of InitializableInterface (adds an unused dependency from Element to Fieldset)
I don't see a coherent solution which doesn't involve overhauling how stuff works.
If you move towards constructor injection this would break many factories people wrote.
Zend\ServiceManager\Initializer\InitializerInterface does not support passing options. If it did you could move the setOptions() logic to there with little BC break.
(DelgatorFactoryInterface does support passing options but you'd have to register it for every element).
How can you initialize if you don't have the options?
This is closely related to https://github.com/zendframework/zend-form/issues/138
Code to reproduce the issue
Expected results
setOptions init
setOptions init
Actual results
init setOptions
setOptions init
Workaround
There are several different workarounds:
$this->add()
in a fieldset. Write factories which initialize elements and fieldsets.Proper fix
I don't see a coherent solution which doesn't involve overhauling how stuff works.
If you move towards constructor injection this would break many factories people wrote.
Zend\ServiceManager\Initializer\InitializerInterface does not support passing options. If it did you could move the setOptions() logic to there with little BC break.
(DelgatorFactoryInterface does support passing options but you'd have to register it for every element).