На работе пришлось столкнуться с очень не нравившейся мне 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, посвященный его улучшению (правда, я не знаю, насколько он сейчас актуален, проверять нет времени :( ).
Кросс-пост из моего блога
