JMSSerializerModule icon indicating copy to clipboard operation
JMSSerializerModule copied to clipboard

Please provide a factory for DoctrineObjectConstrucor

Open berturion opened this issue 10 years ago • 0 comments

Hello. I use this module to keep a serialized doctrine entity in session in json format. I have a problem with the default UnserializeObjectConstructor because when deserialized in a doctrine entity, this entity is considered as a new one. In consequence, if I save a Doctrine object that have a relation with my deserialized entity, Doctrine shows an error like this:

A new entity was found through the relationship (...) that was not configured to cascade persist operations for entity:(...)

So, I figured out that I had to configure Spea/JMSSerializerModule to use DoctrineObjectConstructor instead of UnserializeObjectConstructor.

But, contrary to UnserializeObjectConstructor, DoctrineObjectConstructor is not a simple invokable class. And the constructor needs two objects:

  • interface Doctrine\Common\Persistence\ManagerRegistry $managerRegistry
  • interface JMS\Serializer\Construction\ObjectConstructorInterface $fallbackConstructor

The problem is that there is no implementation of interface ManagerRegistry and obviously, no factory for it.

I resolved this by adding this dependency https://github.com/eddiejaoude/zf2-doctrine2-manager-registry-service in my composer.json.

Once installed I created a factory for DoctrineObjectConstructor:

<?php
namespace Example\Service;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use JMS\Serializer\Construction\DoctrineObjectConstructor;

class DoctrineObjectConstructorFactory implements FactoryInterface
{
    /* (non-PHPdoc)
     * @see \Zend\ServiceManager\FactoryInterface::createService()
     */
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $serv1 = $serviceLocator->get('Doctrine\ManagerRegistry');
        $serv2 = $serviceLocator->get('jms_serializer.unserialize_object_constructor');
        $service = new DoctrineObjectConstructor($serv1, $serv2);
        return $service;
    }

}

And added these entries in my module.config.php:

'service_manager' => array(
    'factories' => array(
        'jms_serializer.doctrine_object_constructor' => 'Example\Service\DoctrineObjectConstructorFactory'
    ),
    'aliases' => array(
        'jms_serializer.object_constructor' => 'jms_serializer.doctrine_object_constructor'
    ),
),

That's it. Now, it works.

My point is that I think that we would not have to use an external module to do this. I think that a ManagerRegistry implementation and factory should be provided by Spea/JMSSerializerModule.

Am I wrong ?

berturion avatar Oct 01 '15 06:10 berturion