エス技研

WordPress、CakePHP、PHP、baserCMSなどの Web系システムを中心に情報を提供します!


CakePHP3のアソシエーションでJOINのタイプのLEFT、INNERを切り替えながら使う方法

      2019/07/28

Tableファイルで INNERが指定してあるアソシエーションのデータを LEFTでの取得を Controller側で指定する方法

 

想定している環境について

 
まず、想定しているテーブルは以下のものです。
 
ユーザ管理、ログイン認証のプラグインである「CakeDC/Users」を使う際に作成するテーブルが「Users」です。
また、ユーザ情報として、ユーザ名や住所、電話番号と言った情報を追加で登録、管理する想定ですが、プラグインで生成される「Users」テーブルには手を付けず、1対1でアソシエーションする「UserDetails」テーブルを作成する仕様を想定しています。
 

 
 
また、この記事の説明は、テーブルのアソシエーションに関連する説明になっています。
そのため、実際に「CakeDC/Users」を利用して動作検証をしようとする場合は、下記の「CakeDC/Users」に関連する記事を確認してください。
 
CakePHP3のユーザ管理・ログイン認証プラグインCakeDC/Usersのインストール解説・3.6以降対応
CakePHP3のCakeDC/Usersのログイン後のリダイレクトとユーザ権限管理の設定解説
CakePHP3のCakeDC/Usersのバリデーションのカスタマイズ方法解説
 
特に、デフォルトだと、UsersTableファイルは「/vendor/cakedc/users/src/Model/Table/UsersTable.php」にあります。
ですが、コアファイルは触らずに、「/src/Model/Table/UsersTabble.php」にファイルを設置し、コアファイルの処理をオーバーライドさせています。
 
 

UsersTabble.phpにアソシエーションの設定をする

 
UserDetailsテーブルを Bakeすると、「/src/Model/Table/UserDetailsTabble.php」の「initialize」には下記のようになっていると思います。
 

 
これだけだと、UserDetails側からアソシエーションの設定を利用して Usersのデータを取得することはできますが、Users側からは UserDetailsのデータを取得することはできません。
 
そのため、Usersの tableファイル「/src/Model/Table/UsersTabble.php」に下記を追記します。

 
「joinType」に「INNER」を指定していますが、指定がない場合はデフォルトとして「LEFT」になります。
 
 
「LEFT」と「INNER」の違いは、Usersに連結させる UserDetailsのテーブルがないときの対応の違いです。
 
「LEFT」の場合は、UserDetailsの部分を NULLが入っているものとして取得します。
「INNER」の場合は、UserDetailsにレコードがある Usesのみ取得します。
 
 


 
 

Usersから contain句を利用してレコードを取得

 
上記のように Tableファイルの設定をしている場合、Usersテーブルから値を取得する場合は、コントローラーには下記のように記述します。
 

 
Tableファイルには INNERでアソシエーションしていますので、UserDetailsにレコードがない場合は、Usersのレコードも取得されません。
 
 
ユーザ情報を一覧表示するようなシステムの場合、必要となるのは、UserDetailsテーブルに情報が登録されているレコードですので、INNERでアソシエーションされている方がいいでしょう。
 
 
ですが、管理画面でユーザ情報を管理する場合は、UsersDetailsにレコードがない Usersのレコードも取得する必要があります。
 
そのため、管理画面では INNERでアソシエーションするのではなく、LEFTでアソシエーションした情報を取得する必要があります。
 
どうやって INNERと LEFTを切り替えればいいのでしょうか?
 
前振りが長くなりましたが、ここが今回の記事のポイントです。
 
 

Controllerで「leftJoinWith()」「innerJoinWith()」を指定する

 
結論は、下記のように「leftJoinWith()」句を使います。
 

 
上記の通り「leftJoinWith()」句を使うことで、UsersTableでは「INNER」が指定してあっても「LEFT」でデータを取得してくることができるようになります。
 
 
ここで紹介した方法と逆に、UsersTableの方で「LEFT」を指定し、レコードを取得する際に「innerJoinWith()」を使う、という方法もあります。
 

 
また、そもそも、UsersTableの方で「LEFT」を指定し、「where()」句で「user_id is not null」で「UserDetails」のレコードがないものを省く方法もあります。
 
 
「leftJoinWith()」「innerJoinWith()」や「is not null」でレコードを取得する場合は、いずれの場合においても、UsersTabble.php に hasOneなどのアソシエーションの設定がないとエラーになります。
 
 

Tableファイルではなく Controllerファイルでアソシエーションの設定を行う方法

 
基本的には Tableファイルでアソシエーションの設定を行うものですが、Tableファイルにアソシエーションの設定がなくても、Controllerファイルでテーブルの連携の設定を行うこともできます。
 

 
ここでの注意点は、テーブル名は Modelで管理しているテーブル名(UserDetails)ではなく、実テーブル名である「user_details」を使う点です。
 
 
詳細は、下記の Cookbookを参照してください。
 
CakePHP3 Cookbook クリエービルダー
https://book.cakephp.org/3.0/ja/orm/query-builder.html#join
 
 

CakePHP3では Tableでアソシエーションを指定するべきもの?

 
ちなみに、この記述方法は、CakePHP3では望ましい書き方ではないのではないか、という感じがします。
 
CakePHP2の頃までは「Recursive」「ContainableBehavior」を使ってアソシエーションのテーブルのデータをコントロールしていたようですが、CakePHP3では「Recursive」「ContainableBehavior」は削除されています。
https://book.cakephp.org/3.0/ja/appendices/orm-migration.html#recursive-containablebehavior
 
CakePHP3では、アソシエーションしたどのテーブルのデータを取得するかは、「contain」で指定するようになりました、というお話ですが、Tableファイルにアソシエーションを設定し、contain句を使って必要なデータを指定すれば、余計なデータを取得して処理が重くなるということも防げるのではないか、と思います。
 
 

CakePHP3の関連記事

CakePHP3でPHP Simple HTML DOM Parserを使ってスクレイピングする方法
CakePHP3のInsert On Duplicate Key Update(upsert)構文を解説・バルク処理も
CakePHP3の1対多での連携を中間テーブルを使った多対多の連携に変更するときの手順
CakePHP3でデフォルトのソート条件を設定してユーザの選択肢たソート条件を有効にする方法
CakePHP3で Ajaxを使う方法の解説。3.6以降対応。Successとthenの両方を解説。
CakePHP3でパンくずの指定は HTMLヘルパーを使って指定する方法を解説
CakePHP3にOGPをfetch、asignを利用してテンプレートごとに指定する方法を解説
CakePHP3のOGPはHTMLヘルパーの$this->Html->meta()を使って設定
CakePHP3でkeywords、DescriptionをHTMLヘルパーを使って設定する
CakePHP3で環境変数を設定して本番環境と開発環境を分けて処理をする場合
 
その他の「CakePHP3」に関する記事一覧
 
 

 - CakePHP 2.x 3.x

GoogleAdwords

GoogleAdwords

最後までお読みいただきましてありがとうございます。
この記事が参考になったと思いましたらソーシャルメディアで共有していただけると嬉しいです!

Message

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

下記の空欄を埋めてください。 * Time limit is exhausted. Please reload CAPTCHA.

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

※入力いただいたコメントは管理者の承認後に掲載されます。

  関連記事

CakePHP3のCakeDC/Usersのバリデーションのカスタマイズ方法解説
CakePHP3のCakeDC/Usersのバリデーションのカスタマイズ方法解説

CakeDC謹製Usersプラグインの紹介。Usersのカスタマイズとして入力項目のバリデーションの変更を、プラグインのファイルは触らずオーバーライドにより実装する方法を解説する。

CakePHP3の検索プラグイン「friendsofcake/search」の設置方法・CakePHP3.6対応
CakePHP3の検索プラグイン「friendsofcake/search」の設置方法・CakePHP3.6対応

CakePHP3で検索を担うプラグイン「friendsofcake/search」の紹介。基本的な設置方法の紹介のほか、処理の記述方法のバリエーション、エラーの解説など。CakeDC/searchより導入は簡単!

CakePHP3で他のテーブルのマスタテーブルからセレクトボックス(プルダウンリスト)を作る
CakePHP3で他のテーブルのマスタテーブルからセレクトボックス(プルダウンリスト)を作る

他のテーブルのマスタのレコードからプルダウンリストを作成し、選択できるようにするサンプルプログラムと解説。ORMの設定によりデータベースの値を取得し、配列を作成し optionsに与える。

CakePHP3のfriendsofcake/searchでブックマークチュートリアルのタグ検索を実装
CakePHP3のfriendsofcake/searchでブックマークチュートリアルのタグ検索を実装

CakePHP3のCookbookにあるブックマークチュートリアル。ここで紹介されているタグで検索する処理を検索プラグイン「friendsofcake/search」で実現する方法を解説しました。

CakePHP3のOGPはHTMLヘルパーの$this->Html->meta()を使って設定
CakePHP3のOGPはHTMLヘルパーの$this->Html->meta()を使って設定

CakePHP3でOGPを設定する方法を解説。metaタグを編集するHTMLヘルパーを利用してOGPのタグを編集する。また、エレメントとして分割することでメンテナンス性も向上させる。

CakePHP3のHtmlHelperのLink設定のまとめ。mailto、URL、Root/Homeのリンクなども
CakePHP3のHtmlHelperのLink設定のまとめ。mailto、URL、Root/Homeのリンクなども

CakePHP3でHtmlHelperを使ってリンクの設定をする方法のまとめ。基本形からURLを指定、class、id、targetを指定、mailtoのリンク、画像をアンカーに、JavaScriptのダイアログなどの解説。

CakePHP3のInsert On Duplicate Key Update(upsert)構文を解説・バルク処理も
CakePHP3のInsert On Duplicate Key Update(upsert)構文を解説・バルク処理も

CakePHP3で Insert … On Duplicate Key Update構文(upsert)を実行する方法を解説。バルク処理の方法も用意されているため大量処理の場合も対応可能。

CakePHP 2.3 bakeの超初心者向けフォロー講座

CakePHP 2.3 bakeの超初心者向けフォロー講座

CakePHP3のCakeDC/Usersでログインユーザの所有レコードのみ更新、削除する権限管理の設定方法
CakePHP3のCakeDC/Usersでログインユーザの所有レコードのみ更新、削除する権限管理の設定方法

CakePHP3のユーザ管理、ログイン認証プラグイン「CakeDC/Users」の権限管理を行う方法やアクセスできるコントローラー、アクションを設定、所有権を持つレコードのみ更新できる設定方法を解説。

CakePHP3にデザインテンプレートBootstrapを導入する方法・friendsofcake/bootstrap-ui使用
CakePHP3にデザインテンプレートBootstrapを導入する方法・friendsofcake/bootstrap-ui使用

CakePHP3にプラグイン「friendsofcake/bootstrap-ui」、デザインテンプレート「Bootstrap」を設置する手順を解説。Bootstrapの簡単な使い方やデフォルトのデザインとの混在方法なども解説。