Использование CDbCriteria в DAO

Не знал какое название дать посту, получилось, что получилось.
Очередной рабочий вечер, работа над интернет-магазином. Для уменьшения нагрузки отказываюсь в некоторых местах от использования AR. Естественно для выборки данных с использованием AR использую класс CDbCriteria. Но отказываясь от AR приходится отказаться и от CDbCriteria. Решил «поплакаться» на этот счет одному из знакомых разработчиков, который подсказал поковырять фреймворк и посмотреть действительно ли необходимо отказаться от CDbCriteria, когда не используешь AR. И как оказалось все не так плохо, иначе бы этот пост и не появился ;).
Ну а теперь к практическому решению:

criteria = new CDbCriteria;
// идет некий сумасшедший сбор критерии.
...
// Дальше необходимо создать экземпляр класса CDbCommandBuilder
$builder = new CDbCommandBuilder(Yii::app()->db->getSchema());
// Дальше если необходимо сделать выборку, то используем createFindCommand
// Если что-то удалить, то createDeleteCommand и т.п.
// Первым параметром передаем название таблицы или объект CDbTableSchema
$command = $builder->createFindCommand('product', $criteria);
// дальше можно использовать queryColumn(), queryAll() и т.п.
$productIds = $command->queryColumn();

Возможно это слишком низкоуровневое решение, но оно работает.

Пример использования CDbCriteria (методы)

В предыдущие заметки, я рассмотрел использование атрибутов класса CDbCriteria. Теперь рассмотрим методы этого класса. Почти все методы последним параметром принимают строку с помощью которой будет происходить конкатенация данного условия с остальной частью запроса, по умолчанию AND. Все будет рассмотрено на примерах.
Понеслась…

// создаем экземпляр класса CDbCriteria
$criteria = new CDbCriteria;
// установим некое начальное условие
$criteria->condition = 'user_id = :userId';
// формирует условие AND price BETWEEN 500 AND 1500
$criteria->addBetweenCondition('price', '500', '1500');
// формирует условие AND (date_create = '2010-12-23' OR status = 'success')
$criteria->addColumnCondition(array('date_create'=>'2010-12-23', 'status'=>'success'), 'OR')
// принимает первым параметром строку или массив строк - условий
// если передан массив строк, то конкатенация будет происходить через 2ой параметр,
// так же как и с остальными условиями, по умолчанию AND
// формирует условие AND (count_viewed <= :countViewed OR count_viewed = '26')
$criteria->addCondition("count_viewed <= :countViewed OR count_viewed = '26'");
// первый параметр, название колонки или валидный SQL
// второй параметр, массив значения
// формирует запрос OR (id IN ('3', '13', '24', '53', '69'))
$criteria->addInCondition('id', array('3', '13', '24', '53', '69'), 'OR');
// тоже самое, только NOT IN
// формирует запрос AND (id NOT IN ('3', '13', '24', '53', '69'))
$criteria->addNotInCondition('id', array('3', '13', '24', '53', '69'));
// первый параметр, название колонки или валидный SQL
// второй параметр, строка поиска, интерпретация зависит от следующих параметров
// третий параметр, экранирование строки поиска. По умолчанию true и строка поиска
// будет обрамлена % на концах. Если false, то строка поиска будет вставлена как есть
// четвертый параметр, строка для конкатенации с другими условиями
// пятый параметр, строка, тип LIKE(по умолчанию), NOT LIKE
$criteria->addSearchCondition('title', 'Some text', true, 'NOT LIKE');
// очень хороший метод, позволяет мержить несколько экземпляров класс CDbCriteria
// первым параметром принимает экземпляр класса с котором надо смержить текущий
// второй параметр, строка для конкатенации условий по умолчанию AND
$criteria1 = new CDbCriteria();
$criteria1->condition = 'date_update < ' . new CDbExpresssion('NOW()');
$criteria->mergeWith($criteria1, 'OR');
// ну и теперь надо исполнить все это))
$count = OrderLog::model()->count($criteria);

Есть еще метод toArray(), который возвращает массив из объекта.
Вот и все, не чего сложно, но надо знать про существование этого хорошего класса, про его методы и атрибуты, которые позволяет облегчить жизнь при работе с ActiveRecord.

Пример использования CDbCriteria

Сегодня хочу описать пример использования такого мощного класса, как CDbCriteria, который предназначен для построения критериев запроса.
Постараюсь описать все атрибуты и методы этого класса. Критерий буду составлять к некой таблице user. И так начнем…

// создаем экземпляр  класса CDbCriteria
$criteria = new CDbCriteria;
// указываем алиас таблицы
$criteria->alias = 'user';
// условие то, что относится к WHERE
// можно использовать плейсхолдеры
$criteria->condition = 'id = :userId AND date_create < NOW()';
// если мы хотим отфильтровать дубликаты, 
// то distinct устанавливаем в значение true
// по умолчанию значение false;
$criteria->distinct = true;
// указываем поля по которым делать группировку, GROUP BY
$criteria->group = 'date_update';
// значения HAVING
$criteria->having = 'MAX(salary) > 10000';
// указываем индекс результирующего массива, полезная фишка, появилась с версии 1.1.5
// по умолчанию значение NULL и будут численный индекс начиная с 0
$criteria->index = 'full_name';
// указываем как приджойнить другую(ие) таблицу(ы)
// джойним некую таблицу 
$criteria->join = 'LEFT JOIN `profile` ON `user`.`id` = `profile`.`user_id`';
// максимальное количество записей которое может вернуть запрос
// если меньше 0, вернет все записи
$criteria->limit = '20';
// смещение
$criteria->offset = '3';
// сортировка
$criteria->order = 'date_create DESC, first_name ASC';
// параметры для плейсхолдеров
$criteria->params = array(':userId'=>$userId);
// поля для выборки, по умолчанию *
$criteria->select = 'id, first_name, last_name, last_visit';
// или
$criteria->select = array('id', 'first_name', 'last_name', 'last_visit');
// если значение true то данные из внешних(связанных) таблицы будут 
// выбраны одним запросом через JOIN. Работает только с отношениями в ActiveRecord
$criteria->together = true;
// отношения, работает только в ActiveRecord
$criteria->with = array('profile', 'comments', 'posts');
$users = User::model()->findAll($criteria);

Вот и все атрибуты данного класса. В следующей заметке постараюсь описать все методы.