Skip to content

Instantly share code, notes, and snippets.

@fesor
Last active March 12, 2024 00:02
Show Gist options
  • Select an option

  • Save fesor/d84451fc6cf00ea62ca5 to your computer and use it in GitHub Desktop.

Select an option

Save fesor/d84451fc6cf00ea62ca5 to your computer and use it in GitHub Desktop.

Revisions

  1. fesor revised this gist Feb 1, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion row_data_gateway.php
    Original file line number Diff line number Diff line change
    @@ -28,7 +28,7 @@ public function update() {
    }

    private function fetchRow() {
    $row = DB::where('id', $this->id')->first();
    $row = DB::where('id', $this->id)->first();
    if (!$row) {
    throw new \UnableToCreateGatewayException('');
    }
  2. fesor revised this gist Feb 1, 2016. 2 changed files with 83 additions and 0 deletions.
    57 changes: 57 additions & 0 deletions row_data_gateway.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,57 @@
    <?php

    class UserGateway {
    // сделав свойства публичным я хочу подчеркнуть то,
    // что этот класс это просто структура данных, состояние без поведения
    private $id;
    public $name;
    public $email;
    public $password;

    // еще раз, это проекция таблицы, а не объект бизнес логики
    public function __constructor(string $id = null) {
    if ($id) {
    $this->id = $id;
    $this->fetchRow();
    } else {
    // если ID не задан, то мы генерируем ноывй
    $this->id = Cuid::cuid();
    }
    }

    public function insert() {
    DB::table($this->tableName)->insert($this->getAttributes());
    }

    public function update() {
    DB::table($this->tableName)->where('id', $this->id)->update($this->getAttributes());
    }

    private function fetchRow() {
    $row = DB::where('id', $this->id')->first();
    if (!$row) {
    throw new \UnableToCreateGatewayException('');
    }
    }

    private function getAttributes() {
    return [
    'id' => $this->id,
    'name' => $this->name,
    'email' => $this->email,
    'password' => $this->password,
    ];
    }
    }

    class User {
    private $gateway;

    public function __construct(UserGateway $gateway) {
    $this->gateway = $gateway;
    }

    public function save() {

    }
    }
    26 changes: 26 additions & 0 deletions table_data_gateway.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,26 @@
    <?php

    class UserTableGateway {
    private $table;

    public function __construct() {
    $this->table = DB::table('users');
    }

    public function insert($name, $email, $password) {
    $this->table->insert(compact('name', 'email', 'password'));
    }

    // пароль должен обновляться отдельно от профиля
    public function updateProfile($id, $name, $email) {
    $this->table->where('id', $id)->update(compact('name', 'email'));
    }

    public function findCoolestUser() {
    return $this->table->orderBy('rating', 'DESC')->first(); //
    }
    }

    $usersTable = new UserTableGateway();
    $usersTable->insert('Sergey', 'fesor@example.com`, password_hash('somepassword', PASSWORD_DEFAULT));
    $user = $usersTable->findCoolestUser(); // вернет нам один ряд
  3. fesor revised this gist Feb 1, 2016. 1 changed file with 25 additions and 5 deletions.
    30 changes: 25 additions & 5 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@

    ## Table Data Gateway

    **Table Data Gateway** предоставляет нам объектное представление отдельных таблиц, с доступом ко всем рядам оных. Его основное предназначение - спрятать SQL как деталь реализации, предоставиви простой CRUD интерфейс для работы с таблицами в соответствии с нуждами приложения. Рассмотрим на примере (для удобства я заменил обычный SQL на Database компонент из Laravel с целью использовать тамошний query builder)
    **Table Data Gateway**, который так же можно встретить под названием DAO (Data Access Object), предоставляет нам объектное представление отдельных таблиц, с доступом ко всем рядам оных. Его основное предназначение - спрятать SQL как деталь реализации, предоставиви простой CRUD интерфейс для работы с таблицами в соответствии с нуждами приложения. Рассмотрим на примере (для удобства я заменил обычный SQL на Database компонент из Laravel с целью использовать тамошний query builder)

    ```php
    class UserTableGateway {
    @@ -33,11 +33,13 @@ $usersTable->insert('Sergey', 'fesor@example.com`, password_hash('somepassword',
    $user = $usersTable->findCoolestUser(); // вернет нам один ряд
    ```

    Основная идея тут - держать все что относится к формированию запросов в одном месте, что бы наш query builder, или же PDO, не расползался по системе. Не изолировать код от хранилища, а предоставить удобный способ взаимодействия с ним. Возможность инкапсулировать различные запросы в рамках этого подхода позволяет сильно уменьшить вероятность ошибок. Однако работать с "сырыми" данными не очень удобно, обычно мы все же хотим работать со всеми данными как с объектами.
    Основная идея тут - держать все что относится к формированию запросов в одном месте, что бы наш SQL, query builder, или же PDO, не расползался по системе. Не изолировать код от хранилища, а предоставить удобный способ взаимодействия с ним. Возможность инкапсулировать различные запросы в рамках этого подхода позволяет сильно уменьшить вероятность ошибок. Однако работать с "сырыми" данными не очень удобно, обычно мы все же хотим работать со всеми данными как с объектами.

    ## Row Data Gateway

    На помощь к нам придет **Row Data Gateway**. При этом подходе мы проэцируем отдельные ряды нашей таблицы на объекты. Ряды знают о том, к какой таблице они пренадлежат, и могут сами себя обновлять и добавлять в таблицу.
    Можно было бы конечно сделать объект, и держать логику хранения данных внутри. Но в таком случае у нас наши сущности будут зависеть от базы данных, и их будет не так уж легко тестировать. Тесты будут требовать подключения к базе данных и от того станут медленными.

    Для решения этой проблемы, нам нужна прослойка между сущностью и базой данных. **Row Data Gateway**. При этом подходе мы проэцируем отдельные ряды нашей таблицы на объекты, которые служат промежуточным звеном и инкпсулируют все детали о том как сохраняется информация в себе. В итоге наши сущности могут работать через этот gateway используя штатные средства языка программирования.

    ```
    class UserGateway {
    @@ -83,18 +85,36 @@ class UserGateway {
    ];
    }
    }
    class User {
    private $gateway;
    public function __construct(UserGateway $gateway) {
    $this->gateway = $gateway;
    }
    public function save() {
    }
    }
    ```

    Данный объект представляет собой простую структуру данных без какого либо поведения. По сути мы могли бы..
    Отдельно стоит заметить, что поскольку Row Data Gateway представляет собой отдельную строку таблицы, для выборки нужных рядов нам нужно уже делать отдельный компонент Finder.

    Как вы можете видеть, с данным подходом мы уже можем добавлять поведение для сущности `User`, работая изнутри с `UserGateway`

    ## Active Record

    Некоторым стало неудобно юзать структурки и они захотели добавлять туда поведение.
    **Active Record** - это Row Data Gateway, к которому добавили логику предметной области. Дописать...

    ## Data Mapper

    AR и Row Data Gateway не очень удобно тестировать. Нам хочется полной независимости от базы данных.

    ## Object Relation Mapping

    TODO

    ## сырой булшит

    По сути мы работаем с объектами нашей базы данных как с обычными объектами. Разлица лишь в том, что каждый способ предоставляет больше возможностей для изоляции от хранилища. Table Data Gateway заставляет нас работать со всей таблицей целиком, Row Data Gateway - с отдельными рядами таблицы. Active Record является развитием идеи Row Data Gateway но уже позволяет инкапсулировать дополнительное поведение. Data Mapper же вообще не приязан к структуре базы данных, и, так же как и в случае с AR, мы можем примешивать объектам поведение.
  4. fesor revised this gist Jan 31, 2016. 1 changed file with 17 additions and 0 deletions.
    17 changes: 17 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -59,12 +59,29 @@ class UserGateway {
    }
    }
    public function insert() {
    DB::table($this->tableName)->insert($this->getAttributes());
    }
    public function update() {
    DB::table($this->tableName)->where('id', $this->id)->update($this->getAttributes());
    }
    private function fetchRow() {
    $row = DB::where('id', $this->id')->first();
    if (!$row) {
    throw new \UnableToCreateGatewayException('');
    }
    }
    private function getAttributes() {
    return [
    'id' => $this->id,
    'name' => $this->name,
    'email' => $this->email,
    'password' => $this->password,
    ];
    }
    }
    ```

  5. fesor revised this gist Jan 31, 2016. 1 changed file with 11 additions and 1 deletion.
    12 changes: 11 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -68,7 +68,17 @@ class UserGateway {
    }
    ```

    Данный объект представляет собой простую структуру данных без какого либо поведения. По сути мы могли бы
    Данный объект представляет собой простую структуру данных без какого либо поведения. По сути мы могли бы..

    ## Active Record

    Некоторым стало неудобно юзать структурки и они захотели добавлять туда поведение.

    ## Data Mapper

    AR и Row Data Gateway не очень удобно тестировать. Нам хочется полной независимости от базы данных.

    ## сырой булшит

    По сути мы работаем с объектами нашей базы данных как с обычными объектами. Разлица лишь в том, что каждый способ предоставляет больше возможностей для изоляции от хранилища. Table Data Gateway заставляет нас работать со всей таблицей целиком, Row Data Gateway - с отдельными рядами таблицы. Active Record является развитием идеи Row Data Gateway но уже позволяет инкапсулировать дополнительное поведение. Data Mapper же вообще не приязан к структуре базы данных, и, так же как и в случае с AR, мы можем примешивать объектам поведение.

  6. fesor revised this gist Jan 30, 2016. 1 changed file with 85 additions and 4 deletions.
    89 changes: 85 additions & 4 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,15 +1,96 @@
    Собственно тут описана основная разница между подходами ActiveRecord и DataMapper. Гидраторы можно впихнуть туда и туда, можно мэпить на любые структуры теоритически, но основное различие в том кто отвечает за сохранение данных.
    Оргенизация слоя хранения данных это всегда не простая задача, с кучей кейсов, вроде блокировки перезаписи, транзакции, сохранение целостности данных. В какой-то момент появились СУБД и обещали решить эти проблемы, но с ними появились новые - как нам работать с состоянием, которое мы храним?

    В рамках ActiveRecord мы работаем с объектами как отображением элементов нашей базы данных, как если бы у нас был прямой доступ к ним без SQL прослойки. В DataMapper мы работаем исключительно с нашими объектами, которые лежат в памяти, и просим отдельную штуку (мэппер) что бы тот синхронизировал состояние объектов в памяти и в базе (сохранил).
    Существует 4 основных подхода для организации рабоыт с базой данных, [Table Gateway](http://martinfowler.com/eaaCatalog/tableDataGateway.html), [Row Data Gateway](http://martinfowler.com/eaaCatalog/rowDataGateway.html), Active Record и Data Mapper. Все эти подходы объеденяет то, что они скрывают от нас базу данных и нюансы работы с ними (в частности SQL). На сегодняшний день самым популярным подходом являются Active Record и Data Mapper, все о них слышали, но для того что бы более полно представлять, как развивалась идея, стоит рассказать и о первых двух.

    Это основное различие в подходах. Мэпить любую структуру на любую структуру мы можем и при том и при другом подходе, но только при варианте с ActiveRecord обычно так не делают (что бы сохранить иллюзию прямой работы с базой). Именно по этому при использовании AR обычно говорят о тестной связанности с базой, а при DM - слабой (мы вообще от нее не зависим по сути).
    ## Table Data Gateway

    **Table Data Gateway** предоставляет нам объектное представление отдельных таблиц, с доступом ко всем рядам оных. Его основное предназначение - спрятать SQL как деталь реализации, предоставиви простой CRUD интерфейс для работы с таблицами в соответствии с нуждами приложения. Рассмотрим на примере (для удобства я заменил обычный SQL на Database компонент из Laravel с целью использовать тамошний query builder)

    ```php
    class UserTableGateway {
    private $table;

    public function __construct() {
    $this->table = DB::table('users');
    }

    public function insert($name, $email, $password) {
    $this->table->insert(compact('name', 'email', 'password'));
    }

    // пароль должен обновляться отдельно от профиля
    public function updateProfile($id, $name, $email) {
    $this->table->where('id', $id)->update(compact('name', 'email'));
    }

    public function findCoolestUser() {
    return $this->table->orderBy('rating', 'DESC')->first(); //
    }
    }

    $usersTable = new UserTableGateway();
    $usersTable->insert('Sergey', 'fesor@example.com`, password_hash('somepassword', PASSWORD_DEFAULT));
    $user = $usersTable->findCoolestUser(); // вернет нам один ряд
    ```

    Основная идея тут - держать все что относится к формированию запросов в одном месте, что бы наш query builder, или же PDO, не расползался по системе. Не изолировать код от хранилища, а предоставить удобный способ взаимодействия с ним. Возможность инкапсулировать различные запросы в рамках этого подхода позволяет сильно уменьшить вероятность ошибок. Однако работать с "сырыми" данными не очень удобно, обычно мы все же хотим работать со всеми данными как с объектами.

    ## Row Data Gateway

    На помощь к нам придет **Row Data Gateway**. При этом подходе мы проэцируем отдельные ряды нашей таблицы на объекты. Ряды знают о том, к какой таблице они пренадлежат, и могут сами себя обновлять и добавлять в таблицу.

    ```
    class UserGateway {
    // сделав свойства публичным я хочу подчеркнуть то,
    // что этот класс это просто структура данных, состояние без поведения
    private $id;
    public $name;
    public $email;
    public $password;
    // еще раз, это проекция таблицы, а не объект бизнес логики
    public function __constructor(string $id = null) {
    if ($id) {
    $this->id = $id;
    $this->fetchRow();
    } else {
    // если ID не задан, то мы генерируем ноывй
    $this->id = Cuid::cuid();
    }
    }
    private function fetchRow() {
    $row = DB::where('id', $this->id')->first();
    if (!$row) {
    throw new \UnableToCreateGatewayException('');
    }
    }
    }
    ```

    Данный объект представляет собой простую структуру данных без какого либо поведения. По сути мы могли бы

    По сути мы работаем с объектами нашей базы данных как с обычными объектами. Разлица лишь в том, что каждый способ предоставляет больше возможностей для изоляции от хранилища. Table Data Gateway заставляет нас работать со всей таблицей целиком, Row Data Gateway - с отдельными рядами таблицы. Active Record является развитием идеи Row Data Gateway но уже позволяет инкапсулировать дополнительное поведение. Data Mapper же вообще не приязан к структуре базы данных, и, так же как и в случае с AR, мы можем примешивать объектам поведение.

    Поскольку первые два подхода практически не используются, рассмотрим Active Record и Data Mapper. В чем координальное отличие?

    В рамках Active Record (или Active State) мы работаем с объектами как отображением элементов нашей базы данных, как если бы у нас был прямой доступ к ним без SQL прослойки. В DataMapper мы работаем исключительно с нашими объектами, которые лежат в памяти, и просим отдельную штуку (мэппер) что бы тот синхронизировал состояние объектов в памяти и в базе (сохранил состояние по сути).

    Доустим у нас есть некий граф объектов, с которым мы работаем в рамках бизнес транзакции. И мы должны сохранить изменения в базу, то есть объект на верху графа и все связанные с ним сущности. Если руководствоваться паттерном "Информационный эксперт", заниматься этим должен тот, кто знает как это делать. В случае AR эта логика выносится прямо в сущности и мы явно задаем в каком порядке что сохранять. В случае же с DM у сущности нет таких знаний и мы выделяем все в отдельный компонент, что дает нам дополнительные варианты как это организовать удобнее для нас. От тупого разруливания графа "руками", до алгоритмов, которые разруливают это автоматически.

    Как доставать объекты из хранилища - это отдельная темам для разговора, и тот и другой подход никак не это не влияют. Спор AR vs DM - это спор о том кто сохраняет объекты.

    Это основное различие в подходах. Мэпить любую структуру на любую структуру мы можем и при том и при другом подходе, но только при варианте с Active Record обычно так не делают (что бы сохранить иллюзию прямой работы с базой), так как этот шаблон подразумевает максимально упрощенную реализацию. Именно по этому при использовании AR обычно говорят о тестной связанности с базой, а при DM - слабой (мы вообще от нее не зависим по сути).

    Остальные нюансы, вроде UnitofWork, Ideniny Map, работа со связями, ленивая инициализация связанных объектов, все это - приблизительно одинаково реализуется при обоих подходах и никакого отношения непосредственно к ActiveRecord или DataMapper не имеет. Но без этого всего сами подходы не предоставляют нам той гибкости, которую мы ожидаем получить от ORM.

    На негодняшний день в чистом виде в рамках существующих ORM вы можете встретить только DataMapper. ORM на основе Active Record так или иначе внутри используют намного более сложные концепции, дабы упростить разработчикам жизнь и снизить сложность.

    ## Реализации ORM использующие Data Mapper
    - Doctrine2 - Самое мощное решение из существующих на данный момент.
    - [Spot2](https://github.com/vlucas/spot2) - легковесная ORM а базе Doctrine DBAL без магии.
    -
    - [Analogue](https://github.com/analogueorm/analogue) - легковесая ORM, использующая в качестве основы Laravel Database
    - [Atlas.Orm](https://github.com/atlasphp/Atlas.Orm) - сырая, но интересная ORM, которая пытается полностью вынести Persistance Model из слоя бизнес логики, но без какой либо магии.

    TODO

  7. fesor revised this gist Jan 29, 2016. 1 changed file with 14 additions and 1 deletion.
    15 changes: 14 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -6,4 +6,17 @@

    Остальные нюансы, вроде UnitofWork, Ideniny Map, работа со связями, ленивая инициализация связанных объектов, все это - приблизительно одинаково реализуется при обоих подходах и никакого отношения непосредственно к ActiveRecord или DataMapper не имеет. Но без этого всего сами подходы не предоставляют нам той гибкости, которую мы ожидаем получить от ORM.

    Сейчас единственная полноценная ORM использующая DataMapper - Doctrine2. Реализации же ActiveRecord намного более распространены в силу упрощенной модели работы. Наиболее интересным видится вариант Propel2, в котором разработчики попытались совместить оба подхода, что закрывает нишу быстро растущих проектов, для которых важны преимущества обоих подходов. Но посмотрим что из этого выйдет.
    ## Реализации ORM использующие Data Mapper
    - Doctrine2 - Самое мощное решение из существующих на данный момент.
    - [Spot2](https://github.com/vlucas/spot2) - легковесная ORM а базе Doctrine DBAL без магии.
    -

    TODO

    ## Реализации ORM использующие Active Record

    TODO

    ## Реализации ORM использующие смешанные подходы

    TODO
  8. fesor revised this gist Jan 29, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -4,6 +4,6 @@

    Это основное различие в подходах. Мэпить любую структуру на любую структуру мы можем и при том и при другом подходе, но только при варианте с ActiveRecord обычно так не делают (что бы сохранить иллюзию прямой работы с базой). Именно по этому при использовании AR обычно говорят о тестной связанности с базой, а при DM - слабой (мы вообще от нее не зависим по сути).

    Остальные нюансы, вроде UnitofWork, Ideniny Map, работа со связями, ленивая инициализация связанных объектов, все это - приблизительно одинаково реализуется при обоих подходах и никакого отношения непосредственно к ActiveRecord или DataMapper не имеет. Но без этого всего эти вещи не предоставляют нам той гибкости, которую мы ожидаем получить от ORM.
    Остальные нюансы, вроде UnitofWork, Ideniny Map, работа со связями, ленивая инициализация связанных объектов, все это - приблизительно одинаково реализуется при обоих подходах и никакого отношения непосредственно к ActiveRecord или DataMapper не имеет. Но без этого всего сами подходы не предоставляют нам той гибкости, которую мы ожидаем получить от ORM.

    Сейчас единственная полноценная ORM использующая DataMapper - Doctrine2. Реализации же ActiveRecord намного более распространены в силу упрощенной модели работы. Наиболее интересным видится вариант Propel2, в котором разработчики попытались совместить оба подхода, что закрывает нишу быстро растущих проектов, для которых важны преимущества обоих подходов. Но посмотрим что из этого выйдет.
  9. fesor revised this gist Jan 29, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    Собственно тут описана основная разница между подходами ActiveRecord и DataMapper. Гидраторы можно впихнуть туда и туда, можно мэпить на любые структуры теоритически, но основное различие в том кто отвечает за сохранение данных.

    В рамках ActiveRecord мы работаем с объектами как отображением элементов нашей базы данных, как если бы у нас был прямой доступ к ним без SQL прослойки. В DataMapper мы работаем исключительно с нашими объектами, которые лежат в памяти, и просим отдельную штуку (мэппар) что бы тот синхронизировал состояние объектов в памяти и в базе (сохранил).
    В рамках ActiveRecord мы работаем с объектами как отображением элементов нашей базы данных, как если бы у нас был прямой доступ к ним без SQL прослойки. В DataMapper мы работаем исключительно с нашими объектами, которые лежат в памяти, и просим отдельную штуку (мэппер) что бы тот синхронизировал состояние объектов в памяти и в базе (сохранил).

    Это основное различие в подходах. Мэпить любую структуру на любую структуру мы можем и при том и при другом подходе, но только при варианте с ActiveRecord обычно так не делают (что бы сохранить иллюзию прямой работы с базой). Именно по этому при использовании AR обычно говорят о тестной связанности с базой, а при DM - слабой (мы вообще от нее не зависим по сути).

  10. fesor revised this gist Jan 29, 2016. 1 changed file with 9 additions and 1 deletion.
    10 changes: 9 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1 +1,9 @@
    Собственно тут описана основная разница между подходами ActiveRecord и DataMapper. Гидраторы можно впихнуть туда и туда, можно мэпить на любые структуры теоритически, но основное различие в том кто отвечает за сохранение данных.
    Собственно тут описана основная разница между подходами ActiveRecord и DataMapper. Гидраторы можно впихнуть туда и туда, можно мэпить на любые структуры теоритически, но основное различие в том кто отвечает за сохранение данных.

    В рамках ActiveRecord мы работаем с объектами как отображением элементов нашей базы данных, как если бы у нас был прямой доступ к ним без SQL прослойки. В DataMapper мы работаем исключительно с нашими объектами, которые лежат в памяти, и просим отдельную штуку (мэппар) что бы тот синхронизировал состояние объектов в памяти и в базе (сохранил).

    Это основное различие в подходах. Мэпить любую структуру на любую структуру мы можем и при том и при другом подходе, но только при варианте с ActiveRecord обычно так не делают (что бы сохранить иллюзию прямой работы с базой). Именно по этому при использовании AR обычно говорят о тестной связанности с базой, а при DM - слабой (мы вообще от нее не зависим по сути).

    Остальные нюансы, вроде UnitofWork, Ideniny Map, работа со связями, ленивая инициализация связанных объектов, все это - приблизительно одинаково реализуется при обоих подходах и никакого отношения непосредственно к ActiveRecord или DataMapper не имеет. Но без этого всего эти вещи не предоставляют нам той гибкости, которую мы ожидаем получить от ORM.

    Сейчас единственная полноценная ORM использующая DataMapper - Doctrine2. Реализации же ActiveRecord намного более распространены в силу упрощенной модели работы. Наиболее интересным видится вариант Propel2, в котором разработчики попытались совместить оба подхода, что закрывает нишу быстро растущих проектов, для которых важны преимущества обоих подходов. Но посмотрим что из этого выйдет.
  11. fesor revised this gist Jan 29, 2016. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    Собственно тут описана основная разница между подходами ActiveRecord и DataMapper. Гидраторы можно впихнуть туда и туда, можно мэпить на любые структуры теоритически, но основное различие в том кто отвечает за сохранение данных.
  12. fesor revised this gist Jan 29, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion datamapper.php
    Original file line number Diff line number Diff line change
    @@ -39,7 +39,7 @@ class DataMapper {
    public function save(User $user) {
    $attributes = $this->hidrator->dehydrate($user);
    if ($this-isNewRecord($user)) {
    $this->db->setIdentity($user); // selectx next sequence value as ID (only postgresq, oracle, mssql)
    $this->db->setIdentity($user); // selects next sequence value as ID (only postgresq, oracle, mssql)
    $this-db->insert($this->getTableName($user), $attributes);
    } else {
    $this->db->update($this->getTableName($user), $attributes, $this->getFindByIdentityCriteria($user));
  13. fesor revised this gist Jan 29, 2016. 1 changed file with 54 additions and 0 deletions.
    54 changes: 54 additions & 0 deletions datamapper.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,54 @@
    <?php

    class User {
    private $id;
    private $email;
    private $password;
    private $profile;

    public function __construct(string $email, string $password, UserProfile $profile) {
    $this->email = $email;
    $this->password = $password;
    $this->profile = $profile;
    }
    }

    class UserProfile {
    private $firstName;
    private $lastname;

    public function __construct(string $firstName, string $lastName) {
    $this->firstName = $firstName;
    $this->lastName = $lastName;
    }
    }

    /** Maps data to this table structure:
    *
    * ------------------------------
    * id | int |
    * email | string |
    * password | string |
    * profile_first_name | string |
    * profile_last_name | string |
    */

    class DataMapper {
    private $db, $hidrator;

    public function save(User $user) {
    $attributes = $this->hidrator->dehydrate($user);
    if ($this-isNewRecord($user)) {
    $this->db->setIdentity($user); // selectx next sequence value as ID (only postgresq, oracle, mssql)
    $this-db->insert($this->getTableName($user), $attributes);
    } else {
    $this->db->update($this->getTableName($user), $attributes, $this->getFindByIdentityCriteria($user));
    }
    }

    public function remove(User $user) {
    $this->db-delete($this->getTableName($user), $this->getIdentity($user));
    }

    // ...
    }
  14. fesor revised this gist Jan 29, 2016. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions activerecord.php
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    <?php

    class User extends ActiveRecord {
    public $id;
    public $email;
  15. fesor created this gist Jan 29, 2016.
    40 changes: 40 additions & 0 deletions activerecord.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,40 @@
    class User extends ActiveRecord {
    public $id;
    public $email;
    public $password;
    public $firstName;
    public $lastName;
    }

    /* maps all this on table:
    Table users
    ------------------------
    | id | int |
    | email | string |
    | password | string |
    | first_name | string |
    | last_name | string |
    ------------------------ */

    abstract class ActiveRecord {
    public function save() {
    if ($this->isNewRecord()) {
    $this->insert();
    } else {
    $this->update();
    }
    }
    public function update() {
    $this->db->update($this->tableName, $this->attrs, ['id' => $this->id]);
    }

    public function insert() {
    $this->db->insert($this->tableName, $this->attrs);
    }

    public function delete() {
    $this->db->insert($this->tableName, $this->attrs);
    }
    // ...
    }