Timeline Taxi Out now: my sci-fi novel Timeline Taxi is published!

array_find in PHP 8.4

PHP 8.4 adds a handful of functions that have been missing for a while: array_find() and its variants. The purpose of array_find() is simple: pass it an array and a callback, and return the first element for which the callback returns true.

$numbers = [1, 2, 3, 4, 5, 6];

$firstMatch = array_find(
    array: $numbers, 
    callback: fn (int $number) => $number % 2 === 0
);

To start off with, I want to make a note on naming conventions: in Laravel, the function that returns the first element from an array that matches a callback is called Collection::first() instead of find. This might cause some confusion for people expecting array_find() to return all elements that match the callback's condition.

The decision for array_find() over array_first() isn't all that weird though: lots of languages implement a method to find the first matching element from an array, and those functions are always called find. Just to name two examples: JavaScript and Rust.

If you need a way to get multiple elements from the array based on a callback, then the array_filter() function is what you're looking for.

$numbers = [1, 2, 3, 4, 5, 6];

$allMatches = array_filter(
    array: $numbers, 
    callback: fn (int $number) => $number % 2 === 0
);

Another important thing to note is that array_find(), as well as the three other functions (we'll look at those later in this post), they accept both the value and key as arguments in the callback function:

$firstMatch = array_find(
    array: $array, 
    callback: fn (mixed $value, int|string $key) => /* … */
);

By the way, you can read with me through the RFC to learn about all the details:

# array_find_key

Besides array_find(), there's now also a function called array_find_key(). It does exactly the same, but returns the key instead of the value of the matched element:

$numbers = [1, 2, 3, 4, 5, 6];

$firstMatchedKey = array_find_key(
    array: $numbers, 
    callback: fn (int $number) => $number % 2 === 0
);

# array_any and array_all

Finally, there are two related functions added, these two will return a boolean instead of a value. array_any() will return true if at least one element within the array matches a callback's condition, while array_all() will return true, only if all elements match the callback's condition:

$numbers = [1, 2, 3, 4, 5, 6];

// True: at least one element is dividable by 2
array_any(
    array: $numbers,
    callback: fn (int $number) => $number % 2 === 0
);

// False: not all elements are dividable by 2
array_all(
    array: $numbers,
    callback: fn (int $number) => $number % 2 === 0
);

// True: all elements are smaller than 10
array_all(
    array: $numbers,
    callback: fn (int $number) => $number < 10
);