Warning: Undefined array key 2 in /var/www/html/wp-content/themes/jstork_custom/functions.php on line 35
データベースを操作する上でアソシエーションはとても便利ですが、3層以上のデータをまとめて取得する方法を知らずに苦労していました。ついに解決法が見つかりましたので、メモとして残しておきたいと思います。
2層のデータを取得する場合
例えば、ブログ記事を保存するテーブルArticlesと、ユーザ名の管理をするテーブルusersが以下のようにあるとします。
Articlesテーブル
| id | user_id | contents |
| 1 | 0 | 今日は公園に… |
| …. | …. | …. |
Usersテーブル
| id | user_name |
| 0 | 太郎 |
| 1 | 花子 |
このようにArticlesテーブルはUsersテーブルに対してbelongsToのテーブルを持っています。このとき、下記のコードによってまとめてデータを引き出すことが出来ます。
// コントローラーやテーブルのメソッド内で
use Cake\ORM\TableRegistry;
Articles = TableRegistry::getTableLocator()->get('Articles');
Users = TableRegistry::getTableLocator()->get('Users');
// 3.6.0 より前
Articles = TableRegistry::get('Articles');
Users = TableRegistry::get('Users');
//メソッド内でデータを配列として取得
$articles = $this->Articles->find('all')->contain('Users')->toArray()
今回のトピックで重要なのは「contain(‘Users’)」の部分です。このメソッドを使うことにより、Articlesテーブルのデータだけではなく、レコードに紐付いたUsersデータも取得することが出来ます。この場合は以下のようなデータを取得できます。
//$articlesとして以下のような中身を得られる (int) 0 => [ 'id' => 0, 'user_id' => 0, 'contents' => '今日は公園に...', 'usrs' => [ 'user_name' => '太郎' ] ], (int) 1 =>....(略)
3層以上をデータ取得する場合
結論から言えば、3つのテーブルA・B・Cがあったとして以下のコードで実装できます。findに対する引数で指定します。
//上手くいく○
$options = [
'contain' => ['B', 'C'],
];
//AはTableRegistryによるテーブルインスタンス
$this->A->find('all', $options)->toArray();
//エラーが出る×
//AはTableRegistryによるテーブルインスタンス
$this->A->find('all')->contain(['B', 'C'])->toArray();
find()の後にcontain()をつなげることによって2層は取得できたので、そのままリストにしようと思いましたがエラーが出ました。この場合だと、AとCがアソシエーション定義されていないよ、というエラーが出てしまいます。
そのため、find()を使ってしているすることで、Aのレコードに紐付いたBのレコードの紐付いたCのレコードをすべてまとめて引き出すことが出来ます。お試しを!










