Arrays7 min readExamples run on PHP 8.5.10

in_array()

Learn how PHP 8.4 in_array() searches array values, how loose and strict comparison differ, and which mistakes cause surprising matches.

Signature

in_array(mixed $needle, array $haystack, bool $strict = false): bool

Purpose

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

  • $needle is 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'.
  • $haystack is the array to search.
  • $strict defaults to false. With the default, PHP uses loose comparison (like ==). When you pass true, 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.

Example
<?php
$roles = ['admin', 'editor', 'viewer'];
echo json_encode([
    in_array('editor', $roles),
    in_array('Editor', $roles),
    in_array('guest', $roles),
]);
echo "\n";
Output
[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.

Example
<?php
$ids = [1, 2, 3];
echo json_encode([
    in_array('2', $ids),
    in_array('2', $ids, true),
    in_array(2, $ids, true),
]);
echo "\n";
Output
[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.

Example
<?php
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";
Output
{"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 null in loose mode can match values such as 0, "" or false, because they compare as equal to null. Use strict mode if you really mean null.
  • 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() or array_key_exists().

Common mistakes

  1. Leaving out $strict. The default loose comparison can produce matches you did not intend, especially with true, false, null and numeric strings. Unless every type involved is certain, pass true.
  2. Expecting a key. in_array() only says yes or no. Use array_search() to learn where the match is, and remember that a key of 0 is falsy.
  3. Searching keys by accident. To test whether a key exists, use array_key_exists() or isset(), not in_array().
  4. Ignoring case. 'Mac' and 'mac' are different strings.
  5. Passing a non-array. A null haystack, for instance from a missing setting, causes a TypeError. Make sure you really have an array first.
  • 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 not null, 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

Allowlist check with case-sensitive strings
<?php
$roles = ['admin', 'editor', 'viewer'];
echo json_encode([
    in_array('editor', $roles),
    in_array('Editor', $roles),
    in_array('guest', $roles),
]);
echo "\n";
Output
[true,false,false]
Loose versus strict comparison
<?php
$ids = [1, 2, 3];
echo json_encode([
    in_array('2', $ids),
    in_array('2', $ids, true),
    in_array(2, $ids, true),
]);
echo "\n";
Output
[true,false,true]
Edge cases of loose comparison
<?php
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";
Output
{"loose_true_vs_string":true,"strict_true_vs_string":false,"loose_false_vs_zero_string":true,"text_vs_zero":false,"array_needle":true}