Hydrators configuration key

Hi everyone!

I have been trying to create forms using Laminas Form and Doctrine ORM annotations, and I stumbled upon something.
Have the following form:

/**
 * @ORM\Entity
 * @Form\Hydrator("Doctrine\Laminas\Hydrator\DoctrineObject")
 */
class Doi implements JsonSerializable

This code causes an error like this:

Too few arguments to function Doctrine\Laminas\Hydrator\DoctrineObject::__construct(), 0 passed in /srv/www/htdocs/opm/vendor/laminas/laminas-form/src/FormElementManager.php on line 368 and at least 1 expected

FormElementManager L368 is a method called “getHydratorFromName” (copied here for your convenience):

public function getHydratorFromName(string $hydratorName)
    {
        $services = $this->creationContext;

        if ($services && $services->has('HydratorManager')) {
            $hydrators = $services->get('HydratorManager');
            if ($hydrators->has($hydratorName)) {
                return $hydrators->get($hydratorName);
            }
        }

        // file_put_contents("debug.log", $services->has($hydratorName) ? "has $hydratorName": "does not have $hydratorName");
        if ($services && $services->has($hydratorName)) {
            return $services->get($hydratorName);
        }

        if (! class_exists($hydratorName)) {
            throw new Exception\DomainException(sprintf(
                'Expects string hydrator name to be a valid class name; received "%s"',
                $hydratorName
            ));
        }

        return new $hydratorName();
    }

What suprises me about this method that the execution even reaches the very last line (return new $hydratorName), because my application is both laminas-mvc and laminas-servicemanager based.
My application configuration contains a “HydratorManager”, which points not to the Standalone, but to the full “HydratorPluginManager”:

"service_manager" => array:5 [▼
    "aliases" => array:35 [▼
      //cleared
      "HydratorManager" => "Laminas\Hydrator\HydratorPluginManager"
      //cleared
    ],
    //other keys
]

Additionally, the doctrine-orm-module registers the DoctrineObject-Hydrator like so:

"hydrators" => array:1 [▼
    "factories" => array:1 [▼
      "Doctrine\Laminas\Hydrator\DoctrineObject" => "DoctrineORMModule\Service\DoctrineObjectHydratorFactory"
    ]
  ]

Which should work, because laminas-hydrator registers a service manager with the ServiceListener (laminas-hydrator/src/Module.php#L34) working exactly with that configuration key.

That’s where I pretty much gave up; does anybody know why the FormElementManager is (seemingly) unable to get the Hydrator from the Container despite it being registered (maybe properly)?

This part should initialize the DoctrineObject hydrator since it is mentioned in the hydrators configuration within the laminas-hydrator module.

Seems a bit confusing. Are you sure the Doctrine Laminas Hydrator package is installed and ready to run? Checked the composer.json file already? Is the DoctrineORMModule or DoctrineModule registered in the modules.config.php? Have you dumped the autoload via composer dump-autoload already?

It is usable through a controller action like this:

$builder = new EntityBasedFormBuilder($this->entityManager);
$form = $builder->createForm($opus);
$hydrator = new DoctrineObject($this->entityManager);
$form->setHydrator($hydrator)->setObject($opus);
$form->bind($opus);

Modules are registered and autoload is dumped - exception remains (if DoctrineORMModule and DoctrineModule would not be registered, the whole application which uses doctrine annotations, form builders and entity manager would not function properly, would it?)

The import part is missing here because if no builder with type Laminas\Form\Annotation \AbstractBuilder is set then the hydrator manager of your application can not be found.
Please complete your code example.

Oh sorry, example updated!

You create the entity form builder separated from your application so all custom form elements, element overwrites, hydrators, input filter, filters, validators, etc. can not be used.

You must add the form element manager of your application to the annotation builder. See the code example with “if you need access to the form factory”:


I suggest creating a feature request in the issue tracker of the Doctrine ORM module to simplify the process via a factory or something similar.