PHPの連想配列の検索について

採用はこちら

PHPでは、配列のキーに文字列を指定したものを連想配列と呼びます。

例えば、次のような配列です。

$user = [
    'id' => 1,
    'name' => 'Tanaka',
    'email' => 'tanaka@example.com',
    'age' => 28,
];

通常の配列では 012 のような数値インデックスで値を管理しますが、連想配列では 'name''email' のようなキーを使って値を管理します。

echo $user['name'];
// Tanaka

PHPで連想配列を検索する場合、主に次のような処理を行います。

// キーが存在するか調べる
array_key_exists('email', $user);

// 値が存在するか調べる
in_array('Tanaka', $user, true);

// 値からキーを取得する
array_search('Tanaka', $user, true);

// 条件に合う要素を抽出する
array_filter($users, fn($user) => $user['age'] >= 20);

連想配列の検索では、「キーを探したいのか」「値を探したいのか」「条件に合う要素を取り出したいのか」によって使う関数が変わります。

そのため、まずは目的別に使い分けを理解することが大切です。

目次

PHPの連想配列検索でよく使う関数

連想配列の検索でよく使う関数は、主に次のとおりです。

目的使用する関数
キーが存在するか調べるarray_key_exists()
キーが存在し、値が null でないか調べるisset()
値が存在するか調べるin_array()
値からキーを取得するarray_search()
条件に合う要素を抽出するarray_filter()
特定の列だけを取り出すarray_column()
値をキーに変換して検索しやすくするarray_flip()
条件に合う最初の値を取得するarray_find()
条件に合う最初のキーを取得するarray_find_key()

ただし、array_find()array_find_key() はPHP 8.4以降で使える関数です。

PHP 8.3以前の環境では使えないため、古い環境も考慮する場合は foreach を使った検索方法も覚えておくとよいでしょう。

キーが存在するか検索する方法

array_key_exists() を使う

連想配列で、特定のキーが存在するか調べたい場合は array_key_exists() を使います。

$user = [
    'id' => 1,
    'name' => 'Tanaka',
    'email' => 'tanaka@example.com',
];

if (array_key_exists('email', $user)) {
    echo 'emailキーは存在します';
} else {
    echo 'emailキーは存在しません';
}

実行結果は次のようになります。

emailキーは存在します

array_key_exists() は、指定したキーが配列に存在するかを調べる関数です。

連想配列で「その項目があるかどうか」を確認したい場合によく使います。

値が null でもキーの存在を判定できる

array_key_exists() の大きな特徴は、値が null でもキーが存在すれば true を返すことです。

$user = [
    'name' => 'Tanaka',
    'email' => null,
];

var_dump(array_key_exists('email', $user));

実行結果は次のとおりです。

bool(true)

email の値は null ですが、email というキー自体は存在しています。

そのため、array_key_exists()true を返します。

これは、フォーム入力やAPIレスポンスなどで「値が空かどうか」ではなく、「項目自体が存在するか」を確認したい場合に便利です。

array_key_exists() が向いているケース

array_key_exists() は、次のようなケースに向いています。

$config = [
    'debug' => true,
    'cache' => false,
    'timezone' => 'Asia/Tokyo',
];

if (array_key_exists('cache', $config)) {
    echo 'cache設定があります';
}

この例では、cache の値は false です。

しかし、cache というキーは存在しているため、array_key_exists() では true になります。

設定配列では、falsenull に意味がある場合もあります。

そのような場合は、値の真偽ではなく、キーの存在を確認できる array_key_exists() が適しています。

isset() でキーの存在を確認する方法

isset() の基本的な使い方

isset() でも、連想配列のキーが存在するかを確認できます。

$user = [
    'name' => 'Tanaka',
    'email' => 'tanaka@example.com',
];

if (isset($user['email'])) {
    echo 'emailは設定されています';
}

実行結果は次のとおりです。

emailは設定されています

isset() は、指定した変数や配列の要素が存在し、なおかつ値が null ではない場合に true を返します。

isset()null の場合に false になる

isset() を使うときに注意したいのは、値が null の場合です。

$user = [
    'name' => 'Tanaka',
    'email' => null,
];

var_dump(isset($user['email']));
var_dump(array_key_exists('email', $user));

実行結果は次のようになります。

bool(false)
bool(true)

email キーは存在しています。

しかし、値が null のため、isset()false を返します。

一方、array_key_exists() はキーの存在だけを見るため、true を返します。

array_key_exists()isset() の違い

array_key_exists()isset() の違いは、次のように整理できます。

状態array_key_exists()isset()
キーがあり、値もあるtruetrue
キーがあり、値が nulltruefalse
キーがないfalsefalse

つまり、キーの存在だけを確認したい場合は array_key_exists()、値が null ではないことも確認したい場合は isset() を使います。

// キーが存在するか確認したい
array_key_exists('email', $user);

// キーが存在し、値がnullではないか確認したい
isset($user['email']);

この違いは、PHPの連想配列検索で特に重要です。

値が存在するか検索する方法

in_array() を使う

連想配列の中に特定の値が存在するか調べる場合は、in_array() を使います。

$user = [
    'id' => 1,
    'name' => 'Tanaka',
    'email' => 'tanaka@example.com',
];

if (in_array('Tanaka', $user, true)) {
    echo 'Tanakaは存在します';
}

実行結果は次のとおりです。

Tanakaは存在します

in_array() は、配列の中に指定した値があるかどうかを調べる関数です。

連想配列でも通常の配列と同じように使用できます。

第3引数には true を指定する

in_array() を使うときは、第3引数に true を指定するのがおすすめです。

in_array(検索する値, 配列, 厳密比較するか);

第3引数を true にすると、値だけでなく型も含めて比較します。

例えば、次のコードを見てください。

$data = [
    'code' => '1',
];

var_dump(in_array(1, $data));
var_dump(in_array(1, $data, true));

実行結果は次のようになります。

bool(true)
bool(false)

第3引数を省略した場合、文字列の '1' と整数の 1 が同じように扱われることがあります。

一方、第3引数に true を指定すると、文字列 '1' と整数 1 は別の値として扱われます。

そのため、実務では次のように書くのが安全です。

in_array($value, $array, true);

特に、ID、ステータスコード、数値文字列などを扱う場合は、型の違いによる誤判定を防ぐために厳密比較を使いましょう。

値からキーを検索する方法

array_search() を使う

値を検索して、その値に対応するキーを取得したい場合は array_search() を使います。

$user = [
    'id' => 1,
    'name' => 'Tanaka',
    'email' => 'tanaka@example.com',
];

$key = array_search('Tanaka', $user, true);

echo $key;

実行結果は次のとおりです。

name

'Tanaka' という値は 'name' キーに入っているため、array_search()name を返します。

array_search() の戻り値に注意する

array_search() は、値が見つかった場合は対応するキーを返します。

見つからなかった場合は false を返します。

$user = [
    'id' => 1,
    'name' => 'Tanaka',
];

$key = array_search('Suzuki', $user, true);

var_dump($key);

実行結果は次のとおりです。

bool(false)

ここで注意したいのは、キーが 0 の場合です。

$data = [
    0 => 'apple',
    1 => 'banana',
];

$key = array_search('apple', $data, true);

if ($key) {
    echo '見つかりました';
} else {
    echo '見つかりませんでした';
}

実行結果は次のようになります。

見つかりませんでした

apple は見つかっています。
しかし、返ってきたキーが 0 のため、if ($key) では false と判定されてしまいます。

そのため、array_search() の結果を判定するときは、必ず !== false を使います。

$key = array_search('apple', $data, true);

if ($key !== false) {
    echo '見つかりました。キーは ' . $key . ' です';
} else {
    echo '見つかりませんでした';
}

実行結果は次のとおりです。

見つかりました。キーは 0 です

array_search() を使うときは、次の書き方を基本にしましょう。

$key = array_search($value, $array, true);

if ($key !== false) {
    // 見つかった場合の処理
}

条件に合う要素を検索する方法

array_filter() を使う

単純に値が一致するかどうかではなく、条件に合う要素を抽出したい場合は array_filter() を使います。

例えば、年齢が20歳以上のユーザーだけを取り出す場合は、次のように書けます。

$users = [
    'user1' => ['name' => 'Tanaka', 'age' => 28],
    'user2' => ['name' => 'Suzuki', 'age' => 35],
    'user3' => ['name' => 'Sato', 'age' => 19],
];

$adults = array_filter($users, function ($user) {
    return $user['age'] >= 20;
});

print_r($adults);

実行結果は次のとおりです。

Array
(
    [user1] => Array
        (
            [name] => Tanaka
            [age] => 28
        )

    [user2] => Array
        (
            [name] => Suzuki
            [age] => 35
        )
)

array_filter() は、配列の各要素をコールバック関数に渡し、戻り値が true になった要素だけを残します。

array_filter() はキーを保持する

array_filter() を使うと、元のキーが保持されます。

$numbers = [
    10 => 'A',
    20 => 'B',
    30 => 'C',
];

$result = array_filter($numbers, function ($value) {
    return $value !== 'B';
});

print_r($result);

実行結果は次のとおりです。

Array
(
    [10] => A
    [30] => C
)

キーは 01 のように振り直されません。

元の 1030 がそのまま残ります。

通常の配列でも同じです。

$numbers = [10, 20, 30, 40];

$result = array_filter($numbers, function ($number) {
    return $number >= 30;
});

print_r($result);

実行結果は次のようになります。

Array
(
    [2] => 30
    [3] => 40
)

このように、条件に合う要素だけを残した結果、キーが飛び飛びになることがあります。

キーを振り直す場合は array_values() を使う

array_filter() の結果を連番の配列にしたい場合は、array_values() を使います。

$numbers = [10, 20, 30, 40];

$result = array_filter($numbers, function ($number) {
    return $number >= 30;
});

$result = array_values($result);

print_r($result);

実行結果は次のとおりです。

Array
(
    [0] => 30
    [1] => 40
)

APIレスポンスとしてJSONを返す場合は、この違いが特に重要です。

$numbers = [10, 20, 30, 40];

$result = array_filter($numbers, function ($number) {
    return $number >= 30;
});

echo json_encode($result);

実行結果は次のようになる場合があります。

{"2":30,"3":40}

キーが連番でないため、JSONでは配列ではなくオブジェクトのような形になります。

配列として返したい場合は、array_values() でキーを振り直します。

$result = array_values($result);

echo json_encode($result);

実行結果は次のようになります。

[30,40]

キーと値の両方を使って検索する方法

ARRAY_FILTER_USE_BOTH を使う

array_filter() では、値だけでなくキーも使って検索できます。

キーと値の両方を使いたい場合は、ARRAY_FILTER_USE_BOTH を指定します。

$data = [
    'apple' => 120,
    'banana' => 80,
    'orange' => 100,
];

$result = array_filter(
    $data,
    function ($value, $key) {
        return $value >= 100 && str_contains($key, 'a');
    },
    ARRAY_FILTER_USE_BOTH
);

print_r($result);

実行結果は次のとおりです。

Array
(
    [apple] => 120
    [orange] => 100
)

この例では、次の2つの条件を満たす要素を取り出しています。

値が100以上
かつ
キーに a が含まれる

ARRAY_FILTER_USE_BOTH を指定すると、コールバック関数に値とキーの両方が渡されます。

キーだけを使って検索する場合は ARRAY_FILTER_USE_KEY を使う

キーだけを条件にして検索したい場合は、ARRAY_FILTER_USE_KEY を使います。

$data = [
    'user_name' => 'Tanaka',
    'user_email' => 'tanaka@example.com',
    'admin_name' => 'Suzuki',
];

$result = array_filter(
    $data,
    function ($key) {
        return str_starts_with($key, 'user_');
    },
    ARRAY_FILTER_USE_KEY
);

print_r($result);

実行結果は次のとおりです。

Array
(
    [user_name] => Tanaka
    [user_email] => tanaka@example.com
)

この例では、キーが user_ で始まる要素だけを抽出しています。

Webマーケティングやアクセス解析の処理では、次のように utm_ で始まるパラメータだけを取り出したいケースがあります。

$params = [
    'utm_source' => 'google',
    'utm_medium' => 'cpc',
    'utm_campaign' => 'summer_sale',
    'page' => 3,
    'sort' => 'new',
];

$utmParams = array_filter(
    $params,
    function ($key) {
        return str_starts_with($key, 'utm_');
    },
    ARRAY_FILTER_USE_KEY
);

print_r($utmParams);

実行結果は次のようになります。

Array
(
    [utm_source] => google
    [utm_medium] => cpc
    [utm_campaign] => summer_sale
)

多次元連想配列から検索する方法

多次元連想配列の例

実務では、次のような多次元配列を検索することが多いです。

$users = [
    [
        'id' => 1,
        'name' => 'Tanaka',
        'email' => 'tanaka@example.com',
        'role' => 'admin',
    ],
    [
        'id' => 2,
        'name' => 'Suzuki',
        'email' => 'suzuki@example.com',
        'role' => 'editor',
    ],
    [
        'id' => 3,
        'name' => 'Sato',
        'email' => 'sato@example.com',
        'role' => 'editor',
    ],
];

このような配列から、特定のIDを持つユーザーや、特定の役割を持つユーザーを検索できます。

特定のIDを持つユーザーを検索する

id2 のユーザーを検索する場合は、array_filter() を使って次のように書けます。

$result = array_filter($users, function ($user) {
    return $user['id'] === 2;
});

print_r($result);

実行結果は次のとおりです。

Array
(
    [1] => Array
        (
            [id] => 2
            [name] => Suzuki
            [email] => suzuki@example.com
            [role] => editor
        )
)

この場合も、array_filter() は元のキーを保持します。

そのため、結果のキーは [0] ではなく [1] になっています。

検索結果から1件だけ取り出す

array_filter() の結果から1件だけ取り出したい場合は、array_values() を使うと扱いやすくなります。

$result = array_filter($users, function ($user) {
    return $user['id'] === 2;
});

$user = array_values($result)[0] ?? null;

print_r($user);

実行結果は次のとおりです。

Array
(
    [id] => 2
    [name] => Suzuki
    [email] => suzuki@example.com
    [role] => editor
)

?? null を付けておくと、条件に合う要素が見つからなかった場合でもエラーを防ぎやすくなります。

条件に合う最初の1件だけ取得する方法

PHP 8.4以降では array_find() が使える

PHP 8.4以降では、条件に合う最初の要素を取得する array_find() が使えます。

$users = [
    ['id' => 1, 'name' => 'Tanaka'],
    ['id' => 2, 'name' => 'Suzuki'],
    ['id' => 3, 'name' => 'Sato'],
];

$user = array_find($users, function ($user) {
    return $user['id'] === 2;
});

print_r($user);

実行結果は次のとおりです。

Array
(
    [id] => 2
    [name] => Suzuki
)

array_find() は、コールバック関数が true を返した最初の要素を返します。

見つからなかった場合は null を返します。

1件だけ取得したい場合、array_filter() よりも意図がわかりやすい書き方です。

$user = array_find($users, fn($user) => $user['id'] === 2);

PHP 8.3以前では foreach を使う

PHP 8.3以前では array_find() が使えないため、foreach を使う方法が実用的です。

$found = null;

foreach ($users as $user) {
    if ($user['id'] === 2) {
        $found = $user;
        break;
    }
}

print_r($found);

実行結果は次のとおりです。

Array
(
    [id] => 2
    [name] => Suzuki
)

foreach を使う方法は、見つかった時点で break できるため、無駄な処理を減らせます。

大量のデータから1件だけ探す場合は、array_filter() で全件走査して配列を作るよりも、foreach で見つけた時点で処理を止める方が効率的です。

自作関数を作る場合は関数名に注意する

PHP 8.3以前で、array_find() のような処理を使い回したい場合は、自作関数を作ることもできます。

ただし、PHP 8.4以降では array_find() が標準関数として存在します。

そのため、自作関数名を array_find() にすると、関数名が衝突する可能性があります。

自作する場合は、例えば次のように別名にすると安全です。

function find_first(array $array, callable $callback): mixed
{
    foreach ($array as $key => $value) {
        if ($callback($value, $key)) {
            return $value;
        }
    }

    return null;
}

使用例は次のとおりです。

$user = find_first($users, function ($user) {
    return $user['id'] === 2;
});

print_r($user);

標準関数と同じ名前を使わないようにすることで、PHPのバージョンアップ時のトラブルを避けやすくなります。

条件に合う最初のキーを取得する方法

PHP 8.4以降では array_find_key() が使える

条件に合う最初の要素のキーを取得したい場合、PHP 8.4以降では array_find_key() が使えます。

$users = [
    'user1' => ['id' => 1, 'name' => 'Tanaka'],
    'user2' => ['id' => 2, 'name' => 'Suzuki'],
    'user3' => ['id' => 3, 'name' => 'Sato'],
];

$key = array_find_key($users, function ($user) {
    return $user['id'] === 2;
});

echo $key;

実行結果は次のとおりです。

user2

array_find_key() は、条件に合う最初の要素のキーを返します。

見つからなかった場合は null を返します。

PHP 8.3以前では foreach でキーを取得する

PHP 8.3以前の環境では、foreach を使ってキーを取得します。

$foundKey = null;

foreach ($users as $key => $user) {
    if ($user['id'] === 2) {
        $foundKey = $key;
        break;
    }
}

echo $foundKey;

実行結果は次のとおりです。

user2

キーと値の両方を扱いたい場合、foreach ($array as $key => $value) の形が便利です。

条件に合う要素があるか調べる方法

PHP 8.4以降では array_any() が使える

条件に合う要素が1つでも存在するか調べたい場合、PHP 8.4以降では array_any() が使えます。

$users = [
    ['name' => 'Tanaka', 'role' => 'admin'],
    ['name' => 'Suzuki', 'role' => 'editor'],
    ['name' => 'Sato', 'role' => 'editor'],
];

$hasAdmin = array_any($users, function ($user) {
    return $user['role'] === 'admin';
});

var_dump($hasAdmin);

実行結果は次のとおりです。

bool(true)

array_any() は、1つでも条件に合う要素があれば true を返します。

「該当データがあるかどうかだけ知りたい」という場合に便利です。

PHP 8.3以前では foreach で判定する

PHP 8.3以前では、foreach で判定できます。

$hasAdmin = false;

foreach ($users as $user) {
    if ($user['role'] === 'admin') {
        $hasAdmin = true;
        break;
    }
}

var_dump($hasAdmin);

実行結果は次のとおりです。

bool(true)

見つかった時点で break すれば、それ以上の処理を行わずに済みます。

すべての要素が条件を満たすか調べる方法

PHP 8.4以降では array_all() が使える

すべての要素が条件を満たしているか調べたい場合、PHP 8.4以降では array_all() が使えます。

$users = [
    ['name' => 'Tanaka', 'age' => 28],
    ['name' => 'Suzuki', 'age' => 35],
    ['name' => 'Sato', 'age' => 19],
];

$allAdults = array_all($users, function ($user) {
    return $user['age'] >= 20;
});

var_dump($allAdults);

実行結果は次のとおりです。

bool(false)

この例では、Sato の年齢が19歳なので、すべてのユーザーが20歳以上ではありません。

そのため、false が返ります。

PHP 8.3以前では foreach で判定する

PHP 8.3以前では、次のように foreach で判定できます。

$allAdults = true;

foreach ($users as $user) {
    if ($user['age'] < 20) {
        $allAdults = false;
        break;
    }
}

var_dump($allAdults);

実行結果は次のとおりです。

bool(false)

条件を満たさない要素が見つかった時点で break できるため、効率的です。

array_column() を使って検索しやすくする方法

特定のカラムだけを取り出す

多次元配列から特定の項目だけを取り出したい場合は、array_column() が便利です。

$users = [
    [
        'id' => 1,
        'name' => 'Tanaka',
        'email' => 'tanaka@example.com',
    ],
    [
        'id' => 2,
        'name' => 'Suzuki',
        'email' => 'suzuki@example.com',
    ],
    [
        'id' => 3,
        'name' => 'Sato',
        'email' => 'sato@example.com',
    ],
];

$names = array_column($users, 'name');

print_r($names);

実行結果は次のとおりです。

Array
(
    [0] => Tanaka
    [1] => Suzuki
    [2] => Sato
)

array_column() を使うと、多次元配列から指定した列だけを取り出せます。

特定カラムの値に含まれるか検索する

名前一覧に Suzuki が含まれているか調べたい場合は、array_column()in_array() を組み合わせます。

$names = array_column($users, 'name');

if (in_array('Suzuki', $names, true)) {
    echo 'Suzukiさんが存在します';
}

実行結果は次のとおりです。

Suzukiさんが存在します

このように、特定の列だけを取り出してから検索すると、コードがわかりやすくなります。

IDをキーにした配列を作る

array_column() の第3引数を使うと、特定の値をキーにした配列を作れます。

$usersById = array_column($users, null, 'id');

print_r($usersById);

実行結果は次のようになります。

Array
(
    [1] => Array
        (
            [id] => 1
            [name] => Tanaka
            [email] => tanaka@example.com
        )

    [2] => Array
        (
            [id] => 2
            [name] => Suzuki
            [email] => suzuki@example.com
        )

    [3] => Array
        (
            [id] => 3
            [name] => Sato
            [email] => sato@example.com
        )
)

こうしておくと、IDから直接データを取り出せます。

$user = $usersById[2] ?? null;

print_r($user);

実行結果は次のとおりです。

Array
(
    [id] => 2
    [name] => Suzuki
    [email] => suzuki@example.com
)

何度もIDで検索する場合は、毎回 array_filter() を使うよりも、あらかじめIDをキーにした配列を作っておくと便利です。

IDが重複する場合は上書きに注意する

array_column($users, null, 'id') は便利ですが、IDが重複している場合は注意が必要です。

$users = [
    ['id' => 1, 'name' => 'Tanaka'],
    ['id' => 1, 'name' => 'Suzuki'],
];

$usersById = array_column($users, null, 'id');

print_r($usersById);

実行結果は次のようになります。

Array
(
    [1] => Array
        (
            [id] => 1
            [name] => Suzuki
        )
)

同じキーがある場合、後の要素で上書きされます。

そのため、array_column($users, null, 'id') は、IDが一意である場合に使うのが基本です。

複数条件で連想配列を検索する方法

array_filter() で複数条件を指定する

複数の条件に合う要素を検索したい場合は、array_filter() のコールバック内で条件を組み合わせます。

例えば、roleeditor で、名前が Suzuki のユーザーを探す場合は次のように書きます。

$users = [
    [
        'id' => 1,
        'name' => 'Tanaka',
        'role' => 'admin',
    ],
    [
        'id' => 2,
        'name' => 'Suzuki',
        'role' => 'editor',
    ],
    [
        'id' => 3,
        'name' => 'Sato',
        'role' => 'editor',
    ],
];

$result = array_filter($users, function ($user) {
    return $user['role'] === 'editor'
        && $user['name'] === 'Suzuki';
});

print_r($result);

実行結果は次のとおりです。

Array
(
    [1] => Array
        (
            [id] => 2
            [name] => Suzuki
            [role] => editor
        )
)

&& を使うと、複数の条件をすべて満たす要素だけを抽出できます。

外部変数を検索条件に使う

検索条件を変数で指定したい場合は、無名関数で use を使います。

$targetRole = 'editor';

$result = array_filter($users, function ($user) use ($targetRole) {
    return $user['role'] === $targetRole;
});

print_r($result);

実行結果は次のようになります。

Array
(
    [1] => Array
        (
            [id] => 2
            [name] => Suzuki
            [role] => editor
        )

    [2] => Array
        (
            [id] => 3
            [name] => Sato
            [role] => editor
        )
)

use ($targetRole) を指定することで、無名関数の外側にある変数を関数内で使えるようになります。

アロー関数で短く書く

PHP 7.4以降では、アロー関数を使って短く書くこともできます。

$targetRole = 'editor';

$result = array_filter($users, fn($user) => $user['role'] === $targetRole);

アロー関数では、外側の変数を自動的に参照できます。

そのため、use ($targetRole) を書く必要がありません。

ただし、処理が複雑になる場合は、通常の無名関数を使った方が読みやすいこともあります。

部分一致で連想配列を検索する方法

str_contains() を使う

文字列の一部が一致するか調べたい場合は、str_contains() を使います。

例えば、名前に Sa を含むユーザーを検索する場合は次のように書きます。

$users = [
    ['id' => 1, 'name' => 'Tanaka'],
    ['id' => 2, 'name' => 'Suzuki'],
    ['id' => 3, 'name' => 'Sato'],
];

$keyword = 'Sa';

$result = array_filter($users, function ($user) use ($keyword) {
    return str_contains($user['name'], $keyword);
});

print_r($result);

実行結果は次のとおりです。

Array
(
    [2] => Array
        (
            [id] => 3
            [name] => Sato
        )
)

str_contains() はPHP 8以降で使える関数です。

PHP 7系では strpos() を使う

PHP 7系など、str_contains() が使えない環境では strpos() を使います。

$keyword = 'Sa';

$result = array_filter($users, function ($user) use ($keyword) {
    return strpos($user['name'], $keyword) !== false;
});

strpos() は、文字列が見つかった位置を返します。

見つからなかった場合は false を返します。

そのため、判定には必ず !== false を使います。

strpos($user['name'], $keyword) !== false;

if (strpos(...)) のように書くと、先頭に一致した場合に 0 が返り、誤って false と判定される可能性があります。

前方一致・後方一致で検索する方法

str_starts_with() で前方一致検索をする

キーや値が特定の文字列で始まるか調べたい場合は、str_starts_with() を使います。

$data = [
    'user_name' => 'Tanaka',
    'user_email' => 'tanaka@example.com',
    'admin_name' => 'Suzuki',
];

$result = array_filter(
    $data,
    function ($key) {
        return str_starts_with($key, 'user_');
    },
    ARRAY_FILTER_USE_KEY
);

print_r($result);

実行結果は次のとおりです。

Array
(
    [user_name] => Tanaka
    [user_email] => tanaka@example.com
)

str_starts_with() はPHP 8以降で使える関数です。

PHP 7系で同じことをしたい場合は、strpos() を使います。

strpos($key, 'user_') === 0;

str_ends_with() で後方一致検索をする

文字列が特定の文字列で終わるか調べたい場合は、str_ends_with() を使います。

例えば、メールアドレスが @example.com で終わるユーザーを検索する場合は次のように書きます。

$users = [
    ['name' => 'Tanaka', 'email' => 'tanaka@example.com'],
    ['name' => 'Suzuki', 'email' => 'suzuki@example.net'],
    ['name' => 'Sato', 'email' => 'sato@example.com'],
];

$domain = '@example.com';

$result = array_filter($users, function ($user) use ($domain) {
    return str_ends_with($user['email'], $domain);
});

print_r($result);

実行結果は次のようになります。

Array
(
    [0] => Array
        (
            [name] => Tanaka
            [email] => tanaka@example.com
        )

    [2] => Array
        (
            [name] => Sato
            [email] => sato@example.com
        )
)

str_ends_with() もPHP 8以降で使える関数です。

PHP 7系で書く場合は、次のように substr() を使えます。

substr($email, -strlen($domain)) === $domain;

大文字・小文字を無視して検索する方法

strtolower() を使う

PHPの文字列比較は、基本的に大文字・小文字を区別します。

$user = [
    'name' => 'Tanaka',
];

var_dump(in_array('tanaka', $user, true));

実行結果は次のとおりです。

bool(false)

Tanakatanaka は別の文字列として扱われます。

大文字・小文字を無視したい場合は、比較前に小文字化します。

$users = [
    ['name' => 'Tanaka'],
    ['name' => 'Suzuki'],
];

$keyword = 'tanaka';

$result = array_filter($users, function ($user) use ($keyword) {
    return strtolower($user['name']) === strtolower($keyword);
});

print_r($result);

実行結果は次のとおりです。

Array
(
    [0] => Array
        (
            [name] => Tanaka
        )
)

日本語やマルチバイト文字を扱う場合は mb_strtolower() を検討する

日本語や全角英字など、マルチバイト文字を含む可能性がある場合は、mb_strtolower() を使うとよいでしょう。

$keyword = 'TANAKA';

$result = array_filter($users, function ($user) use ($keyword) {
    return mb_strtolower($user['name']) === mb_strtolower($keyword);
});

日本語そのものには大文字・小文字の概念がない場合も多いですが、全角英字やアルファベットを含むデータでは、表記ゆれ対策として役立ちます。

重複した値を検索する方法

array_search() は最初のキーだけを返す

array_search() は、同じ値が複数ある場合でも、最初に見つかったキーだけを返します。

$data = [
    'a' => 'apple',
    'b' => 'banana',
    'c' => 'apple',
];

$key = array_search('apple', $data, true);

echo $key;

実行結果は次のとおりです。

a

apple'a''c' の両方にあります。

しかし、array_search() は最初に見つかった 'a' だけを返します。

同じ値を持つキーをすべて取得する

同じ値を持つキーをすべて取得したい場合は、array_keys() を使います。

$data = [
    'a' => 'apple',
    'b' => 'banana',
    'c' => 'apple',
];

$keys = array_keys($data, 'apple', true);

print_r($keys);

実行結果は次のとおりです。

Array
(
    [0] => a
    [1] => c
)

array_keys() の第2引数に検索したい値を指定すると、その値を持つキーを取得できます。

第3引数に true を指定すると、型まで含めて厳密に比較できます。

array_flip() を使って検索しやすくする方法

値をキーに変換する

大量のデータに対して、何度も「値が存在するか」を調べたい場合は、array_flip() を使う方法があります。

$allowedRoles = ['admin', 'editor', 'author'];

$allowedRoleMap = array_flip($allowedRoles);

var_dump(isset($allowedRoleMap['editor']));
var_dump(isset($allowedRoleMap['guest']));

実行結果は次のとおりです。

bool(true)
bool(false)

array_flip() を使うと、配列のキーと値が入れ替わります。

[
    'admin' => 0,
    'editor' => 1,
    'author' => 2,
]

こうしておくと、isset() を使ってキーの存在を高速に確認できます。

isset($allowedRoleMap['editor']);

in_array() を何度も実行するより、値をキー化しておいた方が検索しやすい場面があります。

array_flip() の注意点

array_flip() を使う場合は、いくつか注意点があります。

まず、値は文字列または整数である必要があります。

$data = [
    ['name' => 'Tanaka'],
    ['name' => 'Suzuki'],
];

$result = array_flip($data);

このように、値が配列やオブジェクトの場合はキーにできません。

また、重複する値がある場合は後の値で上書きされます。

$data = ['admin', 'editor', 'admin'];

$result = array_flip($data);

print_r($result);

実行結果は次のようになります。

Array
(
    [admin] => 2
    [editor] => 1
)

admin が重複しているため、後のインデックスで上書きされています。

そのため、array_flip() は、値が重複しない前提で使うとよいでしょう。

empty() を使うときの注意点

empty() は存在確認とは意味が違う

PHPでは、値が空かどうかを調べるために empty() を使うことがあります。

$input = [
    'name' => 'Tanaka',
    'email' => '',
];

if (empty($input['email'])) {
    echo 'emailは空です';
}

実行結果は次のとおりです。

emailは空です

ただし、empty() は「キーが存在するか」を調べるものではありません。

あくまで、値が空として扱われるかどうかを判定するものです。

empty() で空扱いされる値

empty() は、次のような値を空として扱います。

''
0
'0'
null
false
[]

例えば、次のコードを見てください。

$data = [
    'count' => 0,
];

if (empty($data['count'])) {
    echo 'countは空です';
}

実行結果は次のとおりです。

countは空です

count というキーは存在しています。

値も 0 として意味があるかもしれません。

しかし、empty() では 0 が空として扱われるため、true になります。

存在確認と空判定は分けて考える

連想配列を扱うときは、存在確認と空判定を分けて考えることが大切です。

$data = [
    'count' => 0,
];

// キーが存在するか
array_key_exists('count', $data);

// 値がnullではないか
isset($data['count']);

// 空文字ではないか
$data['count'] !== '';

フォーム入力やAPIレスポンスでは、0false、空文字、null の意味がそれぞれ異なることがあります。

そのため、単純に empty() だけで判定すると、意図しない結果になる場合があります。

実務でよく使う連想配列検索の例

設定配列にキーがあるか調べる

設定配列では、値が false でも意味を持つ場合があります。

$config = [
    'debug' => true,
    'timezone' => 'Asia/Tokyo',
    'cache' => false,
];

if (array_key_exists('cache', $config)) {
    echo 'cache設定があります';
}

実行結果は次のとおりです。

cache設定があります

この場合、cache の値は false ですが、キー自体は存在します。

そのため、設定項目の存在確認には array_key_exists() が向いています。

フォーム入力に項目があるか調べる

フォーム入力では、項目が送信されたかどうかを確認したいことがあります。

$input = [
    'name' => 'Tanaka',
    'email' => '',
];

if (array_key_exists('email', $input)) {
    echo 'email項目は送信されています';
}

実行結果は次のとおりです。

email項目は送信されています

この例では、email の値は空文字です。

しかし、email という項目は送信されています。

「項目があるか」と「値が空でないか」は別の判定です。

// 項目が送信されたか
array_key_exists('email', $input);

// 値が空でないか
$input['email'] !== '';

このように、目的に応じて判定方法を分けましょう。

APIレスポンスから特定データを探す

APIレスポンスの中から、特定のIDを持つデータを探すケースもよくあります。

$response = [
    'status' => 'success',
    'data' => [
        ['id' => 1, 'title' => 'Article A'],
        ['id' => 2, 'title' => 'Article B'],
        ['id' => 3, 'title' => 'Article C'],
    ],
];

$article = null;

foreach ($response['data'] as $item) {
    if ($item['id'] === 2) {
        $article = $item;
        break;
    }
}

print_r($article);

実行結果は次のとおりです。

Array
(
    [id] => 2
    [title] => Article B
)

1件だけ取得したい場合は、foreach + break がシンプルでわかりやすいです。

PHP 8.4以降であれば、次のように array_find() を使うこともできます。

$article = array_find($response['data'], fn($item) => $item['id'] === 2);

WordPressの配列から設定値を探す

WordPressでは、投稿データ、メタ情報、オプション値などで連想配列を扱うことがあります。

$meta = [
    'description' => '記事の説明文',
    'keywords' => 'PHP,WordPress,SEO',
    'noindex' => false,
];

if (array_key_exists('noindex', $meta)) {
    echo 'noindex設定があります';
}

実行結果は次のとおりです。

noindex設定があります

SEO設定などでは、false という値にも意味があります。

そのため、存在確認に empty() を使うと誤判定になる場合があります。

if (empty($meta['noindex'])) {
    echo 'noindexは空です';
}

この場合、false は空として扱われます。

設定項目が存在するか確認したい場合は、次のように書く方が安全です。

array_key_exists('noindex', $meta);

値が true かどうかを確認したい場合は、次のように厳密に比較します。

$meta['noindex'] === true;

PHPの連想配列検索でよくあるミス

array_search() の結果を if ($key) で判定してしまう

array_search() の結果を次のように判定するのは避けましょう。

$key = array_search('apple', $data, true);

if ($key) {
    echo '見つかりました';
}

キーが 0 の場合、見つかっていても false と判定される可能性があります。

正しくは、次のように書きます。

if ($key !== false) {
    echo '見つかりました';
}

in_array() の第3引数を省略してしまう

in_array() の第3引数を省略すると、型変換によって意図しない一致が起きる場合があります。

in_array(1, ['1']);

この場合、true になる可能性があります。

厳密に比較したい場合は、次のように書きます。

in_array(1, ['1'], true);

実務では、基本的に第3引数に true を指定するのがおすすめです。

isset()array_key_exists() を混同してしまう

isset()array_key_exists() は似ていますが、null の扱いが異なります。

$data = [
    'name' => null,
];

var_dump(isset($data['name']));
var_dump(array_key_exists('name', $data));

実行結果は次のとおりです。

bool(false)
bool(true)

値が null の可能性がある場合は、isset() だけでキーの存在を判断しないようにしましょう。

array_filter() 後のキーを意識していない

array_filter() は、元のキーを保持します。

$numbers = [10, 20, 30, 40];

$result = array_filter($numbers, fn($number) => $number >= 30);

print_r($result);

実行結果は次のとおりです。

Array
(
    [2] => 30
    [3] => 40
)

連番の配列として扱いたい場合は、array_values() を使います。

$result = array_values($result);

特に、JSONとして返す場合は注意しましょう。

array_column() のキー重複を見落としてしまう

array_column($users, null, 'id') は便利ですが、キーに指定した値が重複していると上書きされます。

$users = [
    ['id' => 1, 'name' => 'Tanaka'],
    ['id' => 1, 'name' => 'Suzuki'],
];

$usersById = array_column($users, null, 'id');

この場合、id が同じなので、後の Suzuki のデータで上書きされます。

IDが一意でない場合は、array_filter() やグルーピング処理を使う方が安全です。

PHPバージョン別の検索方法

PHP 8.4以降で使いやすい関数

PHP 8.4以降では、配列検索に便利な関数が追加されています。

関数役割
array_find()条件に合う最初の値を返す
array_find_key()条件に合う最初のキーを返す
array_any()条件に合う要素が1つでもあれば true
array_all()すべての要素が条件を満たせば true

例えば、条件に合う最初のユーザーを取得する場合は次のように書けます。

$user = array_find($users, fn($user) => $user['id'] === 2);

条件に合う要素があるかだけを調べる場合は、次のように書けます。

$hasAdmin = array_any($users, fn($user) => $user['role'] === 'admin');

PHP 8.4以降を前提にできる環境では、これらの関数を使うとコードが読みやすくなります。

PHP 8.3以前でも使える方法

PHP 8.3以前では、array_find()array_any() は使えません。

そのため、次のような方法を使います。

// 条件に合う最初の1件を取得
$found = null;

foreach ($users as $user) {
    if ($user['id'] === 2) {
        $found = $user;
        break;
    }
}
// 条件に合う要素をすべて取得
$result = array_filter($users, fn($user) => $user['role'] === 'editor');
// 値が存在するか確認
in_array($value, $array, true);
// キーが存在するか確認
array_key_exists($key, $array);

古いPHP環境も考慮する必要がある場合は、foreacharray_filter()array_search()in_array() を中心に使うとよいでしょう。

目的別の使い分けまとめ

キーが存在するか調べたい場合

キーが存在するか調べたい場合は、array_key_exists() を使います。

array_key_exists('name', $array);

値が null でもキーの存在を確認できます。

キーがあり、値が null でないか調べたい場合

値が null ではないことも確認したい場合は、isset() を使います。

isset($array['name']);

ただし、値が null の場合は false になる点に注意しましょう。

値が存在するか調べたい場合

値が配列内に存在するか調べたい場合は、in_array() を使います。

in_array('Tanaka', $array, true);

第3引数には true を指定し、厳密比較にするのがおすすめです。

値からキーを取得したい場合

値からキーを取得したい場合は、array_search() を使います。

$key = array_search('Tanaka', $array, true);

判定するときは、必ず !== false を使います。

if ($key !== false) {
    // 見つかった場合の処理
}

条件に合う要素をすべて取得したい場合

条件に合う要素をすべて取得したい場合は、array_filter() を使います。

$result = array_filter($array, function ($item) {
    return 条件;
});

array_filter() はキーを保持するため、必要に応じて array_values() を使いましょう。

$result = array_values($result);

条件に合う最初の1件を取得したい場合

PHP 8.4以降では、array_find() が使えます。

$found = array_find($array, function ($item) {
    return 条件;
});

PHP 8.3以前では、foreach を使います。

$found = null;

foreach ($array as $item) {
    if (条件) {
        $found = $item;
        break;
    }
}

条件に合う最初のキーを取得したい場合

PHP 8.4以降では、array_find_key() が使えます。

$key = array_find_key($array, function ($item) {
    return 条件;
});

PHP 8.3以前では、foreach でキーを取得します。

$foundKey = null;

foreach ($array as $key => $item) {
    if (条件) {
        $foundKey = $key;
        break;
    }
}

多次元配列の特定カラムを検索したい場合

特定の列だけを取り出したい場合は、array_column() を使います。

$names = array_column($users, 'name');

取り出した値に対して検索したい場合は、in_array() と組み合わせます。

in_array('Suzuki', $names, true);

IDをキーにした配列を作りたい場合は、次のように書きます。

$usersById = array_column($users, null, 'id');

ただし、IDが重複する場合は上書きされるため注意が必要です。

まとめ

PHPの連想配列検索は目的に応じて関数を使い分ける

PHPの連想配列検索では、何を探したいかによって使う関数が変わります。

キーを探したい場合は array_key_exists()isset()、値を探したい場合は in_array()、値からキーを取得したい場合は array_search() を使います。

条件に合う要素を取り出したい場合は array_filter() が便利です。

また、PHP 8.4以降では、条件に合う最初の要素を取得する array_find() や、条件に合う最初のキーを取得する array_find_key() も使えます。

基本の使い分け

PHPの連想配列検索では、次の使い分けを覚えておくと便利です。

// キーが存在するか
array_key_exists('key', $array);

// キーがあり、値がnullではないか
isset($array['key']);

// 値が存在するか
in_array($value, $array, true);

// 値に対応するキーを取得
array_search($value, $array, true);

// 条件に合う要素をすべて取得
array_filter($array, fn($item) => 条件);

// PHP 8.4以降で、条件に合う最初の値を取得
array_find($array, fn($item) => 条件);

// PHP 8.4以降で、条件に合う最初のキーを取得
array_find_key($array, fn($item) => 条件);

実務では厳密比較と戻り値の判定に注意する

実務で特に注意したいのは、次の3点です。

// in_array() は第3引数 true を付ける
in_array($value, $array, true);

// array_search() は !== false で判定する
$key = array_search($value, $array, true);

if ($key !== false) {
    // 見つかった
}

// array_filter() 後に必要なら array_values() でキーを振り直す
$result = array_values($result);

PHPの配列検索では、0falsenull、空文字などの扱いで誤判定が起きやすいです。

そのため、型まで含めて比較すること、戻り値を正しく判定すること、キーが保持される仕様を理解することが重要です。

連想配列の検索を正しく使い分けられるようになると、フォーム処理、APIレスポンス処理、設定配列の管理、WordPressのカスタマイズなど、さまざまな場面で安全で読みやすいコードを書けるようになります。

以上、PHPの連想配列の検索についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次