はじめに

Laravel でネストした構造(リレーション)において、取得するカラムを絞りつつ Eager Load する方法についてまとめた。

TL;DR

  • カラムの絞り込み: : の後に , 区切りでカラムを列挙
  • ネスト構造: . で繋げる
  • 上記の組合せ: with に渡す引数を分けて書く
    • with(['posts:title', 'posts.images:url'])

目次

  1. はじめに
  2. TL;DR
  3. 環境・条件
  4. 詳細
    1. 前置き: Eager Loading について
      1. カラムの絞り込み
      2. ネスト構造
    2. 本題: ネスト構造 + 絞り込み
  5. まとめ
  6. 参考文献

環境・条件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.1
BuildVersion: 19B88

$ php -v
PHP 7.3.9 (cli) (built: Sep 10 2019 17:45:01) ( NTS )

$ composer -V
Composer version 1.9.0 2019-08-02 20:55:32

$ composer info laravel/framework
name : laravel/framework
versions : * v5.7.28

詳細

前置き: Eager Loading について

Eager Loading - Eloquent:リレーション 5.8 Laravel

カラムの絞り込み

Eager Load 時に取得するカラムを絞り込むには、table:col1,col2,... のように : の後に , 区切りでカラムを列挙すれば良い。

1
2
3
User::with([
'posts:id,title'
])->get();

ネスト構造

ネストした構造を Eager Load するには . で繋げると良い。

1
2
3
User::with([
'posts.images'
])->get();

本題: ネスト構造 + 絞り込み

では、ネストした構造で各テーブルの取得カラムを絞り込むには?

最下層だけで良いなら組み合わせて下記でいける。

1
2
3
User::with([
'posts.images:id,url'
])->get();

しかし、下記だと Column not found: 1054 Unknown column 'title.images' in 'field list' という感じで、title.images がカラムと認識されてしまいエラーになる。

1
2
3
4
User::with([
'posts:id,title.images:id,url'
])->get();
// Illuminate/Database/QueryException with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'title.images' in 'field list'

こういうケースでは、配列の要素を分けると上手くいく。

1
2
3
4
User::with([
'posts:id,title',
'posts.images:id,url'
])->get();

ちなみに Has Many 関係の場合は問題ないが、Belongs To 関係の場合には外部キーも含めないと上手く取得できないので注意。

1
2
3
4
5
6
7
8
9
10
11
// OK
Image::with([
'post:id,title,user_id',
'post.user:id,name',
])

// ダメな例
Image::with([
'post:id,title', // user_id が無いので user が取得できない
'post.user:id,name',
])

これは select() でカラムを絞る場合も同様。

1
2
3
4
5
6
7
8
9
10
11
12
13
// OK
Image::select('id', 'url', 'post_id')
->with([
'post:id,title,user_id',
'post.user:id,name',
])

// ダメな例
Image::select('id', 'url') // post_id が無いので post が取得できない
->with([
'post:id,title,user_id',
'post.user:id,name',
])

まとめ

  • カラムの絞り込み: : の後に , 区切りでカラムを列挙
  • ネスト構造: . で繋げる
  • 上記の組合せ: with に渡す引数を分けて書く
    • with(['posts:title', 'posts.images:url'])

参考文献

関連記事