array_find() / array_find_key() (PHP 8.4)
debt(d7/e1/b1/t5)
Closest to 'only careful code review or runtime testing' (d7). The detection_hints.tools field is unspecified. The main misuse — expecting multiple results from array_find() or checking === false instead of === null — produces no error, just a silent logical bug returning null where the developer expects false or a collection. No standard linter rule targets this pattern; it requires code review or test-driven discovery. Slightly better than d9 because null-vs-false bugs do surface when the value is actually used downstream.
Closest to 'one-line patch or single-call swap' (e1). The quick_fix is explicit: replace a foreach-with-break pattern with a single array_find() call, or swap the null check from === false to === null. Both corrections are single-line or near-single-line changes with no cross-component impact.
Closest to 'minimal commitment' (b1). array_find() is a single utility call applied at the call site. It does not impose structural obligations on the rest of the codebase, carries no persistent architectural weight, and is easily swapped out for array_filter() or a foreach if needed. The applies_to scope (web, cli) is broad but the function itself is localised at call sites.
Closest to 'notable trap' (t5). The misconception is explicit: developers familiar with array_filter() expect array_find() to return all matches (an array), or expect false on no-match like reset(), but it returns only the first match or null. This is a documented gotcha that PHP developers coming from array_filter() usage will encounter, but it is a single well-defined surprise rather than a systemic contradiction.
Also Known As
TL;DR
Explanation
Finding the first matching element in an array was always awkward in PHP — either a foreach with a break, or array_filter() which returns all matches followed by reset() or current() to grab the first. PHP 8.4 adds four related functions: array_find() returns the first value where the callback returns true, array_find_key() returns its key, array_any() returns true if any element matches, and array_all() returns true if all elements match. These mirror JavaScript's Array.find(), Array.findIndex(), Array.some(), and Array.every(). All four short-circuit — they stop iterating as soon as the result is determined.
Common Misconception
Why It Matters
Common Mistakes
- Expecting array_find() to return false on no match like reset() — it returns null, so check with '=== null' not '=== false'.
- Using array_find() when you need all matches — use array_filter() for multiple results.
- Forgetting array_any() and array_all() exist — 'count(array_filter(...)) > 0' is a common pattern these replace cleanly.
- Using these functions in PHP < 8.4 — they are not available; polyfill with a helper function or upgrade.
Code Examples
<?php
// ❌ Verbose first-match patterns
$firstAdmin = null;
foreach ($users as $user) {
if ($user['role'] === 'admin') {
$firstAdmin = $user;
break;
}
}
// Or the filter+reset hack
$admins = array_filter($users, fn($u) => $u['role'] === 'admin');
$firstAdmin = reset($admins); // false if empty, not null
<?php
// ✅ PHP 8.4 — clean, intent-revealing
$firstAdmin = array_find($users, fn($u) => $u['role'] === 'admin');
// Returns null if not found (not false)
$adminKey = array_find_key($users, fn($u) => $u['role'] === 'admin');
$hasAdmin = array_any($users, fn($u) => $u['role'] === 'admin');
$allActive = array_all($users, fn($u) => $u['active'] === true);
// Null-safe chaining when element may not exist
$email = array_find($users, fn($u) => $u['id'] === 42)?->email;