Take this into account when using doctrine
Tags: doctrine, php, symfony
Published: 2023-04-06 10:43:57

I would like to share with you a common error which can happen when using doctrine and it can be a nightmare until you notice why it's happening.

Let's see it using an example. Imagine we are working with these entities:

```php
#[ORM\Entity(repositoryClass: UserRepository::class)]
class User {

    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;
   
    #[ORM\Column(length: 150)]
    private string $name;

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

    #[ORM\Column(length: 100)]
    private string $email;

    // getters & setters
}

#[ORM\Entity(repositoryClass: UserAddressRepository::class)]
class UserAddress {

    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\ManyToOne]
    private User $user;
   
    #[ORM\Column(length: 150)]
    private string $address;

    // getters & setters
}

```
Now, when you get a request for a new register you do something like this:

```php
$user = new User();
$user->setName('Peter');
$user->setPass('xxxxx');
$user->setEmail('peter.morris@gmail.com');

$address = new UserAddress();
$address->setUser($user);
$address->setAddress('Down street 25B');

$em->persist($user);
$em->persist($address);
$em->flush();

$eventDispatcher->dispatch(new UserRegisteredEvent($user));
```

So far, this code seems right. It creates a user and an Address, persists them on the database and dispatches and event. Let's see now the subscriber:

```php

class UserSubscriber implements EventSubscriberInterface {

    public static function getSubscribedEvents(): array
    {
        return [
            UserRegisteredEvent::class => 'onUserRegistered'
        ];
    }

    public function onUserRegistered(UserRegisteredEvent $e){
       $user = $e->getUser();
       $address = $user->getAddress();
       $addrName = $address->getAddress();
    }
}

```
After executing line _$addrName = $address->getAddress()_ you will get the following error:

```shell                                                
  Call to a member function getAddress() on null  
```

That happens because we've persisted both entities but we have not refreshed user entity. 

To avoid this kind of errors, we can follow the next steps (among others of course):

#### Refresh user object before passing it to the event

```php
$em->persist($user);
$em->persist($address);
$em->flush();

$em->refresh($user);

$eventDispatcher->dispatch(new UserRegisteredEvent($user))
```
This allows us to having user re-hydrated before using in the subscriber.

#### Passing user identifier to the event

```php
$em->persist($user);
$em->persist($address);
$em->flush();

$eventDispatcher->dispatch(new UserRegisteredEvent($user->getId()));

// -------------------------------------------------------

public function onUserRegistered(UserRegisteredEvent $e){
    
    $user = $em->getRepository(User::class)->find($e->getId());

    $user = $e->getUser();
    $address = $user->getAddress();
    $addrName = $address->getAddress();
}
```
This way pass the user identifier to the event so it's the subscriber who gets a fresh user from the database

### Conclusion

This can seem a really simple error but it can be a nightmare when you have a project working on production and you start getting this kind of errors and your code is syntactically correct but not semantically.