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

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


limb3:ru:packages:wact:fetch_tags

Использование fetch и active_record:fetch тегов-ов в WACT-шаблонах

Что такое fetcher-ы

Fetcher-ы используются для получения данных непосредственно из WACT-шаблонов.

Два слова о том, что такое fetcher-ы. Это такие классы, которые реализуют интерфейс WactFetcher или наследники от lmbFetcher класса, которые поддерживают метод fetch(). Этот метод всегда должен возвращать итератор (это важно!).

В шаблонах fetcher-ы используются для получения данных через тег <fetch>. Другой тег <active_record:fetch>, который должен быть вам знаком по базовому туториалу и по разделу "Использование ACTIVE_RECORD"", является аналогом тега <fetch>. Класс тега <active_record:fetch> наследуется от класса тега <fetch>, но первый по-умолчанию использует класс lmbActiveRecordFetcher (limb/web_app/src/fetcher/lmbActiveRecordFetcher.class.php) для получения данных.

То есть fetcher-ы нужны чтобы делать запросы на получение каких-либо данных прямо из шаблонов.

Fetcher-ы могут содержать различные методы, которыми их можно параметрировать. Эти методы имеют вид setSomeParam($value). По-умолчанию fetcher-ы поддерживают следующие методы:

  • setOrder() - для задания сортировки
  • setLimit() - для ограничения количесва элементов в выборке
  • setOffset() - для указания отступа от начала выборки, начиная с которого нужно передавать данные в шаблон (offset).

Различные fetcher-ы поддерживают другие методы для задания параметров, например, класс lmbActiveRecordFetcher поддерживает методы setRecordId(), setRecordIds, setFind().

В шаблонах для задания параметров fetcher-ов используется тег <fetch:param>, каждый атрибут которого преобразуется в вызов метода вида setParamName($param_value).

Использование <fetch> тега в WACT-шаблонах

Вывод списка объектов

Пусть нам необходимо получить итератор с данными. Допустим, что мы будем использовать особый fetcher - NewsFetcher, который, допустим, возвращает список новостей. :

<fetch using='src/fetcher/NewsFetcher' target='news' />
 
<list:list id='news'>
<table>
  <list:item>
  <tr><td>{$date}</td><td>{$title}</td></tr>
  </list:item>
</table>
</list:list>

Атрибут тега using указывает на путь до класса fetcher-а(обычно такие классы кладутся в папку src/fetcher/ проекта).

Атрибут target указывает, куда необходимо передать данные; в нашем случае это будет тег <list:list>, который занимается отображением данных.

Вывод единичного объекта

Пусть теперь нам необходимо отобразить только одну первую новость:

<fetch using='src/fetcher/NewsFetcher' target='news' first='true'/>
 
<core:datasource id='last_news'>
<div class='date'>{$date}</div><div class='title'>{$title}</div>
</core:datasource>

Обратите внимание на атрибут тега first, который говорит <fetch> тегу, что нужно передать не весь список данных, а только первый полученный элементв из итератора.

В атрибуте target мы указали идентификатор тега <core:datasource> - это так называемый единичный контейнер данных, в отличие от <list:list> тега. Если вы забудете указать first, тогда шаблонизатор предпримет попытку передать весь итератор (даже если в нем будет всего 1 элемент) в <core:datasource> и будет сгенерировано исключение во время работы шаблона. см. также раздел "Контейнеры данных WACT".

Задание сортировки данных

Допустим, нам необходимо вывести все новости отсортировав их по заголовку. Если по-умолчанию новости сортируются по дате, есть способ изменить способ сортировки прямо из шаблона. Для этого можно использовать атрибут order. Это можно сделать так:

<fetch using='src/fetcher/NewsFetcher' target='news' order='title=ASC'/>
[...]

Или так:

<fetch using='src/fetcher/NewsFetcher' target='news'>
  <fetch:param order='title=ASC'/>
</fetch>
[...]

Тег <fetch:param> приводит к вызову метода setAttributeName($value) у fetcher-а для каждого своего атрибута. То есть NewsFetcher получит вызов метода setOrder('title=ASC').

Можно указать несколько сортировок, разделяя их запятыми:

<fetch using='src/fetcher/NewsFetcher' target='news'>
  <fetch:param order='title=ASC,id=DESC'/>
</fetch>
[...]

Использование order на самом деле приводит к вызову метода sort() для итератора полученного из NewsFetcher, для последнего примера это будет $dataset→sort(array('title' ⇒ 'ASC', 'id' ⇒ 'DESC'));

Ограничение размера выборки

Иногда перед нами стоит задача вывести только некоторое количество объектов в шаблоне, например, только 3 последние новости. Для этого мы можем использовать атрибуты offset и limit:

<fetch using='src/fetcher/NewsFetcher' target='latest_news' limit='3' order='date=DESC'/>
[...]

Это можно сделать и так:

<fetch using='src/fetcher/NewsFetcher' target='latest_news'>
  <fetch:param limit='3' order='date=DESC'/>
</fetch>
[...]

Допустим нам нужно вывести 3 новости, начиная с 3-й:

<fetch using='src/fetcher/NewsFetcher' target='latest_news'>
  <fetch:param offset='2' limit='3'/>
</fetch>
[...]

Создание своих fetcher-ов.

Допустим, у нас есть задача - сделать свой fetcher для выборки объектов класса Node по своим параметрам. Приведем класс этого fetcher-а, который мы назвали NodeKidsFetcher:

<?php
lmb_require('limb/web_app/src/fetcher/lmbFetcher.class.php');
lmb_require('limb/active_record/src/lmbActiveRecord.class.php');
lmb_require('limb/dbal/src/criteria/lmbSQLCriteria.class.php');
 
class NodeKidsFetcher extends lmbFetcher
{
  protected $type;
  protected $parent_id = 0;
  protected $path;
 
  function setType($type)
  {
    $this->type = $type;
  }
 
  function setParentId($parent_id)
  {
    if($parent_id)
      $this->parent_id = $parent_id;
  }
 
  function setParentPath($path)
  {
    $this->path = $path;
  }
 
  protected function _createDataSet()
  {
    $toolkit = lmbToolkit :: instance();
 
    if($this->path && !$this->parent_id)
    {
      if($node = Node :: findByPath('Node', $path))
        $this->parent_id = $node->id;
    }
 
    $criteria = new lmbSQLCriteria("parent_id = " . (int)$this->parent_id);
    if($this->type)
    {
      $type_id = NodeType :: generateIdFor($this->type);
      $criteria->addAnd(new lmbSQLCriteria('type_id ='. $type_id));
    }
 
    return lmbActiveRecord :: find('Node', $criteria);
  }
}
?>

Обратите внимание, что дочерние классы должны расширять защищенный метод _createDataset(). Это реализовано исходя из того, что родительский класс lmbFetcher содержит функционал по ограничению (offset, limit), по сортировке (order) полученного итератора и этот функционал должен быть всегда доступен клиентам fetcher-ов. Поэтому дочерние классы не перекрывают метод getDataset().

Пример использование созданного нового fetcher-класса

Глядя на методы класса NodeKidsFetcher, можно сделать вывод, что в шаблонах мы можем использовать параметры parent_path, parent_id и type, например:

<fetch using='src/fetcher/NodeKidsFetcher' target='kids'>
<fetch:param parent_id='{$#request.id}'>
</fetch>
<fetch using='src/fetcher/NodeKidsFetcher' target='kids'>
<fetch:param parent_id='{$#request.id}' type='File'>
</fetch>
<fetch using='src/fetcher/NodeKidsFetcher' target='kids'>
<fetch:param parent_id='{$#request.id}' parent_path='/files'>
</fetch>

Атрибут using указывает на класс fetcher-а, при помощи которого будут получены данные.

В последнем примере, если в запросе ничего не придет, будут выбраны дочерние элементы родителя по пути /files.

Использование тега <active_record:fetch>

Тег <active_record:fetch> в основном работает аналогично тегу <fetch>.

Отличия заключаются в следующем:

  • в атрибуте using указывается не путь до fetcher-а, а путь до класса, дочернего от lmbActiveRecord
  • можно использовать любой find()-метод класса ActiveRecord, если указать параметр find.
  • можно передавать любые параметры в find()-методы при помощи тега <find:params>.

Подробнее об использовании тега <active_record:fetch> см. в разделе "Использование ACTIVE_RECORD в шаблонах WACT".

Обсуждение

Ваш комментарий. Вики-синтаксис разрешён:
   __  ___   __ __   ___   __  __  __  __
  /  |/  /  / // /  / _ | / / / / / / / /
 / /|_/ /  / _  /  / __ |/ /_/ / / /_/ / 
/_/  /_/  /_//_/  /_/ |_|\____/  \____/
 
limb3/ru/packages/wact/fetch_tags.txt · Последние изменения: 2010/11/10 10:02 (внешнее изменение)