When it comes to working with data in an application, you are probably going to need an ORM in one form or another. An ORM is the layer between the database and your application. By using an ORM, a lot of the hard work of creating, updating, reading and deleting from the database is taken care for us.
I think for the most part, you don’t need to worry about what type of ORM you are using. The majority of modern frameworks usually ship with an ORM out of the box. Laravel for instance ships with Eloquent.
However as you delve deeper into how applications are designed and built and you start to work on applications that have specific characteristics, it’s worth exploring the different types of ORMs that you have available to you.
The two most popular implementations of ORM are Active Record and Data Mapper. In this article I’m going to be exploring the differences between the two patterns, what are the benefits and drawbacks of choosing one over the other and what you should consider when working with an ORM in your own projects.
What is an ORM and why do you need one?
Before I jump into the weeds of explaining the difference between Active Record and Data Mapper, first let me explain what an ORM is and why you need one.
An ORM (Object Relational Mapper) is the layer that sits between your database and your application. In Object Oriented Programming, you work with Objects as your main point of reference.
So for example you might have the following object:
$user = new User(); $user->name = "philipbrown";
However databases such as MySQL can only store values as strings and integers:
+—-+————-+ | id | username | +—-+————-+ | 1 | philipbrown | +—-+————-+
User might have many posts within our application. To retrieve the user’s posts, we might do something like this:
$posts = $user->posts;
However, in the database, the posts would be stored in a table, like this:
+—-+———+——-+ | id | user_id | title | +—-+———+——-+ | 1 | 2 | "..." | +—-+———+——-+
When working with objects in our application, we work with a single object that stores all of the object’s properties and relationships.
However that data is stored as individual values across many tables in a database.
An ORM is the magic layer that transforms data in the form of objects into relational data that can be stored in a database and vice versa.
Now that I’ve explained what an ORM is and why you would want to use one, lets now look at the two most popular implementations of ORM, Active Record and Data Mapper.
What is the Active Record pattern?
The first ORM pattern I will look at is probably also the most popular, Active Record.
If you have ever used a framework such as Ruby on Rails or Laravel, you will probably be already familiar with the Active Record style of ORM.
A typical usage example of Active Record would be:
$user = new User(); $user->username = "philipbrown"; $user->save();
In the example above I’m creating a new
User object, setting the
username and then saving the object to the database.
Active Record style ORMs map an object to a database row. In the example above, we would be mapping the
User object to a row in the
When you crack open the
User model file, you will notice that you don’t have to specify the properties of the object and how they relate to the database. With Active Record style ORMs, the model is able to determine the properties of the model automatically by looking at the schema of the database.
One of the benefits of the Active Record style is that you can simple call the
save() method on the object to update the database. Each model object inherits from a base Active Record object and so you have access to all the methods relating to persistence. This makes the Active Record style very easy to get started with because it is very intuitive.
What is the Data Mapper pattern?
The big difference between the Active Record style and the Data Mapper style is, the Data Mapper style completely separates your domain from the persistence layer. This means none of your model objects know anything about the database.
When using the Data Mapper style, your code will look something like this:
$user = new User(); $user->username = "philipbrown";
So far, not that different to the Active Record style.
However, Data Mapper model objects are just plain PHP objects that have no knowledge of the database. This means we can’t call the
save() method on the object to persist it to the database because it doesn’t exist.
Instead we need to use a completely different service known as an *Entity Manager:
$user = new User(); $user->username = "philipbrown"; EntityManager::persist($user);
The big benefit of the Data Mapper pattern is, your domain objects don’t need to know anything about how they are stored in the database. This means that your objects will be lighter because they don’t have to inherit the full ORM, but also there will be a stricter, more formal process for interacting with the database because you can’t just call the
save() method anywhere in your code.
What are the differences between Active Record and Data Mapper?
Now that I’ve briefly covered the difference between Active Record and the Data Mapper patterns, now I will talk about the benefits and drawbacks of using each style.
I think both Active Record and Data Mapper have both positives and negatives and I definitely don’t think that one pattern is better than the other. As with just about everything else in programming, I think the right answer for choosing which pattern to use is “it depends”.
With that in mind, I think there are two main areas where you should judge which pattern is right for you.
The type of application you are building
The first thing to think about is, what type of application you are building.
I think generally speaking, there are two types of web application, CRUD based applications and Domain based applications.
A CRUD based application is where your code maps cleanly to a database. Typically you will be creating, reading, updating and deleting entities. You might also have relationships between your models, but for the most part, there isn’t really strict rules around how those relationships should be enforced.
When you are building an application that has this kind of “database mindset”, Active Record is the perfect solution. Active Record will allow you to quickly and easily get up and running with a working application.
If however, your application is not built with this “database mindset”, but rather, you are building an application to satisfy the rules and procedures of a business, the Data Mapper pattern might be a better choice. The Data Mapper pattern will enforce certain restrictions of dealing with data and persistence, and it will allow you to encapsulate those business rules within your entities.
The application and the environment you are building it in
Secondly, I think the nature of the application and the environment you are building it in should also be a factor when basing your decision on which pattern to use.
If you are building an Minimum viable product application to test the waters of a new market, I think it makes more sense to use the Active Record pattern. At the outset you don’t know what business rules are going to be important and you never will if you obsess over the architecture of your application.
On the other hand, if you have been brought into an existing business to build a new application from a legacy system, I think it usually makes more sense to use the Data Mapper pattern. An existing business will already have rules and procedures around how their business works. By using the Active Record pattern you will end up trying to force those business rules to play nicely with the “database mindset” of Active Record. The Data Mapper pattern will allow you to encapsulate the domain rules of the business so working with the application is clear and intuitive.
I strongly believe that both the Active Record and the Data Mapper patterns have a place within our developer tool belts. I think it is wrong to categorically say that one pattern is better than the other. Hopefully I’ve shown in this article that each pattern has a time and a place.
Choosing the wrong pattern for an application will always be a mistake, but you can’t blame the tools at your disposal. By being aware of the different methods and ideologies of patterns such as Active Record or Data Mapper, we can make better, more informed decisions on the tools we choose for the current project.
This article has been mostly theory without any real practical examples. If you want to see an excellent, practical tutorial on the differences between Active Record and Data Mapper, I would highly recommend reading How We Code: ORMs and Anemic Domain Models by Chris Fidao.