Active record (Eloquent) vs Data mapper (Doctrine)
In the most of systems need to save data somewhere and in some way. ORM (Object-Relational Mapping), is the way of mapping the system to the database. ORM is the layer between database and application which deals with creating, updating, reading and deleting.
How we can see in this picture DataMapper and ActiveRecord belong to layer Data access, which for example during getting data from the database returns respectively filled object instead of plain record.
Active record
The instance of a model in Active record pattern is highly coupled with the single database record. The specific implementation of a model inherits from the base model. Don’t need to set properties of the object, because they’re the same as columns in the table. For example in Eloquent (Laravel’s ORM) in the base model is used magic method __get() and if we want to get the email from the User model we should write code like following:
echo $user->email;
Inside of is executing accordingly:
public function __get($key) { return $this->getAttribute($key); }
And:
public function getAttribute($key) { if (! $key) { return; } // If the attribute exists in the attribute array or has a "get" mutator we will // get the attribute's value. Otherwise, we will proceed as if the developers // are asking for a relationship's value. This covers both types of values. if (array_key_exists($key, $this->attributes) || $this->hasGetMutator($key)) { return $this->getAttributeValue($key); } // Here we will determine if the model base class itself contains this given key // since we don't want to treat any of those methods as relationships because // they are all intended as helper methods and none of these are relations. if (method_exists(self::class, $key)) { return; } return $this->getRelationValue($key); }
So the model keeps the record from the database loaded to an array and just returns specific values.
If we want to save the model we will invoke:
$user->save();
Here we have the violation of Single Responsibility Principle. The object saving itself. However Active Record isn’t a bad choice. Everything depends on what application we’re creating. If these are simple CRUDs, no business logic then this pattern is a good solution for them. With Active record, it will work Database first approach, so first database project then code. Another advantage is the fast development of applications based on this pattern. Using Data mapper we have to handle more things, so in effect give us more work hours. So Active record is also good for creating prototypes.
Data mapper
The model in Data mapper pattern is the completely separated entity, which isn’t aware how and where it’s saving. In the case of complex models is a big advantage. In effect business logic is clearly exposed to programmers.
In this pattern filled are also real properties of an object, so the model automatically grow up, because we have to implement them all and specific accordingly.
<?php use Doctrine\ORM\Mapping AS ORM; /** * @ORM\Entity * @ORM\Table(name="users") */ class User { /** * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") */ private $id; /** * @ORM\Column(type="string") */ private $email; ... }
Saving models look something like that:
$entityManager->persist($user); $entityManager->flush();
In the case when the model is anemic i.e. contains only setters, getters and doesn’t have behaviors, a better choice is Active Record. Of course, during designing application, we need to think, because even from a very complex model it’s possible to make anemic, moving responsibilities to services, controllers or in any other place.
Designing in this case should start from code, not from the database.
Subscribe and master unit testing with my FREE eBook (+60 pages)! 🚀
In these times, the benefits of writing unit tests are huge. I think that most of the recently started projects contain unit tests. In enterprise applications with a lot of business logic, unit tests are the most important tests, because they are fast and can us instantly assure that our implementation is correct. However, I often see a problem with good tests in projects, though these tests’ benefits are only huge when you have good unit tests. So in this ebook, I share many tips on what to do to write good unit tests.
Leave a Reply