01 · THE IDEAREAD → TRY → LEARN
Two questions about an array
Searching an array usually means one of two things:
- Is this value in the array? Use
in_array(), which returns a bool. - Where is this value? Use
array_search(), which returns the first matching key, orfalsewhen nothing matches.
The signature of the first is in_array(mixed $needle, array $haystack, bool $strict = false): bool. The third parameter decides how values are compared, and its default is the risky choice.
Loose versus strict comparison
Without strict, PHP compares with loose equality (==). Values of different types can then count as equal. The manual notes, for example, that true matches any truthy string and false matches both "" and "0". Unless you know the types of every value involved, pass true as the third argument. Strict mode checks the type as well as the value, like ===.
The first example shows the difference on a list of numeric strings.
$values = ["1", "2", "3"];
echo json_encode([in_array(1, $values), in_array(1, $values, true)]);
echo "\n";[true,false]
The integer 1 loosely equals the string "1", so the first call finds it. The strict call does not, because an int is not a string. String needles are always compared case-sensitively, with or without strict.
The key-zero trap
array_search() returns the key, and the first element of a list has key 0. In a boolean test, 0 is falsy, which is exactly the same as the false that means "not found". Code like if (array_search($x, $list, true)) therefore treats a match at the very first position as a failure.
The fix is to compare the result with false using !==:
$colors = ["red", "green"];
$key = array_search("red", $colors, true);
echo json_encode(["key" => $key, "falsy" => !$key, "found" => $key !== false]);
echo "\n";{"key":0,"falsy":true,"found":true}
The key is 0, !$key is true, and yet the value was found. Only the identity check $key !== false answers the question correctly. The same applies to the shortcut ?:: writing array_search(...) ?: null would turn key 0 into null.
Falsy-looking values under strict mode
Strict mode also makes it safe to look for values such as 0, "0", false, "" and null, which loose comparison blurs together.
$items = [0, "0", false, ""];
echo json_encode([
array_search(false, $items, true),
array_search("", $items, true),
array_search("0", $items, true),
array_search(null, $items, true),
]);
echo "\n";[2,3,1,false]
Each lookup lands on its own position, and null is absent, so that call returns false. The keys are 2, 3, 1 and then false.
Worked design: a null-for-missing wrapper
Because false is awkward as a "not found" marker, a small wrapper can translate the result. Call array_search($needle, $items, true), store the result, and return null when it is identical to false. Otherwise return the key unchanged. That way the caller can use === null to detect a miss, and 0 stays a valid answer. The wrapper also works with string keys, because array_search() returns whatever key holds the first match.
Edge cases
- An empty haystack never matches, so the wrapper returns
null. - If a value appears several times, only the first key is returned.
- Arrays used as needles are compared as whole arrays.
- In strict mode, objects match only when they are the same instance.
Exercise contract
Write find_key(array $items, mixed $needle): int|string|null. It must return the key of the first element strictly identical to $needle, or null if there is none. The tests check that key 0 is returned as 0, that 10 does not match "10", that false is found at its own position among 0 and "0", and that an empty array gives null.
Recap
- Pass
trueas the third argument unless loose matching is truly what you want. array_search()returns a key orfalse; always test it with!==or===.- Never use truthiness on an
array_search()result, since key0is falsy. - Wrap the search when you want a clearer "missing" value such as
null.
Functions · Arrays · Types
- Use strict in_array and array_search without losing key zero
- Implement and test a deterministic PHP 8.4 function