Инструменты пользователя

Инструменты сайта


limb3_2007_2:ru:usage:active_record:sql_exec

Создание новых find() методов. Выполнение своих sql-запросов.

В процесс работы вам немременно необходимо будет создавать новые 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.

Обсуждение

Ваш комментарий. Вики-синтаксис разрешён:
  ____   _____  ____   _____   __ 
 / __ \ / ___/ / __ \ / ___/  / / 
/ /_/ // (_ / / /_/ // (_ /  / /__
\___\_\\___/  \___\_\\___/  /____/
 
limb3_2007_2/ru/usage/active_record/sql_exec.txt · Последние изменения: 2010/11/10 10:02 (внешнее изменение)