常に連結させたくないテーブルがあり、場合によっては連結させてデータを取りたいときも出てくる
そんなときに「メソッドが呼び出されたタイミングで連結を行う」これをバインドという
[php]
public function adduser(){
$belongsTo = array(
‘User’ => array(
‘className’ => ‘User’,
‘foreignKey’ => ‘user_id’
));
$this->bindModel(array("belongsTo" => $belongsTo));
$data = $this->find(‘all’);
return $data;
}
[/php]
「アソシエーション」カテゴリーアーカイブ
hasMany through
hasManyを保存する[saveAssociated ]
http://book.cakephp.org/2.0/ja/models/saving-your-data.html
https://github.com/markstory/cakephp-docs/blob/master/ja/models/saving-your-data.rst
[php]
CREATE TABLE `coursememberships` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`days_attended` varchar(255) NOT NULL,
`grade` varchar(255) NOT NULL,
`created` datetime default NULL,
`modified` datetime default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=28 ;
CREATE TABLE `students` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`first_name` varchar(255) NOT NULL,
`last_name` varchar(255) NOT NULL,
`created` datetime default NULL,
`modified` datetime default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=28 ;
CREATE TABLE `courses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`created` datetime default NULL,
`modified` datetime default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=28 ;
[/php]
[php]
// Controller/CourseMembershipController.php
class CourseMembershipsController extends AppController {
public $uses = array(‘CourseMembership’);
public function index() {
$this->set(‘courseMembershipsList’, $this->CourseMembership->find(‘all’));
}
public function add() {
if ($this->request->is(‘post’)) {
if ($this->CourseMembership->saveAssociated($this->request->data)) {
$this->redirect(array(‘action’ => ‘index’));
}
}
}
}
// View/CourseMemberships/add.ctp
<?php echo $this->Form->create(‘CourseMembership’); ?>
<?php echo $this->Form->input(‘Student.first_name’); ?>
<?php echo $this->Form->input(‘Student.last_name’); ?>
<?php echo $this->Form->input(‘Course.name’); ?>
<?php echo $this->Form->input(‘CourseMembership.days_attended’); ?>
<?php echo $this->Form->input(‘CourseMembership.grade’); ?>
<button type="submit">Save</button>
<?php echo $this->Form->end(); ?>
[/php]
[php]
// View/CourseMemberships/add.ctp
<?php echo $form->create(‘CourseMembership’); ?>
<?php echo $this->Form->input(‘Student.id’, array(‘type’ => ‘text’, ‘label’ => ‘Student ID’, ‘default’ => 1)); ?>
<?php echo $this->Form->input(‘Course.id’, array(‘type’ => ‘text’, ‘label’ => ‘Course ID’, ‘default’ => 1)); ?>
<?php echo $this->Form->input(‘CourseMembership.days_attended’); ?>
<?php echo $this->Form->input(‘CourseMembership.grade’); ?>
<button type="submit">Save</button>
<?php echo $this->Form->end(); ?>
[/php]
リレーションしてるテーブルをまとめて保存
http://d.hatena.ne.jp/g2_girichan/20090327/1238154524
http://d.hatena.ne.jp/sutara_lumpur/20100702/1278029850
[CakePHP]アソシエイションを持つモデルをsaveall()する際に受け付けるデータ構造
CakePHP2 で Model::saveAssociated を使って1回で複数のテーブルにデータを保存します♪
テーブルの結合について
等価結合・・・2つのテーブルのカラムを指定し、一致したカラムのデータのみ抽出する
外部結合・・・指定したカラムのデータがテーブルのどちらか一方にしかない場合もデータを抽出できる。結合方法は、左外部結合、右外部結合、完全外部結合がある。
左外部結合・・・左側のテーブルのデータをすべて抽出し、右側のテーブルの一致したデータのみを抽出する。「LEFT JOIN」
右外部結合・・・右側のテーブルのデータをすべて抽出し、左側のテーブルの一致したデータのみを抽出する。「RIGHT JOIN」
完全外部結合・・・2つのテーブルそれぞれに一致しない結果も抽出結果として表示します。「FULL OUTER JOIN」
再帰結合・・・同じテーブル同士での結合を行ないます。再帰結合はテーブル名での区別が出来ないため「AS」でテーブルに別名をつけ結合させます。
複数アソシエーションの書き方について
AテーブルとBテーブルが結合されており、BテーブルとCテーブルが結合されている状態で、AテーブルでCテーブルのデータを取りたい場合。
1.通常のアソシエーションを利用
Bテーブルを軸にし、beloggToでAテーブルとCテーブルのデータを取得する
2..joinを扱う
$hasMany
1対多 “他”のほうのテーブルに“1”側のIDを持たせる
HasAndBelongsToMany
class Recipe extends AppModel { public $name = 'Recipe'; public $hasAndBelongsToMany = array( 'Ingredient' => array( 'className' => 'Ingredient', 'joinTable' => 'ingredients_recipes', 'foreignKey' => 'recipe_id', 'associationForeignKey' => 'ingredient_id', 'unique' => true, 'conditions' => '', 'fields' => '', 'order' => '', 'limit' => '', 'offset' => '', 'finderQuery' => '', 'deleteQuery' => '', 'insertQuery' => '' ) ); }
className: 元モデルに関連付けられるモデルのクラス名。Recipe HABTM Ingredient を定義したい場合、’Ingredient’となります。
joinTable: このアソシエーションに使う中間テーブルの名前。テーブル名がHABTMテーブルの規約に従っていない場合に指定します。
with: joinするテーブルのモデル名を定義します。デフォルトではCakePHPはモデルを自動的に生成します。上記のサンプルでは、IngredientsRecipeです。このキーを使うことで、このデフォルトの名前を上書きすることができます。この名前のモデルクラスを生成することで、他の通常のモデルと同じようにたとえば追加の列や情報を取得するようにカスタム動作を定義できます。
foreignKey: アソシエーション先のモデルを検索するための外部キーの名前。これは複数のHABTMを定義するためによく使われます。このキーのデフォルト値はアソシエーション先のモデルの単数形に _id がついたものです。
associationForeignKey: アソシエーション先のもう一方のモデルを検索するための外部キーの名前。これは複数のHABTMを定義するためによく使われます。このキーのデフォルト値はアソシエーション先のモデルの単数形に _id がついたものです。
unique: bool値、または文字列で keepExisting を指定します。
trueを指定すれば(これがデフォルトです)、新しいレコードを挿入する前に既存の関連するレコードを削除します。
falseを指定すれば、saveを実行してレコードを挿入したあとに、joinできないレコードがあれば削除されます。
keepExisting を指定すれば、 true を指定した時と似ていますが、既存の関連レコードは削除されません。
conditions: find()に指定するconditionsと互換性のある配列もしくはSQL文字列を指定します。アソシエーション先のテーブルに条件を指定したければ、’with’ に指定したモデルを使って必要なbelongsToアソシエーションを定義してください。
fields: アソシエーション先のモデルから取得するフィールドのリスト。デフォルトで全フィールドが含まれます。
order: find()に指定するorderと互換性のある配列もしくはSQL文字列を指定します。
limit: アソシエーションモデルのデータの最大行数。
offset: アソシエーションモデルのデータをスキップする行数。
finderQuery, deleteQuery, insertQuery: データ取得、削除、追加の時に使われるSQLクエリを指定します。これは、動作をカスタマイズしたい時に使います。
参考
http://book.cakephp.org/2.0/ja/models/associations-linking-models-together.html
http://www.webopixel.net/cakephp/259.html
belongsTo
<?php class Profile extends AppModel { var $name = 'Profile'; var $belongsTo = array( 'User' => array( 'className' => 'User', 'foreignKey' => 'user_id' ) ); } ?>
belongsTo 関連の配列で有効なキーは以下のようになります:
- className: 現在のモデルに関連したモデルのクラス名。‘Profile belongsTo User’ という関係を定義する場合、className キーは‘User’になります。
- foreignKey: 現在のモデルにある外部キー名。複数の belongsTo 関係を定義する必要がある場合に、これは特に便利です。このキーのデフォルト値は、他のモデル名のアンダースコアで区切られた単数形で、末尾に‘_id’が付きます。
- conditions: 関連モデルのレコードを限定するために使用する SQL。SQL にモデル名を使用するのは良い習慣となります: “User.active = 1” は常に“active = 1”よりも推奨されます。
- fields: 関連モデルのデータを取得した際に取り出すフィールドのリスト。デフォルトではすべてのフィールドを返します。
- counterCache: (bool) true にセットすると、save() または delete() が呼び出されるたびに、関連モデルは自動的に外部テーブルの“[singular_model_name]_count”というフィールドをインクリメントまたはデクリメントします。カウンタフィールドの値は関連する行の番号を表します。
- order: 返される関連する行の並び順を定義する SQL。
$hasOne
class User extends AppModel { var $name = 'User'; var $hasOne = array( 'Profile' => array( 'className' => 'Profile', 'conditions' => array('Profile.published' => '1'), 'dependent' => true ) );
- className: 現在のモデルに関連したモデルのクラス名。‘User hasOne Profile’ という関係を定義する場合、className キーは‘Profile’ になります。
- foreignKey: もう一方のモデルにある外部キーの名前。複数の hasOne 関係を定義する必要がある場合に特に便利です。このキーのデフォルト値は、現在のモデル名のアンダースコア区切りの単数形で、末尾に‘_id’をつけたものです。上記の例では、’user_id’ となります。
- conditions: 関連モデルのレコードを限定するための SQL。SQL 内でモデル名を使用することを習慣にしておくようにしておきましょう:“approved = 1.” よりも、“Profile.approved = 1” の方が良い記述です。
- fields: 関連モデルのデータが取得された際に取り出すフィールドのリストです。デフォルトではすべてのフィールドを返します。
- dependent: dependent キーを true にセットし、delete() メソッドの cascade 引数を true をセットして呼び出すと、関連するモデルのレコードも併せて削除されます。この場合、true をセットしているので、User を削除すると、関連する Profile も削除します。