使用工厂形成自定义元素

Form custom elements with factories

我们习惯于使用 ZF2,但对于我们的上一个项目,我们决定从 ZF3 开始。
现在我在创建表单时遇到了问题。

我想要做的是创建一个自定义 select 填充从数据库中检索的值。

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

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

}

然后,在表格中使用它,给出全名就足够了

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

现在这不再可能了,因为服务定位器已被删除并且必须使用工厂,但我正在努力寻找如何做同样的事情。

牢记使用工厂,我在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 的工厂不被调用。

一个简单的解决方案是直接以 class 的形式填充 select,但我更愿意为元素使用工厂并在我想要的任何地方重用它,就像我做的那样在 ZF2.

是否有人遇到过这个问题并找到了解决方案?

您是否在“__construct”函数中添加了该元素?如果是这样,请尝试 "init"

编辑:

首先,您无需创建自定义 select 即可通过数据库进行填写。只需使用工厂创建一个表单,从工厂中的数据库中获取数据并传递给表单。并使用表格 class 中的数据作为 select 的值选项。

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

如果您将表单创建为:

new MyForm();

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

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

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

配置:

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

元素:

class CustomElement extends Text
{
}

元素工厂:

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工厂:

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