I cant load my CustomValidator via factory:
namespace My\Validator;
class CustomValidator extends AbstractValidator
{
public function __construct(EntityManager $em, AuthenticationService $auth)
{
$this->auth = $auth;
$this->em = $em;
parent::__construct();
}
Module (My) Config:
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'
),
),
CustomForm:
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);
}
I get a PHP error saying that __construct's first parameter ($em) must be an instance of EntityManager, none given... My Factory is not instantiated... I think my CustomValidator is still created by some other factory (or ValidatorPluginManager?)... How do I have to change my code to get my CustomValidatorFactory working?
EDIT - complete Exception by rendering view with form which has my custom validator attached:
( ! ) 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);
}
}
CustomController
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 - View:
<?php
namespace My;
$form = $this->form;
$form->prepare(); ?>
<!-- HTML Stuff... ->
<?php echo $this->form($form, null); ?>
<!-- HTML Stuff... ->
Well I am using a custom form-renderer too - https://github.com/neilime/zf2-twb-bundle.
I filed an issue at zf2's git: https://github.com/zendframework/zf2/issues/7688
You are creating the form's via the ServiceManager
.
$customForm = $realServiceLocator->get('My\Form\CustomForm');
Which means you have the abstract factory registered with the service manager rather than the form element manager. By doing this the form will be created without form factory's input filter being correctly prepared.
Move this config to the 'form_elements' key.
'form_elements' => [
'abstract_factories' => [
'My\Form\FormAbstractFactory',
],
]
In CustomControllerFactory
you would need to update to.
$formElementManager = $realServiceLocator->get('FormElementManager');
$customForm = $formElementManager->get('My\Form\CustomForm');
And finally the FormAbstractFactory::createServiceWithName()
method will now need $serviceLocator = $serviceLocator->getServiceLocator()
at the top.