zendframework / zend-form

Form component from Zend Framework
BSD 3-Clause "New" or "Revised" License
69 stars 87 forks source link

Element::init is called before Element::setOptions when using Zend\Form\Factory but not when using FormElementManager #221

Open Erikvv opened 6 years ago

Erikvv commented 6 years ago

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

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:

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).

weierophinney commented 4 years ago

This repository has been closed and moved to laminas/laminas-form; a new issue has been opened at https://github.com/laminas/laminas-form/issues/3.