Logo

dev-resources.site

for different kinds of informations.

Creating focused domain applications. A Symfony approach (Saving the entity)

Published at
11/15/2024
Categories
symfony
php
ddd
cleancode
Author
icolomina
Categories
4 categories in total
symfony
open
php
open
ddd
open
cleancode
open
Author
9 person written this
icolomina
open
Creating focused domain applications. A Symfony approach (Saving the entity)

Introduction

In this third post of this series, we are going to create an entity ready to be persisted to the database from the DTO we created in the first article of the series.

Transforming the UserInputDTO into an entity

To start with this section, let's assume we are using doctrine to communicate with the database and our User entity looks like this:

#[ORM\Entity(repositoryClass: UserRepository::class)]
class User
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 150)]
    private string $firstname;

    #[ORM\Column(length: 255)]
    private string $lastname;

    #[ORM\Column(length: 25)]
    private string $dob;

    #[ORM\Column]
    private \DateTimeImmutable $createdAt;

    #[ORM\Column]
    private string $token;

    // getters and setters
}
Enter fullscreen mode Exit fullscreen mode

The fields email, firstname, lastname and dob will be filled with the UserInputDTO values and the createdAt and token fields will be filled following the next rules:

  • The createdAt field will hold the current date.
  • The token field will hold a string of 50 alphanumeric characters.

As we have decided how we are going to fill the entity fields, this part of the code will belong to the domain since it contains domain business rules. So, we need a service domain to do the stuff. Let's code it.

class UserEntityBuilder {

    public function buildEntity(UserInputDTO $userInputDto): User
    {
        $user = new User();
        $user->setEmail($userInputDto->email);
        $user->setFirstname($userInputDto->firstname);
        $user->setLastname($userInputDto->lastname);
        $user->setDob($userInputDto->dob);
        $user->setToken(bin2hex(random_bytes(50)));
        $user->setCreatedAt(new \DateTimeImmutable());

        return $user;
    }
}
Enter fullscreen mode Exit fullscreen mode

As you can see, the UserEntityBuilder buildEntity method creates the User entity following the pre-established rules and returns the entity.

An application service to create and save the entity

Now, we need a service which will be in charge of coordinating the processes involved in saving the entity:

  • Creating the User entity by using our recently created UserEntityBuilder domain service.
  • Using the doctrine EntityManager service to persist the entity on the database. The EntityManager service should be considered as an infrastructure service since it is provided by the Symfony framework through its symfony/orm-pack component.

Let's code it.

class UserCreator {

    public function __construct(
        private readonly UserEntityBuilder $userEntityBuilder,
        private readonly EntityManagerInterface $em,
    ){}

    public function createUser(UserInputDTO $userInputDto): object
    {
        $user = $this->userEntityBuilder->buildEntity($userInputDto);
        $this->em->persist($user);
        $this->em->flush();

        return '.....'; // Return a DTO ready to be used by the presentation layer
    }
}
Enter fullscreen mode Exit fullscreen mode

As you can see in the code above, the UserCreator application layer service uses first the UserEntityBuilder to create the entity and then uses the Doctrine entity manager to save it to the database.

You may have noticed that the "return" line is not complete. ¿ What should we return here?. We will see it in the next and last article of this series :)

What about the entities. Do they belong to the domain ?

This is a good question. In my opinion, they would belong to our domain since, although they represent a mapping of database tables to objects in our application, they encapsulate our decisions regarding the project's data model.
Now, the fact that they can belong to our domain does not mean that they can be used as DTO's. They should be isolated and only be used for saving data to the database and receiving data from there.

Conclusion

In this third article, we have created a domain service to create a User entity ready to be persisted to the database and also have created an application service which saves the entity to the database by using the domain service to create the user and the doctrine entity manager to save it.
In the next and last article, we will learn hot to create an output DTO with the saved user information ready to be returned to the presentation layer.

If you like my content and enjoy reading it and you are interested in learning more about PHP, you can read my ebook about how to create an operation-oriented API using PHP and the Symfony Framework. You can find it here: Building an Operation-Oriented Api using PHP and the Symfony Framework: A step-by-step guide

symfony Article's
30 articles in total
Favicon
From Legacy to Modern: Creating Self-Testable APIs for Seamless Integration
Favicon
Symfony Station Communiqué — 10 January 2025 — A look at Symfony, Drupal, PHP, and other programming news!
Favicon
Symfony Station Communiqué — 03 January 2025 — A look at Symfony, Drupal, PHP, and other programming news!
Favicon
Exploring PHP Frameworks: In-Depth Comparison of Laravel, Symfony, and CodeIgniter
Favicon
WebForms Core Technology in PHP
Favicon
symfony
Favicon
Best PHP, Laravel, and Symfony conferences to attend in 2025
Favicon
PHP Frameworks: hidden errors to avoid
Favicon
Handle your Symfony assets without WebpackEncoreBundle, ViteBundle or AssetMapper
Favicon
Hello from Symfony
Favicon
Symfony Station Communiqué — 27 December 2024 — A look at Symfony, Drupal, PHP, and other programming news!
Favicon
Build a Symfony 7 boilerplate using FrankenPHP, Docker, PostgreSQL and php 8.4
Favicon
SymfonyCon Vienna 2024: Recap of our Experience
Favicon
Using Memcache for Session Storage in Legacy Symfony 1.4/1.5 Projects
Favicon
Doctrine’s Collection filter method - a double-edged sword
Favicon
5 Ways to Optimize Symfony Application Performance
Favicon
Symfony Station Communiqué — 06 December 2024 — A look at Symfony, Drupal, PHP, and other programming news!
Favicon
Symfony monitoring library implementation
Favicon
Symfony Station Communiqué - 29 November 2024. A look at Symfony, Drupal, PHP, and programming news!
Favicon
How To Handle Custom S/DQL Queries On Different Database Engine with DoctrineExpression
Favicon
Symfony Station Communiqué — 15 November 2024. A look at Symfony, Drupal, PHP, and programming news!
Favicon
Another Way to Structure your Symfony Project
Favicon
Automate Symfony EventSubscriberInterface::getSubscribedEvents()
Favicon
Using Symfony’s HeaderBag as a Service: A Debugging Superpower in API Contexts
Favicon
Creating focused domain applications. A Symfony approach (Saving the entity)
Favicon
Symfony Station Communiqué — 11 October 2024. A look at Symfony, Drupal, PHP, and Programming News!
Favicon
Symfony Station Communiqué — 08 November 2024. A look at Symfony, Drupal, PHP, and programming news!
Favicon
Introducing PHP Env Manager: Simplify Environment Management in PHP Applications
Favicon
Creating focused domain applications. A Symfony approach (Returning the result)
Favicon
That Strange PHP Code in Frameworks and CMSs

Featured ones: