-
Notifications
You must be signed in to change notification settings - Fork 52
Ru:criteria:howitworks
(это еще не законченная статья, пожалуйста, не надо в нее вставлять куски больших непонятных примеров, без пояснений, со всякими вспомогательными классами Debug не относящимися к onPHP и т.п. Однако подправка логических ошибок, опечаток, корректировка фраз и т.д. приветствуется ;) )
Для более правильного использования Criteria необходимо иметь ввиду как именно она работает. Для примера будет использовать мету из первой статьи.
Возьмем простой запрос из предыдущего примера - получение списка актеров, живущих в США плюс уберем вокруг 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), который сами вы не угадаете и запрос составиться некорректно.
В результате прохода всех элементов через toMapped и guessAtom получается правильно заполненный SelectQuery. Этот SelectQuery передается в getListByQuery того самого DAO, который сетиться в Criteria при создании, а DAO уже возвращает сформированный список нужных объектов.
При этом в случае включенного кэширования запросов нужно иметь ввиду, что запрос привязан именно к этому DAO и его раcкэшивание будет происходить по запросу раскэшивания запросов этого DAO, а не какого-то другого.
- В случае вызова метода 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
- Пока считаю свою попытку изложить внутреннии механизмы работы Criteria унылой и статье нужна доработка/переработка :) Не смог найти всех правильных слов что бы просто все это описать :)