Как правильно формировать criteria для связи HAS_MANY?

183
19 декабря 2016, 19:42

Есть модель POST. И есть модель category_r В последней 3 столбца: id, Post_id, category_id.

Мне нужно сделать выборку постов, где category_id равна 1 и 2, к примеру. ВОт моя criteria:

$criteria->condition = 'category.category_id=2 AND category.category_id=1';

Выдает ошибку в sql-запросе, Если добавить $criteria->together = true;, то возвращает пустую модель.

С одним условием, например:

criteria->condition = 'category.category_id=2' - тут все отлично.

Что не так делаю?

Answer 1

В одной и то же записи не может быть и category_id=2 и category_id=1, используйте OR

$criteria->condition = 'category.category_id=2 OR category.category_id=1'; 

После дополнительной информации:

Можно использовать подзапрос (т.к. нет понимая вашей структуры то код примерный)

$cat = Category::model();
$sub_query = new CDbCriteria();
$sub_query->select = ['post_id'];
$sub_query->addCondition('category_id = 1 OR category_id = 2');
$sub_query->group = 'post_id';
$sub_query->having = 'COUNT(post_id) = 2';
$sub_query = $cat->getCommandBuilder()->createFindCommand($cat->getTableSchema(),$sub_query)->getText();
$posts = new CDbCriteria();
$posts->addCondition('id IN ('.$sub_query.')');
$posts->params = [':sub_query'=>$sub_query];
$events = Post::model()->findAll($posts);

Ну или без второй критерии:

$sub_query = 'SELECT post_id FROM '.Category::model()->tableName().' WHERE category_id = 1 OR category_id = 2 GROUP BY post_id HAVING COUNT(post_id) = 2';
$posts = new CDbCriteria();
$posts->addCondition('id IN ('.$sub_query.')');
$posts->params = [':sub_query'=>$sub_query];
$events = Post::model()->findAll($posts);

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

$criteria = new CDbCriteria();
$criteria->select = ['*', 'GROUP_CONCAT(DISTINCT category.category_id  SEPARATOR ",") as cat_id '];
$criteria->with = ['category'];
$criteria->group = 't.id';
$criteria->having = 'cat_id REGEXP "1" = 1 AND cat_id REGEXP "2" = 1';
Post::model()->findAll($criteria);

Ну или вот так:

$category_table = Category::model()->tableName();
$posts = new CDbCriteria();
$posts->join = 'LEFT JOIN '.$category_table.' as cat_1 ON t.id = cat_1.post_id AND cat_1.category_id=1 '.
               'LEFT JOIN '.$category_table.' as cat_2 ON t.id = cat_2.post_id AND cat_2.category_id=2 ';
$posts->condition = 'cat_1.post_id = t.id AND cat_2.post_id = t.id ';

Вы просто должны понимать что если вы будите пытаться так же выбрать данные из таблицы category_r (category_id = 1 AND category_id = 2), то ничего вы не получите, так как в одной записи только одно значение category_id, то же самое происходит когда вы используете JOIN. На основе этого вы можете пробовать строить свои запросы.

READ ALSO
Неправильный расчёт даты возврата книг

Неправильный расчёт даты возврата книг

Я написал код для подсчёта количества дней, через которые должны вернуть книги, взятые в библиотеке, но, к сожалению, код не правильно считает

187
Вопрос по substr_count($_SERVER['REQUEST_URI']

Вопрос по substr_count($_SERVER['REQUEST_URI']

Как показать информацию на нескольких страницах с помощью substr_count($_SERVER['REQUEST_URI']?

257
Как давно был опубликован комментарий

Как давно был опубликован комментарий

Нужно сделать вывод даты комментариев так:

176
Долго грузится сайт [закрыто]

Долго грузится сайт [закрыто]

Залил сайт на хостинг, очень долго грузятся страницы, иногда вылетает ошибка 500Вот ссылка на сайт: ссылка

211