Сложный SQL запрос

Подскажите, пожалуйста, как правильно в Yii реализовать следующее:

Есть:

  1. рестораны (таб. restaurants);

  2. меню ресторана: тут меню – это отдельное блюдо (таб. menu);

  3. отношение М:М (хотя реально отношение 1:М (у ресторанов много блюд)) (связующая таб. restaurants_menu);

  4. кухня (поле cuisine_id в таблице menu);

  5. категории блюд меню (поле category_id в таблице menu);

У ресторана есть блюда (таб. menu), а у блюд есть связь с видом кухни (cuisine_id в таблице menu) и с категорией (поле category_id в таблице menu). У ресторанная могут быть блюда с разными кухнями и категориями. Прямой связи между рестораном и кухнями или категориями нет.

Задача:

Необходимо реализовать фильтр ресторанов (см.скриншот) по:

  • кухням (поле cuisine_id в таблице menu),

  • категориям блюд (тип блюд) (поле category_id в таблице menu)

  • параметрам ресторана (

  • бесплатная доставка (поле gratis в таб. restaurants),

  • популярный (поле popular в таб. restaurants),

  • открытий сейчас (поле open в таб. restaurants),

  • новый (поле new в таб. restaurants),

  • с акциями (поле has_actions в таб. restaurants),

)

Все параметры «И». Например, я хочу найти рестораны итальянской кухни, которые доставляют пиццы и сейчас открыты и у них есть акции. Или найти рестораны

Есть еще постоянный параметр «тип ресторана» (поле type_id в таб. restaurants – значение = 1)

И параметры сортировки (

  • в алфавитном порядке,

  • по рейтингу (поле rate в таб. restaurants),

  • количеству акций (поле actions_count в таб. restaurants),

)

Запрос содержит еще такие постоянные параметры:

't.type_id= 1 AND is_independent IS NULL AND t.active = 1

                    AND (parent_restaurant_id IS NULL OR parent_restaurant_id = "") ';

На мой взгляд копать тебе надо в сторону использования Query Builder . Вышеописанное не сложно реализовывается при помощи создания массива для where(), который делаешь, последовательно вкладывая условия:




$whereStr='cuisine_id='.$cuisine;

if (/*установлен фильтр по категории блюд*/){

$whereStr=array('and','category_id='.$catId,$whereStr);

}// и т.д.



в конце цепляешь твои постоянные параметры




$whereStr=array('and','t.type_id= 1 AND is_independent IS NULL AND t.active = 1 AND (parent_restaurant_id IS NULL OR parent_restaurant_id = "")  ',$whereStr);



и выполняешь как-то так:




$find=Yii::app()->db->createCommand()

  ->select('*')

  ->from(array('tbl_restaurants','tbl_menu','tbl_tbl t'))

  ->where($whereStr)

  ->queryRow()



в таком случае каким образом я могу получить в результат объекты, как при использовании AR?

queryRow вернет строку в виде массива, ключи которого - имена полей таблиц (если не использовал false при вызове queryRow) . Обращаешься к ним:




$myId=$find['id']; $myName=$find['name']



Если надо не одну строку, используй queryAll - вернет массив строк. Конечно, AR-объекты ты не получишь таким образом.

Если надо именно AR использовать, попробуй поиграть с объектом CDbCriteria, который передашь в какой-нибудь FindAllByAttribute. CDbCriteria->condition должен получить ту же where-строку. Ее, кстати, можно построить через Query Builder, получить так:




$criteria=new CDbCriteria;

$criteria->condition=Yii::app()->db->createCommand()->where($whereStr)->getWhere()

Сложность будет представлять объединение таблиц, разруливай через Model::relations().

UncleSym прав, для работы через AR уместно использовать CDBCriteria. Добавлю, что если нужно добавить условие по столбцу, то


$criteria->addColumnCondition(); 

а если столбец "name" находится в связанной таблице "menu", то


$criteria->with('menu');

$criteria->addColumnCondition(array("menu.name"=>'Бизнес - ланч  №1'));

Конечно надо настроить ‘relations’ для этих моделей

Извините за возможно простой вопрос, скажите пожалуйста:

  1. как связываются условия при многократном применении метода $criteria->addColumnCondition();? Если связываются по AND то как связать по OR?

  2. Возможно ли этой с помощью данного метода создать конечное условие которое будет выглядеть примерно так: (op1=1 or op2=2) and (op3=3 or op4=4)?