我们曾经使用ZF2,但是在上一个项目中,我们决定从ZF3开始。现在我在表单创建中遇到了一个问题。
我想做的是创建一个自定义选择,其中填充了从数据库中检索到的值。
我在ZF2中所做的工作是使用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'
)
);
Now这不可能了,因为已删除了服务定位符,并且有必要使用工厂,但是我一直在努力寻找如何做同样的事情。
记住使用工厂,我在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的工厂。
一个简单的解决方案是直接在表单类中填充选择,但是我更喜欢使用工厂作为元素,并在需要的任何地方重用它,就像我在ZF2中所做的那样。
是否有人已经遇到此问题并找到了解决方案?
编辑:
首先,您不需要创建自定义选择即可通过数据库进行填充。只需使用工厂创建一个表单,在工厂中从db获取数据并传递给表单即可。并使用表单类中的数据作为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上运行。
Config:
return [
'controllers' => [
'factories' => [
MyController::class => MyControllerFactory::class
]
],
'form_elements' => [
'factories' => [
CustomElement::class => CustomElementFactory::class,
MyForm::class => MyFormFactory::class,
]
]
];
不要忘记将“ Zend \ Form”添加到应用程序配置的“模块”。
Element:
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', ], ]) ; } }
字段集/表单工厂:
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); ); } }