PHPの連想配列のキーの存在を確認する方法について

採用はこちら

PHPで連想配列のキーが存在するか確認する方法には、主に次の2つがあります。

array_key_exists('key', $array);
isset($array['key']);

どちらも配列のキーを確認する際に使われますが、値がnullの場合の扱いが異なります

この違いを理解しておかないと、キーが存在しているにもかかわらず「存在しない」と誤判定する可能性があります。

目次

array_key_exists()でキーの存在を確認する

array_key_exists()は、指定したキーが配列内に存在するかどうかを確認する関数です。

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

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

キーが存在すればtrue、存在しなければfalseを返します。

値がnullでもtrueになる

array_key_exists()は、キーに設定されている値がnullでも、キー自体が存在すればtrueを返します。

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

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

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

bool(true)

emailの値はnullですが、配列内にemailキーが定義されているため、結果はtrueになります。

array_key_exists()が適している場面

array_key_exists()は、次のような場面で適しています。

  • キーそのものが定義されているか確認したい
  • 値がnullでも「キーあり」と判定したい
  • APIレスポンスのフィールド構造を確認したい
  • 未指定と明示的なnullを区別したい
  • 設定配列に項目が含まれているか検証したい

isset()でキーと値を確認する

isset()は、指定したキーが存在し、なおかつ値がnullではない場合にtrueを返します。

$user = [
    'name' => '田中',
];

if (isset($user['name'])) {
    echo 'nameキーが存在し、値はnullではありません';
}

厳密には、isset()は通常の関数ではなくPHPの言語構造です。

値がnullの場合はfalseになる

次の例では、emailキー自体は存在しています。

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

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

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

bool(false)

キーは存在していますが、値がnullなのでisset()falseを返します。

isset()では区別できない状態

isset()は、次の2つの状態を区別できません。

// キーが存在しない
$data = [];

// キーは存在するが値がnull
$data = [
    'email' => null,
];

どちらの場合も、次の結果はfalseになります。

isset($data['email']);

キーが存在しない状態と、値がnullの状態を区別したい場合は、array_key_exists()を使用します。

array_key_exists()isset()の違い

次の配列を例に比較します。

$data = [
    'name'   => '山田',
    'email'  => null,
    'age'    => 0,
    'active' => false,
    'memo'   => '',
];

それぞれの結果は次のようになります。

キーarray_key_exists()isset()
name'山田'truetrue
emailnulltruefalse
age0truetrue
activefalsetruetrue
memo''truetrue
存在しないキーなしfalsefalse

実際のコードで確認すると、次のようになります。

var_dump(array_key_exists('email', $data)); // true
var_dump(isset($data['email']));            // false

var_dump(array_key_exists('age', $data));   // true
var_dump(isset($data['age']));              // true

var_dump(array_key_exists('unknown', $data)); // false
var_dump(isset($data['unknown']));            // false

基本的な使い分け

キーそのものが存在するか確認する場合は、array_key_exists()を使います。

if (array_key_exists('email', $user)) {
    // emailキーが存在する
}

キーが存在し、値がnullではないことを確認する場合は、isset()を使います。

if (isset($user['email'])) {
    // emailキーが存在し、値はnullではない
}

実務では、次のように整理すると分かりやすいです。

// 配列にキーが含まれているか
array_key_exists('key', $array);

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

??演算子でデフォルト値を設定する

キーが存在しない場合や、値がnullの場合にデフォルト値を設定したいときは、Null合体演算子の??が便利です。

$name = $user['name'] ?? 'ゲスト';

このコードは、おおむね次の処理と同じです。

$name = isset($user['name'])
    ? $user['name']
    : 'ゲスト';

存在しないキーを安全に取得できる

例えば、GETパラメータを取得する場合に利用できます。

$page = $_GET['page'] ?? 1;

pageキーが存在しない場合や、値がnullの場合は1が代入されます。

??もキーなしとnullを区別しない

次の配列を考えます。

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

次のコードでは、デフォルト値が使用されます。

$message = $data['message'] ?? 'メッセージなし';

echo $message;

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

メッセージなし

キー自体は存在していますが、値がnullなので右辺の値が採用されます。

キーが存在する場合は、値がnullでもそのまま取得したいなら、array_key_exists()を使います。

$message = array_key_exists('message', $data)
    ? $data['message']
    : 'メッセージなし';

ネストした連想配列のキーを確認する

多次元の連想配列では、途中の階層も考慮する必要があります。

$user = [
    'profile' => [
        'name' => '佐藤',
        'age'  => 30,
    ],
];

isset()でネストしたキーを確認する

isset()は、ネストしたキーをまとめて確認できます。

if (isset($user['profile']['name'])) {
    echo $user['profile']['name'];
}

途中のキーが存在しない場合でも、通常は安全にfalseを返します。

if (isset($user['profile']['address']['city'])) {
    echo $user['profile']['address']['city'];
}

ただし、最終的な値がnullの場合もfalseになります。

array_key_exists()は一階層ずつ確認する

array_key_exists()でネストしたキーを確認する場合は、途中の値が配列であることも確認します。

if (
    array_key_exists('profile', $user)
    && is_array($user['profile'])
    && array_key_exists('name', $user['profile'])
) {
    echo 'nameキーが存在します';
}

例えば、値がnullの場合でもキーの存在を検出できます。

$user = [
    'profile' => [
        'name' => null,
    ],
];

var_dump(isset($user['profile']['name']));
// false

var_dump(
    isset($user['profile'])
    && is_array($user['profile'])
    && array_key_exists('name', $user['profile'])
);
// true

ドット区切りでは確認できない

標準のarray_key_exists()には、ドット区切りで深い階層を確認する機能はありません。

array_key_exists('profile.name', $user);

このコードは、profile配列の中にあるnameキーではなく、profile.nameという文字列のキーを探します。

empty()との違い

empty()は、値がPHPの基準で空かどうかを確認するための言語構造です。

if (!empty($user['name'])) {
    echo 'nameに空ではない値があります';
}

ただし、empty()は単純なキーの存在確認ではありません。

empty()が空と判定する主な値

次のような値は、empty()で空と判定されます。

null
false
0
0.0
'0'
''
[]

例を見てみます。

$data = [
    'count'  => 0,
    'active' => false,
    'code'   => '0',
    'memo'   => '',
    'items'  => [],
];

var_dump(empty($data['count']));  // true
var_dump(empty($data['active'])); // true
var_dump(empty($data['code']));   // true
var_dump(empty($data['memo']));   // true
var_dump(empty($data['items']));  // true

キーの存在確認には向かない

例えば、countキーが存在して値が0でも、empty()では空と判定されます。

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

if (!empty($data['count'])) {
    echo 'countキーがあります';
}

この処理は実行されません。

キーの存在を確認したい場合は、次のようにします。

if (array_key_exists('count', $data)) {
    echo 'countキーがあります';
}

empty()は、次の状態を区別できません。

  • キーが存在しない
  • 値がnull
  • 値がfalse
  • 値が0
  • 値が'0'
  • 値が空文字列
  • 値が空配列

そのため、配列の構造確認には向いていません。

in_array()との違い

in_array()は、配列のキーではなく値を検索する関数です。

$roles = [
    'admin',
    'editor',
    'viewer',
];

if (in_array('admin', $roles, true)) {
    echo 'adminが含まれています';
}

連想配列に対して使った場合も、検索対象は値です。

$user = [
    'name' => '鈴木',
    'age'  => 25,
];

var_dump(in_array('鈴木', $user, true)); // true
var_dump(in_array('name', $user, true)); // false

nameキーが存在するか確認したい場合は、array_key_exists()を使用します。

var_dump(array_key_exists('name', $user)); // true

違いを整理すると、次のとおりです。

array_key_exists('name', $user); // キーを検索
in_array('鈴木', $user, true);   // 値を検索

in_array()では、型も厳密に比較したい場合、第三引数にtrueを指定するのが安全です。

key_exists()という別名もある

PHPには、array_key_exists()の別名としてkey_exists()も用意されています。

if (key_exists('name', $user)) {
    echo 'nameキーが存在します';
}

動作はarray_key_exists()と同じです。

ただし、配列のキーを確認していることが分かりやすいため、一般的にはarray_key_exists()を使う方が読みやすいでしょう。

array_key_exists('name', $user);

数値キーの存在も確認できる

array_key_exists()は、文字列キーだけでなく整数キーにも使用できます。

$data = [
    0 => 'PHP',
    1 => 'JavaScript',
];

var_dump(array_key_exists(0, $data)); // true
var_dump(array_key_exists(2, $data)); // false

通常の添字配列でも利用できます。

$items = ['apple', 'orange'];

if (array_key_exists(1, $items)) {
    echo $items[1];
}

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

orange

APIレスポンスでの実用例

APIレスポンスでは、フィールドが存在しない状態と、明示的にnullが返されている状態を区別したいことがあります。

$response = [
    'status' => 'success',
    'data'   => null,
];

dataキーが含まれているか確認する

if (array_key_exists('data', $response)) {
    echo 'APIレスポンスにdataフィールドがあります';
}

値がnullでも、キーが存在するため条件は成立します。

datanull以外の値があるか確認する

if (isset($response['data'])) {
    echo 'dataにnull以外の値があります';
}

この場合、dataの値がnullなので条件は成立しません。

3つの状態を区別する

次のように記述すると、フィールドの状態を正確に判定できます。

if (!array_key_exists('data', $response)) {
    echo 'dataフィールドが返されていません';
} elseif ($response['data'] === null) {
    echo 'dataフィールドはありますが、値はnullです';
} else {
    echo 'dataに値があります';
}

これにより、次の状態を区別できます。

  • フィールド自体が存在しない
  • フィールドは存在するが値がnull
  • フィールドが存在し、値も設定されている

フォームデータでの実用例

フォームデータでも、キーの存在確認が必要になります。

$name = trim((string) ($_POST['name'] ?? ''));

if ($name === '') {
    echo '名前を入力してください';
}

チェックボックスの注意点

HTMLのチェックボックスは、チェックされていない場合、通常はキーそのものが送信されません。

<input type="checkbox" name="newsletter" value="1">

チェックされた場合は、次のようなデータになります。

$_POST = [
    'newsletter' => '1',
];

チェックされていない場合は、通常、次のようになります。

$_POST = [];

そのため、チェックされているかだけを確認するなら、次のように書けます。

$newsletter = isset($_POST['newsletter']);

送信値まで厳密に確認する場合は、次のようにします。

$newsletter = ($_POST['newsletter'] ?? null) === '1';

値がfalse0の場合の注意

次のような設定配列を考えます。

$config = [
    'cache'       => false,
    'retry_count' => 0,
];

この場合、isset()はどちらもtrueを返します。

var_dump(isset($config['cache']));       // true
var_dump(isset($config['retry_count'])); // true

false0nullではないためです。

一方、値をそのまま条件式に入れるとfalseになります。

if ($config['cache']) {
    echo 'キャッシュ有効';
}

これはキーが存在しないのではなく、値がfalseだからです。

3つの確認は意味が異なる

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

isset($config['cache']);
// キーが存在し、値がnullではないか

if ($config['cache']) {
}
// 値が真として評価されるか

真偽値を厳密に確認する場合は、===を使います。

if (
    array_key_exists('cache', $config)
    && $config['cache'] === true
) {
    echo 'キャッシュ有効';
}

キーが存在しない状態とfalseを同じ扱いにしてよい場合は、次のようにも書けます。

if (($config['cache'] ?? false) === true) {
    echo 'キャッシュ有効';
}

複数のキーをまとめて確認する

複数のキーがすべて存在するか確認したい場合は、関数化できます。

すべてのキーが存在するか確認する

function hasAllKeys(array $array, array $keys): bool
{
    foreach ($keys as $key) {
        if (!array_key_exists($key, $array)) {
            return false;
        }
    }

    return true;
}

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

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

var_dump(hasAllKeys($user, ['name', 'email']));
// true

emailの値はnullですが、キー自体は存在するためtrueです。

すべてのキーが存在し、値がnullではないか確認する

確認対象のキーが固定されている場合、isset()には複数の引数を渡せます。

if (isset($user['name'], $user['email'])) {
    echo '両方のキーが存在し、値はnullではありません';
}

ただし、どちらか一方でも値がnullならfalseになります。

動的なキー一覧を確認する場合は、関数化すると便利です。

function allKeysAreSet(array $array, array $keys): bool
{
    foreach ($keys as $key) {
        if (!isset($array[$key])) {
            return false;
        }
    }

    return true;
}

一つでもキーが存在するか確認する

function hasAnyKey(array $array, array $keys): bool
{
    foreach ($keys as $key) {
        if (array_key_exists($key, $array)) {
            return true;
        }
    }

    return false;
}

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

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

var_dump(hasAnyKey($data, ['email', 'phone']));
// true

array_keys()を使う方法

array_keys()を使うと、配列のキー一覧を取得できます。

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

$keys = array_keys($user);

var_dump($keys);

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

[
    'name',
    'email',
]

キー一覧に特定の値が含まれているか確認することもできます。

if (in_array('email', array_keys($user), true)) {
    echo 'emailキーが存在します';
}

ただし、単一キーの存在確認だけなら冗長です。

// 冗長な書き方
in_array('email', array_keys($user), true);

// 直接的な書き方
array_key_exists('email', $user);

通常はarray_key_exists()を使用する方が、処理の意図が明確です。

オブジェクトのプロパティを確認する場合

array_key_exists()は配列用の関数です。

オブジェクトのプロパティを確認する場合は、property_exists()isset()を使います。

$user = new stdClass();
$user->name = null;

var_dump(property_exists($user, 'name')); // true
var_dump(isset($user->name));             // false

property_exists()は、値がnullでもプロパティが定義されていればtrueを返します。

一方、isset()は値がnullの場合にfalseを返します。

マジックプロパティには注意する

__get()__isset()を使って動的に値を提供しているクラスでは、property_exists()isset()の結果が異なる場合があります。

class User
{
    public function __isset(string $name): bool
    {
        return $name === 'name';
    }
}

$user = new User();

var_dump(isset($user->name));             // true
var_dump(property_exists($user, 'name')); // false

nameは実際に宣言されたプロパティではないため、property_exists()ではfalseになります。

フレームワークやORMのオブジェクトを扱う場合は、この違いにも注意が必要です。

よくある間違い

isset()だけでキーの存在を確認する

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

if (isset($data['result'])) {
    echo 'resultキーがあります';
}

この処理は実行されません。

キーそのものの存在を確認する場合は、array_key_exists()を使用します。

if (array_key_exists('result', $data)) {
    echo 'resultキーがあります';
}

empty()をキーの存在確認に使う

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

if (!empty($data['count'])) {
    echo 'countキーがあります';
}

0は空と判定されるため、この処理は実行されません。

if (array_key_exists('count', $data)) {
    echo 'countキーがあります';
}

配列要素を直接条件式に入れる

if ($data['active']) {
}

キーが存在しない場合は警告の原因になる可能性があります。

また、値がfalseの場合とキーが存在しない場合を混同しやすくなります。

if (isset($data['active']) && $data['active'] === true) {
}

キーの有無と値を明確に分けるなら、次のように書けます。

if (!array_key_exists('active', $data)) {
    echo '設定がありません';
} elseif ($data['active'] === true) {
    echo '有効です';
} else {
    echo '無効です';
}

まとめ

PHPで連想配列のキーを確認するときは、目的に応じて使い分けることが重要です。

キーそのものが存在するか確認する

array_key_exists('key', $array);

値がnullでも、キーが存在すればtrueになります。

キーが存在し、値がnullではないか確認する

isset($array['key']);

キーが存在しない場合だけでなく、値がnullの場合もfalseになります。

キーがない場合やnullの場合にデフォルト値を使う

$value = $array['key'] ?? 'デフォルト値';

PHPの基準で空ではないか確認する

!empty($array['key']);

ただし、0false'0'、空文字列、空配列なども空と判定されます。

最も重要な違いは、次のとおりです。

array_key_exists('key', $array);
// nullを含めて、キーそのものの存在を確認する

isset($array['key']);
// キーが存在し、値がnullではないことを確認する

以上、PHPの連想配列のキーの存在を確認する方法についてでした。

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

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