Skip to content

Ru:criteria:howitworks

AlexeyDsov edited this page Apr 19, 2011 · 9 revisions

Как работает Criteria

(это еще не законченная статья, пожалуйста, не надо в нее вставлять куски больших непонятных примеров, без пояснений, со всякими вспомогательными классами Debug не относящимися к onPHP и т.п. Однако подправка логических ошибок, опечаток, корректировка фраз и т.д. приветствуется ;) )

Введение

Для более правильного использования Criteria необходимо иметь ввиду как именно она работает. Для примера будет использовать мету из первой статьи.

Формирование OSQL

Возьмем простой запрос из предыдущего примера - получение списка актеров, живущих в США плюс уберем вокруг USA обертку из DBValue

<?php
Criteria::create(Actor::dao())->
	add(Expression::eq('country', 'USA'))->
	add(OrderBy::create('name'))
	getList();
?>

Как именно Criteria в этом случае догадывается что country - это property объекта, а 'USA' это значение?

У классов Expression, OrderBy, SQLFunction, Projection и др. подобных есть интерфейс MappableObject:

interface MappableObject extends DialectString
{
	/**
	 * @return MappableObject
	**/
	public function toMapped(ProtoDAO $dao, JoinCapableQuery $query);
}

В этом методе классы создают новый инстанс себя (new $this) и передают в новый объект свои параметры прогнанные через метод ProtoDAO::guessAtom. В этом методе в зависимости от типа переданного объекта с ним происходят следующие изменения:

  • Если передан объект DBField или DBValue - возвращаются без изменения
  • Если передан объект instanceof MappableObject, то у него вызывается метод toMapped и возвращается результат выполнения
  • Если передана строка, то DAO пытается найти соотвествующей ей path из property. И в случае country и name она его находит, а в случае USA нет. Таким образом country и name оборачиваются в DBField, а USA в DBValue.

Выводы, который стоит сделать:

  • все что не должно именно значением извне и может случайно совпасть с каким-то path'ем (например, передача в Expression параметра, а не захардкоженного значения) - нужно оборачивать в DBValue, иначе в каких-то случаях могут происходить забавные и не очень казусы.
  • Если вы уверены что это значение никогда не пересечеться с каким-либо path'ем - оборачивать в DBValue его не обязательно
  • В Criteria никогда не нужно использовать DBField. Все DBField должны быть собраны по path'ам, т.к. при сборке Field'ов каждому ставиться alias таблицы (например, a1b2c3d4_roles.description), который сами вы не угадаете и запрос составиться некорректно.

DAO и OSQL

В результате прохода всех элементов через toMapped и guessAtom получается правильно заполненный SelectQuery. Этот SelectQuery передается в getListByQuery того самого DAO, который сетиться в Criteria при создании, а DAO уже возвращает сформированный список нужных объектов.

При этом в случае включенного кэширования запросов нужно иметь ввиду, что запрос привязан именно к этому DAO и его раcкэшивание будет происходить по запросу раскэшивания запросов этого DAO, а не какого-то другого.

Не getList методы, связанные с формированием SelectQuery и результата

  • В случае вызова метода get() происходит такое же формирование SelectQuery, но у dao вызывается метод getByQuery
  • В случае getResult - формируется один запрос, затем он клонируется и у отключаются limit и offset, очищается список полей и добавляется одно поле - count(id). Дальше через dao получают результаты обоих запросов и они сетяться в созданный QueryResult, который и возвращается
  • Метод getCustom возвращает все поля (если аргумент null) или возвращает список значений конкретного поля-property, указанного в аргументе. Как правило используется, если в Criteria используются Projection'ы
  • Метод getCustomList возвращает выборку в виде массива ассоциативных массивов полей, например array(array('id' => '1', 'name' => 'Johny Depp'), array('id' => '2', 'name' => 'Harrison Ford')
  • Метод toSelectQuery возвращает SelectQuery, который формирует criteria
  • Метод toDialectString возвращает строку-запрос на переднном в качестве аргумента Dialect'е (например, PostgresDialect:me()
  • Метод toString возвращает строку-запрос на Dialect'е DAO, заданного в Criteria

Примечание

  1. Пока считаю свою попытку изложить внутреннии механизмы работы Criteria унылой и статье нужна доработка/переработка :) Не смог найти всех правильных слов что бы просто все это описать :)
Clone this wiki locally