key_exists
Checks whether a key exists in an array, even when its value is null; an alias of array_key_exists().
key_exists(string|int|float|bool|resource|null $key, array $array): bool- Added in PHP 4.0.6
Parameters
| Parameter | Type | Description |
|---|---|---|
$key | string|int|float|bool|resource|null | The key to look for. Any value usable as an array index; floats and bools are cast to int, and null is cast to an empty string. |
$array | array | The array whose keys are checked. Only the first dimension is searched. |
Return value
boolReturns true if the key is present in the array, false otherwise — true even when the key's value is null.
Errors
Throws a TypeError if array is not an array — objects have not been accepted since PHP 8.0.
Changelog
- PHP 8.5.0Passing null as the key is deprecated; pass an empty string instead.
- PHP 8.0.0The key parameter formally accepts bool, float, int, null, resource and string.
- PHP 8.0.0Passing an object as array is no longer supported; use property_exists() instead.
- PHP 7.4.0Passing an object as array was deprecated.
key_exists() is an alias of array_key_exists(). It answers one question: does this array have this key, whatever the value happens to be?
That last clause is the whole point. isset($arr['k']) returns false when the key is present but holds null, so isset() cannot tell "absent" from "explicitly null". key_exists() can. Reach for it whenever null is meaningful: a nullable database column, a JSON body where "middle_name": null means "we asked and there is none", or a settings array where a null override must beat a default.
The lookup is shallow — first dimension only. For $a['user']['id'] you need two checks, or the null-safe ?? operator if a null value would be acceptable anyway.
Which name to use
Write array_key_exists() in new code. The short alias predates the array_* naming convention and reads inconsistently next to array_key_first() and array_keys(). Behaviour is identical.
Two version notes matter: since PHP 8.0 the second argument must really be an array, since objects were deprecated in 7.4 and are now rejected — use property_exists() for those. And since PHP 8.5, passing null as the key is deprecated; pass '' instead.
Example
When to use it
- Distinguish an absent JSON field from one explicitly set to null when validating a request body.
- Check whether a config array supplies an option before falling back to a default.
- Guard a cache lookup where null is itself a valid cached result.
- Verify a CSV header row contains a required column name.
Frequently asked questions
What is the difference between key_exists and array_key_exists?
None at all — key_exists() is a registered alias of array_key_exists() with identical behaviour and performance. Prefer array_key_exists() in new code for consistency with the other array_* functions.
What is the difference between key_exists and isset?
isset() returns false when the key exists but its value is null, whereas key_exists() returns true. isset() is a language construct and slightly faster, so use it unless null is a value you need to distinguish from absence.
Does key_exists work on multidimensional arrays?
It only searches the first dimension. To reach a nested key, check each level: key_exists('user', $a) && key_exists('id', $a['user']).
More examples
Validating a JSON payload
The 'middle' row shows key_exists=yes but isset=no — the client sent the field with an explicit null. The 'nickname' row is no/no because it was never sent. If you validate with isset() alone you cannot tell those two cases apart.
<?php
$payload = json_decode('{"name":"Ada","middle":null}', true);
foreach (['name', 'middle', 'nickname'] as $field) {
printf("%-9s key_exists=%-3s isset=%s\n",
$field,
key_exists($field, $payload) ? 'yes' : 'no',
isset($payload[$field]) ? 'yes' : 'no');
}Overrides where null is a real value
Prints "timeout => NULL" and "retries => 3". The caller deliberately disabled the timeout by setting it to null, and key_exists() honours that. Using $overrides[$k] ?? $default instead would have silently restored 30.
<?php
$defaults = ['timeout' => 30, 'retries' => 3];
$overrides = ['timeout' => null];
foreach ($defaults as $k => $default) {
$value = key_exists($k, $overrides) ? $overrides[$k] : $default;
echo $k, ' => ', var_export($value, true), "\n";
}The check is one level deep
The first call is false: 'id' lives in the nested array, not the top level. The third is true. The last line shows the other common mix-up — in_array() searches values, key_exists() searches keys.
<?php
$data = ['user' => ['id' => 1, 'email' => null]];
var_dump(key_exists('id', $data));
var_dump(key_exists('user', $data));
var_dump(key_exists('id', $data['user']));
var_dump(in_array(1, $data['user'], true));
Discussion