Both patterns deal with how you control your persistence layer in an object-oriented project on relational bases. The two standards were proposed by Martin Fowler in the book "Patterns of Enterprise Application Architecture". Trying to explain the patterns:
Active Record
In Active Record the object has its basic CRUD operations in itself. This makes it easier to consult it. Exemplifying in PHP would look something like this:
class Customer
{
// Necessário injetar a base aqui
protected $db;
// Propriedades do objeto (colunas)
public $id;
public $name;
public function __construct(PDO $db) {
$this->db = $db;
}
public function do_something() {
$this->bar .= uniqid();
}
public function save() {
if ($this->id) {
$sql = "UPDATE customer SET name = :bar WHERE id = :id";
$statement = $this->db->prepare($sql);
$statement->bindParam("name", $this->name);
$statement->bindParam("id", $this->id);
$statement->execute();
}
else {
$sql = "INSERT INTO customer (name) VALUES (:name)";
$statement = $this->db->prepare($sql);
$statement->bindParam("bar", $this->name);
$statement->execute();
$this->id = $this->db->lastInsertId();
}
}
}
In my business class, to manipulate this object, it’s simple, just call his own methods, without delegating to a third class. For example.
class BusinessLogic {
public function saveNewCustomer() {
$customer = new Customer($db);
$customer->name = 'Meu Cliente';
$customer->save();
}
}
Data Mapper
In Data Mapper your class will not have any method relative to CRUD or its operations. There will only be possible getters and setters attributes (depending on the language) and some methods such as clone()
, toString()
and others, if necessary. Thus this object becomes more "clean".
Therefore, to work with an object in the Data Mapper pattern, you must pass the object to a third class that will perform the implemented operations (usually a DAO).
Let us exemplify:
// Classe só com os atributos
class Customer {
public $id;
public $name;
}
And then a DAO that will perform the operations on top of the object Customer
.
class CustomerDAO {
// Necessário injetar o banco ou conexão aqui
protected $db;
public function __construct(PDO $db) {
$this->db = $db;
}
public function saveCustomer(Customer &$customer) {
if ($foo->id) {
$sql = "UPDATE customer SET name = :name WHERE id = :id";
$statement = $this->db->prepare($sql);
$statement->bindParam("name", $foo->name);
$statement->bindParam("id", $foo->id);
$statement->execute();
}
else {
$sql = "INSERT INTO customer (name) VALUES (:name)";
$statement = $this->db->prepare($sql);
$statement->bindParam("name", $foo->name);
$statement->execute();
$foo->id = $this->db->lastInsertId();
}
}
}
And in my business class:
class BusinessLogic {
public function saveNewCustomer() {
$customer = new Customer();
$customer->name = 'Meu Cliente';
$dao = new CustomerDAO($db);
$dao->saveCustomer($customer);
}
}
Finalizing
Well, I’m not going to say which is better or worse. Both patterns have their advantages and disadvantages. I’ve worked with both. In Java with Data Mappers and in Ruby on Rails with Active Record. Test both. There are several frameworks in several languages. See some in PHP:
PHP - Active Record
Most PHP frameworks implement their own Active Record solution. So does Cakephp. In addition to Cake there are a few others:
Take a look, if you can, at Ruby on Rails Active Record.
PHP - Data Mapper
Thank you very much, it was really clear!
– Marcelo Aymone
The answer would be perfect if you put here the advantages and disadvantages of each.
– Maniero
There is only one misconception here: Synfomy is an agnostic framework of "Model", since it is more "centered" on HTTP, like Django. Usually who uses symfony, integrates it with Doctrine or Propel. But in Symfony is with you the part of the model.
– felipsmartins