array_key_exists('key', $array) returns true if the array has that key and false if it does not. Note the order: the key comes first, the array second. It returns true even when the value stored under the key is null, which is the one thing isset() does not do.
To check a value rather than a key, use in_array().
array_key_exists vs isset
Both check for a key. They disagree only when the value is null: isset() treats a null value as "not set", array_key_exists() reports what is actually in the array.
0 and '' count as set for both; only null splits them. Which one you want depends on what null means in your data:
- Use
isset()whennullmeans "no value". It is the common case, it is a language construct (slightly faster), and it accepts nested paths and undefined variables without a warning. - Use
array_key_exists()whennullis a real value you must tell apart from a missing key: a JSON field sent asnull, a database column that isNULL, an option explicitly set tonullto clear it.
The isset page covers its other uses, including checking several variables at once.
Tell null apart from missing in a JSON payload
A typical case where only array_key_exists() gives the right answer: an API that updates a record from JSON. A field sent as null means "clear it", a field left out means "do not touch it". isset() sees both as the same.
With isset($patch[$field]) the phone number would stay, because the null would look like a missing field.
key_exists() is the same function
key_exists() is an alias of array_key_exists(), kept from early PHP. Same arguments, same result. Prefer the full name, which is what readers expect to see.
Key types: "1" and 1 are the same key
Array keys are integers or strings, and a string that is a plain decimal integer is stored as an integer. So array_key_exists('1', $arr) finds the key 1, and the other way round. A string like '01' stays a string and is a different key.
Check nested keys and several keys
array_key_exists() looks at one level. For a nested path where null does not matter, isset($a['x']['y']) checks every level at once. For a path where it does, a short helper walks the levels. To check that several keys are all present, compare against array_diff_key().
array_flip($required) turns the list of names into keys so array_diff_key() can compare them with the input's keys; what is left over is the list of missing fields, ready for an error message.
Objects need property_exists
Older PHP accepted an object in array_key_exists(). PHP 8 throws a TypeError instead. For objects, property_exists() checks for a declared or dynamic property (even one set to null), and isset($obj->prop) works like isset() on arrays.
The last two lines show the other route: get_object_vars() turns the object's accessible properties into an array, and then the array functions apply.
Frequently Asked Questions
Why does isset return false when array_key_exists returns true?
The key holds null. isset($arr['k']) is true only if the key exists and its value is not null, while array_key_exists('k', $arr) is true whenever the key is in the array. For any other value, including 0, '' and false, both return the same answer.
What is key_exists in PHP?
An alias of array_key_exists(). key_exists('id', $row) and array_key_exists('id', $row) behave the same. Most code uses the longer name.
How do I check if a nested key exists in PHP?
Check each level: isset($data['user']['address']['city']) checks the whole path at once and never warns when a level is missing. If null values must count as present, walk the path with array_key_exists() level by level.
Can I use array_key_exists on an object?
No. Since PHP 8.0 passing an object throws a TypeError. Use property_exists($obj, 'name') for declared properties, or isset($obj->name).