Поиск в Yii с несколькими условиями MANY_MANY - PullRequest
1 голос
/ 08 ноября 2011

В структуре Yii я пытаюсь выяснить, как запрашивать и получать результаты, соответствующие нескольким тегам в следующей системе:

posts
id

tags
id

post_tags
post_id
tag_id

Я пытаюсь выяснить, как вернуть результат постов, которые соответствуют тегу 1 и тегу 2. Любая помощь с этим будет очень признательна.


EDIT

Пока у меня, кажется, все работает так:

В Post отношениях:

array(
    'tags'  => array( self::MANY_MANY, 'Tag', Yii::app()->db->tablePrefix . 'post_tag(post_id,tag_id)' ),
);

В PostTag отношениях

array( 
    'post'  => array( self::BELONGS_TO, 'Post', 'post_id' ),
    'tag'   => array( self::BELONGS_TO, 'Tag', 'tag_id' ),
);

По моему Controller

$tags   = array( 1, 2, 3 ); // Match N tags

$criteria           = new CDbCriteria();
$criteria->with = 'post';
$criteria->addInCondition( 'tag_id', $tags );
$criteria->group    = 'post_id';
$criteria->having   = 'COUNT(*) = ' . count( $tags );

$matchedPostTags    = PostTag::model()->findAll( $criteria );
foreach( $matchedPostTags as $matchedPostTag )
{
    $post   = $matchedPostTag->post;
    // Do what you want with it.
}

Теперь, если кто-нибудь сможет понять, как заставить это работать с CActiveDataProvider, я был бы признателен.

Ответы [ 2 ]

6 голосов
/ 08 ноября 2011

Для любого любопытного, вот как я заставил его работать:

Post отношения

array(
    'tags'      => array( self::MANY_MANY, 'Tag', Yii::app()->db->tablePrefix . 'post_tag(post_id,tag_id)' ),
    'post_tags' => array( self::HAS_MANY, 'PostTag', 'post_id' ),
);

PostTag Отношения

array( 
    'post'  => array( self::BELONGS_TO, 'Post', 'post_id' ),
    'tag'   => array( self::BELONGS_TO, 'Tag', 'tag_id' ),
);

Controller

$tags   = array( 1, 2, 3 ); // Match N tags

$criteria           = new CDbCriteria();
$criteria->with = array( 
    'post_tags' => array(
        'condition' => 'tag_id IN ('.implode($tags).')',
        'group'     => 'post_id',
        'having'    => 'COUNT(*) = ' . count( $tags ),
    )
);
$criteria->together = true;

$dataProvider   = new CActiveDataProvider( 'Post', array(
    'criteria'  => $criteria,
) );

Это теперь работает с моим ListView, чтобы показывать только сообщения, которые соответствуют ВСЕМ указанным тегам.

0 голосов
/ 08 ноября 2011

Вы должны добавить отношения между Post и PostTag в вашем Post классе.Поместите его на relations()

public function relations() {
    return array(
        'post_tags'=>array(self::HAS_MANY, 'PostTag', 'post_id'),
    );
}

После этого в вашем классе контроллера добавьте этот код:

$criteria = new CDbCriteria();
$criteria->addInCondition('post_tags.tag_id', array(1, 2));
$criteria->with('post_tags');

$models = Post::model()->findAll($criteria);
...