Laravelのwhenメソッドの使い方|条件分岐をスマートに書くテクニック

基本文法・構文ガイド

プログラミングを行う上で、条件分岐は非常に基本的かつ重要な操作です。PHPフレームワークであるLaravelでは、この条件分岐をさらにスマートに、そしてコードを読みやすくするためのメソッドとしてwhenが提供されています。この記事では、Laravelのwhenメソッドを使ってどのように効率的に条件分岐を実現できるのか、具体例を交えて解説します。

Laravelのwhenメソッドとは?

Laravelのwhenメソッドは、コレクションやクエリビルダーなどのコンテキストで使用されるメソッドであり、特定の条件が真である場合にのみ指定したクロージャを実行するためのものです。このメソッドは、コードをより簡潔で読みやすくし、条件分岐を扱いやすくすることを目的としています。

whenメソッドの基本構文

whenメソッドは一般的に以下のような構文で使用します。

$collection->when($condition, function ($collection) {
    // 条件がtrueの場合に実行される処理
});

また、条件がfalseの場合に別の処理をさせたい場合には、第二引数にその処理を記述することも可能です。

$collection->when($condition, function ($collection) {
    // trueの場合の処理
}, function ($collection) {
    // falseの場合の処理
});

コレクションでの使用例

まず、簡単な配列を考えてみましょう。この配列の中から偶数だけを取り出して操作を行いたいとします。通常の条件分岐を用いた場合、コードは以下のようになるかもしれません。

$numbers = collect([1, 2, 3, 4, 5, 6]);

$filtered = $numbers->filter(function ($value) {
    return $value % 2 === 0;
});

$result = $filtered->map(function ($value) {
    return $value * 2;
});

このコードでは、フィルタリングとマッピングを個別に行っていますが、whenメソッドを使用することでより簡潔に表現することができます。

$numbers = collect([1, 2, 3, 4, 5, 6]);

$result = $numbers->when(true, function ($collection) {
    return $collection->filter(function ($value) {
        return $value % 2 === 0;
    });
})->map(function ($value) {
    return $value * 2;
});

この例では、whenメソッドの条件が常にtrueであるため、毎回フィルタリングが行われます。ただし、必要に応じて、条件を動的に設定することが可能です。

クエリビルダーでの使用例

whenメソッドはクエリビルダーにおいても有用です。例えば、ユーザーのクエリを条件によってフィルタリングする場合に使用できます。以下に、アクティブなユーザーのみを取得する例を示します。

$is_active = true; // ここは動的な値になることが多い

$users = DB::table('users')
    ->when($is_active, function ($query) {
        $query->where('active', 1);
    })
    ->get();

ここでは、$is_activetrueの場合にのみactiveカラムを基に絞り込むクエリが構築されます。条件がfalseであれば、元のクエリがそのまま実行されます。

複数条件での使用例

多くの場合、1つの条件に依存することは稀で、複数の条件を持つことが多いです。whenメソッドはそのような状況においても非常に効果的です。

例えば、次のような状況を考えてみましょう:ユーザーが特定の役割を持つ場合に、さらに追加のフィルタリングを行う。

$role = 'admin'; // ユーザーの役割が例えば管理者

$users = DB::table('users')
    ->when($role, function ($query, $role) {
        $query->where('role', $role);
    })
    ->when($is_active, function ($query) {
        $query->where('active', 1);
    })
    ->get();

この例では、$roleがnullや空の場合は役割によるフィルタリングがスキップされ、$is_activetrueであるときのみアクティブユーザーを絞り込みます。

また、検索条件に応じて「無効なデータを除外する」ようなクエリを動的に追加したい場合にも、when と除外クエリの組み合わせが役立ちます。

$excludeInactive = true;
$excludeRole = 'guest';

$users = DB::table('users')
    ->when($excludeInactive, function ($query) {
        $query->whereNot('status', 'inactive');
    })
    ->when($excludeRole, function ($query, $excludeRole) {
        $query->whereNotIn('role', [$excludeRole, 'banned']);
    })
    ->get();

除外条件(whereNotwhereNotIn)の詳細な書き方やインデックスの注意点については、Laravel whereNot/whereNotInの使い方と違い|除外条件の書き方と実践例 をご覧ください。

カスタムメソッドでの活用

whenメソッドの強みはそれだけではありません。クエリビルダーやコレクションの中でカスタムメソッドを利用するときにも役立ちます。カスタムメソッドは再利用可能なロジックを整理するのに最適です。

Collection::macro('filterActives', function () {
    return $this->filter(function ($user) {
        return $user->active;
    });
});

$users = collect($userList);

$activeUsers = $users->when($is_active, function ($collection) {
    return $collection->filterActives();
});

ここでfilterActivesはカスタムメソッドで、コレクション内のアクティブなユーザのみをフィルタリングします。これにより、同じロジックを繰り返すことなく、条件に応じたフィルタリングを簡潔に実行できます。メソッドチェーンの途中経過を確認したい場合は、tapメソッドを併用するとデバッグしやすくなります。

バリデーションでの条件分岐(Rule::when)

Laravelでは、コレクションやクエリビルダーだけでなく、リクエストのバリデーション時にも Rule::when() を使って条件付きルールをスマートに定義できます。

例えば、「管理者として登録する場合のみ、管理者コード(admin_code)の入力を必須にする」といった処理を簡潔に書くことができます。

use Illuminate\Validation\Rule;

$validated = $request->validate([
    'name' => ['required', 'string', 'max:255'],
    'email' => ['required', 'email'],
    'admin_code' => [
        Rule::when($request->boolean('is_admin'), ['required', 'string', 'min:8']),
    ],
]);

if 文でルール配列を後から書き換える必要がなく、宣言的に条件付きバリデーションを組み立てられます。FormRequestの活用や Rule::whensometimesrequired_if など条件付き検証を含むバリデーション全般の実装方法は、Laravel Validationの使い方完全ガイド|基本ルール・FormRequest・カスタム検証まで徹底解説 を参照してください。

よくある質問

whenとif文の違いは?

if文でも同じ条件分岐は書けますが、whenを使うとメソッドチェーンを途切れさせずに条件処理を差し込めます。特にクエリビルダーやコレクション操作を1行で組み立てたい場合、ifで分岐して変数に代入し直すよりも可読性が高くなります。

unlessメソッドとの違いは?

unlesswhenの逆で、条件がfalseのときにクロージャを実行します。「通常は処理するが、特定条件のときだけスキップしたい」場合はunlessを使うと、条件式を否定形(!$condition)にしなくて済み、意図が読み取りやすくなります。

whenの第一引数にモデルやコレクション自体を渡すとどうなる?

when()の第一引数には真偽値だけでなく、任意の値を渡せます。値がtruthy(0や空文字、nullなどでない)であればクロージャが実行され、渡した値自体がクロージャの第二引数として渡されます。$roleのような文字列や配列をそのまま条件として使えるのはこのためです。

結論

Laravelのwhenメソッドを使うことで、コードの可読性と保守性が大きく向上します。クエリビルダーでの動的な条件絞り込み(whereNot/whereNotInなどとの組み合わせ)や、リクエストバリデーション(Rule::when)の動的構築など、様々な場面でその効果を発揮します。条件分岐をよりスマートに整理するために、ぜひプロジェクトに取り入れてみてください。

レン (Wren)

こんにちは。レンです。

Laravelのコードの森に住んでいる、小さな案内役です。
ルーティングの枝やクラスの影を歩きながら、コードの流れや仕組みを眺めています。

このサイトでは、Laravelの基本から実装のコツまで、開発で役立つポイントを静かに整理しています。
難しいことを増やすのではなく、コードの見通しが少し良くなるヒントを届けるのが役目です。

「この処理はどこに書くのがいいのか」
「Laravelではどう考えると整理できるのか」

そんな疑問に、小さなメモを残すような気持ちで記事を書いています。

コードを書いている途中で迷ったとき、
このサイトが少し立ち止まって整理できる場所になればうれしいです。

レン (Wren)をフォローする

コメント