与工厂形成自定义元素 [英] Form custom elements with factories

查看:85
本文介绍了与工厂形成自定义元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们曾经使用ZF2,但是在上一个项目中,我们决定从ZF3开始.
现在,我在表单创建过程中遇到了一个问题.

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.

我在ZF2中所做的是使用ServiceLocatorAwareInterface创建一个扩展选择的类,例如:

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.

记住要使用工厂,我在module.config.php中尝试了此配置:

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');
        }
    ]
]

结果:始终调用CarForm的工厂,但不调用ManufacturerSelect的工厂.

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

一个简单的解决方案是直接在表单类中填充选择,但是我更喜欢使用工厂作为元素,并在需要的任何地方重用它,就像我在ZF2中所做的那样.

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?

推荐答案

是否在"__construct"函数中添加了该元素?如果是这样,请尝试初始化"

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

首先,您不需要创建自定义选择即可通过数据库进行填充.只需使用工厂创建一个表单,从工厂中的db获取数据,然后传递给表单即可.并将表单类中的数据用作select的值选项.

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
    ]
]);

如果您将表单创建为:

new MyForm();

表单元素管理器不会触发自定义元素的工厂.但是;

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

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

触发自定义元素的工厂.这是一个工作示例.它正在ZF3上运行.

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

配置:

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

不要忘记在应用程序配置的模块"中添加"Zend \ Form".

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

元素:

class CustomElement extends Text
{
}

元素工厂:

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

字段集/表单:

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

字段集/表单工厂:

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

控制器的工厂:

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);
            );
        }
}

这篇关于与工厂形成自定义元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆