Skip to main content

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

This blog post might be outdated!
This blog post was published more than one year ago and might be outdated!
· 2 min read
Stephan Hochdörfer
Head of IT Business Operations

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();