# 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)