array_search — 配列から値を検索してキーを取得する使い方

基本文法・構文ガイド
  • カテゴリ: PHP
  • 掲載バージョン: PHP 8.4(PHP 8.0以降の変更点も記載)
  • 名前空間 / FQCN / コマンド: array_search(mixed $needle, array $haystack, bool $strict = false): int|string|false
  • 関連: in_array / array_key_exists / array_keys / isset(array_flip()) / Laravel Collection::search / Collection::contains
  • 変更履歴: PHP 8.0 以降、$haystack に配列以外を渡すと TypeError になる(従来は警告を出して null を返していた)

要点(TL;DR)

  • 用途:配列の中から指定した値を探し、最初に見つかった要素のキーを返す(見つからなければfalse
  • 最低限:$key = array_search($needle, $haystack);
  • 存在確認だけならin_array()、キーが不要な連想配列の存在確認ならarray_key_exists()の方が適切
  • 罠:
    • 戻り値の判定は必ず!== falseを使う(キー0が見つかった場合と「見つからない」を区別するため)
    • デフォルトは緩い比較(==のため、数値の0falseと文字列が誤って一致することがある
    • 複数一致する要素があっても最初の1件のキーしか返らない。全件必要ならarray_keys()を使う

概要

array_search() は配列の中から指定した値($needle)を探し、最初に見つかった要素のキーを返す関数です。値が存在するかどうかだけでなく「どの位置(キー)にあるか」も同時に知りたいときに使います。設定値の配列から特定の項目を探す、選択肢一覧から選ばれた値のインデックスを取得する、といった場面でよく使われます。見つからない場合はfalseを返すため、戻り値の判定方法に注意が必要です。

構文 / シグネチャ

array_search(mixed $needle, array $haystack, bool $strict = false): int|string|false

引数(表)

引数必須既定値説明
$needlemixedはい検索したい値
$haystackarrayはい検索対象の配列
$strictboolいいえfalsetrueの場合、型も含めて厳密に比較(===相当)

戻り値int|string(見つかった要素のキー)またはfalse(見つからない場合)

例外/副作用:元の配列は変更しない(非破壊)。PHP 8.0 以降、$haystack に配列以外の値を渡すとTypeErrorが発生する。

使用例

最小例:値からキーを取得

<?php
$fruits = ['apple', 'banana', 'orange', 'grape'];

$key = array_search('orange', $fruits);

var_dump($key);
// int(2)

$missing = array_search('melon', $fruits);
var_dump($missing);
// bool(false)

戻り値の正しい判定:!== falseを使う

<?php
$statuses = ['pending', 'approved', 'rejected'];

$key = array_search('pending', $statuses);

// NG: キーが0のとき if ($key) は false になり誤判定する
if ($key) {
    echo "見つかった: {$key}"; // 実行されない($keyは0のため)
}

// OK: 必ず !== false で判定する
if ($key !== false) {
    echo "見つかった: {$key}"; // 正しく "見つかった: 0" と出力される
}

strict比較:型の違いによる誤マッチを防ぐ

<?php
$values = [0, 'apple', 'banana'];

// 緩い比較(既定):'apple' は 0 とも == で一致してしまう場合がある
var_dump(array_search('apple', $values));       // int(1)(この例では意図通り)

// 数値0を含む配列で文字列を探すと誤爆しやすい例
$mixed = [0 => 0, 1 => 'yes', 2 => 'no'];
var_dump(array_search('yes', $mixed));          // int(1)
var_dump(array_search(false, $mixed, false));   // int(0)(0とfalseが緩く一致)
var_dump(array_search(false, $mixed, true));    // bool(false)(型まで厳密に比較)

// 意図しない一致を避けるため、基本的には第三引数に true を渡す
$key = array_search('yes', $mixed, true);
var_dump($key); // int(1)

実務例:複数一致するすべてのキーを取得する

<?php
$tags = ['php', 'laravel', 'php', 'javascript', 'php'];

// array_search は最初の1件しか返らない
$firstKey = array_search('php', $tags);
var_dump($firstKey);
// int(0)

// すべてのキーが欲しいときは array_keys() を使う
$allKeys = array_keys($tags, 'php', true);
print_r($allKeys);
// [0, 2, 4]

応用例:一致した要素を配列から取り除く(ループ処理)

<?php
$codes = ['a', 'b', 'a', 'c', 'a'];

// NG: != を使うとキー0のとき無限ループになりうる
// while (($key = array_search('a', $codes)) != null) { ... }

// OK: !== false で判定してから unset する
while (($key = array_search('a', $codes)) !== false) {
    unset($codes[$key]);
}

print_r(array_values($codes));
// ['b', 'c']

よくある落とし穴・注意

  • 戻り値の判定に==!=を使わない:キー0falsenullと緩く一致してしまい、見つかったのに「見つからない」扱いになるバグを引き起こす。必ず=== false / !== falseで判定する。
  • デフォルトは緩い型比較:数値の0やブール値falseを含む配列で文字列を検索すると、意図しない要素にマッチすることがある。型を厳密に扱いたい場合は第三引数にtrueを渡す。
  • 複数一致時は最初の1件のみ:同じ値が配列内に複数あっても、返るキーは最初に見つかったものだけ。全件のキーが必要ならarray_keys($array, $value, true)を使う。
  • 多次元配列はそのまま検索できないarray_searchは1階層目の要素しか比較しない。連想配列の集合から特定キーの値を探すには、array_column()で対象列を抽出してから検索する。
  • 非破壊array_search()は元の配列を変更しない。要素を取り除きたい場合は、返ってきたキーを使って自分でunset()する必要がある。

多次元配列からの検索例(array_columnと組み合わせる)

<?php
$users = [
    ['id' => 1, 'name' => 'Taro'],
    ['id' => 2, 'name' => 'Jiro'],
    ['id' => 3, 'name' => 'Saburo'],
];

// NG: array_search はそのままでは配列同士を比較するので使えない
// $key = array_search(2, $users); // false になる

// OK: id列だけを抽出してから検索する
$ids = array_column($users, 'id');
$key = array_search(2, $ids, true);

var_dump($key);        // int(1)
print_r($users[$key]); // ['id' => 2, 'name' => 'Jiro']

代替・関連APIとの比較

関数/メソッド戻り値用途
array_searchキー または false値が存在するかに加えて、そのキー(インデックス)も欲しいとき
in_arraybool値が配列に存在するかだけを知りたいとき。最も可読性が高い
array_key_existsbool値ではなくキーが存在するかを調べたいとき
array_keys($array, $value)array一致するすべてのキーを取得したいとき
isset(array_flip($arr)[$v])bool同じ配列に対して繰り返し検索する場合の高速化(存在確認のみ)
Laravel Collection::searchキー または falseLaravelのコレクションを扱っていて、コールバックでの判定も行いたいとき

選定基準

  • 存在するかどうかだけを知りたい → in_array()
  • 存在すればキー(インデックス)も欲しい → array_search()
  • 一致するキーが複数あり得て全部欲しい → array_keys()
  • 連想配列でキーそのものの存在を調べたい → array_key_exists()
  • Laravelのコレクションチェーンの中で使いたい → Collection::search() / Collection::contains()

テスト例(Pest)

<?php
// tests/ArraySearchFunctionTest.php
it('returns the key of the first matching element', function () {
    $result = array_search('orange', ['apple', 'banana', 'orange']);

    expect($result)->toBe(2);
});

it('returns false when the value is not found', function () {
    $result = array_search('melon', ['apple', 'banana', 'orange']);

    expect($result)->toBeFalse();
});

it('distinguishes between key 0 and not found using strict comparison', function () {
    $result = array_search('pending', ['pending', 'approved']);

    expect($result)->toBe(0)
        ->and($result !== false)->toBeTrue();
});

it('avoids loose type matches when strict mode is enabled', function () {
    $mixed = [0 => 0, 1 => 'yes'];

    expect(array_search(false, $mixed, true))->toBeFalse()
        ->and(array_search(false, $mixed, false))->toBe(0);
});

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

症状/エラー原因対処
要素が存在するのにif ($key)falseになる見つかったキーが0で、if評価時にfalseとみなされているif ($key !== false)のように厳密な比較に書き換える
array_search(): Argument #2 ($haystack) must be of type array, null given検索対象が配列でない(未初期化変数やnullを渡している)渡す前にis_array()で検証、または$haystack ?? []のようにフォールバックを用意
探しているはずの値が見つからない(falseが返る)多次元配列やオブジェクトを含む配列に対して、そのまま値を検索しているarray_column()で対象の列を抽出してから検索する
意図しない要素がヒットするデフォルトの緩い比較(==)で型の異なる値(0false''など)が一致している第三引数にtrueを渡して厳密比較にする

参考リンク

レン (Wren)

こんにちは。レンです。

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

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

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

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

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

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

コメント