Doctrine 2 and the law of demeter

Tags:

Doctrine 2 makes it very convenient to access related objects in your code: Just do a $entity->getRelatedSomething()->getThingValue();

However, this kind of pattern makes for easy errors when getRelatedSomething returns null – and as a side effect of this, you can end up with a lot of code which checks if the value exists before accessing it.

This in turn can make your code more convoluted because of all the conditionals used. The thing is, this is easy to avoid if you stop violating the law of demeter!

The law of demeter?

Simply put, the law of demeter means that you can only access your direct “friends”.

The code

$entity->getRelatedSomething()->getThingValue();

breaks the law.

Our code directly knows $entity, thus we are allowed to access any methods on it. However, getRelatedSomething() returns another object that is not directly known – it’s only directly known by $entity – and thus we are not allowed to access it.

For a more in depth explanation, see Law of Demeter on Wikipedia.

How and why should my code conform to this law?

Let’s consider a practical example:

A User entity might have an avatar image. Or it might not.

Typical code to show the user’s avatar might look like this:

class User {
    /* other stuff here */
 
    public function getAvatar() {
        return $this->avatar;
    }
}
 
<div>
    <?php if($this->user->getAvatar()): ?>
        <img src="<?= $this->user->getAvatar()->getUrl(); ?>" alt="" />
    <?php else: ?>
        <img src="default avatar.jpg" alt="" />
    <?php endif; ?>
</div>

Now this clearly violates the law again: We are accessing the avatar entity which is not directly known to the calling code (it isn’t a member of $this in this case)

Why don’t we just write it like this instead?

<div>
    <img src="<?= $this->user->getAvatarUrl(); ?>" alt="" />
</div>

Doesn’t that look much simpler?

In this case, the entity itself performs the checks necessary, and this simplifies all code which uses it:

class User {
    /* other stuff here */
 
    public function getAvatarUrl() {
        if($this->avatar) {
            return $this->avatar->getUrl();
        }
 
        return '';
    }
}

Why this is good

Besides the most obvious, reduction of complexity in code, this approach also reduces the coupling of the code.

In the first examples, the code which is using the User entity is aware of the internal structure of the relation, even though it only needs the avatar’s URL. Consider that perhaps at some point you might want to change it (maybe to just storing the URL as a field in the user, instead of a relation), and you would need to go and change all the code which used this.

Now, if you wrote the code like in the second example which hides the relation, you would only need to change how the getAvatarUrl method works in the case you wanted to change the structure.

In closing

Of course as with most things, I don’t really recommend just randomly changing all your code to conform to this.

It can require some effort at times and may not be beneficial, but if you find yourself in a case where the code would be simplified by applying this law, then by all means – Fix it!