Permalink
Fetching contributors…
Cannot retrieve contributors at this time
328 lines (250 sloc) 8.28 KB
layout title date categories tags excerpt permalink thumbnail comment private
post
Using DRY concept in Symfony2 Entities
2016-07-25 00:00:00 -0700
articles
Symfony
Symfon2
Doctrine
ORM
Entities
HasLifecycleCallbacks
This is an effort to make Symfony2 workflow (bit more) DRY where Entities are mapped with Doctrine ORM.
true
false

This is an effort to make Symfony2 workflow (bit more) DRY where Entities are mapped with Doctrine ORM.

Such mapped entities sometimes share same attributes between them i.e. id, timestamps etc. In order to use DRY concept here we can create a base entity and then every new entity can extend it to share those attributes. Let's start by creating two entities with repeated attributes.

An Entity is simply a PHP class.

Here are two Entities User and Address, and they are structured as following:

{% highlight php %}

createdAt = new \DateTime(); $this->updatedAt = new \DateTime(); } /** * @ORM\PreUpdate */ public function setUpdatedTimestamp() { $this->updatedAt = new \DateTime(); } ... {% endhighlight %} Now we have two additional custom methods, `setTimestamps` and `setUpdatedTimestamp`. The names for these methods do not really matter so we can name those as we want. First method sets the values for `createdAt` and `updatedAt` attributes just before we **persist a new record** to database. We set the values as `DateTime` object and Symfony2/Doctrine will automatically convert those to required format for database entry. Second method only updates the `updatedAt` value when a database **record is updated**. > We can simply extend the `BaseEntity` to any entity and need not worry about generating a primary key attribute (`id`) and timestamps now on. ### Additional enhancements: We can have as many as enhancement we like to the `BaseEntity` and those will be automatically extended to sub-entities. For example we can have a `save` method to persist the record by keeping all logic in `BaseEntity` instead of a controller. In current situation if we are creating a user we will use following steps inside a controller: {% highlight php %} setName('Foo'); $user->setEmail('foo@bar.co'); $em = $this->getDoctrine()->getEntityManager(); $em->persist($user); $em->flush(); ... {% endhighlight %} By adding following helper method into our `BaseEntity` we can shorten it from 3 lines to 1: {% highlight php %} persist($this); $em->flush(); } ... {% endhighlight %} Now we can simply use the `save` method inside our controller: {% highlight php %} setName('Foo'); $user->setEmail('foo@bar.co'); $user->save(); ... {% endhighlight %} {% highlight php %} ... $addr = new Address(); $addr->setProperty('123'); $addr->setStreet('Foo Road'); $addr->setTown('Fondon'); $addr->save(); ... {% endhighlight %} I hope that this was useful for anyone refactoring their Symfony2 project. Here is the complete [BaseEntity class as a Gist](https://gist.github.com/jabranr/e74b80958a997ffc62b8f8173b7a1e3e). Feel free to suggest any enhancements.