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 并将其提供给控制器。在控制器本身中,您可以使用受保护的表单 属性.

访问您的表单