【问题标题】:ZF2 - Custom Validator via factoryZF2 - 通过工厂定制验证器
【发布时间】:2016-03-13 20:48:20
【问题描述】:

我无法通过工厂加载我的 CustomValidator

namespace My\Validator;
class CustomValidator extends AbstractValidator
{
public function __construct(EntityManager $em, AuthenticationService $auth)
{
    $this->auth = $auth;
    $this->em = $em;

    parent::__construct();
}

模块(我的)配置

namespace My;
...
'service_manager' => array(
  'abstract_factories' => array(
    'Application\Factory\FormAbstractFactory'
  ),
),
'controllers' => array(
    'factories' => array(
        'My\Controller\CustomController' => 'My\Factory\Controller\CustomControllerFactory',
    ),
),
'validators' => array(
    'factories' => array(
        'My\Validator\CustomValidator' => 'My\Factory\Validator\CustomValidatorFactory'
    ),
),

自定义表单

namespace My\Form;
class CustomForm extends SearchForm implements InputFilterProviderInterface {
    public function __construct(ObjectManager $objectManager, Translator $translator) {
        parent::__construct ($objectManager, $translator,  "customForm" );
        // Here are some elements added...
        $this->add(array("name" => "search", /* some more properties */));
    }

    public function getInputFilterSpecification()
    {
        return array(
            'search' => array(
                'validators' => array(
                    array(
                        'name' => 'My\Validator\CustomValidator'
                    )
                )
            )
        );
    }
}

CustomValidatorFactory

namespace My\Factory\Validator;
class CustomValidatorFactory implements FactoryInterface {
public function createService(ServiceLocatorInterface $serviceLocator)
{
    $sl = $serviceLocator->get("service_manager");
    $entityManager = $sl->get('doctrine.entitymanager.orm_default');
    $auth = $sl->get('zfcuser_auth_service');

    return new CustomValidator($entityManager, $auth);
}

我收到一个 PHP 错误,说 __construct 的第一个参数 ($em) 必须是 EntityManager 的一个实例,没有给出... 我的工厂没有实例化......我认为我的 CustomValidator 仍然是由其他一些工厂(或 ValidatorPluginManager?)创建的...... 如何更改我的代码才能让我的 CustomValidatorFactory 正常工作?

编辑 - 通过使用附加了我的自定义验证器的表单呈现视图来完成异常:

( ! ) Fatal error: Uncaught TypeError: Argument 1 passed to My\Validator\CustomValidator::__construct() must be an instance of Doctrine\ORM\EntityManager, none given, called in /xxxxxx/vendor/zendframework/zend-servicemanager/src/AbstractPluginManager.php on line 252 and defined in /xxxxxx/module/My/src/My/Validator/CustomValidator.php on line 32
( ! ) TypeError: Argument 1 passed to My\Validator\CustomValidator::__construct() must be an instance of Doctrine\ORM\EntityManager, none given, called in /xxxxxx/vendor/zendframework/zend-servicemanager/src/AbstractPluginManager.php on line 252 in /xxxxxx/module/My/src/My/Validator/CustomValidator.php on line 32
Call Stack
#   Time    Memory  Function    Location
1   0.0001  369208  {main}( )   .../index.php:0
2   0.1165  11279664    Zend\Mvc\Application->run( )    .../index.php:28
3   0.2780  17578688    Zend\Mvc\Application->completeRequest( )    .../Application.php:356
4   0.2780  17578688    Zend\EventManager\EventManager->triggerEvent( ) .../Application.php:384
5   0.2780  17578688    Zend\EventManager\EventManager->triggerListeners( ) .../EventManager.php:251
6   0.2781  17580376    call_user_func:{/xxxxxx/vendor/zendframework/zend-eventmanager/src/EventManager.php:490} ( )    .../EventManager.php:490
7   0.2781  17580376    Zend\Mvc\View\Http\DefaultRenderingStrategy->render( )  .../EventManager.php:490
8   0.2781  17580376    Zend\View\View->render( )   .../DefaultRenderingStrategy.php:103
9   0.2786  17591848    Zend\View\View->renderChildren( )   .../View.php:200
10  0.2787  17592840    Zend\View\View->render( )   .../View.php:236
11  0.2789  17593272    Zend\View\Renderer\PhpRenderer->render( )   .../View.php:207
12  0.2792  17633952    include( '/xxxxxx/module/My/view/my/view/index.phtml' ) .../PhpRenderer.php:502
13  0.2810  17743208    Zend\Form\Form->prepare( )  .../index.phtml:13
14  0.2810  17743208    Zend\Form\Form->getInputFilter( )   .../Form.php:203
15  0.2819  17885496    Zend\Form\Form->attachInputFilterDefaults( )    .../Form.php:696
16  0.2836  18054248    Zend\InputFilter\Factory->createInput( )    .../Form.php:801
17  0.2837  18054888    Zend\InputFilter\Factory->populateValidators( ) .../Factory.php:265
18  0.2837  18054944    Zend\Validator\ValidatorChain->attachByName( )  .../Factory.php:408
19  0.2837  18054944    Zend\Validator\ValidatorChain->plugin( )    .../ValidatorChain.php:194
20  0.2837  18057312    Zend\ServiceManager\AbstractPluginManager->get( )   .../ValidatorChain.php:97
21  0.2839  18068224    Zend\ServiceManager\ServiceManager->get( )  .../AbstractPluginManager.php:161
22  0.2839  18068920    Zend\ServiceManager\ServiceManager->create( )   .../ServiceManager.php:532
23  0.2839  18068920    Zend\ServiceManager\ServiceManager->doCreate( ) .../ServiceManager.php:599
24  0.2839  18068920    Zend\ServiceManager\AbstractPluginManager->createFromInvokable( )   .../ServiceManager.php:640
25  0.2839  18069160    My\Validator\CustomValidator->__construct( )    .../AbstractPluginManager.php:252

EDIT2 - FormAbstractFactory

class FormAbstractFactory implements AbstractFactoryInterface {

    public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
    {
        return (fnmatch('*Form', $requestedName)) ? true : false;
    }

    public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
    {
        if (class_exists($requestedName)) {
            $entityManager = $serviceLocator->get('doctrine.entitymanager.orm_default');
            $translator    = $serviceLocator->get('translator');

            return new $requestedName($entityManager, $translator);
        }

        return false;
    }

}

CustomControllerFactory:

namespace My\Factory\Controller;
use My\Controller\CustomController;
class CustomControllerFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $realServiceLocator = $serviceLocator->getServiceLocator();
        $entityManager      = $realServiceLocator->get('doctrine.entitymanager.orm_default');
        // Created through FormAbstractFactory
        $customForm          = $realServiceLocator->get('My\Form\CustomForm');
        $orderByService     = $realServiceLocator->get('Application\Service\OrderByServiceAbstract');

        return new CustomController($entityManager, $customForm, $orderByService);
    }
}

自定义控制器

namespace My\Controller;

class CustomController extends AbstractActionController
{
    public function __construct(ObjectManager $entityManager, CustomForm $customForm, OrderByService $orderByService)
    {
        $this->em = $entityManager;
        $this->form = $customForm;
        $this->orderByService = $orderByService;
    }

    public function indexAction()
    {
        // some code...

        $vm = new ViewModel (array(
            "form" => $this->form
        ));

        $vm->setTemplate("my/custom/index");

        return $vm;
    }
}

my/custom/index - 查看:

<?php
namespace My;
$form = $this->form;
$form->prepare(); ?>
<!-- HTML Stuff... ->
<?php echo $this->form($form, null); ?>
<!-- HTML Stuff... ->

我也在使用自定义表单渲染器 - https://github.com/neilime/zf2-twb-bundle

我在 zf2 的 git 提交了一个问题:https://github.com/zendframework/zf2/issues/7688

【问题讨论】:

  • 工厂第一行$serviceLocator-&gt;get("service_manager")应该是$serviceLocator-&gt;getServiceLocator()。此外,将 $serviceLocator 变量重命名为 $validatorPluginManager 可能更有意义,以免造成混淆。
  • 谢谢...我编辑了我的代码并重试了 - 但仍然没有运气。显示的异常仍然提示 AbstractPluginManager 尝试从 Invokable 创建验证器:Zend\ServiceManager\AbstractPluginManager->createFromInvokable()。我认为我配置验证器的方式有问题...有什么线索吗?
  • 你有什么应该工作,虽然我觉得奇怪的是输入过滤器在视图中而不是控制器中抛出这个错误 - 让我认为视图是创建表单的第一个地方?另外,您是通过$formElementManager-&gt;get('name_of_form') 创建表单吗?
  • 请告诉我们您如何实例化表单。只是为了记录,工厂被命名为AlertValidatorFactory,但在配置中你将它称为CustomValidatorFactory。如果您使用 PHP 5.5 使用 FQCNs 而不是字符串,现代编辑器会在该类是否丢失时输入提示,例如:My\Validator\CustomValidator::class =&gt; My\Factory\Validator\CustomValidatorFactory::class
  • @mike sorry 是一个错字(想通过不使用我的域特定关键字(如警报)使其更通用,更正了我的问题)。我在我的配置中测试了你的方法,IDE(Jetbrains PHPStorm)没有抱怨缺少类:namespace My; ... 'validators' => 数组('factories' => 数组(Validator\CustomValidator::class=> Factory\Validator\CustomValidatorFactory::class ), ), ...

标签: forms zend-framework2 factory instantiation custom-validators


【解决方案1】:

您正在通过ServiceManager 创建表单。

$customForm = $realServiceLocator->get('My\Form\CustomForm');

这意味着您将抽象工厂注册到服务管理器而不是表单元素管理器。通过这样做,表单将被创建without form factory's input filter being correctly prepared

将此配置移至“form_elements”键。

'form_elements' => [
     'abstract_factories' => [
          'My\Form\FormAbstractFactory',
     ],
 ]

CustomControllerFactory 你需要更新到。

$formElementManager = $realServiceLocator->get('FormElementManager');
$customForm = $formElementManager->get('My\Form\CustomForm');

最后,FormAbstractFactory::createServiceWithName() 方法现在需要顶部的 $serviceLocator = $serviceLocator-&gt;getServiceLocator()

【讨论】:

  • 非常感谢!我没看到!验证器现在通过工厂实例化。
  • 哦要补充一点:数组键是“abstract_factories”而不是“abstract_factory”...
  • 您可以自己对任何人的帖子提出修改建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-03
  • 2016-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-22
相关资源
最近更新 更多