# Active Record vs Data Mapper
###### tags: `其他`
當我們要對資料庫進行操作時,蠻常使用 ORM(Object-Relational Mapping) 的方式,讓我們以物件的方式對資料庫進行操作,可以讓數據結構變得簡單易懂,ORM 亦可防止 SQL-Injection
以下是簡單的 ORM 範例,假設 DB 有 User Table,有欄位 `name`,對應的 ORM 物件會變成這樣子:
```php
$user = new User;
$user->name = 'Burgess';
```
假設 user 有關聯多個 group 資料,可使用下列方式取得:
```php
$user->groups;
```
ORM 常見有兩種 pattern,Active Record 及 Data Mapper,以下分別介紹
## Active Record
最廣泛使用的 ORM 模式,例如 PHP Laravel 的 Eloquent、golang 的 GORM 等等,基本上主流的大型 framework 大部分都是使用這種 pattern,因為簡單易上手。
Active Record 有幾項特點
- object 既有資料(data)也有行為(behavior),可以把資料邏輯放在 model 裡頭,讓使用的人知道如何去取用
```php
$user = new User;
$user->name;
$user->all();
$user->find(1);
```
- 會將 object 對應到 database row,不用特別指定 model properties 跟 database 的關係,也可以直接操作 properties
```php
//Active Record 會把 user object 轉換成 database row
$user = new User;
$user->name = 'Burgess II';
$user->isHandsome = true;
$user->save();
...
```
- 總之會有一個功能強大的 object,可以支援各種的資料操作行為。
## Data Mapper
分成 Domain Object(Entity) 及 persistence layer(EntityManager),domain object 不會去管理資料如何存取,資料存取交由 persistence layer(EntityManager) 負責
以下以 PHP Doctrine ORM 為例
```php
class User
{
private $id;
private $name;
public function getName(): string
{
return $this->name;
}
public function setName(string $name): void
{
$this->name = $name;
}
}
```
```php
//update
$user = new User();
$user->setName('Burgess II');
$entityManager->persist($user);
$entityManager->flush();
// get
$userRepository = $entityManager->getRepository('User');
$users = $userRepository->findAll();
$user = $entityManager->find('User', 1);
```
對資料進行操作時,需要透過 entityManager,不會有萬能卻肥大的 Domain Object(Entity),但是寫法上可能稍微複雜一些
## 參考資料
- [What's the difference between Active Record and Data Mapper?](https://culttt.com/2014/06/18/whats-difference-active-record-data-mapper)
- [Martin Fowler Active Record](https://www.martinfowler.com/eaaCatalog/activeRecord.html)
- [Doctrine ORM](https://www.doctrine-project.org/projects/doctrine-orm/en/latest/index.html)