В процесс работы вам немременно необходимо будет создавать новые find() и get() методы в ваших ActiveRecord-ах.
Мы для себя уславливаемся обычно, что find()-методы это статические методы, а getter-ы - это instance-методы, например:
class Document extends lmbActiveRecord { static function findPublished() { $time = time(); return lmbActiveRecord :: find('Document', "is_published = 1 AND (date_start <= {$time} AND date_end >= {$time})"); } static function findKidsForParent($parent_id) { $sql = 'SELECT document.* '. ' FROM document LEFT JOIN node ON node.object_id = document.id '. ' WHERE node.parent_id = '. $parent_id; return lmbActiveRecord :: decorateRecordSet($this->_query($sql), 'Document'); } function getPublishedKids() { $sql = 'SELECT document.* '. ' FROM document LEFT JOIN node ON node.object_id = document.id '. ' WHERE node.parent_id = '. $this->getNode()->getId() . ' AND document.date_start <= :time: AND document.date_end >= :time:'. ' AND document.is_published = 1 ' . ' ORDER BY node.priority ASC,document.date DESC'; $stmt = $this->_createSQLStatement($sql); $stmt->setInteger('time', time()); return $this->decorateRecordSet($stmt->getRecordSet()); } }
На что здесь нужно обратить внимание:
$rs = $this->_query($sql);
lmbActiveRecord :: _query($sql) возвращает объект типа RecordSet, который имплементирует интерфейс Iterator и позволяет пошагово перебрать всю выборку без лишних затрат памяти.
$stmt = $this->_createSQLStatement($sql);
lmbActiveRecord :: _createSQLStatement($sql) создает объект типа Statement, нужного класса, который зависит от типа используемого драйвера базы данных.
Statement позволяет правильным образом установить параметры запроса, с учетом особенностей драйвера, как это сделано в методе Document :: getPublishedKids().
Обратите внимание также на следующие две строки:
return lmbActiveRecord :: decorateRecordSet($stmt->getRecordSet(), 'Document');
и
return $this->decorateRecordSet($stmt->getRecordSet());
По своей сути это - две одинаковые строки. Более правильно использовать именно первый вариант, так как lmbActiveRecord :: decorateRecordSet($dataset, $class_name = null) задумывался как статический метод.
Суть применения этого метода - в декорировании RecordSet-а специальным декоратором (класса lmbARRecordSetDecorator), который из каждой записи итератора формирует полноценный ActiveRecord. После применения этого декоратора вы можете использовать все, что относится к ActiveRecord-ам, например, доступ к связям между объектами. В целях оптимизации вы можете не использовать этот декоратор в каких-то методах.
Как вы поняли lmbActiveRecord :: find($params = array()) и другие find()-методы применяют этот декоратор по-умолчанию.
Стоит еще отметить, что в создаваемый ActiveRecord из записи итератора передаются все поля, даже если они не относятся непосредственно к ActiveRecord, поэтому иногда можно указывать дополнительное количество полей в выборках, например:
class Document extends lmbActiveRecord { [...] static function findKidsForParent($parent_id) { $sql = 'SELECT document.*, node.identifier as node_identifier, node.title as node_title '. ' FROM document LEFT JOIN node ON node.object_id = document.id '. ' WHERE node.parent_id = '. $parent_id; return lmbActiveRecord :: decorateRecordSet($this->_query($sql), 'Document'); } [...] }
Дополнительно о создании своих sql-запросов в описании пакета DBAL.
Обсуждение