Cakephp находит все запросы по нескольким моделям

Я пытаюсь сделать следующее, чтобы получить все статьи, которые принадлежат MenuItem 6 и имеют тип содержания статьи «блог». Он находит все статьи с content_type='blog'. Но я хочу, чтобы он возвращал статью только в том случае, если он принадлежит Menuitem 7. И теперь он возвращает пустое значение для MenuItem, если не 7.

Как я могу добиться того, чтобы он загружал только статьи из MenuItem 7?

MenuItem имеет связь HABTM со статьей

код:

 $d=$this->Article->find('all' , array('contain' => array(
        'MenuItem' => array(
            'conditions' => array(
                'MenuItem.id ' => 7,        
             ),
                'fields'=>'id'
        ),
        'Tag'=>array(
            'conditions'=>array(
                'Tag.name'=>'tag1'
            ),
            'fields'=>'name'
        )
      ),
      'conditions'=>array('Article.content_type' => 'blog'),
      'fields'=>array('id','content_type'),
      'recursive'=>1
     ));

     debug($d);

множество:

 array(
      (int) 10 => array(
    'Article' => array(
        'id' => '15',
        'content_type' => 'blog'
    ),
    'Tag' => array(),
    'MenuItem' => array()
),
     (int) 11 => array(
    'Article' => array(
        'id' => '16',
        'content_type' => 'blog'
    ),
    'Tag' => array(),
    'MenuItem' => array(
        (int) 0 => array(
            'id' => '7',
            'MenuItemsArticle' => array(
                'id' => '18',
                'title' => '',
                'article_id' => '16',
                'menu_item_id' => '7'
            )
        )
    )
      )
 )

person waterschaats    schedule 16.08.2012    source источник
comment
Хороший вопрос. Я помню, как однажды решал эту проблему, но с плохим кодом. Надеюсь, кто-то может дать хороший ответ.   -  person L. Sanna    schedule 16.08.2012
comment
Это должно быть один на один, чтобы результаты можно было разбивать на страницы.   -  person waterschaats    schedule 16.08.2012


Ответы (1)


Я думаю, что для этого типа условия поиска лучше всего изменить свои модели, чтобы они использовали имеет много через (модель соединения). Вот пример, который я тестировал, который делает то, что вы хотите:

Article.php

class Article extends AppModel {
    public $hasMany = array('ArticleMenuItem');
}

MenuItem.php

class MenuItem extends AppModel {
    public $hasMany = array('ArticleMenuItem');
}

ArticleMenuItem.php

class ArticleMenuItem extends AppModel {
    public $useTable = 'articles_menu_items';

    public $belongsTo = array(
        'Article',
        'MenuItem'
    );
}

Вызов поиска

$articles = $this->ArticleMenuItem->find('all', array(
    'conditions' => array(
        'menu_item_id' => 7,
        'Article.content_type' => 'blog'
    ),
    'contain' => array(
        'Article' => array(
            'fields' => array(
                'id',
                'title'
            )
        ),
        'Tag'
    )
));

Вот что он производит:

array(
    (int) 0 => array(
        'ArticleMenuItem' => array(
            'article_id' => '1',
            'menu_item_id' => '7'
        ),
        'Article' => array(
            'id' => '1',
            'content_type' => 'blog',
            'title' => 'test blog'
        )
    ),
    (int) 1 => array(
        'ArticleMenuItem' => array(
            'article_id' => '4',
            'menu_item_id' => '7'
        ),
        'Article' => array(
            'id' => '4',
            'content_type' => 'blog',
            'title' => 'another'
        )
    )
)

И вот запрос, который он генерирует:

SELECT `ArticleMenuItem`.`article_id`, `ArticleMenuItem`.`menu_item_id`, `Article`.`id`, `Article`.`content_type`, `Article`.`title` FROM `caketest`.`articles_menu_items` AS `ArticleMenuItem` LEFT JOIN `caketest`.`articles` AS `Article` ON (`ArticleMenuItem`.`article_id` = `Article`.`id`) WHERE `menu_item_id` = 7 AND `Article`.`content_type` = 'blog'

Я также установил $recursive = -1 в своей AppModel. Я бы предложил сделать то же самое, поскольку вы используете сдерживаемое поведение, это намного эффективнее, потому что извлекает только те данные, которые вам нужны. :)

Надеюсь, это поможет, любые вопросы просто дайте мне знать.

person Hoff    schedule 16.08.2012
comment
Спасибо! Это выглядит очень хорошо, я попытаюсь применить это к моей ситуации. - person waterschaats; 16.08.2012
comment
Это отлично работает, спасибо! Могу ли я уменьшить поля вывода? Теперь он возвращает все поля таблицы Article. - person waterschaats; 16.08.2012
comment
В статье также есть тег (HABTM), связанный с ним, могу ли я получить их также в массиве? - person waterschaats; 16.08.2012
comment
Я обновил вызов find, чтобы показать вам, как указывать поля, а также включать теги. Я предлагаю прочитать о сдерживаемом поведении, его действительно легко использовать. Кроме того, не забудьте отметить это как ответ, если он ответил на ваш вопрос :) - person Hoff; 16.08.2012
comment
Большое спасибо! Нужно ли прикреплять поведение Coontainable к ArticleMenuItem, чтобы заставить это работать? - person waterschaats; 16.08.2012
comment
Прикрепите его к своей AppModel: public $actsAs = array('Containable'); - person Hoff; 16.08.2012