Symfony Doctrineでページネーション処理を完全ガイド!初心者でもわかるデータ分割の基本
生徒
「Symfonyで記事一覧を表示するときに、全部のデータを一度に表示するとページが重くなってしまいます。どうやって分割したらいいんですか?」
先生
「それはページネーションという方法を使います。ページごとにデータを小分けにして表示する仕組みのことですよ。」
生徒
「ページネーションって難しそうに聞こえますが、Doctrineでも簡単にできるんでしょうか?」
先生
「大丈夫です。Doctrineにはページネーション向けの仕組みが用意されていますし、Symfonyと組み合わせるともっと便利になります。まずはやさしく仕組みから説明しますね。」
1. ページネーションとは?初心者向けのわかりやすいイメージ
ページネーションとは、たくさんのデータを複数のページに分けて表示する仕組みのことです。インターネットのショッピングサイトで、商品一覧が「1ページ目・2ページ目」と並んでいるのを見たことがあると思います。これがページネーションです。
もしページネーションがなければ、数千件の商品が一気に読み込まれ、画面が重くなります。SymfonyのDoctrine ORMでも同じで、記事やユーザーなどのデータを全部読み込むとパフォーマンスが低下します。そこでDoctrineの仕組みを利用して、必要な分だけデータを取得する方法がとても重要になります。
初心者の方には「本を読むときに一度に全部のページを開かず、1ページずつ読むイメージ」と伝えると理解しやすくなります。
2. Doctrine ORMでページネーションを行う基本的な流れ
Doctrineでは、ページネーションを実現するために「どこから」「いくつ」取り出すかを指定します。これはSQLの世界では LIMIT と OFFSET と呼ばれる考え方です。SymfonyではRepository内で QueryBuilder を使い、ページごとに取得するデータを調整します。
ページネーションで必要なのは、次の2つです。
- 取得する件数(limit)
- どこから取得するか(offset)
例えば1ページ10件表示したい場合、1ページ目は0件目から、2ページ目は10件目から、3ページ目は20件目から取得する、といった計算になります。Doctrineはこの考え方を簡単に実装できるようになっています。
3. Repositoryクラスでページネーション処理を実装する
ここでは Doctrine の QueryBuilder を使ってページネーションを実装する基本形を紹介します。初心者の方は、細かい書き方よりも「ページごとにデータを分けている」というイメージを持つことが大切です。
<?php
public function findPaginated(int $page, int $limit): array
{
$offset = ($page - 1) * $limit;
return $this->createQueryBuilder('a')
->orderBy('a.id', 'DESC')
->setFirstResult($offset)
->setMaxResults($limit)
->getQuery()
->getResult();
}
この例では、ページ番号と表示件数から offset を計算し、その結果に応じてデータを分割して取得しています。Symfonyのコントローラ側でページ番号を渡して呼び出すことで、どのページ内容でも柔軟に表示できます。
4. カウント用クエリで総ページ数を計算する方法
ページネーションを行うときにもう一つ大切なのが「総ページ数の計算」です。総件数を知らないと「全部で何ページあるか」が分からず、ナビゲーションリンクが作れません。
Doctrineの QueryBuilder を使って総件数を取得する例は次の通りです。
public function countAll(): int
{
return (int) $this->createQueryBuilder('a')
->select('COUNT(a.id)')
->getQuery()
->getSingleScalarResult();
}
COUNT は SQL の集計関数で、レコードの数量を数える仕組みです。この件数を limit で割ることで総ページ数が求められます。
5. コントローラでページネーション処理を呼び出す流れ
Repositoryでページネーションの準備が整ったら、Symfonyのコントローラで実際にデータを取得します。ページ番号をURLパラメータから受け取り、Repositoryに渡して処理するだけで実装できます。
$page = $request->query->getInt('page', 1);
$limit = 10;
$articles = $articleRepository->findPaginated($page, $limit);
$total = $articleRepository->countAll();
$totalPages = ceil($total / $limit);
このように、ページ番号を受け取り、総ページ数を計算すれば、Twigでページネーションリンクを作成できます。Symfonyアプリケーションでよく使われる基本的な流れです。
6. Doctrineページネーションを使うときの注意点と最適化の考え方
ページネーションは便利ですが、注意点もあります。特に大量のデータがある場合、COUNTクエリが時間のかかる処理になることがあります。これを避けるためにキャッシュを導入したり、データの取得範囲を絞るといった工夫が必要になる場合もあります。
また、ページネーションを行うときは、並び順(order by)を明確にしておくことが重要です。同じデータでも順番が毎回変わってしまうと、ユーザーがどこまで見たかわからなくなってしまうからです。
初心者の方はまず「何件表示するか」「どこから取得するか」の2つの仕組みをしっかり理解することが大切です。Doctrine ORMはこの考え方を柔軟に扱えるツールなので、ページネーションを導入するとアプリの使いやすさが大きく向上します。