初めての[CakePHP2.x]での開発、そして挫折するまで日記~その3 LEFT JOINを試す

cake-logo

cake-logo

前回までの続き

前回DBからデータをひっぱてきて表示させるまでいきました。

最近、会社での仕事でシステムを作るということになったので

せっかくなのでCakePHPを使ってやってみようと思いました。

・・・自分のサイトつくりにも役に立つし♪

なので、仕事で使う内容なども入れてやっていきます。

どれくらいで作れるのかな?

スポンサードリンク

テーブルの結合の仕方

今回はテーブルを結合して表示させてたいと思ったのですが、

まずどういう風にやるのかわかりませんでした。

SQLならJOINとかWHERE使うんだけど、

CakePHPではどういう風に書くのだろう?

色々調べてみると

CakePHPではアソシエーションと言って

モデルのなかに記述すると結合できるようです。

種類は以下の4つあります

・hasOne
・hasMany
・belongsTo
・hasAndBelongsToMany

イメージだとこんな感じでしょうか?

joinイメージ

joinイメージ

固有のidを持っているモデルから、そのidが使われているモデルへ向けてはhasOneとhasManyで

逆に他のモデルの固有のidを使っているモデルから、固有のidを持っているモデルへ向けてはbelognsToかな?

hasAndBelongsToManyは【多対多】で間にテーブルを用意しなければいけないみたい。

今回は、試していません。

他の3つを試してみた感じ以下のようです。

hasOne

主になるテーブルidに関連するものが結合されるテーブルにある場合で1つの結果を出す

(例)
※Postモデルで処理する場合

モデル名 Postモデル UserPostモデル
テーブル名 posts user_posts
関連するフィールド名 id post_id

Postモデルには基本こんな感じで書きます。

<?php 
class Post extends AppModel{
  public $hasOne = 'UserPost';  //結合モデル
}
?>

上記で命名規則に従っていれば自動的にLEFT JOINされます。

オプションで指定する場合は以下のようです。

<?php 
class Post extends AppModel{
  public $hasOne = 'array(
        'UserPost'=>array(
            'className' => 'UserPost',
            'foreignKey'=> 'post_id',
            'conditions'=> array('UserPost.status'=>1),
            'fields' => null ,
            'order'=> null ,
            'dependent'=> true,
         )  
     );
  }
}
?>

●className: 関連付けられるモデルのクラス名。

●foreignKey: アソシエーション先のモデルを検索するための外部キーの名前。デフォルト値は元モデルの単数形に _id がついたもの。

●conditions: array(‘Profile.approved’ => true) のような、find()に指定するconditionsと互換性のある配列、もしくはSQL文字列を指定します。(WHEREみたいな感じかな?)

●fields: 取得するフィールドのリスト。デフォルトで全フィールドが含まれます。

●order: array(‘Profile.last_name’ => ‘ASC’) のような、find()に指定するorderと互換性のある配列、もしくはSQL文字列を指定します。

●dependent: このキーにtureがセットされていて、かつモデルのdeleteメソッドのcascadeパラメータにtrueがセットされて呼び出された時、アソシエーション先のモデルのレコードも一緒に削除されます。

取り出し方はviewで

<?php echo h($product['モデル名']['カラム名']); ?>

で表示される。

hasMany

上記のhasOneが【1対1】で1つの結果しか返さないのと比べて

hasManyは【1対多】なので複数の結果を返してくれる。

しかし、hasManyはLEFT JOINするわけではなく

SQLを複数出します。

例えば、1つhasManyでアソシエーションすると

2つSQLを発動します。

結果は連想配列にまとめられます。

(例)
※Postモデルで処理する場合

モデル名 Postモデル UserPostモデル
テーブル名 posts user_posts
関連するフィールド名 id post_id

Postモデルには基本こんな感じで書きます。

<?php 
class Post extends AppModel{
  public $hasMany = 'UserPost';  //結合モデル
}
?>

上記で命名規則に従っていれば自動的にLEFT JOINされます。

オプションで指定する場合は以下のようです。

<?php 
class Post extends AppModel{
  public $hasMany = 'array(
        'UserPost'=>array(
            'className'     => 'UserPost',
            'foreignKey'    => 'post_id',
            'conditions'    => array('UserPost.status' => '1'),
            'order'         => 'UserPost.created DESC',
            'limit'         => '5',
            'dependent'     => true
        )  
     );
  }
}
?>

●className: 関連付けられるモデルのクラス名。

●foreignKey: 外部キーの名前。デフォルト値はアソシエーション先のモデルの単数形に _id がついたものです。

●conditions: array(‘Comment.visible’ => true) のような、find()に指定するconditionsと互換性のある配列、もしくはSQL文字列を指定します。

●order: array(‘Profile.last_name’ => ‘ASC’) のような、find()に指定するorderと互換性のある配列、もしくはSQL文字列を指定します。

●limit: アソシエーションモデルのデータの最大行数。

●offset: アソシエーションモデルのデータをスキップする行数。

●dependent: trueをセットすれば、データを再帰的に削除するようになります。たとえばPostレコードが削除されたら、UserPostレコードも削除されます。

●exclusive: trueをセットすれば、deleteAll()を呼び出した時にデータを再帰的に削除するようになります。

●finderQuery: アソシエーションモデルのレコードを取得する時に使われるSQLクエリ。取得結果をカスタムしたい時に使います。
(例)Apple hasMany Orangeというアソシエーションの場合、以下のようなクエリになるでしょう。SELECT Orange.* from oranges as Orange WHERE Orange.apple_id = {$__cakeID__$};

取り出し方はviewで

<?php echo h($product['モデル名']['カラム名']); ?>

belongsTo

hasOneを逆のモデルから見た場合で

結果はhasOneと同じ結果が返ります。

(例)
※UserPostモデルで処理する場合

モデル名 Postモデル UserPostモデル
テーブル名 posts user_posts
関連するフィールド名 id post_id

UserPostモデルには基本こんな感じで書きます。

<?php 
class UserPost extends AppModel{
  public $blongsTo = 'Post';  //結合モデル
}
?>

上記で命名規則に従っていれば自動的にLEFT JOINされます。

オプションで指定する場合は以下のようです。

<?php 
class UserPost extends AppModel{
  public $belongsTo = 'array(
        'Post'=>array(
            'className'    => 'Post',
            'foreignKey'   => 'post_id'
        )  
     );
  }
}
?>

●className: 関連付けられるモデルのクラス名。

●foreignKey: アソシエーション先のモデルを検索するための外部キーの名前。デフォルト値はアソシエーション先のモデルの単数形に _id がついたものです。

●conditions: array(‘User.active’ => true) のような、find()に指定するconditionsと互換性のある配列、もしくはSQL文字列を指定します。

●type: SQLクエリで使われるテーブル結合種別。結合タイプをleft、right、inner、crossの中から選べる。

●fields: アソシエーション先のモデルから取得するフィールドのリスト。デフォルトで全フィールドが含まれます。

●order: array(‘User.username’ => ‘ASC’) のような、 find()に指定するorderと互換性のある配列、もしくはSQL文字列を指定します。

●counterCache: trueをセットすれば、アソシエーション先のモデルでsave() または delete() を実行した時に、テーブルの”[モデル名の単数形]_count”というフィールドの値を増減します。文字列を指定すれば、指定された文字列のフィールドに対してカウントの操作を行います。キーにフィールド名、値に条件、という配列で指定することもできます。このフィールドの値は関連データの行数を表します。

●counterScope: conterCacheのフィールドを更新する際の追加条件があれば指定します。

取り出し方はviewで

<?php echo h($product['モデル名']['カラム名']); ?>

なかなか覚えられない感じですけど、

使い方次第では簡単にJOINしてくれるので便利ですよね。

今回参考にさせて頂いたサイトです。
cakePHP2.1でJoinする

【CakePHP】アソシエーションの図解

CakePHP2 実践入門 (WEB DB PRESS plus)

新品価格
¥3,110から
(2015/1/27 23:08時点)

スポンサードリンク

コメントを残す

サブコンテンツ

このページの先頭へ