Using Doctrine, ramsey/uuid-doctrine and willdurand/hateoas

Using Doctrine, ramsey/uuid-doctrine and willdurand/hateoas

Recently I experimented a bit with Doctrine ORM and the willdurand/Hateoas library to expose my Doctrine objects via an HATEOAS api which luckily is a fairly trivial thing to do. All you need to do is set up the Hateoas serializer and call the respective serialize() method passing your Doctrine object as well the serialization type:

/** @var \Hateoas\Hateoas $hateoas */
$hateoas = \Hateoas\HateoasBuilder::create()
    ->setCacheDir('/tmp')
    ->addMetadataDir('/tmp')
    ->build();

/** @var \Doctrine\ORM\EntityRepository $repository */
$user = $repository->find('33f90f95-3050-4c4e-b381-97140751e88d'); 
echo $hateoas->serialize($user, 'json');


The downside of this approach is that we currently expose our autoincrement database identifiers to the caller which is never a good idea. Luckily the ramsey/uuid-doctrine package offers a Uuid datatype for Doctrine. Simply install the package via Composer and register the datatype with Doctrine:

Type::addType('uuid', 'Ramsey\Uuid\Doctrine\UuidType');

$orm = [
    'url' => 'mysql://myuser:mypass@myhost/mydb', 
    'driver' = 'pdo_mysql'
];
$config = Setup::createAnnotationMetadataConfiguration([
    __DIR__ . '/src/App/Domain'
]);
/** @var EntityManager $entityManager */
$entityManager = EntityManager::create($orm, $config);
$entityManager->getConnection()->getDatabasePlatform()
->registerDoctrineTypeMapping('uuid', 'uuid');


Now the new "uuid" datatype can be used in your domain object, e.g. configure your $id properties like this:

/**
  * @var Uuid
  * @Id
  * @Column(type="uuid")
  * @GeneratedValue(strategy="NONE")
  */


Additionally create a new Uuid instance in the constructor of your domain object:

public function __construct()
{
    $this->id = Uuid::uuid4();
}


Since our "primary key" is now an Uuid object the JMS\Serializer used by the Hateoas library will expose the Uuid object as an object not as the string representation in which are mainly interested in. Luckily there`s a solution to it: Simply register a serialization handler for the Uuid::class like this:

/** @var \JMS\Serializer\SerializerBuilder $seralizer */
$seralizer = \JMS\Serializer\SerializerBuilder::create();
$seralizer->configureHandlers(function(HandlerRegistry $registry) {
    $registry->registerHandler('serialization', Uuid::class, 'json',
	function($visitor, Uuid $obj, array $type) {
	    return $obj->toString();
	}
    );
});


The $seralizer configuration needs to be passed to the \Hateoas\HateoasBuilder on creation time:

/** @var \Hateoas\Hateoas $hateoas */
$hateoas = \Hateoas\HateoasBuilder::create($seralizer)
    ->setCacheDir('/tmp')
    ->addMetadataDir('/tmp')
    ->build();


Tags: , ,

Eintrag von Stephan Hochdörfer am 12.01.2016

comments powered by Disqus