CakePHP のバリデーションの基本を勉強します。 | oki2a24 の次の投稿となります。
以前ひとつのテーブルからのデータ取得を行いました。それも、モデルなしで。今回はモデルをしっかり使って、そしてテーブルは複数を連携させて、という例となります。2つのテーブルを使用しますが、連携のさせ方を網羅させて、しらみつぶしに動きを調べようと思います。
今回は、hasAndBelongsToMany を除いた hasOne、belongTo、hasMany の3パターンを取り扱います。
ポイント
- モデルに連携したい相手のモデルを書く。書き方は、hasOne、belongTo、hasMany、hasAndBelongsToMany の4種類ある。
- hasOne 1:1。相手テーブルに自テーブルの id 値を設定します。例、users テーブルの1つの行は、profiles テーブルの1つの行を持っている。
- belongTo n:1。自テーブルに相手テーブルの id 値を設定します。例、users テーブルの1行は、recipes テーブルの多くの行を持つことができる。
- hasMany 1:n。相手テーブルに自テーブルの id 値を設定します。例、recipes テーブルの多くの行は、users テーブルの1つの行に所属している。
- belongTo と hasMany はどちらも1つに対して複数の対応ですが、1:n ( hasMany )の場合は1つの行に対して複数の行が紐づいた状態でデータを取得できます。一方、n:1 ( belongTo ) の場合は1つの行に対して1つの行が紐づいた状態でデータを取得できます。
- モデルの連携は適当では駄目です。エラーとなります。または、変なデータが取れると思います。
前提
- CakePHP 2.1.3 導入済み。
- ドキュメントルート/cake/sample/(ここにCakePHP が入ってます。app ディレクトリとか、.travis.yml ファイルとか。)
連携のパターンとテーブル
personals テーブルと、boards テーブルの2つを例にとります。boards テーブルに、personal_id 列を設け、これで personals テーブルと連携します。3つの連携方法と組み合わせて、全部で次の6パターンを試しました。
結果も出てしまっていますけれども、パターンは次のとおりです。
| No | 関係 | Personal モデル | Board モデル | Boards コントローラ index アクション | 正誤 |
|---|---|---|---|---|---|
| 1 | Personal hasOne Board | public $hasOne = ‘Board’; | 無 | $this->Personal->find(‘all’); | 正 |
| 2 | Personal belongsTo Board | public $belongsTo = ‘Board’; | 無 | $this->Personal->find(‘all’); | 誤 |
| 3 | Personal hasMany Board | public $hasMany = ‘Board’; | 無 | $this->Personal->find(‘all’); | 正 |
| 4 | Board hasOne Personal | 無 | public $hasOne = ‘Personal’; | $this->Board->find(‘all’); | 誤 |
| 5 | Board belongsTo Personal | 無 | public $belongsTo = ‘Personal’; | $this->Board->find(‘all’); | 正 |
| 6 | Board hasMany Personal | 無 | $this->Board->find(‘all’); | 誤 |
テーブルは次の二つです。行データのSQL も載せておきます。
-- DB、ユーザ、の作成。パスワードの設定 GRANT ALL PRIVILEGES ON sampledb.* TO sampleuser@localhost IDENTIFIED BY 'samplepassword'; FLUSH PRIVILEGES; CREATE DATABASE sampledb CHARACTER SET utf8; -- -- テーブルの構造 `boards` -- CREATE TABLE IF NOT EXISTS `boards` ( `id` INT NOT NULL AUTO_INCREMENT, `personal_id` INT NOT NULL, `title` varchar(255) NOT NULL, `content` text NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ; -- -- テーブルのデータをダンプしています `boards` -- INSERT INTO `boards` (`id`, `personal_id`, `title`, `content`) VALUES (1, 1, 'はっけよーい', 'のこった!★のこった!★'), (2, 1, '位置について、よーい', 'ドン!ドン!ドン!ドドンガドン! ドン!ドン!ドン!ドドンガドン! '), (3, 1, 'こんにちは!', 'こんにちは!こんにちは!'), (4, 1, 'おはよう!', 'おはようっ!ぐっとモーニング!'), (5, 1, 'はっけはっけ', 'のこった!のこった!のこった!のこった!'), (6, 2, 'かかかかkっか', 'カッカッカッカッカッ!'), (7, 2, '佐藤佐藤!!', '佐藤佐藤佐藤佐藤'), (8, 2, 'あまいよ', 'あっま~い!甘い、砂糖だよ♪'), (9, 3, 'しましま', 'しまうましまうまサファリアフリカ'); -- -- テーブルの構造 `personals` -- CREATE TABLE IF NOT EXISTS `personals` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(255) NOT NULL, `password` varchar(255) NOT NULL, `comment` varchar(255) DEFAULT NULL, `created` datetime DEFAULT NULL, `modified` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ; -- -- テーブルのデータをダンプしています `personals` -- INSERT INTO `personals` (`id`, `username`, `password`, `comment`, `created`, `modified`) VALUES (1, 'yamada', 'yamada', '山田', NULL, NULL), (2, 'sato', 'sato', '佐藤', NULL, NULL), (3, 'kato', 'kato', '加藤', NULL, NULL);
ソース
cake/sample/app/Model/Personal.php
<?php
class Personal extends AppModel {
public $name = 'Personal';
// public $hasOne = 'Board';
// public $belongsTo = 'Board';
// public $hasMany = 'Board';
}
?>
4、5、6行目のコメントパターンによって外して試します。
cake/sample/app/Model/Board.php
<?php
class Board extends AppModel {
public $name = 'Board';
// public $hasOne = 'Personal';
// public $belongsTo = 'Personal';
// public $hasMany = 'Personal';
}
?>
こちらも、4、5、6行目のコメントパターンによって外して試します。
cake/sample/app/Controller/BoardsController.php
<!--?php class BoardsController extends AppController { // The name of this controller. Controller names are plural, named after the model they manipulate. public $name = 'Boards'; // An array containing the class names of models this controller uses. public $uses = array('Board', 'Personal'); /** * 初期表示 */ public function index() { // Personal を取得。 // $data = $this--->Personal->find('all');
// Board を取得。
// $data = $this->Board->find('all');
// ビューで使えるように DB データをセット
$this->set('data', $data);
}
}
?>
public $uses でこのコントローラーで使用するモデルを指定します。2つのテーブルの連携を試すので、2つのモデルを指定しています。
14、16行目で、どちらのモデルから find するかをパターンによって切り替えます。
cake/sample/app/View/Boards/index.ctp
<h1>複数テーブル連携サンプル</h1> <pre> <?php print_r($data); ?> </pre>
結果 1.Personal hasOne Board
以下、http://localhost/cake/sample/boards/ にアクセスしたときの結果となります。
その前に、テーブルの連携図を掲載します。
結果の要点です。
Array
(
[0] => Array
(
[Personal] => Array
(
[id] => 1
[username] => yamada
[password] => yamada
[comment] => 山田
[created] =>
[modified] =>
)
[Board] => Array
(
[id] => 1
[personal_id] => 1
[title] => はっけよーい
[content] => のこった!★のこった!★
)
)
・・・
)
発行された SQL です。
SELECT `Personal`.`id`, `Personal`.`username`, `Personal`.`password`, `Personal`.`comment`, `Personal`.`created`, `Personal`.`modified`, `Board`.`id`, `Board`.`personal_id`, `Board`.`title`, `Board`.`content` FROM `sampledb`.`personals` AS `Personal` LEFT JOIN `sampledb`.`boards` AS `Board` ON (`Board`.`personal_id` = `Personal`.`id`) WHERE 1 = 1
結果 2.Personal belongsTo Board
結果の要点です。
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Personal.board_id' in 'on clause'
発行された SQL です。
SELECT `Personal`.`id`, `Personal`.`username`, `Personal`.`password`, `Personal`.`comment`, `Personal`.`created`, `Personal`.`modified`, `Board`.`id`, `Board`.`personal_id`, `Board`.`title`, `Board`.`content` FROM `sampledb`.`personals` AS `Personal` LEFT JOIN `sampledb`.`boards` AS `Board` ON (`Personal`.`board_id` = `Board`.`id`) WHERE 1 = 1
結果 3.Personal hasMany Board
結果の要点です。
Array
(
[0] => Array
(
[Personal] => Array
(
[id] => 1
[username] => yamada
[password] => yamada
[comment] => 山田
[created] =>
[modified] =>
)
[Board] => Array
(
[0] => Array
(
[id] => 1
[personal_id] => 1
[title] => はっけよーい
[content] => のこった!★のこった!★
)
[1] => Array
(
[id] => 2
[personal_id] => 1
[title] => 位置について、よーい
[content] => ドン!ドン!ドン!ドドンガドン! ドン!ドン!ドン!ドドンガドン!
)
[2] => Array
(
[id] => 3
[personal_id] => 1
[title] => こんにちは!
[content] => こんにちは!こんにちは!
)
[3] => Array
(
[id] => 4
[personal_id] => 1
[title] => おはよう!
[content] => おはようっ!ぐっとモーニング!
)
[4] => Array
(
[id] => 5
[personal_id] => 1
[title] => はっけはっけ
[content] => のこった!のこった!のこった!のこった!
)
)
)
・・・
)
発行された SQL です。
1 SELECT `Personal`.`id`, `Personal`.`username`, `Personal`.`password`, `Personal`.`comment`, `Personal`.`created`, `Personal`.`modified` FROM `sampledb`.`personals` AS `Personal` WHERE 1 = 1 2 SELECT `Board`.`id`, `Board`.`personal_id`, `Board`.`title`, `Board`.`content` FROM `sampledb`.`boards` AS `Board` WHERE `Board`.`personal_id` IN (1, 2, 3)
結果 4.Board hasOne Personal
結果の要点です。
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Personal.board_id' in 'on clause'
発行された SQL です。
SELECT `Board`.`id`, `Board`.`personal_id`, `Board`.`title`, `Board`.`content`, `Personal`.`id`, `Personal`.`username`, `Personal`.`password`, `Personal`.`comment`, `Personal`.`created`, `Personal`.`modified` FROM `sampledb`.`boards` AS `Board` LEFT JOIN `sampledb`.`personals` AS `Personal` ON (`Personal`.`board_id` = `Board`.`id`) WHERE 1 = 1
結果 5.Board belongsTo Personal
結果の要点です。
Array
(
[0] => Array
(
[Board] => Array
(
[id] => 1
[personal_id] => 1
[title] => はっけよーい
[content] => のこった!★のこった!★
)
[Personal] => Array
(
[id] => 1
[username] => yamada
[password] => yamada
[comment] => 山田
[created] =>
[modified] =>
)
)
・・・
)
発行された SQL です。
SELECT `Board`.`id`, `Board`.`personal_id`, `Board`.`title`, `Board`.`content`, `Personal`.`id`, `Personal`.`username`, `Personal`.`password`, `Personal`.`comment`, `Personal`.`created`, `Personal`.`modified` FROM `sampledb`.`boards` AS `Board` LEFT JOIN `sampledb`.`personals` AS `Personal` ON (`Board`.`personal_id` = `Personal`.`id`) WHERE 1 = 1
結果 6.Board hasMany Personal
結果の要点です。
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Personal.board_id' in 'field list'
発行された SQL です。
SELECT `Personal`.`id`, `Personal`.`username`, `Personal`.`password`, `Personal`.`comment`, `Personal`.`created`, `Personal`.`modified`, `Personal`.`board_id` FROM `sampledb`.`personals` AS `Personal` WHERE `Personal`.`board_id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9)
おわりに
結果の画面をキャプチャしたものも載せておきます。すごく長い投稿となってしまいました!
1.ersonal hasOne Board
2.ersonal belongsTo Board
3.ersonal hasMany Board
4.oard hasOne Personal
5.oard belongsTo Personal
6.oard hasMany Personal













「CakePHP2 のアソシエーション!モデルを連携させて複数テーブルからデータを取得する勉強します!」への4件の返信
[…] CakePHP のアソシエーション!モデルを連携させて複数テーブルからデータを取得する勉強します! | oki2a24 の続きの投稿となります。 […]
[…] #8216;samplepassword’; FLUSH PRIVILEGES; CREATE DATABASE sampledb CHARACTER SE… >>CakePHP2 のアソシエーション!モデルを連携させて複数テーブルからデータを取得する勉強します! | oki2a24 Author: […]
大変参考になります。
原作本のフォローが中途半端で ちゃんと動作しないから
途方にくれていました。
コメントありがとう存じます。お役に立てましたら幸いです。