in_array($needle, $haystack) devuelve true si el valor está en algún lugar del array y false si no. Pasa true como tercer argumento, in_array($needle, $haystack, true), para exigir también el mismo tipo; esa forma estricta es la que deberías usar por defecto.
in_array() solo mira los valores. Para comprobar si existe una clave, usa array_key_exists() o isset().
El parámetro strict
Sin el tercer argumento, in_array() compara con ==, que convierte los tipos antes de comparar. Con true, compara con ===: tienen que coincidir el valor y el tipo. La diferencia aparece en cuanto el array mezcla números y cadenas, algo habitual con datos de formularios, URLs y archivos CSV.
Cada celda de abajo es lo que devuelven == y === para esa pareja de valores en PHP 8.3. in_array() responde true si la aguja y cualquier elemento dan true en la tabla del modo que uses. Cambia entre las pestañas y mira las filas de null, true y las cadenas numéricas.
| $a == $b | true | false | null | 0 | 1 | "0" | "1" | "" | "abc" | "10" | "1e1" | 10 | [] |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| true | |||||||||||||
| false | |||||||||||||
| null | |||||||||||||
| 0 | |||||||||||||
| 1 | |||||||||||||
| "0" | |||||||||||||
| "1" | |||||||||||||
| "" | |||||||||||||
| "abc" | |||||||||||||
| "10" | |||||||||||||
| "1e1" | |||||||||||||
| 10 | |||||||||||||
| [] |
Una regla cambió en PHP 8: una cadena no numérica ya no es igual a 0, así que in_array('abc', [0]) hoy es false pero en PHP 7 era true. El código escrito para PHP 7 a veces dependía de eso, y es un motivo más para pasar true y no depender de las reglas de conversión. La página de operadores de comparación las explica por completo.
in_array sin distinguir mayúsculas y minúsculas
in_array() compara las cadenas exactamente, así que 'PHP' y 'php' son distintas. Pasa a minúsculas la aguja y el array antes de comprobar. mb_strtolower() también maneja letras con tilde y no latinas.
Comprobar varios valores a la vez
in_array() acepta una sola aguja. Para varias, compara los arrays como conjuntos: array_diff() devuelve las agujas que faltan, así que un resultado vacío significa que están todas, y array_intersect() devuelve las agujas que se encontraron.
array_diff() y array_intersect() comparan los valores como cadenas, así que ahí 1 y '1' cuentan como iguales.
in_array en un array multidimensional
in_array() no busca dentro de arrays anidados. Para comprobar si alguna fila tiene un campo con un valor dado, extrae antes ese campo con array_column() y luego busca en la lista plana.
La última línea muestra que la aguja puede ser también un array: coincide con una fila idéntica, con las mismas claves, valores y orden.
in_array vs array_search vs isset
Las tres responden "¿está ahí?", pero devuelven cosas distintas y tienen velocidades distintas:
| Llamada | Devuelve | Velocidad con un array grande |
|---|---|---|
in_array($v, $arr, true) | true o false | recorre todos los elementos |
array_search($v, $arr, true) | la clave, o false | recorre todos los elementos |
isset($set[$v]) | true o false | una búsqueda en tabla hash |
Usa array_search() cuando necesites saber dónde está el valor. Cuando compruebes muchos valores contra la misma lista grande, invierte la lista una vez para que sus valores se conviertan en claves, y usa isset().
Los tiempos cambian de una ejecución a otra, pero la diferencia no: la búsqueda con isset() se mantiene constante mientras que in_array() crece con el tamaño de la lista. array_flip() solo funciona con valores de tipo cadena y entero, y los duplicados se reducen a una clave, lo que no importa para comprobar si un valor pertenece a la lista.
Preguntas frecuentes
¿Qué hace el tercer parámetro de in_array?
Activa la comparación estricta. in_array($x, $arr, true) compara con ===, así que tiene que coincidir el tipo además del valor: in_array('1', [1, 2], true) es false. Sin él, PHP compara con == y convierte antes los tipos.
¿Debo usar siempre el modo estricto con in_array?
Normalmente sí. El modo flexible hace que in_array(null, [0]), in_array(true, ['any string']) e in_array('1e1', ['10']) devuelvan true. Desactívalo solo cuando quieras a propósito que un '5' de un formulario coincida con el entero 5.
¿Cómo hago que in_array no distinga mayúsculas y minúsculas?
Pasa los dos lados a minúsculas: in_array(strtolower($needle), array_map('strtolower', $haystack), true). Usa mb_strtolower cuando el texto pueda contener letras no ASCII.
¿Cómo compruebo si varios valores están en un array?
Para exigir todos, comprueba que no sobra ninguno: !array_diff($needles, $haystack). Para exigir al menos uno, comprueba que hay intersección: (bool) array_intersect($needles, $haystack).
¿Es lento in_array?
Recorre el array elemento a elemento, así que es lento con arrays grandes que se comprueban muchas veces. Invierte el array una vez con $set = array_flip($haystack); y usa isset($set[$value]), que es una sola búsqueda en una tabla hash.