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

hasOneアソシエーション:/lib/Cake/Model/Model.php
Models > Associations > hasOne
  • このエントリーをはてなブックマークに追加

関連記事

ユーザ登録(仮登録・メール・本登録)

以前1.3版で投稿した「ユーザ登録」処理の2.x版を作成しました。フローは同じで以下のようにします。 1. メールアドレス・パスワードでユーザ登録 2. この時点では仮登録として、本登録用のU

ログローテーション

CakePHP 2.xではbootstrap.php内にあらかじめアプリケーションログの設定が書かれています。2.xで日付ごとにログファイルが切り替わるよう設定してみました。 日ごとにログを切り替え

CSS/JSをひとまとめにして軽量化するプラグイン「Minify plugin for CakePHP」

「Minify plugin for CakePHP」は、インクルードするCSSもしくはJSファイルをひとまとめにしてキャッシュ化してくれるプラグインです。 導入 ダウンロード・解凍し

バリデーション前後に処理を追加できる「beforeValidate」「afterValidate」

CakePHPでは、「beforeValidate」「afterValidate」というバリデーション処理の前後で追加の処理を実装できるコールバック関数が用意されています。 beforeVali

recursive設定によるfind()性能改善

CakePHPでは、モデルにアソシエーションを設定している場合、recursive(=>joinする階層)はデフォルトで0に設定されています。「recursiveゼロ」の意味するところとは、「1跨ぎま

Cookieログイン

今回は、ログイン画面でよくみかけるクッキーログインの機能を使ってみます。 CakePHPには、Cookieコンポーネントがあります。(PHPのsetcookieメソッドのラッパー)メソッドはwr

Js/Cssファイルの読み込みや出力する方法

CakePHPのHTMLヘルパーにはjsファイルやcssファイルを読み込むためのメソッドが用意されています。ファイルを読み込むのに加えて、出力先を複数指定できるようになっています。 また、インライン

テーブルからランダムにデータを取り出す(find)

CakePHPでテーブルから特定件数のレコードをランダムに取得するには以下のように指定するとできます。 $this->data = $this->Bulkdata->find( 'all',

入力文字列の長さ(文字数)をバリデーション

CakePHP 2には、コアバリデーションに文字列の長さを検証する関数が用意されています。 文字列長(コア)バリデーション minLength - 最小文字数以上であること maxLengt

FullCalendarを使用してカレンダーアプリケーション

カレンダーアプリケーションを作成するため、カレンダー表示できるプラグインを探索して出会ったFullcalendarを試してみました。シンプルに使用できる上に、オプションがかなり豊富です。ダウンロード

Comment

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

    PAGE TOP ↑