Configuring API Platform resources by following DDD principles

Ivan Brcko
Distant Horizons
Published in
3 min readMay 28, 2020

API Platform is a powerful API building tool created on top of the Symfony framework. It makes bootstrapping your API resources with CRUD functionalities by annotating your entities with the @ApiResource() annotation almost trivial.

But, as it turns out, there are some drawbacks to that approach. By using the API Platform, you are coupling your domain entities with the API Platform resources and you are exposing your domain entities to the client. And don’t even get me started on the DDD principles.

Luckily, amazing people behind the API Platform have thought about that and have added a mechanism to decouple your entities from your API resources.

In this post, I’m going to show you how to configure your API resources in an XML format, decoupled from your domain models, and I’ll also add a cherry on top with a couple of elements regarding serialization.

How to make our entities/domain models

And that’s it, now we have our domain models.

Let’s repeat what we are aiming for:

  1. Our domain models to be decoupled from the API Platform configuration
  2. Our domain models to not be the same as API resources

How to configure our API resources in an XML format

First, let’s tweak our API Platform configuration file to read mappings from our XML file:

Now, after we have told the API Platform where to look for API resources configuration, the only thing left is to create our XML file.

Our API resources configuration is pretty simple. We have made our model available as a resource, supporting a single item retrieval and item creation, but with a twist. And we’ve also added the input and output attributes to those operations.

Input and output attributes are saying which classes are accepted as objects for reading and creating a resource instance. Or as the docs say:

The input attribute is used during the deserialization process when transforming the user-provided data to a resource instance. Similarly, the output attribute is used during the serialization process.

We have also added attributes for serialization groups (denormalization and normalization contexts), which allow us to choose which resource attributes will be exposed during a serialization process.

Next step — we should create our DTOs.

How to create our DTOs

Great, that was easy.
Let’s continue and create data transformers that will be in charge of converting our input DTO to the resource object and the other way around.

How to create data transformers

An input transformer:

And an output transformer:

And we are done!
We have successfully achieved our goals:

  1. Our models are decoupled from the API Platform configuration
  2. Our models are not resources exposed through the API

And as a cherry on top, let’s make use of those aforementioned serialization groups.

How to configure serialization groups in an XML format

Like we already did, let’s update our framework configuration file first:

And now we can create that XML file, and add groups to all of the attributes that we want to be serialized and deserialized:

What we configured in serialization.xml is:

When /GET request is sent to retrieve a Post, our API will expose:

When a /POST request is sent to create a new Post, we allow a Comment to be created together with it, and payload sent to the API should look like:

And that’s that — thank you for sticking with me. Happy configuring!

_____
We’re available for partnerships and open for new projects.
If you have an idea you’d like to discuss, share it with our team!

Originally published at https://www.bornfight.com.

--

--