Как запросить ассоциацию HasMany на основе одного значения в CakePHP 3.x - PullRequest
0 голосов
/ 09 апреля 2019

У меня есть таблица статей и таблица комментариев. Статьи имеет много комментариев. Каждый комментарий относится к статусу комментария (comment_status_id): 1. Хорошо, или 2. Плохо или 3. Гадкий.

Я хочу сделать запрос, чтобы найти все статьи, которые имеют ТОЛЬКО комментарии со статусом 3 (Гадкий). То есть исключить статьи, которые имеют какие-либо комментарии со статусом 1 или 2.

Я могу написать подзапрос и запрос, чтобы получить всю статью, у которой есть комментарий с Status Ugly:

$matchingComments = $this->Articles->getAssociation('Comments')->find()
    ->select(['article_id'])
    ->distinct()
    ->where(['comment_status_id' => 3]);

$query = $this->Articles->find()
    ->where(['Articles.id IN' => $matchingComments]);

Это дает мне все статьи, у которых есть любой комментарий, который имеет статус 3. Но он также включает в себя статьи, которые имеют комментарии со статусом 2 или 1, а также по крайней мере один комментарий со статусом 3.

Итак, мой вопрос: Существует ли эффективный / элегантный способ заставить этот запрос работать с построителем запросов, чтобы в результате получались только статьи с комментариями ВСЕМ comment_status 3 (некрасиво)?

Я уверен, что могу проанализировать результаты $ запроса с помощью цикла for и создать новый массив результатов, но я хотел бы посмотреть, есть ли лучший способ сделать это в начальном запросе и / или / с подзапрос. Заранее спасибо за любой совет!

D.

Ответы [ 2 ]

1 голос
/ 10 апреля 2019

Следуя совету ndm, чтобы сначала запустить raw sql, этот запрос работал для моего запроса matchComments

SELECT `article_id`
FROM `comments`
GROUP BY `article_id`
HAVING MIN(`comment_status_id`) = 3
AND MAX(`comment_status_id`) = 3;

Итак, в моем контроллере Cake это работает:

$matchingComments = $this->Articles->getAssociation('Comments')->find()
    ->select(['article_id'])
    ->group('article_id')
    ->having(['MIN(comment_status_id)' => 3])
    ->having(['MAX(comment_status_id)' => 3])

$query = $this->Articles->find()
    ->where(['Articles.id IN' => $matchingComments]);

Не уверен, что есть лучший способ, но это прекрасно работает. Еще раз спасибо ndm. D.

0 голосов
/ 10 апреля 2019

С Cake Book - Получение наборов данных и результатов

$articles = $this->Articles
    ->find()
    ->contain(['Comments'])
    ->notMatching('Comments.CommentStatus', function($q) {
        return $q->where(['CommentStatus.comment_status_id' => '3'];
    });
...