Symfony DoctrineでEager/Lazyローディングを完全ガイド!初心者でも違いがわかる読み込み制御の基礎
生徒
「Symfonyでデータを取り出すときに、関連データが自動で読み込まれたり、読み込まれなかったりするのはどうしてなんでしょうか?」
先生
「それはDoctrineのEagerローディングとLazyローディングという仕組みが関わっています。データの読み込み方を制御する重要な設定なんですよ。」
生徒
「難しそうな言葉だけど、どう違うんですか?アプリの動きに影響したりしますか?」
先生
「大きく影響します。読み込み方を間違えると、アプリが遅くなったり、必要なデータが取れなかったりします。今日はその違いと使い方をわかりやすく説明します。」
1. EagerローディングとLazyローディングとは?初心者向けに例えで理解しよう
EagerローディングとLazyローディングは、SymfonyのDoctrine ORMがデータベースから関連データを読み込むタイミングを決める仕組みです。初心者の方には難しい言葉に見えますが、日常生活の例で考えるととてもわかりやすくなります。
Lazyローディングは「必要になるまで取りに行かない」方式です。買い物でいうと、「買いたい物が決まってから店に行く」のに似ています。必要なときにだけ動き出すので、最初の処理は軽く済みます。
逆にEagerローディングは「最初から全部まとめて取ってくる」方式です。例えば、料理の前に必要な材料を全部そろえてから始めるイメージです。事前に集めておく分、あとで追加で取りに行く必要がありません。
SymfonyのDoctrineでは、この2つの読み込み方式を制御しながら、アプリを効率よく動かすことができます。
2. DoctrineのデフォルトはLazyローディング
Doctrine ORMでは、基本的に関連データはLazyローディングで処理されます。つまり、エンティティを最初に読み込んだ段階では関連データは取得せず、後から必要になったタイミングでデータベースへアクセスします。
例えば、記事とコメントの関係を考えると、Articleエンティティをロードしたときにコメントはまだ読み込まれません。コメント一覧を表示するときに初めて、Doctrineが関連するコメントデータを取りに行く仕組みです。このLazyローディングは最初の読み込みを軽くするメリットがあります。
3. Eagerローディングを使いたいときの設定
Eagerローディングは、関連するデータを最初からまとめてロードしたい場合に使います。たとえば、管理画面で大量の一覧を扱うときには、関連データをまとめて読み込むことでデータベースへのアクセス回数を減らせます。
以下はDoctrineでEagerローディングを設定する例です。
#[ORM\OneToMany(mappedBy: 'article', fetch: 'EAGER')]
private Collection $comments;
fetch: 'EAGER' とすることで、Articleエンティティを読み込むと同時にcommentsも取得されます。Symfonyで一覧を表示するときに特に効果的です。
4. Lazyローディングでパフォーマンスを最適化する方法
Lazyローディングは基本設定ですが、うまく使わないとページ遷移のたびにデータベースアクセスが発生してしまうことがあります。特に、関連データを何度もループの中で呼び出す場合、気づかないうちに大量のクエリが発行されてしまう可能性があります。
しかし、Lazyローディングを適切に使うことで、最初のページ読み込みをとても軽くすることができます。「必要なときだけ取りに行く」という仕組みは、Symfonyのアプリケーションが大規模になっても、不要な処理を避けるための大きなメリットになります。
5. QueryBuilderでEagerローディングを制御する方法
Doctrineでは、エンティティの設定だけでなく、Repositoryでクエリを書くときにもEagerローディングを行えます。これはfetch joinという仕組みを使います。SymfonyのRepositoryでデータ取得をカスタマイズしたいときによく使われる方法です。
public function findWithComments(): array
{
return $this->createQueryBuilder('a')
->leftJoin('a.comments', 'c')
->addSelect('c')
->getQuery()
->getResult();
}
addSelect を使うことで、関連するコメントもまとめて取得するEagerローディングが行われます。エンティティの設定を変えずに、取得時だけEagerにしたい場合に非常に便利です。
6. EagerとLazyの使い分けと実践的な考え方
EagerローディングとLazyローディングにはそれぞれメリットがあり、どちらが正しいというわけではありません。大切なのは「どの画面でどのデータが必要か」という点を理解して使い分けることです。
例えば、一覧画面では関連データをまとめて使うのでEagerローディングが適しています。一方、詳細画面では必要になる関連データが少ないことも多く、Lazyのほうが無駄がありません。Symfonyのアプリケーションではページごとに必要なデータ量が違うため、状況に応じてDoctrineの読み込み方式を選ぶことが性能にも大きく影響します。
初心者の方はまず「Lazyは必要なときだけ取りにいく」「Eagerは最初から全部取ってくる」という基本イメージをつかむことが大切です。Doctrine ORMはこの2つを柔軟に組み合わせて効率よく動作させられる強力なツールなので、少しずつ仕組みに慣れていけば、Symfonyでの開発がますます楽しくなります。