【Laravel基礎】Query Builder(クエリビルダー)とCollection(コレクション)の違い

2025.10.24

Laravelで開発をしていたある日・・・
きちんと動作していたコードの中の1行を、少し位置を変えただけでエラーになってしまうという現象が起きました。

例えば、「お知らせの最新3件を取得し、古い順に並べ替えたい」という目的で、コントローラーに以下のコードを書いていたとします。

// このコードは問題なく動作します
$informations = Information::with('author')
    ->take(3)
    ->get()
    ->sortBy('created_at');

上記のコードでは正常に動きますが、下記のコードのようにsortBy の位置を get() の前に移動すると、エラーが発生します。

// NG!エラーが出ます
$informations = Information::with('author')
    ->take(3)
    ->sortBy('created_at') // この位置ではエラーに
    ->get();


//BuilderクラスにsortBy()メソッドが存在しない、というエラーが表示される
Call to undefined method Illuminate\Database\Eloquent\Builder::sortBy()

このエラーに遭遇したときは「位置を変えただけなのになんでエラーになるの??」となりました。

なぜ、同じ sortBy メソッドなのに get() の前後で挙動が変わってしまうのでしょうか?

調べてみると、その原因はLaravelにおける Query Builder(クエリビルダー) と Collection(コレクション) という、2つの異なる状態が原因ということが分かりました。
クエリを組み立てる段階(Query Builder)と、データが取得された後の段階(Collection)で使えるメソッドが違う ため、エラーが起きていたのです。

そこで、この記事では、エラーについて調べていく中で分かったQuery Builder(クエリビルダー)とCollection(コレクション)の違いについて解説します。


🧐 なぜエラーが出るの? 2つのメソッドの正体

まず、今回のエラーのコードを見てみましょう。

❌ エラーが出るコード

// NG!エラーが出ます
$informations = Information::with('author')
    ->take(3)
    ->sortBy('created_at')
    ->get();

✅ 問題無く動くコード

// OK!正しく動きます
$informations = Information::with('author')
    ->take(3)
    ->get()
    ->sortBy('created_at');

どちらのコードも「お知らせの古い順の3件を取得する」という同じ目的ですが、なぜ片方はエラーになるのでしょうか?

その答えは、get() というメソッドを境に、コードが「Query Builder」から「Collection」へと変化しているからです。

先述したように、Query BuilderとCollectionそれぞれで使えるメソッドが違うため、エラーになってしまうのです。


🔍 Query Builder(クエリビルダー)とCollection(コレクション)ってなに?

自分も含めLaravelを学び始めたばかりの人にとって、この2つの単語は聞きなれないかもしれません。
ここでは、レストランでの注文を例に、2つの役割を分かりやすく説明します。

Query Builder:データベースへの「注文書」📝

Query Builderは、データベースから「どんなデータを、どんな条件で取得するか」を組み立てるためのツールです。

例えるなら、 「レストランの注文書」 です。

まだ料理(データ)が手元に届いていない状態で、「こういう料理をお願いします」とシェフ(データベース)に指示を出している段階です。

この段階では、主にデータベースで処理するメソッドを使います。

使えるメソッドの例

  • orderBy(): データベースでデータの並び順を指定
  • take() / limit(): データベースで取得する件数を制限
  • where(): データベースで検索条件を指定
  • with(): 関連するデータも一緒に取得

Collection:手元に届いた「料理の皿」🥢

一方、Collectionは、get()メソッドを実行して実際にデータベースから取得したデータのことです。

例えるなら、 「テーブルに並べられた料理の皿」 です。

データがすでに手元にあるので、それをPHPのコードで好きなように並び替えたり、絞り込んだりといった加工ができます。

この段階では、PHPの機能を使ってデータを操作するメソッドを使います。

使えるメソッドの例

  • sortBy() / sortByDesc(): PHPでデータの並び替え
  • filter(): PHPで特定のデータを絞り込み
  • map(): PHPでデータの形を変換
  • count(): PHPでデータの件数をカウント

💡 基本的にQuery Builder(クエリビルダー)を使うようにする

結果として同じデータを取得できますが、基本的には できる限りQuery Builderを使う方が良いです。

なぜなら、処理の効率が圧倒的に良いからです。

Query Builder(注文書)の場合

「新しい順の3件をください」とシェフに頼めば、シェフは必要な3件だけ作ってくれます。
データベースから取得するデータが少ないので、高速でメモリも節約できます。

// 新しい順の3件だけを取得する
Information::orderBy('created_at', 'desc')->take(3)->get();

Collection(料理の皿)の場合

「全部の料理をください」と頼んでから、手元に届いた大量の料理の中から、新しい順の3つだけを選ぶようなものです。

// 全件取得してから、手元で3件に絞り込み
Information::all()->sortByDesc('created_at')->take(3);

データベースに1万件のデータがあったら、まず1万件すべてのデータを取得し、その後で不要な9,997件を捨てることになります。これは無駄な通信とメモリ消費が発生し、パフォーマンスが低下します。

以上のことから、出来る限りQuery Builderを使う方が良いということがお分かりいただけたかと思います。


🧐 どんなときにCollectionを使うべき?

処理の効率を考えるとQuery Builderを優先すべきですが、Collectionで処理した方が良いケースも存在します。

それは、 データベースでは処理できないロジックを適用したい場合 です。

複雑な計算やアプリケーションのロジックを適用する場合

データベースは単純な値の比較や集計は得意ですが、複数のカラムを組み合わせた複雑な計算や、データベースとは別の場所にある情報を使った条件分岐は苦手です。
そのようなときにCollectionが役立ちます。

例:キャンペーンによる割引価格で絞り込む

あるオンラインストアで、pricediscount_rateというカラムを持つ商品データがあるとします。
しかし、discount_rateは0.1(10%オフ)や0.2(20%オフ)といった値で、実際の割引価格は price * (1 - discount_rate) という計算が必要です。
さらに、「割引後の価格が1,000円以下の商品だけを表示したい」という要件があるとします。

この計算式はデータベースのWHERE句に直接書くには複雑です。
そこで、一度全てのデータを取得し、PHP側で計算して絞り込みます。

コード例:

// 全ての商品データを取得
$products = Product::all();

// 割引後の価格が1,000円以下の商品だけを絞り込む
$discountedProducts = $products->filter(function ($product) {
    // 💡 データベースではできない計算をPHPで行う
    $finalPrice = $product->price * (1 - $product->discount_rate);
    return $finalPrice <= 1000;
});

解説:
このコードは、Product::all()で全ての商品データをCollectionとして取得します。
次に、filter()メソッドを使って、それぞれの商品のpricediscount_rateを使ってPHPで 動的に最終価格を計算 し、「1,000円以下」という条件に合うものだけを抽出しています。

このように、データベースの列を直接使えない複雑な計算や、独自のビジネスロジックを適用したい場合に、Collectionのメソッドが非常に有効です。
パフォーマンスの観点から推奨されるのはQuery Builderですが、柔軟性が必要な場面ではCollectionの出番となります。

違いを理解したうえで、正しく使い分けることが大切になりますね。


まとめ

Query Builder(クエリビルダー)Collection(コレクション)
役割データベースへの指示書を作る取得したデータをPHPで操作する
メソッドorderBy()where()take() などsortBy()filter()map() など
境界線get() より前get() より後
効率✅ 良い(データベースで処理)❌ 悪い(PHPで処理)

この2つの違いを理解すれば、Laravelでのコーディングがぐっとスムーズになります。

エラーに遭遇したときも、まずは 「今、コードはQuery Builderの状態かな? Collectionの状態かな?」 と立ち止まって考えることが出来ますね。

解説した2つの違いを理解し、Laravelでのシステム開発にお役立てください。

それでは。


🏢 株式会社ハジメクリエイトについて

この記事は、 株式会社ハジメクリエイト のエンジニアが執筆しました。


💻 Webシステム開発のプロフェッショナル

私たちは、ビジネスの成長をサポートするため、 PHPを用いたオーダーメイドのシステム開発 を提供しています。
お客様一人ひとりのニーズに応じたカスタムシステムを、 企画から開発・運用まで一貫してサポート
さらに、 React Nativeを活用したiOS/Android対応のアプリ開発 も得意としています。

単に「作る」だけでなく、
課題の本質に向き合い、最適な解決策を提案する のがハジメクリエイトのスタイルです。


🧑‍💻 一緒に働く仲間を探しています!

株式会社ハジメクリエイトでは、 自ら考え行動できるエンジニア を募集しています。
「私はこれがしたい!」という想いを持つあなた、一緒にモノづくりを楽しみませんか?

  • 技術で人の役に立ちたい
  • 意見が通る小さなチームで働きたい
  • フロントエンドもバックエンドも、いろいろ挑戦してみたい
  • お客さんと一緒にプロジェクトを育てたい

そんな気持ちがある方なら、きっと居心地のいい環境だと思います。
正社員はもちろん、パートタイムでの参加も歓迎中! 柔軟な関わり方で、あなたらしく働いてください。

👉 採用情報を見る
👉 お問い合わせはこちら


ちょっとでも「この会社、気になるな」と思ったら、ぜひお気軽にご連絡ください📩
最後まで読んでいただきありがとうございました!

  • Laravel
  • PHP

この記事を書いた人

Morimoto

Programmer Morimoto

Web制作をメインに、最近はWeb開発にも携わるようになってきました。新しく学んだことやつまづいたことなどを書いていきます。three.jsを使った3Dアニメーションにも興味があります。

Morimotoの書いた記事一覧へ

ハジメクリエイトでは一緒に働く仲間を募集しています!

関連記事