array_filter — 配列を条件でフィルタリングする使い方

基本文法・構文ガイド
  • カテゴリ: PHP
  • 掲載バージョン: PHP 8.4(PHP 8.0以降の変更点も記載)
  • 名前空間 / FQCN / コマンド: array_filter(array $array, ?callable $callback = null, int $mode = 0): array
  • 関連: array_map / array_walk / array_values / Collection::filter / Arr::where
  • 変更履歴: PHP 8.0 以降、$callback が nullable に対応。また参照渡しパラメータを期待するコールバックを渡すと E_WARNING が発生するように変更

要点(TL;DR)

  • 用途:配列の各要素をコールバックでテストし、trueを返した要素だけを残す
  • 最低限:$result = array_filter($array, fn($v) => $v > 0);
  • コールバック省略時は「空とみなされる値」(false / 0 / '' / null / '0' / 空配列)を除去する簡易フィルタになる
  • 罠:
    • 元のキーが保持されるため連番に穴が空く(再連番は array_values()
    • デフォルトはコールバックに値のみ渡る。キーも使うには $mode の指定が必要
    • コールバック省略時は文字列 '0' も除去される(strlen 判定などとは挙動が異なる)

概要

array_filter() は配列の各要素をコールバック関数でテストし、true を返した要素だけを新しい配列として返す関数です。コールバックを省略すると「空とみなされる値」を取り除く簡易フィルタとして動作します。フォーム入力から空値を除く、条件に合う要素だけを抜き出す、null を含む配列をクレンジングするといった場面でよく使います。

構文 / シグネチャ

array array_filter(array $array, ?callable $callback = null, int $mode = 0)

$mode に指定できる値

  • 0(既定):コールバックに値のみを渡す
  • ARRAY_FILTER_USE_KEY:コールバックにキーのみを渡す
  • ARRAY_FILTER_USE_BOTH:コールバックに値, キーの順で渡す

引数(表)

引数必須既定値説明
$arrayarrayはいフィルタ対象の配列
$callback?callableいいえnull各要素をテストするコールバック。省略時は空とみなされる値を除去
$modeintいいえ0コールバックに渡す引数を指定するフラグ

戻り値array(条件を満たした要素のみ。元のキーを保持

例外/副作用:コールバック内で例外を投げればそのまま呼び出し元に伝播する。PHP 8.0 以降、コールバックが参照渡しパラメータを期待している場合は E_WARNING が発生する。元の配列自体は変更しない(非破壊)。

使用例

最小例:条件に合う要素だけ抽出

<?php
$numbers = [1, -2, 3, -4, 5, 0];

$positive = array_filter($numbers, fn($n) => $n > 0);

print_r($positive);
// [0 => 1, 2 => 3, 4 => 5]  ※キーは元のまま(1,3,5番目は除外)

// 連番に振り直したい場合
print_r(array_values($positive));
// [1, 3, 5]

コールバック省略:空とみなされる値をまとめて除去

<?php
$values = ['a', '', 0, null, 'b', false, '0', 'c'];

$clean = array_filter($values);

print_r(array_values($clean));
// ['a', 'b', 'c']  ※ '' / 0 / null / false / '0' はすべて除去される

実務例:フォーム入力のクレンジング(キーも条件に使う)

<?php
$request = [
    'name'    => 'Taro',
    'email'   => '',
    'age'     => 0,
    'note'    => null,
    '_token'  => 'abc123',
];

// 空文字/nullを除去しつつ、アンダースコア始まりのキー(内部用)も除外
$filtered = array_filter(
    $request,
    static fn($value, $key) => $value !== '' && $value !== null && !str_starts_with($key, '_'),
    ARRAY_FILTER_USE_BOTH
);

print_r($filtered);
// ['name' => 'Taro', 'age' => 0]  ※値0の 'age' は条件に一致しないので残る

応用例:array_map と組み合わせて有効なメールだけ取り出す

<?php
$emails = ['a@example.com', 'not-an-email', 'b@example.com', ''];

$validEmails = array_values(array_filter(
    $emails,
    fn($email) => filter_var($email, FILTER_VALIDATE_EMAIL) !== false
));

print_r($validEmails);
// ['a@example.com', 'b@example.com']

よくある落とし穴・注意

  • キーが保持される:フィルタ後も元のキーのまま。連番前提の foreachjson_encode で意図せず連想配列({})になることがある。再連番したいときは array_values() を挟む。
  • 省略時の「空」判定が広い:コールバックなしだと文字列 '0' も除去される。数値の0だけ除きたい・文字列の”0″は残したいといった場合は明示的なコールバックを書く。
  • $mode の渡し忘れ:キーで判定したいのに $mode を省略すると、コールバックには値しか渡らずキーを参照できない。
  • ARRAY_FILTER_USE_BOTH の引数順function($value, $key) の順で渡る。キー→値の順だと誤解して逆に書いてしまうミスが多い。
  • 非破壊array_filter() は元の配列を変更しない。変数への再代入を忘れると呼び出し結果が反映されない。

代替・関連APIとの比較

  • array_map():要素を変換する(1:1で件数は変わらない)。要素を絞り込みたいなら array_filter、値を作り変えたいなら array_map。両方必要なら組み合わせる。
  • array_walk():配列を参照渡しで書き換える副作用系の関数。要素を間引く用途には向かない。
  • Laravel Collection::filter():メソッドチェーンで書ける版。Laravelアプリでコレクションを扱っているなら Collection::filter() の方が他の操作と繋げやすい(filter — コレクション要素を条件で抽出するを参照)。
  • Laravel Arr::where()array_filter と同様にキー・値の両方で判定できるヘルパー。生配列のままLaravelのユーティリティだけ使いたい場合の選択肢。

選定基準

  • 生配列を条件で絞り込みたい → array_filter()
  • 絞り込みつつ値も変換したい → array_filter() + array_map()
  • 元配列を直接書き換えたい → array_walk()
  • Laravelのコレクションチェーンの中で使いたい → Collection::filter()

テスト例(Pest)

<?php
// tests/ArrayFilterFunctionTest.php
it('filters values with a callback', function () {
    $result = array_filter([1, -2, 3, -4], fn($n) => $n > 0);

    expect($result)->toBe([0 => 1, 2 => 3]);
});

it('removes falsy values without a callback', function () {
    $result = array_filter(['a', '', 0, null, 'b']);

    expect(array_values($result))->toBe(['a', 'b']);
});

it('passes value and key with ARRAY_FILTER_USE_BOTH', function () {
    $result = array_filter(
        ['name' => 'Taro', '_token' => 'x'],
        fn($value, $key) => !str_starts_with($key, '_'),
        ARRAY_FILTER_USE_BOTH
    );

    expect($result)->toBe(['name' => 'Taro']);
});

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

症状/エラー原因対処
array_filter(): Argument #1 ($array) must be of type array, string given対象が配列でない(null や文字列を渡している)渡す前に is_array() で検証、または json_decode($json, true) ?? [] のようにフォールバックを用意
フィルタ後を json_encode すると配列でなくオブジェクト({})になるキーが保持されて連番に穴が空いているarray_values() で再連番してから json_encode
ARRAY_FILTER_USE_BOTH でキー判定が効かないコールバックの引数順を「キー, 値」と誤解している公式仕様どおり function($value, $key) の順で定義する
数値の 0 だけ残したいのに消えてしまうコールバックを省略しているため空判定の対象になっている明示的なコールバック(例:fn($v) => $v !== null && $v !== '')を指定する

参考リンク

レン (Wren)

こんにちは。レンです。

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

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

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

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

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

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

コメント