1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

私は株式会社qnoteにて、勉強会の幹事を務めております。
2023年度勉強会の珠玉のネタを2023Qiitaアドベントカレンダーに投稿していこうと思います。

対象者

この記事は下記のような人を対象にしています。

  • 駆け出しエンジニア
  • プログラミング初学者

結論

  • find()とfirst()は動的プロパティがスマート
  • get()やall()で取得したコレクションをforeach()で処理する場合はwith()を使う

解説

(例) User に複数の Post が紐づく「1対多」のリレーションを考えます。

use Illuminate\Database\Eloquent\Relations\HasMany;

class User extends Model
{
    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }
}
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Post extends Model
{
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }
}
返り値 $q->posts()->get() $q->posts()->first() $q->posts $q->with(’posts’)
find() 単一モデル・オブジェクト △(with()の有無でクエリ数変化なし)
first() 単一モデル・オブジェクト △(with()の有無でクエリ数変化なし)
get() コレクション ×(コレクションにpostsが存在しない) ×(コレクションにpostsが存在しない) ×(コレクションにpostsが存在しない) ○(foreachの外側で使うべし)
all() コレクション ×(コレクションにpostsが存在しない) ×(コレクションにpostsが存在しない) ×(コレクションにpostsが存在しない) ○(foreachの外側で使うべし)
上記4種を使わない ビルダー ×(コレクションにpostsが存在しない) ×(コレクションにpostsが存在しない) ×(コレクションにpostsが存在しない) ○(foreachの外側で使うべし)
// find()とfirst()は動的プロパティを使うのがスマート。
$user1  = User::find(1);
$posts1 = $user1->posts;

$user2  = User::first();
$posts2 = $user2->posts;

// find()とfirst()はwith()使ってもいいが、クエリ発行数は一緒。
$user1  = User::with('posts')->find(1);
$posts1 = $user1->posts;

$user2  = User::with('posts')->first();
$posts2 = $user2->posts;

// find()とfirst()はwith()の記述位置に注意。
$user1  = User::find(1)->with('posts'); // 返り値がBuilder!!!
$user2  = User::first(1)->with('posts'); // 返り値がBuilder!!!

// get()とall()の場合はN+1問題解決のためにwith()を使用すること。
$users3 = User::with('posts')->get();
foreach ($users3 as $user3) {
	$posts3 = $user3->posts;
}

$users4 = User::with('posts')->all();
foreach ($users4 as $user4) {
	$posts4 = $user4->posts;
}

// get()とall()のNGケース
$users3 = User::get();
foreach ($users3 as $user3) {
	$posts3 = $user3->posts; // N+1発生!!!
}

$users4 = User::all();
foreach ($users4 as $user4) {
	$posts4 = $user4->posts; // N+1発生!!!
}

おわりに

with()の正しい使い方についてまとめました。

参考記事

【Laravel】データ取得 find・first・get・all の違いをしっかり理解 【比較】 - エンジニ屋.com(エンジニヤドットコム)
[Laravel] 動的プロパティと Eager Loading - Qiita

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?