0

I am trying to use the DoctrineModule's UniqueObject validator annotation in an entity with Zend\Form (ZF3) but am unable to do so.

Annotation in entity:

 * @Annotation\Validator({"name":"DoctrineModule\Validator\UniqueObject"})

Controller method that uses entity:

public function saveAction()
{   
    $id = (int) $this->params()->fromRoute('id', 0);
    $user = $this->em->getRepository(User::class)->find($id);        
    $builder = new AnnotationBuilder();
    ...

Module.php:

public function getServiceConfig()
{
    return [
        'factories' => [
            'DoctrineModule\Validator\UniqueObject' => function ($serviceManager) {
                $uniqueObject = new DoctrineModule\Validator\UniqueObject(array(
                    'fields' => 'username',
                    'object_repository' => $serviceManager->get('Doctrine\ORM\EntityManager')->getRepository('Application\Entity\User'),
                    'object_manager' => $serviceManager->get('Doctrine\ORM\EntityManager'),
                ));
                return $uniqueObject;
            },
        ],
    ];
}

Error seen:

[Catchable fatal error] Argument 1 passed to DoctrineModule\Validator\UniqueObject::__construct() must be of the type array, none given, called in /var/www/jade/vendor/zendframework/zend-servicemanager/src/Factory/InvokableFactory.php on line 32 and defined
[0] file:///var/www/jade/vendor/doctrine/doctrine-module/src/DoctrineModule/Validator/UniqueObject.php.DoctrineModule\Validator\UniqueObject->__construct:66
[1] file:///var/www/jade/vendor/zendframework/zend-servicemanager/src/Factory/InvokableFactory.php.Zend\ServiceManager\Factory\InvokableFactory->__invoke:32
[2] file:///var/www/jade/vendor/zendframework/zend-servicemanager/src/ServiceManager.php.Zend\ServiceManager\ServiceManager->doCreate:747
[3] file:///var/www/jade/vendor/zendframework/zend-servicemanager/src/ServiceManager.php.Zend\ServiceManager\ServiceManager->get:195
[4] file:///var/www/jade/vendor/zendframework/zend-servicemanager/src/AbstractPluginManager.php.Zend\ServiceManager\AbstractPluginManager->get:143
[5] file:///var/www/jade/vendor/zendframework/zend-validator/src/ValidatorChain.php.Zend\Validator\ValidatorChain->plugin:97
[6] file:///var/www/jade/vendor/zendframework/zend-validator/src/ValidatorChain.php.Zend\Validator\ValidatorChain->attachByName:194
[7] file:///var/www/jade/vendor/zendframework/zend-inputfilter/src/Factory.php.Zend\InputFilter\Factory->populateValidators:428
[8] file:///var/www/jade/vendor/zendframework/zend-inputfilter/src/Factory.php.Zend\InputFilter\Factory->createInput:267
[9] file:///var/www/jade/vendor/zendframework/zend-inputfilter/src/Factory.php.Zend\InputFilter\Factory->createInputFilter:357
[10] file:///var/www/jade/vendor/zendframework/zend-form/src/Factory.php.Zend\Form\Factory->prepareAndInjectInputFilter:545
[11] file:///var/www/jade/vendor/zendframework/zend-form/src/Factory.php.Zend\Form\Factory->configureForm:284
[12] file:///var/www/jade/vendor/zendframework/zend-form/src/Factory.php.Zend\Form\Factory->create:114
[13] file:///var/www/jade/vendor/zendframework/zend-form/src/Factory.php.Zend\Form\Factory->createForm:177
[14] file:///var/www/jade/vendor/zendframework/zend-form/src/Annotation/AnnotationBuilder.php.Zend\Form\Annotation\AnnotationBuilder->createForm:246
[15] file:///var/www/jade/module/Application/src/Controller/UserController.php.Application\Controller\UserController->saveAction:132
[16] file:///var/www/jade/vendor/zendframework/zend-mvc/src/Controller/AbstractActionController.php.Zend\Mvc\Controller\AbstractActionController->onDispatch:78
[17] file:///var/www/jade/vendor/zendframework/zend-eventmanager/src/EventManager.php.Zend\EventManager\EventManager->triggerListeners:271
[18] file:///var/www/jade/vendor/zendframework/zend-eventmanager/src/EventManager.php.Zend\EventManager\EventManager->triggerEventUntil:151
[19] file:///var/www/jade/vendor/zendframework/zend-mvc/src/Controller/AbstractController.php.Zend\Mvc\Controller\AbstractController->dispatch:105
[20] file:///var/www/jade/vendor/zendframework/zend-mvc/src/DispatchListener.php.Zend\Mvc\DispatchListener->onDispatch:119
[21] file:///var/www/jade/vendor/zendframework/zend-eventmanager/src/EventManager.php.Zend\EventManager\EventManager->triggerListeners:271
[22] file:///var/www/jade/vendor/zendframework/zend-eventmanager/src/EventManager.php.Zend\EventManager\EventManager->triggerEventUntil:151
[23] file:///var/www/jade/vendor/zendframework/zend-mvc/src/Application.php.Zend\Mvc\Application->run:332
[24] file:///var/www/jade/public/index.php.include:40
[25] file:///var/www/jade/index.php.{main}:2

Based on discussion in the thread DoctrineModule/issues/585, I injected the FormElementManager into the constructor of the UserController via factory and attached it from there to the AnnotationBuilder:

public function __construct(EntityManager $em, \Zend\Form\FormElementManager $fem)
{
    $this->em = $em;
    $this->fem = $fem;
    ...
}


public function saveAction() {
    ...
    $builder->setFormFactory(new \Zend\Form\Factory($this->fem));
    ...
}

However this simply ended up back at the original error/stack trace. Interestingly, when I dump $this->fem, I do see the UniqueObject validator in the dump output so not clear what's going wrong. I'd appreciate any help or suggestions to get the UniqueObject annotation recognized by the AnnotationBuilder.

Some links I referred to when researching this:

https://github.com/doctrine/DoctrineModule/issues/289 http://permalink.gmane.org/gmane.comp.php.zend.framework.general/41719

Non
  • 1
  • 1

1 Answers1

0

Can try:

<?php
/**
 * Zend Framework Application.
 */

namespace Fork\DoctrineModule\Validator\Factory;

use DoctrineModule\Validator\UniqueObject;

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;

/**
 * UniqueObjectFactory factory.
 *
 * Creates an instance of UniqueObject.
 *
 * @package Blog\Repository\Factory
 * @link    https://github.com/doctrine/DoctrineModule/blob/master/docs/validator.md
 * @link    https://github.com/doctrine/DoctrineModule/blob/master/src/DoctrineModule/Validator/UniqueObject.php
 */
class UniqueObjectFactory implements FactoryInterface
{

    /**
     * Factory for UniqueObject.
     *
     * @param  ContainerInterface $container
     * @param  string $requestedName
     * @param  array $options
     * @return UniqueObject
     */
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        // Get services.
        $entityManager = $container->get('Doctrine\ORM\EntityManager');

        // If 'object_repository' string, try find repository in EntityManager.
        // Sets ObjectManager.
        if (is_string($options['object_repository'])) {
            $options['object_manager']    = $entityManager;
            $options['object_repository'] = $entityManager->getRepository($options['object_repository']);
        }

        return new UniqueObject($options);
    }

}

and in module

<?php
/**
 * Zend Framework Application.
 */

namespace Fork\DoctrineModule;

/**
 * Configuration for Fork\DoctrineModule module.
 *
 * Changes and extends configuration of DoctrineModule module.
 *
 * @link https://github.com/doctrine/DoctrineModule/blob/master/config/module.config.php
 * @link https://github.com/doctrine/DoctrineModule/blob/master/src/DoctrineModule/Module.php
 */
return [
    /**
     * Configurations for Zend Framework services and components.
     */
    'validators' => [
        'factories' => [
            Validator\UniqueObject::class => Validator\Factory\UniqueObjectFactory::class,
        ],
        'aliases' => [
            'UniqueObject' => Validator\UniqueObject::class,
        ],
    ],
];

and in annotation

* @Annotation\Validator({
*    'name': 'UniqueObject',
*    'break_chain_on_failure': 'true',
*    'options': {
*        'object_repository': 'Application\Entity\User', // you have User::class
*        'fields': {'bla-bla-bla'},          // ??? - what you have?
*        'messages': {
*            'objectFound' => "bla-bla-bla"
*       },
*    }, 
* })
novrm
  • 29
  • 1
  • Thanks @novrm. I tried this but the validator does not seem to be located. I see this error: `A plugin by the name "UniqueObject" was not found in the plugin manager Zend\Validator\ValidatorPluginManager #0 /var/www/jade/vendor/zendframework/zend-validator/src/ValidatorChain.php(97): Zend\ServiceManager\AbstractPluginManager->get('UniqueObject', Array) #1 /var/www/jade/vendor/zendframework/zend-validator/src/ValidatorChain.php(194): Zend\Validator\ValidatorChain->plugin('UniqueObject', Array)` – Non Jan 27 '17 at 18:42
  • Seems like this is a common problem: [https://github.com/zendframework/zend-validator/issues/40](https://github.com/zendframework/zend-validator/issues/40) – Non Jan 27 '17 at 18:46