In PHP 8, why should in_array() and array_search() usually be called with the strict flag, and how do you test array_search()'s result?
answer
- third parameter $strict defaults to false
- loose == juggling on every element
- null matches 0, '' and false
- array_search can return key 0
- compare the result with === false
basics
~20 sWithout strict true, in_array() and array_search() compare with ==, so null matches 0 and '', and '1e1' matches '10'. array_search() returns the key or false, and key 0 is falsy, so test its result with === false.
solid answer
~40 s`in_array(mixed $needle, array $haystack, bool $strict = false)` and `array_search()` compare the needle to each element with **loose** `==` unless the third argument is `true`. Loose comparison still juggles types in PHP 8: `null` equals `0`, `''`, `false` and `[]`; two numeric strings compare as numbers, so `'1e1'` matches `'10'`; a non-empty string equals `true`. PHP 8.0 did remove the worst case, a non-numeric string matching `0`, which is why `in_array('abc', [0])` is now `false`. With `$strict = true` both type and value must match, which is almost always the intent for IDs, codes and status values. `array_search()` returns the **key** of the first match or `false`, and since the key can be `0` or `''`, both falsy, its result must be checked with `=== false`, never with `!`.
code
php · 15 lines<?php
$statuses = ['paid', 'packed', 'out'];
var_dump(in_array(true, $statuses)); // bool(true): 'paid' == true
var_dump(in_array(true, $statuses, true)); // bool(false)
$menu = ['croissant', 'baguette'];
$key = array_search('croissant', $menu, true);
if ($key === false) {
echo "not on the menu\n";
} else {
echo "found at key $key\n"; // found at key 0
}
var_dump(in_array(null, [0])); // bool(true)
var_dump(in_array(0, ['abc'])); // bool(false) since PHP 8.0go deeper
Recall that in_array() and array_search() are loose unless the third argument is true, and that array_search() returns a key or false.
Explain which loose matches survive PHP 8 (null, numeric strings, true) and why array_search() needs an === false check because keys can be 0.
Enforce strict searches for IDs, statuses and allow-lists in review, normalise mixed int and string data, and replace repeated scans with keyed lookups.
Decide how the codebase handles type consistency at data boundaries so searches can be strict everywhere without surprising mismatches.
## Two search helpers, one flag PHP's value-search helpers share a signature: - `in_array(mixed $needle, array $haystack, bool $strict = false): bool` answers *is this value present?* - `array_search(mixed $needle, array $haystack, bool $strict = false): int|string|false` answers *under which key is it?* and returns the first matching key, or `false`. `array_keys($array, $filter_value, $strict)` also has the same flag when you want every matching key. In all three, `$strict = false` means each element is compared with `==`, and `$strict = true` means `===`. ## What loose comparison still matches in PHP 8 PHP 8.0 changed how a number compares with a non-numeric string, so `0 == 'abc'` is now `false`. Many other conversions remain, and each one becomes a false positive inside a loose search: | Call | Result | Why | |---|---|---| | `in_array(null, [0])` | `true` | `null` and `0` both convert to `false` | | `in_array(null, [''])` | `true` | `null` compares equal to the empty string | | `in_array('1e1', ['10'])` | `true` | both are numeric strings, compared as numbers | | `in_array('abc', [true])` | `true` | a non-empty string converts to `true` | | `in_array(0, ['abc'])` | `false` | since 8.0; it was `true` in PHP 7 | | `in_array('7', [7])` | `true` | numeric string equals the int | The last row is often the reason code uses loose search on purpose: IDs read from a form arrive as strings while IDs from a database driver may be integers. That is better solved by normalising types first than by relying on juggling. ## Strict mode With `true` as the third argument, an element matches only if it has the same type and value as the needle: - `in_array('7', [7], true)` is `false`. - `in_array(null, [0, '', false], true)` is `false`. - Objects match only when they are the same instance. In a bakery-delivery app, checking an order status against `['paid', 'packed', 'out']` or an allow-list of delivery slot codes should use strict mode, so that a `null` or `true` coming from an unexpected code path cannot slip through. ## The array_search() return trap `array_search()` returns a key, and keys can be `0` or `''`. Both are falsy, so this common pattern is wrong: ```php if (!array_search('croissant', $menu)) { // runs when croissant is NOT found, and ALSO when it is at key 0 } ``` The correct test compares identically with `false`: 1. `$key = array_search('croissant', $menu, true);` 2. `if ($key === false) { /* not found */ }` 3. Otherwise `$key` is a valid key, even if it is `0`. The same care applies when passing the result on: `$menu[$key]` with `$key === false` reads key `0` because `false` is converted to `0`. ## Performance note Both functions scan the array from the start, comparing element by element, so a search is linear in the array's size. When the same haystack is searched many times, for example checking thousands of order lines against a list of discontinued products, build a lookup array keyed by the value once (`array_flip()` does this for string and int values) and test keys with `array_key_exists()`. That trades one pass of preparation for direct key lookups afterwards; note that key lookup is always exact by the converted key, not loose. ## Takeaways - Pass `true` as the third argument unless you deliberately want type juggling. - Compare `array_search()` results with `=== false`. - Normalise mixed int/string data before searching rather than relying on `==`. - For repeated membership tests, index the values as keys.
- How would you speed up checking thousands of order lines against a list of discontinued product codes?Build a lookup once with `array_flip($discontinued)`, so the codes become keys, then test each line with `array_key_exists($code, $lookup)`. That replaces a linear `in_array()` scan per line with a key lookup. Watch key casting: numeric-string codes become integer keys, which is fine for lookups but not when reading keys back.
- What happens if code uses array_search()'s result as a key without checking for false?`false` used as an array key is converted to `0`, so `$menu[$key]` silently reads the element at key 0 when nothing was found. Always test `$key === false` first.
saying these in an interview costs you the question
- in_array() compares strictly by default.
- Since PHP 8, loose comparison is safe, so strict mode is unnecessary.
- if (!array_search(...)) correctly detects a missing value.
- in_array(null, [0]) is false because null is not a number.
- array_search() returns the value it found, or null if absent.