array_key_exists('key', $array) devuelve true si el array tiene esa clave y false si no. Fíjate en el orden: primero la clave, después el array. Devuelve true incluso cuando el valor guardado bajo la clave es null, que es justo lo que isset() no hace.
Para comprobar un valor en lugar de una clave, usa in_array().
array_key_exists vs isset
Las dos comprueban una clave. Solo discrepan cuando el valor es null: isset() trata un valor null como "no definido", y array_key_exists() informa de lo que hay realmente en el array.
0 y '' cuentan como definidos para las dos; solo null las separa. Cuál quieres depende de lo que signifique null en tus datos:
- Usa
isset()cuandonullsignifica "sin valor". Es el caso habitual, es una construcción del lenguaje (algo más rápida) y acepta rutas anidadas y variables no definidas sin ningún warning. - Usa
array_key_exists()cuandonulles un valor real que debes distinguir de una clave ausente: un campo JSON enviado comonull, una columna de base de datos que esNULL, una opción puesta anulla propósito para borrarla.
La página de isset explica sus otros usos, como comprobar varias variables a la vez.
Distinguir null de ausente en un payload JSON
Un caso típico en el que solo array_key_exists() da la respuesta correcta: una API que actualiza un registro a partir de JSON. Un campo enviado como null significa "bórralo", y un campo omitido significa "no lo toques". isset() ve los dos casos igual.
Con isset($patch[$field]) el número de teléfono se quedaría, porque el null parecería un campo ausente.
key_exists() es la misma función
key_exists() es un alias de array_key_exists(), que se conserva desde las primeras versiones de PHP. Mismos argumentos, mismo resultado. Prefiere el nombre completo, que es lo que esperan ver quienes leen el código.
Tipos de clave: "1" y 1 son la misma clave
Las claves de un array son enteros o cadenas, y una cadena que es un entero decimal simple se guarda como entero. Así, array_key_exists('1', $arr) encuentra la clave 1, y al revés. Una cadena como '01' se queda como cadena y es una clave distinta.
Comprobar claves anidadas y varias claves
array_key_exists() mira un solo nivel. Para una ruta anidada en la que null no importa, isset($a['x']['y']) comprueba todos los niveles de una vez. Para una ruta en la que sí importa, una pequeña función auxiliar recorre los niveles. Para comprobar que están presentes varias claves, compara con array_diff_key().
array_flip($required) convierte la lista de nombres en claves para que array_diff_key() pueda compararlas con las claves de la entrada; lo que queda es la lista de campos que faltan, lista para un mensaje de error.
Los objetos necesitan property_exists
Las versiones antiguas de PHP aceptaban un objeto en array_key_exists(). PHP 8 lanza un TypeError en su lugar. Para objetos, property_exists() comprueba una propiedad declarada o dinámica (aunque valga null), e isset($obj->prop) funciona como isset() con arrays.
Las dos últimas líneas muestran la otra vía: get_object_vars() convierte las propiedades accesibles del objeto en un array, y entonces se aplican las funciones de arrays.
Preguntas frecuentes
¿Por qué isset devuelve false cuando array_key_exists devuelve true?
La clave contiene null. isset($arr['k']) solo es true si la clave existe y su valor no es null, mientras que array_key_exists('k', $arr) es true siempre que la clave esté en el array. Con cualquier otro valor, incluidos 0, '' y false, las dos dan la misma respuesta.
¿Qué es key_exists en PHP?
Un alias de array_key_exists(). key_exists('id', $row) y array_key_exists('id', $row) se comportan igual. La mayoría del código usa el nombre largo.
¿Cómo compruebo si existe una clave anidada en PHP?
Comprueba cada nivel: isset($data['user']['address']['city']) comprueba toda la ruta de una vez y nunca avisa cuando falta un nivel. Si los valores null tienen que contar como presentes, recorre la ruta con array_key_exists() nivel a nivel.
¿Puedo usar array_key_exists con un objeto?
No. Desde PHP 8.0, pasar un objeto lanza un TypeError. Usa property_exists($obj, 'name') para las propiedades declaradas, o isset($obj->name).