Signature
in_array(mixed $needle, array $haystack, bool $strict = false): boolPurpose
in_array() answers one question: does this value appear among the values of an array? It returns a plain boolean, so it fits naturally in conditions such as allowlist checks, input validation and simple membership tests. It looks at array values, never at keys.
Signature
Parameters and defaults
$needleis the value you are searching for. It can be any type. When it is a string, the comparison is case-sensitive, so'Editor'does not match'editor'.$haystackis the array to search.$strictdefaults tofalse. With the default, PHP uses loose comparison (like==). When you passtrue, PHP compares with identity (like===), so the type must match as well as the value.
Return value and failure cases
The function returns true when a matching value is found and false otherwise. It never returns a position; use array_search() if you need the key of the match. Because $haystack is declared as array, passing something else, such as null or a string, throws a TypeError rather than quietly returning false.
Example 1: a simple allowlist
The most common use is checking a value against a short list of permitted values.
$roles = ['admin', 'editor', 'viewer'];
echo json_encode([
in_array('editor', $roles),
in_array('Editor', $roles),
in_array('guest', $roles),
]);
echo "\n";[true,false,false]
The second lookup is false because string comparison is case-sensitive. If you want case-insensitive matching, normalize both sides first, for example by lowercasing the needle and the list.
Example 2: loose versus strict
Data from forms, query strings and CSV files usually arrives as strings, while your list may hold integers. The $strict flag decides whether that difference matters.
$ids = [1, 2, 3];
echo json_encode([
in_array('2', $ids),
in_array('2', $ids, true),
in_array(2, $ids, true),
]);
echo "\n";[true,false,true]
The loose search treats the string '2' as equal to the integer 2. The strict search does not, because the types differ. Strict mode is the safer default whenever you know what types should be in the list.
Example 3: edge cases of loose comparison
Loose mode can match values of different types in ways that look odd at first glance.
echo json_encode([
'loose_true_vs_string' => in_array(true, ['hello']),
'strict_true_vs_string' => in_array(true, ['hello'], true),
'loose_false_vs_zero_string' => in_array(false, ['0']),
'text_vs_zero' => in_array('abc', [0]),
'array_needle' => in_array(['p', 'h'], [['p', 'h'], 'o']),
]);
echo "\n";{"loose_true_vs_string":true,"strict_true_vs_string":false,"loose_false_vs_zero_string":true,"text_vs_zero":false,"array_needle":true}
In loose mode true matches any truthy string, and false matches both "" and "0". Since PHP 8.0 a non-numeric string such as 'abc' no longer matches the integer 0: the number is converted to a string and the two strings are compared. The last check shows that an array can be a needle; arrays are compared as whole values, and an element matches only if the arrays compare as equal.
Edge cases to remember
- An empty haystack always gives
false. - Searching for
nullin loose mode can match values such as0,""orfalse, because they compare as equal tonull. Use strict mode if you really meannull. - Numeric strings can match each other loosely even when they are written differently, so values that look like numbers are compared as numbers in loose mode.
- Nested arrays are not searched recursively. The function only compares each top-level element with the needle.
- The search is a linear scan. That is fine for short lists, but for many repeated lookups it is better to build an array whose keys are the values you want to test, then check it with
isset()orarray_key_exists().
Common mistakes
- Leaving out
$strict. The default loose comparison can produce matches you did not intend, especially withtrue,false,nulland numeric strings. Unless every type involved is certain, passtrue. - Expecting a key.
in_array()only says yes or no. Usearray_search()to learn where the match is, and remember that a key of0is falsy. - Searching keys by accident. To test whether a key exists, use
array_key_exists()orisset(), notin_array(). - Ignoring case.
'Mac'and'mac'are different strings. - Passing a non-array. A
nullhaystack, for instance from a missing setting, causes aTypeError. Make sure you really have an array first.
Related functions
array_search()returns the first matching key instead of a boolean.array_key_exists()checks whether a key exists.isset()tests whether a variable or element is set and notnull, and is fast for key lookups.
Recap
Use in_array() to test whether a value appears in an array. It is case-sensitive for strings, loose by default and identity-based when $strict is true. It returns only a boolean, throws a TypeError for a non-array haystack, and scans the list linearly. Prefer strict mode in most code, and switch to key lookups when performance with large lists matters.
Tested examples
$roles = ['admin', 'editor', 'viewer'];
echo json_encode([
in_array('editor', $roles),
in_array('Editor', $roles),
in_array('guest', $roles),
]);
echo "\n";
[true,false,false]
$ids = [1, 2, 3];
echo json_encode([
in_array('2', $ids),
in_array('2', $ids, true),
in_array(2, $ids, true),
]);
echo "\n";
[true,false,true]
echo json_encode([
'loose_true_vs_string' => in_array(true, ['hello']),
'strict_true_vs_string' => in_array(true, ['hello'], true),
'loose_false_vs_zero_string' => in_array(false, ['0']),
'text_vs_zero' => in_array('abc', [0]),
'array_needle' => in_array(['p', 'h'], [['p', 'h'], 'o']),
]);
echo "\n";
{"loose_true_vs_string":true,"strict_true_vs_string":false,"loose_false_vs_zero_string":true,"text_vs_zero":false,"array_needle":true}