LaravelはPHPで最も普及しているフレームワークの一つであり、開発者にとって効率的なコーディングのための様々な機能を提供しています。その中でもデータベースクエリに関する機能は非常に強力です。特に、データの並べ替えを行うためのorderByメソッドは非常に柔軟で、複数の条件を組み合わせてデータを効率よく表示することができます。この記事では、Laravelにおける複数条件のorderByの活用法について詳しく解説し、データの並べ替えをもっと効率的に行うためのコツを紹介します。
複数 orderBy() の最小構成
Laravelで複数条件の並び替えを行うには、orderBy() をチェーンするだけです。以下が最もシンプルな例です。
// 新しい順に並べ、同じ日時なら ID の昇順にする
$posts = Post::orderBy('created_at', 'desc')
->orderBy('id', 'asc')
->get();
最初に書いた orderBy() が最優先の並び順になります。2つ目以降は「同じ値だった場合」の次の基準として機能します。
複数条件のorderByの基本
Laravelのクエリビルダは、データを並べ替えるためのorderByメソッドを提供しています。例えば、articlesテーブルからデータを取得する際にcreated_atを基準に並べたい場合、次のようにします。
$articles = DB::table('articles')->orderBy('created_at')->get();
しかし、実際のアプリケーションでは、単一のカラムだけでなく複数の条件で並べ替えたい場合があります。こんな時は、orderByをチェーンして使うことができます。
$articles = DB::table('articles')
->orderBy('published_at', 'desc')
->orderBy('title', 'asc')
->get();
この例では、まずpublished_atの降順にソートし、その次にtitleの昇順に並べ替えています。
EloquentでのorderBy
Eloquent ORMを使用している場合も、orderByメソッドはほとんど同じように使用できます。Eloquentではモデルを利用して、より直感的な方法で並べ替えが可能です。
$articles = Article::orderBy('published_at', 'desc')
->orderBy('title', 'asc')
->get();
EloquentでorderByメソッドを使う場合も、クエリビルダと同様にチェーンして複数の基準を指定することができます。
よくある並び替えパターン
新しい順 + ID順(重複対策)
最も頻繁に使うパターンです。created_atが同じ値になる場合(同秒投稿など)に備えて、idを第2キーにすることで並び順を安定させます。
$posts = Post::orderBy('created_at', 'desc')
->orderBy('id', 'asc')
->get();
優先度順 + 更新日順
タスク管理やチケット管理システムでよく使われるパターンです。まず優先度で絞り込み、同じ優先度なら最近更新されたものを上に表示します。
$tasks = Task::orderBy('priority', 'asc')
->orderBy('updated_at', 'desc')
->get();
NULLを含む並び替え
NULLの扱いはデータベースによって異なります。MySQLではNULLは昇順で先頭、降順で末尾に並びます。NULLを必ず末尾にしたい場合は orderByRaw() を使います。
// NULL を末尾にして、残りは昇順
$items = Item::orderByRaw('published_at IS NULL')
->orderBy('published_at', 'asc')
->get();
// MySQL 8.0 / MariaDB の場合は NULLS LAST が使えることもある
$items = Item::orderByRaw('published_at ASC NULLS LAST')->get();
リレーション先カラムでの並び替え
Eloquentのリレーションを使いながら関連テーブルのカラムでソートするには、join() と組み合わせるか、サブクエリを使います。
// posts を users テーブルの name でソート
$posts = Post::select('posts.*')
->join('users', 'posts.user_id', '=', 'users.id')
->orderBy('users.name', 'asc')
->orderBy('posts.created_at', 'desc')
->get();
サブクエリでの並び替えも可能です。
$posts = Post::orderBy(
User::select('name')
->whereColumn('users.id', 'posts.user_id')
->limit(1),
'asc'
)->get();
複数条件による並べ替えの便利なケース
商品の価格と評価で並べ替え
ECサイトや商品管理アプリケーションでは、商品の価格やユーザー評価を基準にした並べ替えがよく使われます。例えば、最初に価格の低い順に並べ、それにさらに顧客の評価が高い順で並べ替えることが効率的でしょう。
$products = Product::orderBy('price', 'asc')
->orderBy('rating', 'desc')
->get();
日付とステータスでの並べ替え
イベントの管理システムや予約管理システムなどでは、まず日付で並べ替え、その次にステータス(例えば「未処理」「完了」など)で並べたいことがあります。
$events = Event::orderBy('event_date', 'asc')
->orderBy('status', 'asc')
->get();
latest() / oldest() との違い
latest() と oldest() は orderBy() のショートハンドです。
| メソッド | 相当するコード | 用途 |
|---|---|---|
latest() |
orderBy('created_at', 'desc') |
新しい順(デフォルトは created_at) |
oldest() |
orderBy('created_at', 'asc') |
古い順(デフォルトは created_at) |
// この2つは同じ結果
Post::latest()->get();
Post::orderBy('created_at', 'desc')->get();
// カラム名を指定することもできる
Post::latest('updated_at')->get();
複数条件で並び替えるときは orderBy() を使ってください。 latest() は単一条件の簡易記法なので、チェーンして第2キーを加えることはできません(正確には構文上は書けますが意図した動作になりにくい)。
// NG: latest() の後に orderBy() を付けても期待通りに動かないことがある
Post::latest()->orderBy('id', 'asc')->get();
// OK: orderBy() だけで統一する
Post::orderBy('created_at', 'desc')->orderBy('id', 'asc')->get();
orderByRaw() が必要なケース
ASC / DESC では表現できない複雑な並び替えには orderByRaw() を使います。
特定の値を先頭に固定する(CASE 文)
// 'admin' を先頭に、次いで 'editor'、残りはアルファベット順
$users = DB::table('users')
->orderByRaw("CASE role WHEN 'admin' THEN 1 WHEN 'editor' THEN 2 ELSE 3 END")
->orderBy('name', 'asc')
->get();
NULL を末尾に固定する
// published_at が NULL のものを末尾へ
$posts = Post::orderByRaw('ISNULL(published_at)')
->orderBy('published_at', 'asc')
->get();
文字列をカスタム順に並べる(FIELD 関数)
// status を 'active' → 'pending' → 'inactive' の順で並べる
$users = User::orderByRaw("FIELD(status, 'active', 'pending', 'inactive')")->get();
SQLによるカスタマイズ
時には、単純なASC/DESCではない特定の並べ替えが必要になることもあります。このような場合、SQLのCASE文を使ってカスタマイズすることができます。
$users = DB::table('users')
->orderByRaw("CASE role WHEN 'admin' THEN 1 WHEN 'editor' THEN 2 WHEN 'subscriber' THEN 3 ELSE 4 END")
->orderBy('name', 'asc')
->get();
この例では、ユーザーの役割に応じて並べ替えを行っています。
高度なクエリの場合の注意点
複数のorderByを組み合わせる場合、必然的にクエリの複雑さが増すため、データベースのインデックスを適切に設定することが重要です。インデックスを正しく設定することで、クエリの実行速度を向上させることができます。特に大量のデータを扱う際には、インデックスを考慮する習慣を持つことが必要です。
orderByのパフォーマンスに関するヒント
- インデックスを活用: よく使用する検索条件や並べ替えカラムにインデックスを設定する。
- キャッシングを考慮: 頻繁に変わらない並べ替え結果をキャッシュすることで、パフォーマンスを向上できる。
- ページネーション: 大量の結果を全て取るのではなく、必要な分ずつ取得することで効率よくデータを処理。
FAQ
Laravelで複数の orderBy を指定するには?
orderBy() をチェーンするだけです。書いた順番が優先度の高い順になります。
User::orderBy('last_name', 'asc')
->orderBy('first_name', 'asc')
->get();
orderBy の順番は関係ある?
あります。最初に書いた orderBy() が最優先です。最初のカラムで値が同じレコードがあった場合に限り、2番目以降の条件が適用されます。順番を変えると並び順が変わります。
// 例1: created_at → id の順
Post::orderBy('created_at', 'desc')->orderBy('id', 'asc')->get();
// 例2: id → created_at の順(結果が変わる)
Post::orderBy('id', 'asc')->orderBy('created_at', 'desc')->get();
NULL を最後に並べるには?
MySQLではNULLはASC(昇順)のとき先頭、DESC(降順)のとき末尾になります。ASCで並べてNULLを末尾にしたい場合は orderByRaw() を使います。
// NULL のレコードを末尾にする
Post::orderByRaw('published_at IS NULL')
->orderBy('published_at', 'asc')
->get();
published_at IS NULL は NULLなら1、値があれば0を返すので、先に値ありのレコードが並びます。
DBのorderBy()とコレクションのsortBy()の違い
複数条件で並べ替えたい場合、「orderBy()で書くべきか、取得後にsortBy()で並べ替えるべきか」で迷うことがあります。基本的には、データベース側で並べ替えられるならクエリビルダのorderBy()を優先してください。SQLのORDER BY句とインデックスを活用でき、大量データでもメモリを消費しません。一方、すでにメモリ上にあるコレクション(get()後の結果やAPIレスポンスの配列など)を複数条件で並べ替えたいだけなら、sortByコレクションメソッドのほうが手軽です。
最後に
今回の記事では、Laravelでの複数条件によるorderByの利用方法について詳しく解説しました。複数の条件を組み合わせることで、ユーザーが求める情報を効率よく提供でき、アプリケーション全体のUXを改善することができます。是非、自身のプロジェクトでもこれらのテクニックを活用して、精巧なデータ操作を行ってください。
並べ替えと合わせて絞り込み条件を組み立てたい場合は、複数条件のwhereクエリビルダの使い方や複数条件を用いたJOINクエリの実践ガイドもあわせて参考にしてください。

コメント