Form custom elements with factories

穿精又带淫゛_ 提交于 2020-03-04 23:07:31

问题


We are used to work with ZF2, but for our last project, we decided to start with ZF3.
Now I am facing a problem in the form creation.

What I want to do is to create a custom select populated with values retrieved from database.

What I did in ZF2 was creating a class extending a select, with the ServiceLocatorAwareInterface, like:

class ManufacturerSelect extends Select implements ServiceLocatorAwareInterface {

    public function init() {
        $manufacturerTable = $this->getServiceLocator()->get('Car\Model\ManufacturerTable');
        $valueOptions = [];
        foreach ($manufacturerTable->fetchAll() as $manufacturer) {
            $valueOptions[$manufacturer->getManufacturerId()] = $manufacturer->getName();
        }
        $this->setValueOptions($valueOptions);
    }

    public function getServiceLocator() {
        return $this->serviceLocator;
    }

    public function setServiceLocator(ServiceLocatorInterface $serviceLocator) {
        $this->serviceLocator = $serviceLocator;
    }

}

Then, to use it in a form, it was enough to give the full name

$this->add(
    array(
        'name' => 'manufacturer_id',
        'type' => 'Car\Form\Element\ManufacturerSelect'
    )
);

Now this is not possible anymore, since the service locator was removed and the use of factories is necessary, but I'm struggling to find how to do the same thing.

Keeping in mind to use factories, I tried this configuration in module.config.php:

'form_elements' => [
    'factories' => [
        'Car\Form\Element\ManufacturerSelect' => function ($services) {
            $manufacturerTable = $services->get('Car\Model\ManufacturerTable');
            return new ManufacturerSelect($manufacturerTable);
        },
        'Car\Form\CarForm' => function ($services) {
            $manufacturerTable = $services->get('Car\Model\ManufacturerTable');
            return new CarForm($manufacturerTable, 'car-form');
        }
    ]
]

Result: factory of CarForm is always called, but factory of ManufacturerSelect is not.

A simple solution would be to populate the select directly in the form class, but I would prefer to use the factory for the element and reuse it everywhere I want, like I was doing in ZF2.

Does anyone already encountered this problem and found a solution?


回答1:


Do you add that element in "__construct" function? If so try "init"

EDIT:

First of all you don't need to create a custom select to fill in it via database. Just create a form with factory, fetch data from db in factory and pass to form. And use the data in form class as select's value options.

$this-add([
    'type' => Element\Select:.class,
    'name' => 'select-element'
    'options' => [
        'label' => 'The Select',
        'empty_option' => 'Please choose one',
        'value_options' => $this-dataFromDB
    ]
]);

If you create form as:

new MyForm();

Form Element Manager doesn't trigger custom elements' factories. But;

$container->get('FormElementManager')->get(MyForm::class);

triggers custom elements' factories. Here's a working example. It's working on ZF3.

Config:

return [
    'controllers' => [
        'factories' => [
            MyController::class => MyControllerFactory::class
        ]
    ],
    'form_elements' => [
        'factories' => [
            CustomElement::class => CustomElementFactory::class,
            MyForm::class => MyFormFactory::class,
        ]
    ]
];

don't forget to add 'Zend\Form' to application config's 'modules'.

Element:

class CustomElement extends Text
{
}

Element Factory:

class CustomElementFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        echo 'element factory triggered';
        return new CustomElement();
    }
}

Fieldset/Form:

class MyForm extends Form
{
    public function init()
    {
        $this
            ->add([
                'type'    => CustomElement::class,
                'name'    => 'name',
                'options' => [
                    'label' => 'label',
                ],
            ])
        ;
    }
}

Fieldset/Form Factory:

class MyFormFactory implements FactoryInterface
{
        public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
        {
            echo 'form factory triggered';
            return new MyForm();
        }
}

Controller's Factory:

class MyControllerFactory implements FactoryInterface
{
        public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
        {
            echo 'controller factory triggered';
            return new MyController(
                  $container->get('FormElementManager')->get(MyForm::class);
            );
        }
}


来源:https://stackoverflow.com/questions/44325100/form-custom-elements-with-factories

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!