Условный запрос CakePHP с контроллером hasAndBelongsToMany - PullRequest
1 голос
/ 13 мая 2011

Я прошу прощения за ужасный заголовок, я не мог придумать, как объяснить мою проблему.

В моей базе данных есть следующие таблицы: articles, tags и articles_tags.В статье может быть много тегов.

В настоящее время я могу получить все статьи со всеми тегами, но хочу найти статьи по их тегам.

Мой выборпрост:

$articles = $this->Article->find('all', array(
    // extra condition to check for tag, maybe?
    'conditions'    => array('Article.status' => 'active'), 
    'limit'         => $this->articles_per_page,
    'offset'        => ($page_num-1)*$this->articles_per_page
));

Мой возврат из базы данных выглядит следующим образом:

Array
(
[0] => Array
    (
        [Article] => Array
            (
                [id] => 1
            )

        [Tag] => Array
            (
                [0] => Array
                    (
                        [id] => 1
                        [name] => Ruby
                        [slug] => ruby
                        [uses] => 1
                        [ArticlesTag] => Array
                            (
                                [id] => 1
                                [article_id] => 1
                                [tag_id] => 1
                            )

                    )

            )

    )

Что мне делать, если я хочу вернуть статьи только с тегом Ruby?

Ответы [ 4 ]

2 голосов
/ 13 мая 2011

Для таких условий вы можете использовать LinkableBehavior . Он предназначен для точного желаемого результата. Если вы не хотите его использовать, вам нужно выполнить запрос на контроллере тегов:

$this->Tag->find('all', array('conditions' => array('Tag.name' => 'ruby')));
2 голосов
/ 13 мая 2011

Попробуйте это

// In your Article model
function getArticleByTagSql($tag)
{       
        $dbo = $this->getDataSource();
        $subQuery = $dbo->buildStatement(
        array(
                    'fields' => array('DISTINCT(ArticlesTag.article_id)'),
                    'table' => "articles_tags",                                    
                    'joins' => array(
                                array('table' => 'tags',
                                    'alias' => 'Tag',
                                    'type' => 'INNER',
                                    'conditions' => array('ArticlesTag.tag_id = Tag.id')
                                    )
                                ),
                    'alias'=>"ArticlesTag",                                         
                    'conditions' => array("Tag.name"=>Sanitize::clean($tag_words)),
                    'order' => null,
                    'group' => "ArticlesTag.article_id"
                    ),
                    $this
                    );
                    $subQuery = ' Article.id  IN (' . $subQuery . ')';
                    return $dbo->expression($subQuery);

}

// In your Articles Controller

$this->paginate['conditions'][] = $this->Article->getArticleByTagSql($tag_name);
$this->paginate['conditions'][] = array('Article.status' => 'active');
$this->paginate['limit'] = $this->articles_per_page;



// or as per your example
$articles = $this->Article->find('all', array(
                // extra condition to check for tag, maybe?
                'conditions'    => array('Article.status' => 'active',$this->Article->getArticleByTagSql($tag_name)), 
                'limit'         => $this->articles_per_page,
                'offset'        => ($page_num-1)*$this->articles_per_page
            ));
0 голосов
/ 16 ноября 2017

Я обновляю этот вопрос ответом на CakePHP 3.x.

Вы можете найти все articles для данного tag, используя INNER JOIN. Преимущество этого объединения заключается в том, что оно сохраняет article в качестве основной таблицы в запросе. Сделать это простым решением, когда вы разбиваете на страницы результаты с помощью присоединения HABTM.

$tag_id = 3; // the ID of the tag

$query = $this->Articles->find('all')
                 ->innerJoin('articles_tags', [
                      'Articles.id = articles_tags.article_id',
                      'articles_tags.tag_id' => $tag_id
                 ]);

Первым условием соединения должен быть ключ массива. Если вы используете массив =>, то CakePHP передаст articles_tags.article_id в качестве аргумента string в условие соединения. Который не будет работать.

Вы также можете сложить innerJoin для нескольких условий HABTM. Например; найти все статьи для тега , а также для категории . Вы также можете использовать выражение запроса in для сопоставления нескольких тегов .

Вы также можете использовать вышеперечисленное в нумерации страниц, как это $articles = $this->paginate($query);

Я уверен, что эта информация опубликована в Интернете, но этот вопрос был главным в результатах поиска Google. Так что, возможно, это поможет другим.

0 голосов
/ 13 мая 2011

Непосредственно невозможно.

Самый простой способ - выполнить запрос через контроллер тегов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...