Lesson 48 of 100
Arrays15 min5 checksPHP 8.5

Search Arrays with Strict Membership

Learn how in_array and array_search behave with loose and strict comparison, and how to keep a valid key of 0 from being mistaken for a miss.

01 · THE IDEAREAD → TRY → LEARN

Two questions about an array

Searching an array usually means one of two things:

  1. Is this value in the array? Use in_array(), which returns a bool.
  2. Where is this value? Use array_search(), which returns the first matching key, or false when 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.

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

Example
<?php
$colors = ["red", "green"];
$key = array_search("red", $colors, true);
echo json_encode(["key" => $key, "falsy" => !$key, "found" => $key !== false]);
echo "\n";
Output
{"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.

Example
<?php
$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";
Output
[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 true as the third argument unless loose matching is truly what you want.
  • array_search() returns a key or false; always test it with !== or ===.
  • Never use truthiness on an array_search() result, since key 0 is falsy.
  • Wrap the search when you want a clearer "missing" value such as null.
Before you start

Functions · Arrays · Types

You’ll practice
  • Use strict in_array and array_search without losing key zero
  • Implement and test a deterministic PHP 8.4 function
Your task

Make find_key() pass all 5 checks. Run your code as often as you like, then check your answer.

exercise.phpSaved in this browserPHP 8.5
CONSOLE & CHECKS● Ready

Ready when you are

Your output will appear here.
Make it work. Then make it pass.

PHP loads on your first run. Each check starts fresh. Your code stays in this browser; clearing site data removes your progress. A check or the task looks wrong? Report a problem with this exercise.