ZF2 - 通过工厂自定义验证器
ZF2 - Custom Validator via factory
我无法通过工厂加载我的 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 的一个实例,none 给出...
我的工厂没有实例化......我认为我的 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
您正在通过 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->getServiceLocator()
在顶部。
我无法通过工厂加载我的 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 的一个实例,none 给出... 我的工厂没有实例化......我认为我的 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
您正在通过 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->getServiceLocator()
在顶部。