开发者

What's Going Wrong With My CakePHP HABTM Query?

开发者 https://www.devze.com 2023-01-28 06:42 出处:网络
I have a table called Landmarks and a table called Categories with a HABTM relationship to each other.I am trying to retrieve all the categories for a specific Landmark with the following code:

I have a table called Landmarks and a table called Categories with a HABTM relationship to each other. I am trying to retrieve all the categories for a specific Landmark with the following code:

$this->set('selected_categories', $this->Category->find('list',
    array('contain'=>array(
        'Landmarks'=>array(
           'conditions'=>array('Landmark.num'=>7)
)))));

I've tested the database query that results from this (as printed out in debug level 2), and it seems to get the right results, i.e. a subset of the Categories. However, when I var_dump $selected_categories in the view, I'm getting a list of ALL categories instead.

Am I missing something obvious here?

ETA: I told a lie when I said the above query was working. Something else on the page is generating the SQL query I want! Which is:

SELECT `Categories`.`num`, `CategoriesLandmark`.`category_num`,
  `CategoriesLandmark`.`landmark_num` 
FROM `categories` AS `Categories` JOIN `categories_landmarks` 
AS `CategoriesLandmark` ON (`CategoriesLandmark`.`landmark_num` = 7
AND `Cat开发者_Python百科egoriesLandmark`.`category_num` = `Categories`.`num`) WHERE 1 = 1


Specifying the find type as 'list' is incompatible with the Containable behavior.

Use joins instead to accomplish this:

$selectedCategories = $this->Category->find('list', array(
    'joins' => array(
        array(
            'table' => 'categories_landmarks',
            'alias' => 'CategoriesLandmark',
            'type' => 'inner',
            'conditions' => array("CategoriesLandmark.category_id = Category.id")
        ),
        array(
            'table' => 'landmarks',
            'alias' => 'Landmark',
            'type' => 'inner',
            'conditions' => array(
                "CategoriesLandmark.landmark_id = Landmark.id",
                'Landmark.num' => 7
            )
        ),
    )
));

I would ideally place this directly into the Category model like so:

function fetchListByLandmarkNum($landmarkNum) {
    return $this->find('list', array(
        'joins' => ...
    ));
}

And then call it from the controller:

$selectedCategories = $this->Category->fetchListByLandmarkNum(7);
$this->set(compact('selectedCategories'));

Always make your models fat and your controllers skinny. You can now reuse this function elsewhere. :)


The reason why ALL the categories are being returned is that the condition is applied on the related Landmark models. The result of this Containable query would be to fetch all the Categories, and return only those Landmark models which satisfy num = 7. It should NOT be interpreted as returning only those Categories for which the Landmark models satisfy the condition.

0

精彩评论

暂无评论...
验证码 换一张
取 消