Categories
Web Development

How to access Doctrine in Symfony 5+ services

Scroll down to the answer part if you just want the answer.

From what I can tell the Symfony documentation only shows how to access doctrine in your controllers( I am sure it is somewhere). But what if you need to access it in a service?

Services are any class within a folder inside the src folder, Repository folder for example. In Symfony 5+ every folder within src directory is considered a service folder, meaning the classes inside are services.

My current app has a very complex registration system and other forms. Not all of the fields are saved, and some go to different tables after processes are applied. For example the user alias is turned into a URL safe string to be used as their profile page.

So I started with all of the code I needed directly in the controller method, but that was a few hundred lines. Usually when I have a complex form that needs specific processing I create a processing class and save it in a folder called FormProcessors. Much of this same code can later be used with RabbitMq for example.

Inside the form processors I have public and private methods. I call the public methods from the controller methods to process the forms. You could split the code up within your controller class using private methods. I do that sometimes as I am building the form, I then move it to the form processors.

One added benefit of using the form processors is the logic can be copied over to new classes used with something like RabbitMQ when I move to an Event based system or microservices etc.

So I needed to figure out how to get to the dang doctrine orm inside my form processors, which is a service.

The answer

The answer is to type hint your Service class constructors with EntityManagerInterface like this(there are probably other ways too)

class RegistrationProcessor
{
    private Form $form;
    private array $errors;
    private array $filtered;
    private EntityManagerInterface $entityManager;
    private MysqlConnection $mysqlConnection;
    private UserPasswordEncoderInterface $passwordEncoder;

    public function __construct( EntityManagerInterface $entityManager,
                                 MysqlConnection $mysqlConnection,
                                 UserPasswordEncoderInterface $passwordEncoder,
                                 Form $form)
    {
        $this->entityManager = $entityManager;
        $this->form = $form;
        $this->filtered = array();
        $this->errors = array();
        $this->mysqlConnection = $mysqlConnection;
        $this->passwordEncoder = $passwordEncoder;
    }

Then to use it, you do this where you need it.

public function saveUserAlias( User $user, string $alias, DateTimeInterface $dateTimeObject){
       $userAlias = new UserAlias();
       $userAlias->setUser($user);
       $userAlias->setAlias($alias);
       $userAlias->setDatetimeAdded($dateTimeObject);
       $this->entityManager->persist($userAlias);
       $this->entityManager->flush();
   }

Notice it is as simple as two calls to entityManager. You don’t have to even get the Repository. However you may get an error if you do not have your Repositories defined in your entities.

 

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.