【CakePHP入門】テーブルを結合(JOIN)して検索する方法

こんにちは!フリーエンジニアのせきです。

CakePHPには、関連のあるテーブルを結合して検索する方法がいくつか用意されています。

この記事では、

・関連のあるテーブルをモデルに定義する方法を知りたい
・テーブルを結合して検索する方法を知りたい

という基本的な内容から、

・複数のテーブルと結合する方法を知りたい

といった応用的な内容に関しても解説していきます。

今回はそんなCakePHPでテーブルを結合して検索する方法について、わかりやすく解説します!

モデルを関連付けて検索する方法

サンプルでは、以下のような受注テーブルを作成して、一覧表示します。

テーブル定義

データ

IDCUSTOMER_IDPRODUCT_IDQUANTITY
1122
2221
3231
4313
5332

一覧に顧客名を表示できるよう、顧客テーブルを作成します。

テーブル定義

データ

IDCUSTOMER_NAME
1Tanaka
2Saito
3Yamada

受注テーブル(ACCEPT_ORDER)のCUSTOMER_IDと顧客テーブル(CUSTOMER)のIDが紐づくものとし、受注テーブルに顧客テーブルを結合して検索します。

受注テーブルと顧客テーブルは、1つの顧客IDに対し複数の受注データが存在するので、「多 対 1」という関係になります。

CakePHPのモデルでは、「多 対 1」の関連をbelongsToで定義します。

受注テーブルのModelは以下のようになります。

[プロジェクトのパス]/src/Model/Table/AcceptOrderTable.php
「$this->belongsTo(‘Customer’);」で、顧客テーブルとの関連を定義しています。

テーブルの項目名を「結合するテーブル名_ID」にしておくと、自動でその項目をキーに結合します。

結合される顧客テーブルのModelには、関連の定義は不要です。

[プロジェクトのパス]/src/Model/Table/CustomerTable.php

Entityはそのままです。

[プロジェクトのパス]/src/Model/Entity/AcceptOrder.php
[プロジェクトのパス]/src/Model/Entity/Customer.php

Controllerで検索します。

関連のあるテーブルを結合して検索するには、containを使用し以下のように記述します。

受注テーブルの一覧を表示するControllerです。

[プロジェクトのパス]/src/Controller/AcceptOrderController.php
「$this->AcceptOrder->find(‘all’)->contain([‘Customer’])」で、顧客テーブルと結合しています。

結合したテーブルの値は、以下のように取得できます。

結合したテーブル名は、すべて小文字で記述します。

受注テーブルの一覧を表示するTemplateです。

[プロジェクトのパス]/src/Template/AcceptOrder/index.ctp

「$acceptOrder->customer->CUSTOMER_NAME」で、結合した顧客テーブルの顧客名を表示しています。

「http://[サーバ名]/[プロジェクト名]/acceptOrder」にアクセスすると、以下のように表示されます。
001

検索時にJOINを追加する方法

Modelには手を加えずControllerで検索する時に結合する方法もあります。

検索を行うfind()は、「->」(アロー演算子)を続けて、様々なオプションや条件を指定することができます。

ここではテーブルの結合を行うjoin()leftJoin()を解説します。

join()を使用する方法

join()には、配列で以下のような指定をします。

結合方法には「LEFT」「RIGHT」「INNER」が指定できます。

conditionsに指定した条件で、tableに指定したテーブルと結合します。

さらに、select()を使用して、取得する項目を指定します。

join()を使用したControllerです。

[プロジェクトのパス]/src/Controller/AcceptOrderController.php

テーブルの値は、以下のように取得できます。

これを使用して、Templateは以下のようになります。

[プロジェクトのパス]/src/Template/AcceptOrder/index.ctp

「http://[サーバ名]/[プロジェクト名]/acceptOrder」にアクセスすると、モデルを関連付けて検索した時と同じ画面が表示されます。

leftJoin()を使用する方法

join()で結合方法に「LEFT」を指定する場合には、leftJoin()を使うこともできます

leftJoin()には、以下のような指定をします。

leftJoin()を使用したControllerです。

[プロジェクトのパス]/src/Controller/AcceptOrderController.php

Templateはjoin()の時と同じもので、同じ画面が表示されます。

複数のテーブルと結合する方法

1つのテーブルに、複数のテーブルを結合することもできます。

製品テーブルを作成し、一覧に製品名も表示するようにします。

テーブル定義

データ

IDPRODUCT_NAMEUNIT_PRICE
1Bag5000
2Shoes8000
3Hat3000

Modelに関連を複数定義する場合は、belongsToを追加します。

[プロジェクトのパス]/src/Model/Table/AcceptOrderTable.php

Controllerのcontainにも追加します。

[プロジェクトのパス]/src/Controller/AcceptOrderController.php

製品IDではなく製品名を表示するよう、Templateを修正します。

[プロジェクトのパス]/src/Template/AcceptOrder/index.ctp
「$acceptOrder->product->PRODUCT_NAME」で製品テーブルの製品名が取得できます。

「http://[サーバ名]/[プロジェクト名]/acceptOrder」にアクセスすると、製品名が表示されています。
002

Contorollerのjoin()でも、複数のテーブルを結合することができます。

以下のように、join()にテーブル別名をキーにした連想配列を指定します。

まとめ

今回はテーブルを結合して検索する方法について解説しました。

実際のシステムでは複数のテーブルでデータを管理し、そのデータをユーザが扱いやすいように結合して表示したりするので、テーブルの結合は必須です。

テーブルを結合する方法を忘れてしまったら、この記事を思い出して下さい!

LINEで送る
Pocket

最短でエンジニアを目指すなら侍エンジニア塾

cta_under_bnr

侍エンジニア塾は業界で初めてマンツーマンレッスンを始めたプログラミングスクールです。これまでの指導実績は16,000名を超え、未経験から数多くのエンジニアを輩出しています。

あなたの目的に合わせてカリキュラムを作成し、現役エンジニア講師が専属であなたの学習をサポートするため効率よく学習を進めることができますよ。

無理な勧誘などは一切ありません。まずは無料体験レッスンを受講ください。

無料体験レッスンの詳細はこちら

書いた人

せき

せき

フリーランスでWebシステム開発やゲーム開発をしています。
読者の方にプログラミングの面白さをお伝えしたいです。

おすすめコンテンツ

あなたにぴったりなプログラミング学習プランを無料で診断!

プログラミング学習の効率を劇的に上げる学習メソッドを解説