11

私はCakePHP2.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]が表示されました:列が見つかりません:1054'where句'エラーの不明な列。明らかに「HABTM結合テーブル」からデータをフェッチする必要がありますが、その方法がわかりません。

4

3 に答える 3

24

TLDR:

[HABTM]の関連付けに対する条件に基づいて制限されているデータを取得するには、 [結合]を使用する必要があります。

説明:

以下のコードは[FatModel/ 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)、レストランのフィールドでフィルタリングするためのContainable Behaviorを使用して、関連するレストランを取得します。

$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

[haBTM]の関連付けを設定しているため、[join]を使用する必要はありません。
キッチンモデル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 に答える