hasOne アソシエーション
hasOneアソシエーションはテーブル間で1つのレコードに対して他のテーブルに紐付くレコードが1つの場合にjoinする場合に使用します。
CakePHPのドキュメントにならってUserモデルとProfileモデルで例を。
本来ならば、テーブルに外部キーを設定し、整合性を担保させると思いますが、hasOneを使用するのに必須ではありません。
usersテーブル
CREATE TABLE IF NOT EXISTS `users` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `username` VARCHAR(255) NOT NULL, `password` CHAR(128) NULL, `status` TINYINT NULL, `created` DATETIME NULL, `modified` DATETIME NULL, PRIMARY KEY (`id`), UNIQUE INDEX `username_UNIQUE` (`username` ASC)) ENGINE = InnoDB
profilesテーブル
CREATE TABLE IF NOT EXISTS `lab`.`profiles` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `user_id` INT UNSIGNED NOT NULL, `first_name` VARCHAR(64) NULL, `last_name` VARCHAR(64) NULL, `bio` TEXT NULL, `created` DATETIME NULL, `modified` DATETIME NULL, PRIMARY KEY (`id`)) ENGINE = InnoDB
Userモデル
// app/Model/User.php
public $hasOne = array(
'Profile' => array(
// 'className' => 'Profile',
// 'foreignKey' => 'User_id',
// 'conditions' => array( 'Profile.status' => '1'),
// 'fields' =>
// 'order' => 'Profile.created DESC',
// 'dependent' => true
)
);
className hasOne先のモデル名
conditions JOINする条件
fields 取得するカラム
order 並べ替え
dependent trueの場合、親(User)側レコードが削除された場合に子(Profile)も削除される。(これは別記事にて)
実行SQL
SELECT `User`.`id`, `User`.`username`, `User`.`password`, `User`.`status`, `User`.`created`, `User`.`modified`, `Profile`.`id`, `Profile`.`user_id`, `Profile`.`first_name`, `Profile`.`last_name`, `Profile`.`bio`, `Profile`.`created`, `Profile`.`modified` FROM `users` AS `User` LEFT JOIN `profiles` AS `Profile` ON (`Profile`.`user_id` = `User`.`id`) WHERE 1 = 1
レコード数増に伴う性能改善
レコード数が増えていくと、joinするのに時間がかかっていきますので、インデックスを張って下さい。
4000行のhasOne(Left Join)でDB/Cake両方のキャッシュをOFF
インデックスなしの場合→平均13秒ほど
インデックスありの場合→50ミリ秒ほど
(って、秒数はマシンスペックによります。)
MySQLでの外部キーとインデックスの作成はこちらを参考にして下さい。hasOneの場合はuniqueオプションを使用して下さい。
外部キー(foreign key)を作成するとインデックスもついてくる | MySQL
Models > Associations > hasOne
関連記事
-
-
CSS/JSをひとまとめにして軽量化するプラグイン「Minify plugin for CakePHP」
「Minify plugin for CakePHP」は、インクルードするCSSもしくはJSファイルをひとまとめにしてキャッシュ化してくれるプラグインです。 導入 ダウンロード・解凍し
-
-
パス定数と変更方法やURLの取得
CakePHPは基本的にはディレクトリそのまま配置することで構築が可能ではありますが、設定パスを変更することでセキュリティに考慮した構成にすることや運用性をもたせたものにすることが可能になります。
-
-
ログインに追加の条件を付与する「scope」
ユーザ登録では、仮登録処理(status=1)から送付したメール内のリンクをクリックしてもらい本登録(status=0)を行ってもらう実装をしました。仮登録の状態ではログインできないように実装するには
-
-
入力文字列の長さ(文字数)をバリデーション
CakePHP 2には、コアバリデーションに文字列の長さを検証する関数が用意されています。 文字列長(コア)バリデーション minLength - 最小文字数以上であること maxLengt
-
-
ハッシュ関数の選択とハッシュ化処理
CakePHPでは、ログイン時にはpasswordを自動的にハッシュ化して認証を行ってくれますが、そのパスワードを登録する際は、明示的にハッシュ化する必要があります。 ハッシュ関数の選択 ハッ
-
-
CakePHP 2.x インストール
現在まで私が商用・非商用にリリースしているCakePHPアプリケーションは全て1.3.xベースで作成しています。 まだまだロードマップ的には大丈夫そうですが、お客さん向けに納品しているアプリケーショ
-
-
recursive設定によるfind()性能改善
CakePHPでは、モデルにアソシエーションを設定している場合、recursive(=>joinする階層)はデフォルトで0に設定されています。「recursiveゼロ」の意味するところとは、「1跨ぎま
-
-
checkボックスを実装
selectボックスに引き続いてcheckボックスの実装方法をおさらいしてみます。 コードは、CakePHP 2と1.3両方で実装可能です。デモ モデルは、こちらも以下 CREATE TA
-
-
ユーザ登録(仮登録・メール・本登録)
以前1.3版で投稿した「ユーザ登録」処理の2.x版を作成しました。フローは同じで以下のようにします。 1. メールアドレス・パスワードでユーザ登録 2. この時点では仮登録として、本登録用のU
-
-
CakePHP インストール時エラーの対処
CakePHPインストール時に出くわすであろうエラーの原因と対処方法についてまとめてみました。前提として、WebサーバはApache、データベースはMySQLとしています。 Timezone未設


Comment
http://t.co/cbhroBOPba CakePHP 2.4 - hasOneアソシエーション ブログ投稿