カテゴリー
コンピューター

CakePHP 2.5★今度は逆から SELECT する★Containable ビヘイビアチュートリアル2♪

の続きとなります。前回は、Containable ビヘイビアを使って、User からスタートして hasMany しているデータをたどって最大4階層先の HistoryNote レコードを取得しました。

ふと、思ったのです。

HistoryNote から belongsTo をたどって User のデータを取ることも Containable ビヘイビアならできるはず!と。

今回はその記録を投稿いたします。もちろん、できましたわ♪belongsTo をたどるだけでなく、たどった先のモデルが hasMany しているデータも取得できましたの♪

はじめに。ER図、アソシエーションの確認!

前回はER図の左上から始めて右下へとつなげていってデータを取得しました。

今回は、右下から始めて左上へとつなげていくイメージです♪

cake_containable_er.png

  • User
    • hasMany Account, Post, Profile
  • Profile
    • belongsTo User
  • Account
    • belongsTo User
  • AccountSummary
    • belongsTo Account
  • Post
    • belongsTo User
    • hasMany PostAttachment, Tag
  • PostAttachment
    • belongsTo Post
    • hasMany PostAttachmentHistory
  • PostAttachmentHistory
    • belongsTo PostAttachment
    • hasMany HistoryNote
  • HistoryNote
    • belongsTo PostAttachmentHistory
  • Tag
    • belongsTo Post

前回の投稿からの続きを想定しております。テーブル構造やレコードデータは前回の投稿の最後に掲載しておりますのでご参考に♪

Containalbe ビヘイビアを試すコントローラーの作成!

前回の投稿の続きですから、各テーブルに対応したモデル、ビュー、コントローラーは作成済みの状態です。そこに、次のコントローラーを作成します。

Controller/DishesController.php

<?php
App::uses('AppController', 'Controller');
class DishesController extends AppController {

        public $uses = array('HistoryNote');
/**
 * index method
 *
 * @return void
 */
        public function index() {
                // コントローラーでビヘイビアを有効
                $this->HistoryNote->Behaviors->load('Containable');
                // HistoryNote から繋がるすべてのモデルデータを取得
                $params = array(
                        'contain' => array(
                                'PostAttachmentHistory' => array(
                                        'PostAttachment' => array(
                                                'Post' => array(
                                                        'User' => array(
                                                                'Profile' => array(
                                                                ),
                                                                'Account' => array(                                                                        'AccountSummary'
                                                                )
                                                        ),
                                                        'Tag' => array(
                                                        )
                                                )
                                        )
                                )
                        )
                );
                $data = $this->HistoryNote->find('all', $params);
                debug($data);
        }
}

ポイントはもちろん $params の array の内容ですの。また、地味なポイントとしては、$uses のモデル指定だけではなく、Behaviors->load や find 時のモデル指定を間違えないようにすることですの♪

わたくし、最初間違えて Fatal エラーになってしまいましたわ、てへっ。

さて、これで完成ですけれども、エラー回避のためだけにアクションに対応するビューを作成しておきます。

mkdir -p View/Dishes/
touch View/Dishes/index.ctp

取得できたデータの確認!

さて、例えば http://192.168.56.112/cake2/dishes/ にアクセスしますと次のように狙い通りにデータが取得できましたわ♪

array(
	(int) 0 => array(
		'HistoryNote' => array(
			'id' => '1',
			'post_attachment_history_id' => '1',
			'note' => 'post1 history note1',
			'created' => '2014-09-12 18:53:32',
			'modified' => '2014-09-12 19:10:25'
		),
		'PostAttachmentHistory' => array(
			'id' => '1',
			'post_attachment_id' => '1',
			'histroy' => 'post1history',
			'created' => '2014-09-12 18:51:56',
			'modified' => '2014-09-12 18:51:56',
			'PostAttachment' => array(
				'password' => '*****',
				'id' => '1',
				'post_id' => '1',
				'name' => 'post1attachmentname',
				'pinged' => 'post1pinged',
				'created' => '2014-09-12 18:50:50',
				'modified' => '2014-09-12 18:50:50',
				'Post' => array(
					'id' => '1',
					'user_id' => '1',
					'title' => 'post1',
					'content' => 'post1 content',
					'created' => '2014-09-12 18:46:48',
					'modified' => '2014-09-12 18:46:48',
					'User' => array(
						'password' => '*****',
						'id' => '1',
						'username' => 'user1name',
						'created' => '2014-09-12 18:34:10',
						'modified' => '2014-09-12 18:34:10',
						'Account' => array(
							(int) 0 => array(
								'id' => '1',
								'user_id' => '1',
								'email' => 'user1@example.com',
								'url' => 'http://example.com/user1/',
								'status' => '1',
								'created' => '2014-09-12 18:41:22',
								'modified' => '2014-09-12 18:41:22',
								'AccountSummary' => array(
									(int) 0 => array(
										'id' => '1',
										'account_id' => '1',
										'first_name' => 'Tom',
										'last_name' => 'Cat',
										'color' => 'red',
										'level' => '1',
										'description' => 'user1 Description',
										'created' => '2014-09-12 18:43:19',
										'modified' => '2014-09-12 18:43:19'
									)
								)
							)
						),
						'Profile' => array(
							(int) 0 => array(
								'id' => '1',
								'user_id' => '1',
								'catch_phrase' => 'user1 Catch Phrase',
								'self_introduction' => 'user1 Self Introduction',
								'created' => '2014-09-12 18:38:26',
								'modified' => '2014-09-12 18:38:26'
							)
						)
					),
					'Tag' => array(
						(int) 0 => array(
							'id' => '1',
							'post_id' => '1',
							'name' => 'tag1',
							'created' => '2014-09-12 18:47:02',
							'modified' => '2014-09-12 18:47:02'
						),
						(int) 1 => array(
							'id' => '2',
							'post_id' => '1',
							'name' => 'tag2',
							'created' => '2014-09-12 18:47:10',
							'modified' => '2014-09-12 18:47:10'
						),
						(int) 2 => array(
							'id' => '3',
							'post_id' => '1',
							'name' => 'tag3',
							'created' => '2014-09-12 18:47:16',
							'modified' => '2014-09-12 18:47:16'
						)
					)
				)
			)
		)
	),
	(int) 1 => array(
		'HistoryNote' => array(
			'id' => '2',
			'post_attachment_history_id' => '1',
			'note' => 'post1 history note2',
			'created' => '2014-09-12 19:10:19',
			'modified' => '2014-09-12 19:10:19'
		),
		'PostAttachmentHistory' => array(
			'id' => '1',
			'post_attachment_id' => '1',
			'histroy' => 'post1history',
			'created' => '2014-09-12 18:51:56',
			'modified' => '2014-09-12 18:51:56',
			'PostAttachment' => array(
				'password' => '*****',
				'id' => '1',
				'post_id' => '1',
				'name' => 'post1attachmentname',
				'pinged' => 'post1pinged',
				'created' => '2014-09-12 18:50:50',
				'modified' => '2014-09-12 18:50:50',
				'Post' => array(
					'id' => '1',
					'user_id' => '1',
					'title' => 'post1',
					'content' => 'post1 content',
					'created' => '2014-09-12 18:46:48',
					'modified' => '2014-09-12 18:46:48',
					'User' => array(
						'password' => '*****',
						'id' => '1',
						'username' => 'user1name',
						'created' => '2014-09-12 18:34:10',
						'modified' => '2014-09-12 18:34:10',
						'Account' => array(
							(int) 0 => array(
								'id' => '1',
								'user_id' => '1',
								'email' => 'user1@example.com',
								'url' => 'http://example.com/user1/',
								'status' => '1',
								'created' => '2014-09-12 18:41:22',
								'modified' => '2014-09-12 18:41:22',
								'AccountSummary' => array(
									(int) 0 => array(
										'id' => '1',
										'account_id' => '1',
										'first_name' => 'Tom',
										'last_name' => 'Cat',
										'color' => 'red',
										'level' => '1',
										'description' => 'user1 Description',
										'created' => '2014-09-12 18:43:19',
										'modified' => '2014-09-12 18:43:19'
									)
								)
							)
						),
						'Profile' => array(
							(int) 0 => array(
								'id' => '1',
								'user_id' => '1',
								'catch_phrase' => 'user1 Catch Phrase',
								'self_introduction' => 'user1 Self Introduction',
								'created' => '2014-09-12 18:38:26',
								'modified' => '2014-09-12 18:38:26'
							)
						)
					),
					'Tag' => array(
						(int) 0 => array(
							'id' => '1',
							'post_id' => '1',
							'name' => 'tag1',
							'created' => '2014-09-12 18:47:02',
							'modified' => '2014-09-12 18:47:02'
						),
						(int) 1 => array(
							'id' => '2',
							'post_id' => '1',
							'name' => 'tag2',
							'created' => '2014-09-12 18:47:10',
							'modified' => '2014-09-12 18:47:10'
						),
						(int) 2 => array(
							'id' => '3',
							'post_id' => '1',
							'name' => 'tag3',
							'created' => '2014-09-12 18:47:16',
							'modified' => '2014-09-12 18:47:16'
						)
					)
				)
			)
		)
	),
	(int) 2 => array(
		'HistoryNote' => array(
			'id' => '3',
			'post_attachment_history_id' => '1',
			'note' => 'post1 history note3',
			'created' => '2014-09-12 19:10:46',
			'modified' => '2014-09-12 19:10:46'
		),
		'PostAttachmentHistory' => array(
			'id' => '1',
			'post_attachment_id' => '1',
			'histroy' => 'post1history',
			'created' => '2014-09-12 18:51:56',
			'modified' => '2014-09-12 18:51:56',
			'PostAttachment' => array(
				'password' => '*****',
				'id' => '1',
				'post_id' => '1',
				'name' => 'post1attachmentname',
				'pinged' => 'post1pinged',
				'created' => '2014-09-12 18:50:50',
				'modified' => '2014-09-12 18:50:50',
				'Post' => array(
					'id' => '1',
					'user_id' => '1',
					'title' => 'post1',
					'content' => 'post1 content',
					'created' => '2014-09-12 18:46:48',
					'modified' => '2014-09-12 18:46:48',
					'User' => array(
						'password' => '*****',
						'id' => '1',
						'username' => 'user1name',
						'created' => '2014-09-12 18:34:10',
						'modified' => '2014-09-12 18:34:10',
						'Account' => array(
							(int) 0 => array(
								'id' => '1',
								'user_id' => '1',
								'email' => 'user1@example.com',
								'url' => 'http://example.com/user1/',
								'status' => '1',
								'created' => '2014-09-12 18:41:22',
								'modified' => '2014-09-12 18:41:22',
								'AccountSummary' => array(
									(int) 0 => array(
										'id' => '1',
										'account_id' => '1',
										'first_name' => 'Tom',
										'last_name' => 'Cat',
										'color' => 'red',
										'level' => '1',
										'description' => 'user1 Description',
										'created' => '2014-09-12 18:43:19',
										'modified' => '2014-09-12 18:43:19'
									)
								)
							)
						),
						'Profile' => array(
							(int) 0 => array(
								'id' => '1',
								'user_id' => '1',
								'catch_phrase' => 'user1 Catch Phrase',
								'self_introduction' => 'user1 Self Introduction',
								'created' => '2014-09-12 18:38:26',
								'modified' => '2014-09-12 18:38:26'
							)
						)
					),
					'Tag' => array(
						(int) 0 => array(
							'id' => '1',
							'post_id' => '1',
							'name' => 'tag1',
							'created' => '2014-09-12 18:47:02',
							'modified' => '2014-09-12 18:47:02'
						),
						(int) 1 => array(
							'id' => '2',
							'post_id' => '1',
							'name' => 'tag2',
							'created' => '2014-09-12 18:47:10',
							'modified' => '2014-09-12 18:47:10'
						),
						(int) 2 => array(
							'id' => '3',
							'post_id' => '1',
							'name' => 'tag3',
							'created' => '2014-09-12 18:47:16',
							'modified' => '2014-09-12 18:47:16'
						)
					)
				)
			)
		)
	),
	(int) 3 => array(
		'HistoryNote' => array(
			'id' => '4',
			'post_attachment_history_id' => '2',
			'note' => 'post2 history note1',
			'created' => '2014-09-12 19:11:05',
			'modified' => '2014-09-12 19:11:05'
		),
		'PostAttachmentHistory' => array(
			'id' => '2',
			'post_attachment_id' => '2',
			'histroy' => 'post2history',
			'created' => '2014-09-12 19:07:25',
			'modified' => '2014-09-12 19:08:11',
			'PostAttachment' => array(
				'password' => '*****',
				'id' => '2',
				'post_id' => '2',
				'name' => 'post2attachmentname',
				'pinged' => 'post2 attachment name pinged',
				'created' => '2014-09-12 19:03:06',
				'modified' => '2014-09-12 19:08:59',
				'Post' => array(
					'id' => '2',
					'user_id' => '2',
					'title' => 'post2',
					'content' => 'post2 content',
					'created' => '2014-09-12 18:56:19',
					'modified' => '2014-09-12 18:56:19',
					'User' => array(
						'password' => '*****',
						'id' => '2',
						'username' => 'user2name',
						'created' => '2014-09-12 18:37:03',
						'modified' => '2014-09-12 18:37:03',
						'Account' => array(
							(int) 0 => array(
								'id' => '2',
								'user_id' => '2',
								'email' => 'user2@example.com',
								'url' => 'http://example.com/user2/',
								'status' => '2',
								'created' => '2014-09-12 18:41:47',
								'modified' => '2014-09-12 18:41:47',
								'AccountSummary' => array(
									(int) 0 => array(
										'id' => '2',
										'account_id' => '2',
										'first_name' => 'John',
										'last_name' => 'Dog',
										'color' => 'blue',
										'level' => '2',
										'description' => 'user2 Description',
										'created' => '2014-09-12 18:43:57',
										'modified' => '2014-09-12 18:43:57'
									)
								)
							)
						),
						'Profile' => array(
							(int) 0 => array(
								'id' => '2',
								'user_id' => '2',
								'catch_phrase' => 'user2 Catch Phrase',
								'self_introduction' => 'user2 Self Introduction',
								'created' => '2014-09-12 18:39:41',
								'modified' => '2014-09-12 18:39:41'
							)
						)
					),
					'Tag' => array(
						(int) 0 => array(
							'id' => '4',
							'post_id' => '2',
							'name' => 'tag4',
							'created' => '2014-09-12 19:00:57',
							'modified' => '2014-09-12 19:00:57'
						)
					)
				)
			)
		)
	)
)

また、データを取得するために発行された SQL は次のようになります。1 つの SQL 文ではなく、1モデルに対して1つの SQL を発行しているようですわね。

SELECT `HistoryNote`.`id`, `HistoryNote`.`post_attachment_history_id`, `HistoryNote`.`note`, `HistoryNote`.`created`, `HistoryNote`.`modified`, `PostAttachmentHistory`.`id`, `PostAttachmentHistory`.`post_attachment_id`, `PostAttachmentHistory`.`histroy`, `PostAttachmentHistory`.`created`, `PostAttachmentHistory`.`modified` FROM `cake2db`.`history_notes` AS `HistoryNote` LEFT JOIN `cake2db`.`post_attachment_histories` AS `PostAttachmentHistory` ON (`HistoryNote`.`post_attachment_history_id` = `PostAttachmentHistory`.`id`) WHERE 1 = 1
SELECT `PostAttachment`.`id`, `PostAttachment`.`post_id`, `PostAttachment`.`name`, `PostAttachment`.`pinged`, `PostAttachment`.`password`, `PostAttachment`.`created`, `PostAttachment`.`modified` FROM `cake2db`.`post_attachments` AS `PostAttachment` WHERE `PostAttachment`.`id` = 1
SELECT `Post`.`id`, `Post`.`user_id`, `Post`.`title`, `Post`.`content`, `Post`.`created`, `Post`.`modified` FROM `cake2db`.`posts` AS `Post` WHERE `Post`.`id` = 1
SELECT `User`.`id`, `User`.`username`, `User`.`password`, `User`.`created`, `User`.`modified` FROM `cake2db`.`users` AS `User` WHERE `User`.`id` = 1
SELECT `Account`.`id`, `Account`.`user_id`, `Account`.`email`, `Account`.`url`, `Account`.`status`, `Account`.`created`, `Account`.`modified` FROM `cake2db`.`accounts` AS `Account` WHERE `Account`.`user_id` = (1)
SELECT `AccountSummary`.`id`, `AccountSummary`.`account_id`, `AccountSummary`.`first_name`, `AccountSummary`.`last_name`, `AccountSummary`.`color`, `AccountSummary`.`level`, `AccountSummary`.`description`, `AccountSummary`.`created`, `AccountSummary`.`modified` FROM `cake2db`.`account_summaries` AS `AccountSummary` WHERE `AccountSummary`.`account_id` = (1)
SELECT `Profile`.`id`, `Profile`.`user_id`, `Profile`.`catch_phrase`, `Profile`.`self_introduction`, `Profile`.`created`, `Profile`.`modified` FROM `cake2db`.`profiles` AS `Profile` WHERE `Profile`.`user_id` = (1)
SELECT `Tag`.`id`, `Tag`.`post_id`, `Tag`.`name`, `Tag`.`created`, `Tag`.`modified` FROM `cake2db`.`tags` AS `Tag` WHERE `Tag`.`post_id` = (1)
SELECT `PostAttachment`.`id`, `PostAttachment`.`post_id`, `PostAttachment`.`name`, `PostAttachment`.`pinged`, `PostAttachment`.`password`, `PostAttachment`.`created`, `PostAttachment`.`modified` FROM `cake2db`.`post_attachments` AS `PostAttachment` WHERE `PostAttachment`.`id` = 1
SELECT `Post`.`id`, `Post`.`user_id`, `Post`.`title`, `Post`.`content`, `Post`.`created`, `Post`.`modified` FROM `cake2db`.`posts` AS `Post` WHERE `Post`.`id` = 1
SELECT `User`.`id`, `User`.`username`, `User`.`password`, `User`.`created`, `User`.`modified` FROM `cake2db`.`users` AS `User` WHERE `User`.`id` = 1
SELECT `Account`.`id`, `Account`.`user_id`, `Account`.`email`, `Account`.`url`, `Account`.`status`, `Account`.`created`, `Account`.`modified` FROM `cake2db`.`accounts` AS `Account` WHERE `Account`.`user_id` = (1)
SELECT `AccountSummary`.`id`, `AccountSummary`.`account_id`, `AccountSummary`.`first_name`, `AccountSummary`.`last_name`, `AccountSummary`.`color`, `AccountSummary`.`level`, `AccountSummary`.`description`, `AccountSummary`.`created`, `AccountSummary`.`modified` FROM `cake2db`.`account_summaries` AS `AccountSummary` WHERE `AccountSummary`.`account_id` = (1)
SELECT `Profile`.`id`, `Profile`.`user_id`, `Profile`.`catch_phrase`, `Profile`.`self_introduction`, `Profile`.`created`, `Profile`.`modified` FROM `cake2db`.`profiles` AS `Profile` WHERE `Profile`.`user_id` = (1)
SELECT `Tag`.`id`, `Tag`.`post_id`, `Tag`.`name`, `Tag`.`created`, `Tag`.`modified` FROM `cake2db`.`tags` AS `Tag` WHERE `Tag`.`post_id` = (1)
SELECT `PostAttachment`.`id`, `PostAttachment`.`post_id`, `PostAttachment`.`name`, `PostAttachment`.`pinged`, `PostAttachment`.`password`, `PostAttachment`.`created`, `PostAttachment`.`modified` FROM `cake2db`.`post_attachments` AS `PostAttachment` WHERE `PostAttachment`.`id` = 1
SELECT `Post`.`id`, `Post`.`user_id`, `Post`.`title`, `Post`.`content`, `Post`.`created`, `Post`.`modified` FROM `cake2db`.`posts` AS `Post` WHERE `Post`.`id` = 1
SELECT `User`.`id`, `User`.`username`, `User`.`password`, `User`.`created`, `User`.`modified` FROM `cake2db`.`users` AS `User` WHERE `User`.`id` = 1
SELECT `Account`.`id`, `Account`.`user_id`, `Account`.`email`, `Account`.`url`, `Account`.`status`, `Account`.`created`, `Account`.`modified` FROM `cake2db`.`accounts` AS `Account` WHERE `Account`.`user_id` = (1)
SELECT `AccountSummary`.`id`, `AccountSummary`.`account_id`, `AccountSummary`.`first_name`, `AccountSummary`.`last_name`, `AccountSummary`.`color`, `AccountSummary`.`level`, `AccountSummary`.`description`, `AccountSummary`.`created`, `AccountSummary`.`modified` FROM `cake2db`.`account_summaries` AS `AccountSummary` WHERE `AccountSummary`.`account_id` = (1)
SELECT `Profile`.`id`, `Profile`.`user_id`, `Profile`.`catch_phrase`, `Profile`.`self_introduction`, `Profile`.`created`, `Profile`.`modified` FROM `cake2db`.`profiles` AS `Profile` WHERE `Profile`.`user_id` = (1)
SELECT `Tag`.`id`, `Tag`.`post_id`, `Tag`.`name`, `Tag`.`created`, `Tag`.`modified` FROM `cake2db`.`tags` AS `Tag` WHERE `Tag`.`post_id` = (1)
SELECT `PostAttachment`.`id`, `PostAttachment`.`post_id`, `PostAttachment`.`name`, `PostAttachment`.`pinged`, `PostAttachment`.`password`, `PostAttachment`.`created`, `PostAttachment`.`modified` FROM `cake2db`.`post_attachments` AS `PostAttachment` WHERE `PostAttachment`.`id` = 2
SELECT `Post`.`id`, `Post`.`user_id`, `Post`.`title`, `Post`.`content`, `Post`.`created`, `Post`.`modified` FROM `cake2db`.`posts` AS `Post` WHERE `Post`.`id` = 2
SELECT `User`.`id`, `User`.`username`, `User`.`password`, `User`.`created`, `User`.`modified` FROM `cake2db`.`users` AS `User` WHERE `User`.`id` = 2
SELECT `Account`.`id`, `Account`.`user_id`, `Account`.`email`, `Account`.`url`, `Account`.`status`, `Account`.`created`, `Account`.`modified` FROM `cake2db`.`accounts` AS `Account` WHERE `Account`.`user_id` = (2)
SELECT `AccountSummary`.`id`, `AccountSummary`.`account_id`, `AccountSummary`.`first_name`, `AccountSummary`.`last_name`, `AccountSummary`.`color`, `AccountSummary`.`level`, `AccountSummary`.`description`, `AccountSummary`.`created`, `AccountSummary`.`modified` FROM `cake2db`.`account_summaries` AS `AccountSummary` WHERE `AccountSummary`.`account_id` = (2)
SELECT `Profile`.`id`, `Profile`.`user_id`, `Profile`.`catch_phrase`, `Profile`.`self_introduction`, `Profile`.`created`, `Profile`.`modified` FROM `cake2db`.`profiles` AS `Profile` WHERE `Profile`.`user_id` = (2)
SELECT `Tag`.`id`, `Tag`.`post_id`, `Tag`.`name`, `Tag`.`created`, `Tag`.`modified` FROM `cake2db`.`tags` AS `Tag` WHERE `Tag`.`post_id` = (2)

これ、アプリが複雑になってレコードも多くなってきますと、Model::query()を使って1発の SQL で取得するように改造しなければパフォーマンスの問題がー!となりそうですわね、、、どうなのかしら。

おわりに

今回の投稿は、確かめるまでもない内容だったかもしれません。だって、Containable ビヘイビアの仕様を考えれば、自明ですものね。。。

でも、慣れていなくて疑心暗鬼だったのですから、きちんと確認できて良かったですの。

以上です。

コメントを残す