whereNotIn — 指定キーの値が集合に含まれない要素だけ残す

collection
  • カテゴリ: collection
  • 掲載バージョン: Laravel 12・PHP 8.4
  • 名前空間 / FQCN / コマンド: Illuminate\Support\Collection::whereNotIn
  • 関連: whereIn / where / whereNotInStrict / filter / reject
  • 変更履歴: whereNotInStrict 併存(厳密比較版)

要点(TL;DR)

  • 何に使うか:配列/オブジェクトのコレクションから、特定キーの値が「除外リスト」に含まれない要素だけを抽出する
  • 最低限の使い方$filtered = collect($items)->whereNotIn('status', ['draft','archived']);
  • よくある罠
    • デフォルトは緩い比較(型変換あり)。型を区別したいなら whereNotInStrict を使う
    • クエリビルダwhereNotIn と混同しない(こちらはメモリ上のコレクション操作)
    • 大量件数はパフォーマンスに注意(必要ならDB側で絞り込み)

概要

whereNotIn は、与えたキーの値が指定した集合に存在しない要素を残します。Eloquent の結果を受けた後処理や、API レスポンスの整形で「除外リスト」を適用する用途に向きます。whereIn の逆で、厳密比較が必要なら whereNotInStrict を選びます。

構文 / シグネチャ

// Collection
public function whereNotIn(string|int $key, array|\Illuminate\Support\Enumerable $values): static;

// 厳密比較(===)
public function whereNotInStrict(string|int $key, array|\Illuminate\Support\Enumerable $values): static;

引数(表)

引数必須既定値説明
$key`stringint`
$values`arrayEnumerable`
  • 戻り値Collection(同型)。条件に一致した要素のみを保持
  • 例外/副作用
    • 破壊的でない(元コレクションは変更されない)
    • $values が反復不可能な型だと TypeError になり得る

使用例

最小例

<?php

use Illuminate\Support\Collection;

$users = collect([
    ['id' => 1, 'name' => 'A', 'role' => 'admin'],
    ['id' => 2, 'name' => 'B', 'role' => 'editor'],
    ['id' => 3, 'name' => 'C', 'role' => 'viewer'],
    ['id' => 4, 'name' => 'D', 'role' => 'guest'],
]);

$blocked = ['admin', 'guest'];

$visible = $users->whereNotIn('role', $blocked);
// 結果: role が editor / viewer の要素のみ

実務例(Eloquent結果の後処理)

<?php

use App\Models\Post;

// 例: DBでは公開ステータスで取得し、さらにアプリ側で除外カテゴリを適用
$posts = Post::query()
    ->where('published', true)
    ->get();

$hideCategoryIds = [1, 9, 12]; // 例えばユーザー設定やABテストで動的に

$filtered = $posts->whereNotIn('category_id', $hideCategoryIds);

// ドット記法の例:ネストした配列/属性でもOK
$items = collect([
    ['meta' => ['flag' => 0]],
    ['meta' => ['flag' => 1]],
    ['meta' => ['flag' => 2]],
]);

$out = $items->whereNotIn('meta.flag', [0, 2]); // flag が 1 のみ残る

よくある落とし穴・注意

  • 比較の厳密さwhereNotIn は緩い比較(== 相当)。'1'1 を区別したい場合は whereNotInStrict を使用。
  • キー保持filter ベースのため元のキーを保持します。必要に応じて values() で連番に整形。
  • 大量データ:計算量は概ね O(n)(n=件数、値集合の大きさにも依存)。大量件数のDB結果全件をget→whereNotInは非効率。可能ならクエリビルダ側の whereNotIn で絞る。
  • LazyCollection:同名メソッドで遅延評価に対応。ストリーム処理時は LazyCollection を検討。

代替・関連APIとの比較

  • whereIn:除外ではなく許可リストで残す(逆の意味)。
  • whereNotInStrict:厳密(===)比較。型差が重要ならこちら。
  • where:1値/演算子での条件。複数候補の除外/許可は where(In|NotIn) が簡潔。
  • filter/reject:任意ロジックで柔軟。単純な集合除外なら whereNotIn が可読。

チェックポイント(collectionカテゴリの要件)

  • チェーン可否:可
  • 破壊的/非破壊:非破壊(新しいコレクションを返す)
  • キー保持:保持
  • LazyCollection:対応
  • 計算量の目安:O(n)(n=要素数、除外集合サイズにも一定依存)

入出力対応(小サンプル)

入力(role)除外集合出力に残る?
admin['admin','guest']
editor['admin','guest']
0 (文字列)[0] + whereNotIn✗(緩い比較)
0 (文字列)[0] + whereNotInStrict✔(型が異なるため残る)

テスト例(Pest)

<?php

use Illuminate\Support\Collection;

it('filters items not in the given set', function () {
    $items = collect([
        ['id' => 1, 'status' => 'draft'],
        ['id' => 2, 'status' => 'published'],
        ['id' => 3, 'status' => 'archived'],
    ]);

    $out = $items->whereNotIn('status', ['draft', 'archived'])->values();

    expect($out->pluck('id')->all())->toBe([2]);
});

it('respects strict comparison when using whereNotInStrict', function () {
    $items = collect([
        ['v' => '0'], // string
        ['v' => 0],   // int
    ]);

    $out = $items->whereNotInStrict('v', [0])->values();

    // 厳密比較なので '0' は残り、0 は除外
    expect($out->pluck('v')->all())->toBe(['0']);
});

トラブルシュート(エラー別)

症状/エラー原因対処
期待と違う要素が除外/残存する緩い比較により '1'1 が同一視whereNotInStrict を使用
パフォーマンスが悪い大量データをアプリ側で絞っているDBクエリ段階で whereNotIn を適用、必要列のみ取得
ネストキーで動作しないキー指定が誤り、または値が存在しないドット記法のキーを確認、data_get で値が取れる構造にする
並びが崩れた/キーが飛び番filter で元キー保持のためvalues() でキーを振り直す

参考リンク

レン (Wren)

こんにちは。レンです。

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

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

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

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

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

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