На работе пришлось столкнуться с очень не нравившейся мне ORM'кой собственного производства. Стал делать свою (ну не дурак ли, а? :)), наваял за 3 дня простенькую ORM, отображающую структуру таблиц на обьекты, не контроллируя типов. Итог получился примерно такой:
Примерное использование:
И что-то мне это очень сильно напомнило, а именно — Zend_Db: Zend_Db_Table / Zend_Db_Table_Row. Недолго думая — выкинул нафиг свою систему и залил в проект кусок Zend Framework'а (если нужно — потом скажу, какие именно файлы нужны для полноценной работы всего компонента Zend_Db), а также решил почитать, что сейчас вообще есть в этой Zend_Db, а есть, как оказалось — довольно много:
На самом деле — еще есть вещи, коотрые бы можно было добавить, чтобы они работали автоматически:
Вроде всё. Общее впечатление — просто замечательная система. Использовать легко и приятно. :)
Пример:
Сначала пойдут мои супертипы слоя (кто читал Patters of EAA — поймет):
А теперь — пример использования:
Согласитель — всё просто и удобно, не так ли?
Для заинтересовавшихся — очень советую проштудировать полностью главу о Zend_Db из документации Zend Framework'а. А также — мой пост про Zend_Db_Table, посвященный его улучшению (правда, я не знаю, насколько он сейчас актуален, проверять нет времени :( ).
Кросс-пост из моего блога
- класс базы данных (относледовался от mysqli, pdo использовать было нельзя)
- класс таблицы, хранящий в себе бд, и отвечающий за CRUD записей
- класс записи, перенаправляющий методы CUD классу таблицы
Примерное использование:
<code class="php">$table = new ArticleTable(); $record = $table->fetchOneWhere("slug = 'hello'"); // получаем существующую запись $record->name = 'Fucking Article!'; $record->save(); // вызывает insert/update в зависимости от того, новая ли это запись $record = $table->create(); // создаем новую запись $record->name = 'Fucking Article2!'; $record->slug = 'fucking_article'; // ... $record->save();</code>
И что-то мне это очень сильно напомнило, а именно — Zend_Db: Zend_Db_Table / Zend_Db_Table_Row. Недолго думая — выкинул нафиг свою систему и залил в проект кусок Zend Framework'а (если нужно — потом скажу, какие именно файлы нужны для полноценной работы всего компонента Zend_Db), а также решил почитать, что сейчас вообще есть в этой Zend_Db, а есть, как оказалось — довольно много:
- Хорошая абстракция работы с бд
- Классы записи/таблицы
- Поддержка fetch'инга связанных обьектов
- Поддержка many-to-many связей (этого даже в Propel нет)
На самом деле — еще есть вещи, коотрые бы можно было добавить, чтобы они работали автоматически:
- Валидаторы в зависимости от типов полей таблицы
- Возможность сразу fetch'ить данные из нескольких таблиц (точнее — получить такие данные довольно легко, но вот разбрасывать их по разным обьектам и связывать эти обьекты сейчас нужно ручками, если я не ошибаюсь, но опять же — это проблем не составляет)
Вроде всё. Общее впечатление — просто замечательная система. Использовать легко и приятно. :)
Пример:
Сначала пойдут мои супертипы слоя (кто читал Patters of EAA — поймет):
<code class="php">class Db_Table extends Zend_Db_Table_Abstract { /** * @return Zend_Db_Table_Rowset_Abstract */ public function fetchAllBy($key, $value) { $where = $this->getAdapter()->quoteInto("$key = ?", $value); return $this->fetchAll($where); } /** * @return Zend_Db_Table_Row_Abstract */ public function fetchRowBy($key, $value) { $where = $this->getAdapter()->quoteInto("$key = ?", $value); return $this->fetchRow($where); } public function __call($name, $arguments) { if(strpos($name, 'fetchRowBy') === 0) { array_unshift($arguments, substr($name, 10)); return call_user_func_array(array($this, 'fetchRowBy'), $arguments); } if(strpos($name, 'fetchAllBy') === 0) { array_unshift($arguments, substr($name, 10)); return call_user_func_array(array($this, 'fetchAllBy'), $arguments); } throw new Exception("Undefined method $name"); } } class Db_Record extends Zend_Db_Table_Row_Abstract { }</code>
А теперь — пример использования:
<code class="php">class Item extends Db_Table { protected $_name = 'items'; protected $_rowClass = 'ItemRecord'; protected $_referenceMap = array( 'Group' => array( 'columns' => 'groupid', 'refTableClass' => 'Group', 'refColumns' => 'groupid', ) ); } class ItemRecord extends Db_Record { } class Group extends Db_Table { protected $_name = 'groups'; protected $_rowClass = 'GroupRecord'; protected $_dependentTables = array('Item'); } class GroupRecord extends Db_Record { } $itemTable = new Item(); $item = $itemTable->fetchRowBySlug('hello'); $group = $item->findParentGroup();</code>
Согласитель — всё просто и удобно, не так ли?
Для заинтересовавшихся — очень советую проштудировать полностью главу о Zend_Db из документации Zend Framework'а. А также — мой пост про Zend_Db_Table, посвященный его улучшению (правда, я не знаю, насколько он сейчас актуален, проверять нет времени :( ).
Кросс-пост из моего блога