11

我使用 CakePHP 2.2.2 我有 3 张桌子:餐厅、厨房和 kitchens_restaurants - 加入 HABTM 的桌子。

在餐厅模型中,我有:

public $hasAndBelongsToMany = array(
    'Kitchen' =>
        array(
            'className'              => 'Kitchen',
            'joinTable'              => 'kitchens_restaurants',
            'foreignKey'             => 'restaurant_id',
            'associationForeignKey'  => 'kitchen_id',
            'unique'                 => true,
            'conditions'             => '',
            'fields'                 => 'kitchen',
            'order'                  => '',
            'limit'                  => '',
            'offset'                 => '',
        ),

问题是我的主页有单独的控制器,我需要从具有复杂条件的模型中检索数据。

我添加了

public $uses = array('Restaurant');

到我的主页控制器,这里是我需要你建议的部分。

我只需要选择厨房 = $id 的餐厅。我试图添加

public function index() {   
$this->set('rests', $this->Restaurant->find('all', array(
'conditions' => array('Restaurant.active' => "1", 'Kitchen.id' => "1")
)));

}

我得到了 SQLSTATE[42S22]: Column not found: 1054 Unknown column in 'where 子句' 错误。显然我需要从“HABTM 连接表”中获取数据,但我不知道如何。

4

3 回答 3

24

TLDR:

要检索基于[HABTM]关联的条件受限的数据,您需要使用[Joins]

解释:

下面的代码遵循[ Fat Model/Skinny Controller ]口头禅,因此逻辑大部分都在模型中,并且只是从控制器中调用。

注意:如果您遵循[CakePHP 约定](看起来就是这样),则不需要所有这些 HABTM 参数。

下面的代码还没有经过测试(我在这个网站上写的),但它应该非常接近,至少能让你朝着正确的方向前进。

代码:

//餐厅模型

public $hasAndBelongsToMany = array('Kitchen');

/**
 * Returns an array of restaurants based on a kitchen id
 * @param string $kitchenId - the id of a kitchen
 * @return array of restaurants
 */
public function getRestaurantsByKitchenId($kitchenId = null) {
    if(empty($kitchenId)) return false;
    $restaurants = $this->find('all', array(
        'joins' => array(
             array('table' => 'kitchens_restaurants',
                'alias' => 'KitchensRestaurant',
                'type' => 'INNER',
                'conditions' => array(
                    'KitchensRestaurant.kitchen_id' => $kitchenId,
                    'KitchensRestaurant.restaurant_id = Restaurant.id'
                )
            )
        ),
        'group' => 'Restaurant.id'
    ));
    return $restaurants;
}

//任何控制器

public function whateverAction($kitchenId) {
    $this->loadModel('Restaurant'); //don't need this line if in RestaurantsController
    $restaurants = $this->Restaurant->getRestaurantsByKitchenId($kitchenId);
    $this->set('restaurants', $restaurants);
}
于 2012-09-16T22:35:52.760 回答
2

有一种比 Dave 提供的解决方案更清洁的方法。

首先,您需要厨房模型中设置餐厅厨房之间的反向 HABTM 关系。

比您只需找到您感兴趣的厨房(id = 1),您将获得相关的餐厅,使用可包含行为按餐厅字段进行过滤。

$this->Restaurant->Kitchen->Behaviors->attach('containable'); // Enable Containable for Kitchen Model

$this->Restaurant->Kitchen->find('first', array(
    'recursive' => -1 // don't collect other data associated to Kitchen for performance purpose
    'conditions' => array('Kitchen.id' => 1),
    'contain' => array('Restaurant.active = 1')
));

资源

于 2016-09-28T12:46:59.780 回答
1

您可以不需要使用 [join],因为使用设置了 [HABTM] 的关联
Kitchen 模型 hasAndBelongsToMany Restaurant 模型,因此您可以编写如下代码

KitchensControllers
<?php
  public function index() {
    $this->Kitchen->recursive = 0;
    $kitchens = $this->Kitchen->find('all', array('contain' => array('Restaurant')));
    $this->set('kitchens', $kitchens);
  }
?>

祝你好运!

于 2014-09-14T14:55:14.550 回答