我知道这个话题是在 2 年前讨论过的。但我坚持要解决的困难。
我想创建一个 zf3 表单,其中包含两个以上的 Select 元素。
我想用来自不同存储库的数据填充它们(每个 Select 项目的选项值来自不同的存储库)。
首先,我试图在表单的构造函数中传递服务管理器(从那里我可以访问我的存储库),但我听说这个解决方案根本不适合。
那么如何在我的表单中包含多个存储库来填充我的选择元素?
答案 0 :(得分:1)
Select
的类module.config.php
) 中添加此自定义元素type
Select
的类,例如 BrandSelect
namespace MyModule\Form\Element;
use Laminas\Form\Element\Select;
class BrandSelect extends Select {
protected $repository;
public function __construct($repository, $name = null, $options = []) {
parent::__construct($name, $options);
$this->repository = $repository;
}
/**
* Initialize the element
*
* @return void
*/
public function init() {
$valueOptions = [];
foreach ($this->repository->fetchBrands() as $brand) {
$valueOptions[$brand->getBrandId()] = $brand->getName();
}
asort($valueOptions);
$this->setValueOptions($valueOptions);
}
}
namespace MyModule\Form\Element;
use Laminas\ServiceManager\Factory\FactoryInterface;
use Interop\Container\ContainerInterface;
use MyModule\Db\Repository;
class BrandSelectFactory implements FactoryInterface {
public function __invoke(ContainerInterface $container, $requestedName, $options = null): BrandSelect {
$repository = $container->get(Repository::class);
return new BrandSelect($repository);
}
}
module.config.php
) 中添加此自定义元素namespace MyModule;
return [
// ..
// Other configs
// ..
'form_elements' => [
'factories' => [
Form\Element\BrandSelect::class => Form\Element\BrandSelectFactory::class
]
]
];
type
。 init()
方法中添加所有元素非常重要,否则将无法工作。我还添加了 InputFilterProviderInterface
。module.config.php
配置中添加表单工厂,始终在 form_elements
键下(与 BrandSelect
一样):namespace MyModule\Form;
use Laminas\Form\Form;
use Laminas\InputFilter\InputFilterProviderInterface;
class BrandForm extends Form implements InputFilterProviderInterface {
public function __construct($name = null, $options = []) {
parent::__construct($name, $options);
}
// IT IS REALLY IMPORTANT TO ADD ELEMENTS IN INIT METHOD!
public function init() {
parent::init();
$this->add([
'name' => 'brand_id',
'type' => Element\BrandSelect::class,
'options' => [
'label' => 'Brands',
]
]);
}
public function getInputFilterSpecification() {
$inputFilter[] = [
'name' => 'brand_id',
'required' => true,
'filters' => [
['name' => 'Int']
]
];
return $inputFilter;
}
}
service manager
,而是 FormElementManager
。BrandController
中的表单:<?php
namespace MyModule\Controller;
use Laminas\Form\FormElementManager;
use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\View\Model\ViewModel;
class BrandController extends AbstractActionController {
private $formManager;
public function __construct(FormElementManager $formManager) {
$this->formManager = $formManager;
}
public function addBrandAction() {
$form = $this->formManager->get(\MyModule\Form\BrandForm::class);
// Do stuff
return new ViewModel([
'form' => $form
]);
}
}
namespace MyModule\Controller;
use Laminas\ServiceManager\Factory\FactoryInterface;
use Interop\Container\ContainerInterface;
class BrandControllerFactory implements FactoryInterface {
public function __invoke(ContainerInterface $container, $requestedName, $options = null): BrandController {
$formManager = $container->get('FormElementManager');
return new BrandController($formManager);
}
}
必须在 controllers
中的 module.config.php
键下配置:
namespace MyModule;
return [
// ..
// Other configs
// ..
'controllers' => [
'factories' => [
Controller\BrandController::class => Controller\BrandControllerFactory::class
],
],
'form_elements' => [
'factories' => [
Form\Element\BrandSelect::class => Form\Element\BrandSelectFactory::class
]
]
];