form_elements 键在 ZF3 的 module.config.php 中被忽略
form_elements key is ignored in module.config.php in ZF3
我无法理解工厂的实际运作方式。我准备了简短的文件来测试它的表单元素。
Application/config/module.config.php
<?php
namespace Application;
use Zend\Router\Http\Literal;
use Zend\Router\Http\Segment;
use Zend\ServiceManager\Factory\InvokableFactory;
use Application\Route\StaticRoute;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
use Application\Form\Factory\AbcFormFactory;
use Application\Form\AbcForm;
return [
'form_elements' => [
'factories' => [
AbcForm::class => AbcFormFactory::class,
],
],
//(...)
];
Application/src/Form/Factory/AbcFormFactory.php
<?php
namespace Application\Form\Factory;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use Application\Form\AbcForm;
class AbcFormFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new AbcForm("It works");
}
}
Application/src/Form/AbcForm.php
<?php
namespace Application\Form;
use Zend\Form\Element;
use Zend\Form\Form;
use Zend\Hydrator\ClassMethods as ClassMethodsHydrator;
use Zend\InputFilter\InputFilter;
class AbcForm extends Form
{
public function __construct($letter='no factory')
{
die($letter);
}
}
上面的代码显示no factory
,所以工厂被忽略了。如果它没有被忽略,它会显示 It works
.
如何为 form_elements 创建合适的工厂?
更新
我在控制器中调用表单:
<?php
namespace Application\Controller;
use Application\Form\AbcForm;
use Zend\Mvc\Controller\AbstractActionController;
class AbcController extends AbstractActionController
{
public function indexAction()
{
$form = new AbcForm();
}
}
什么触发了表单工厂 __invoke 方法?我认为,当通过 new 实现表单 class 时,表单工厂 __invoke 方法应该 运行。还是不行?
您可以通过 new
运算符直接实例化您的表单。在 zend framework 3 中有一个服务容器,其中包含您在模块配置中记下的所有 classes。在本例中,它是 AbcForm
class,它应该通过工厂创建。在这种情况下,您的控制器 class 也应该使用工厂创建。使用依赖注入来告诉控制器使用哪种形式是一种常见的做法。
看看下面的例子。
控制器工厂
namespace Application\Controller\Service;
use Application\Form\AbcForm;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class AbcControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$form = $container->get('FormElementManager')->get(AbcForm::class);
$controller = new AbcController($form);
return $controller;
}
}
控制器本身
namespace Application\Controller;
use Application\Form\AbcForm;
use Zend\Mvc\Controller\AbstractActionController;
class AbcController extends AbstractActionController
{
protected $form;
public function __construct(AbcForm $form)
{
$this->form = $form;
}
public function indexAction()
{
if ($this->form->isValid()) {
// ... and so on
}
}
}
你的模块配置
return [
'controllers' => [
'factories' => [
AbcController::class => AbcControllerFactory::class,
],
],
'form_elements' => [
'factories' => [
AbcForm::class => AbcFormFactory::class,
],
],
'router' => [
'routes' => [
'your-abcform-application' => [
'type' => Literal::class,
'options' => [
'route' => '/application/abcform/',
'defaults' => [
'controller' => AbcController::class,
],
],
],
],
],
];
您必须通过依赖注入将表单移交给控制器的构造函数。因此,我们创建了控制器工厂,它实例化您的表单 class 并将其提供给控制器。在控制器本身中,您可以使用受保护的表单 属性.
访问您的表单
我无法理解工厂的实际运作方式。我准备了简短的文件来测试它的表单元素。
Application/config/module.config.php
<?php
namespace Application;
use Zend\Router\Http\Literal;
use Zend\Router\Http\Segment;
use Zend\ServiceManager\Factory\InvokableFactory;
use Application\Route\StaticRoute;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
use Application\Form\Factory\AbcFormFactory;
use Application\Form\AbcForm;
return [
'form_elements' => [
'factories' => [
AbcForm::class => AbcFormFactory::class,
],
],
//(...)
];
Application/src/Form/Factory/AbcFormFactory.php
<?php
namespace Application\Form\Factory;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use Application\Form\AbcForm;
class AbcFormFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new AbcForm("It works");
}
}
Application/src/Form/AbcForm.php
<?php
namespace Application\Form;
use Zend\Form\Element;
use Zend\Form\Form;
use Zend\Hydrator\ClassMethods as ClassMethodsHydrator;
use Zend\InputFilter\InputFilter;
class AbcForm extends Form
{
public function __construct($letter='no factory')
{
die($letter);
}
}
上面的代码显示no factory
,所以工厂被忽略了。如果它没有被忽略,它会显示 It works
.
如何为 form_elements 创建合适的工厂?
更新 我在控制器中调用表单:
<?php
namespace Application\Controller;
use Application\Form\AbcForm;
use Zend\Mvc\Controller\AbstractActionController;
class AbcController extends AbstractActionController
{
public function indexAction()
{
$form = new AbcForm();
}
}
什么触发了表单工厂 __invoke 方法?我认为,当通过 new 实现表单 class 时,表单工厂 __invoke 方法应该 运行。还是不行?
您可以通过 new
运算符直接实例化您的表单。在 zend framework 3 中有一个服务容器,其中包含您在模块配置中记下的所有 classes。在本例中,它是 AbcForm
class,它应该通过工厂创建。在这种情况下,您的控制器 class 也应该使用工厂创建。使用依赖注入来告诉控制器使用哪种形式是一种常见的做法。
看看下面的例子。
控制器工厂
namespace Application\Controller\Service;
use Application\Form\AbcForm;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class AbcControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$form = $container->get('FormElementManager')->get(AbcForm::class);
$controller = new AbcController($form);
return $controller;
}
}
控制器本身
namespace Application\Controller;
use Application\Form\AbcForm;
use Zend\Mvc\Controller\AbstractActionController;
class AbcController extends AbstractActionController
{
protected $form;
public function __construct(AbcForm $form)
{
$this->form = $form;
}
public function indexAction()
{
if ($this->form->isValid()) {
// ... and so on
}
}
}
你的模块配置
return [
'controllers' => [
'factories' => [
AbcController::class => AbcControllerFactory::class,
],
],
'form_elements' => [
'factories' => [
AbcForm::class => AbcFormFactory::class,
],
],
'router' => [
'routes' => [
'your-abcform-application' => [
'type' => Literal::class,
'options' => [
'route' => '/application/abcform/',
'defaults' => [
'controller' => AbcController::class,
],
],
],
],
],
];
您必须通过依赖注入将表单移交给控制器的构造函数。因此,我们创建了控制器工厂,它实例化您的表单 class 并将其提供给控制器。在控制器本身中,您可以使用受保护的表单 属性.
访问您的表单