PHPで検索条件の空データを除外するスマートな方法【array_filterと関数化の実践例】

検索フォームやフィルター画面など、ユーザーから受け取った検索パラメータには、実際には使わない空値が含まれていることがよくあります。
そこで、意味のある値だけを抽出し、検索条件として使えるように整形する方法を、array_filter()再利用可能な関数 を使って紹介します。


概要

  • 空文字 ('')、null、空配列 ([])、数値の 0 などの「検索条件として使わない値」を除外したい
  • ただし、0 が「有効な条件」である項目(例:is_active = 0)は除外したくない
  • フィルター処理を共通関数化し、複数ページ・APIでも使い回したい

完成コード:buildSearchParams() 関数

function buildSearchParams(array $input): array
{
    // 1. 許可される値の一覧(ホワイトリスト)
    $allowed_status  = [0, 1, 9];
    $allowed_tags    = [1, 2, 3, 4];
    $allowed_regions = [10, 20, 30];

    $params = [];

    // 2. 任意入力項目:trimして文字列の空白を除去
    $params['keyword']    = trim($input['keyword'] ?? '');
    $params['extra_info'] = trim($input['extra_info'] ?? '');

    // 3. 単一選択:値をintに変換してホワイトリストに含まれるか判定
    $status = isset($input['status']) ? (int)$input['status'] : null;
    if (in_array($status, $allowed_status, true)) {
        $params['status'] = $status;
    }

    $category_id = isset($input['category_id']) ? (int)$input['category_id'] : null;
    if ($category_id > 0) {
        $params['category_id'] = $category_id;
    }

    // 4. 明示的に 0 を許可する項目(例:未公開)
    $is_active = isset($input['is_active']) ? (int)$input['is_active'] : null;
    if (in_array($is_active, [0, 1], true)) {
        $params['is_active'] = $is_active;
    }

    // 5. 複数選択:配列にキャストしてから int に変換 → 許可された値のみ残す
    $tags = array_map('intval', (array)($input['tag_ids'] ?? []));
    $tags = array_values(array_intersect($tags, $allowed_tags));
    if ($tags) {
        $params['tag_ids'] = $tags;
    }

    $regions = array_map('intval', (array)($input['region_ids'] ?? []));
    $regions = array_values(array_intersect($regions, $allowed_regions));
    if ($regions) {
        $params['region_ids'] = $regions;
    }

    // 6. 空データを除外(is_active の 0 は残す)
    return array_filter(
        $params,
        function ($value, $key) {
            if ($key === 'is_active') return true;
            return !($value === '' || $value === null || $value === [] || $value === 0);
        },
        ARRAY_FILTER_USE_BOTH
    );
}

各ブロックのポイント解説

1. 許可リスト(ホワイトリスト)を用意する

検索条件として使える値を制限することで、
無効なIDや意図しない数値が混入するのを防ぐことができます。

$allowed_status = [0, 1, 9];

→ 例:ステータスが「公開」「下書き」「削除済み」など


2. 任意入力は trim() のみでOK

テキスト入力は基本的に空白を除去すれば十分です。

$params['keyword'] = trim($input['keyword'] ?? '');

→ 未入力であれば '' になるので、後の array_filter で除外されます。


3. 単一の数値入力は intval() と in_array() を併用

GETパラメータは文字列として渡ってくるため、まず整数に変換し、
許容された値かどうかをチェックします。

$status = isset($input['status']) ? (int)$input['status'] : null;

in_array(..., true) によって型比較(===)を強制し、"0" のような文字列を除外できます。


4. 0 を意味のある値として許可したい場合

例:is_active = 0 は「無効」の意味があるので、除外してはいけません。
そのため、後段のフィルターで特別扱いするようにします。

if (in_array($is_active, [0, 1], true)) {
    $params['is_active'] = $is_active;
}

5. 複数選択肢は「キャスト→フィルタ」の2段階

  • $_GET['tag_ids'] が単一か複数か不明なときも (array) キャストで安定化
  • intval() で文字列数値を強制的に整数化
  • array_intersect() で不要なID(例:99など)を削除
$tags = array_map('intval', (array)($input['tag_ids'] ?? []));

6. 最後に不要値を一括除外(ただし例外キーは残す)

この部分が今回のポイントです。

return array_filter(
    $params,
    function ($value, $key) {
        if ($key === 'is_active') return true;
        return !($value === '' || $value === null || $value === [] || $value === 0);
    },
    ARRAY_FILTER_USE_BOTH
);
  • ARRAY_FILTER_USE_BOTH により「キー」も条件に使える
  • 特定のキー(例:is_active)を例外的に残すことが可能
  • 一般的な空要素('', null, [], 0)は削除されます

使用例

$searchParams = buildSearchParams($_GET);

この $searchParams をそのままSQLやAPIに渡すことで、
無駄のない、精度の高い検索条件として活用できます。


応用・拡張アイデア

  • 許容値リスト(ホワイトリスト)を関数外から渡すようにするとより汎用的になります
  • 除外対象キーを複数指定したい場合は、配列で持って in_array($key, $exempt_keys) にする
  • LaravelやSlimでは、この関数をサービスクラスやヘルパークラスに配置するとより自然です

まとめ

  • array_filter()ARRAY_FILTER_USE_BOTH の組み合わせで、値とキーを柔軟に評価可能
  • 「0」を除外したくないケースでは、キーによる例外処理が非常に有効
  • 関数化すれば、再利用性・可読性・保守性が大きく向上

コメント

タイトルとURLをコピーしました