# RFC: array_find

- Status: Implemented (PHP 8.4)
- Authors: Joshua Rüsweg, josh@php.net
- Date: 2024-04-07
- Version: 1.2.0
- Implementation: https://github.com/php/php-src/pull/14108
- Original: https://wiki.php.net/rfc/array_find
- Page: https://externals.io/rfc/array_find
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

## Votes

### Add array_find() and array_find_key()? (closed)

Yes: 21 · No: 0

Voters: alcaeus (Yes), ashnazg (Yes), beberlei (Yes), cpriest (Yes), crell (Yes), derick (Yes), galvao (Yes), jimw (Yes), josh (Yes), kguest (Yes), levim (Yes), mbeccati (Yes), mfonda (Yes), nicolasgrekas (Yes), nielsdos (Yes), petk (Yes), ramsey (Yes), seld (Yes), sergey (Yes), timwolla (Yes), weierophinney (Yes)

### Add array_any() and array_all()? (closed)

Yes: 20 · No: 0

Voters: alcaeus (Yes), ashnazg (Yes), cpriest (Yes), crell (Yes), derick (Yes), galvao (Yes), jimw (Yes), josh (Yes), kguest (Yes), levim (Yes), mbeccati (Yes), mfonda (Yes), nicolasgrekas (Yes), nielsdos (Yes), petk (Yes), ramsey (Yes), seld (Yes), sergey (Yes), timwolla (Yes), weierophinney (Yes)

## Discussions on the mailing list

- [RFC \[Discussion\]: array_find](https://externals.io/message/123015.md) — started on 2024-04-07, 27 messages
- [\[RFC\] \[VOTE\] array_find](https://externals.io/message/123321.md) — started on 2024-05-15, 2 messages
- [Fwd: Request for RFC Karma to Propose any_empty and all_empty Methods](https://externals.io/message/123437.md) — started on 2024-05-27, 1 messages
- [Fwd: Request for RFC Karma to Propose any_empty and all_empty Methods](https://externals.io/message/123512.md) — started on 2024-06-04, 1 messages
- [Fwd: Request for RFC Karma to Propose any_empty and all_empty Methods](https://externals.io/message/123587.md) — started on 2024-06-11, 1 messages

---

## Introduction

This RFC proposes the addition of new array functions: `array_find`, `array_find_key`, `array_any` and `array_all`, which are helper functions for common patterns of checking an array for the existence of elements matching a specific condition.

There are currently several functions processing arrays using a callback. However still missing are functions to find a single element matching a condition and the closely related functions of checking whether or not there are elements matching a condition. Implementing these functions in userland is relatively simple, but these functions are often required, leading to the wheel being reinvented over and over. Furthermore these type of functions are implemented in other programming languages like Rust, JavaScript or C++, too. Therefore there is a reason to include these functions as standard with the next PHP version. In addition, the implementation of these functions is quite similar to `array_filter` and relatively trivial to implement, so the maintenance effort should be low.

## Proposal

This RFC proposes to add four new function, `array_find`, `array_find_key`, `array_any` and `array_all`.

### array\_find

`array_find` returns the value of the first element for which the `$callback` returns `true`. If no matching element is found the function returns `NULL`.

```php
function array_find(array $array, callable $callback): mixed {
    foreach ($array as $key => $value) {
        if ($callback($value, $key)) {
            return $value;
        }
    }
 
    return null;
}
```

#### Parameters

`array $array`

The array that should be searched.

`callable $callback`

The callback function to call to check each element. The first parameter contains the value, the second parameter contains the corresponding key. If this function returns `true`, the value is returned from `array_find` and the callback will not be called for further elements.

#### Return Value

The function returns the value of the first element for which the `$callback` returns `true`. If no matching element is found the function returns `NULL`.

#### Examples

```php
$array = [
    'a' => 'dog',
    'b' => 'cat',
    'c' => 'cow',
    'd' => 'duck',
    'e' => 'goose',
    'f' => 'elephant'
];
 
// Find the first animal with a name longer than 4 characters.
var_dump(array_find($array, function (string $value) {
    return strlen($value) > 4;
})); // string(5) "goose"
 
// Find the first animal whose name begins with f.
var_dump(array_find($array, function (string $value) {
    return str_starts_with($value, 'f');
})); // NULL
 
// Find the first animal where the array key is the first symbol of the animal.
var_dump(array_find($array, function (string $value, $key) {
   return $value[0] === $key;
})); // string(3) "cow"
 
// Find the first animal where the array key matching a RegEx.
var_dump(array_find($array, function ($value, $key) {
   return preg_match('/^([a-f])$/', $key);
})); // string(3) "dog"
```

### array\_find\_key

`array_find_key` returns the key of the first element for which the `$callback` returns `true`. If no matching element is found the function returns `NULL`.

```php
function array_find_key(array $array, callable $callback): mixed {
    foreach ($array as $key => $value) {
        if ($callback($value, $key)) {
            return $key;
        }
    }
 
    return null;
}
```

#### Parameters

`array $array`

The array that should be searched.

`callable $callback`

The callback function to call to check each element. The first parameter contains the value, the second parameter contains the corresponding key. If this function returns `true`, the key is returned from `array_find_key` and the callback will not be called for further elements.

#### Return Value

The function returns the key of the first element for which the `$callback` returns `true`. If no matching element is found the function returns `NULL`.

#### Examples

```php
$array = [
    'a' => 'dog',
    'b' => 'cat',
    'c' => 'cow',
    'd' => 'duck',
    'e' => 'goose',
    'f' => 'elephant'
];
 
// Find the first animal with a name longer than 4 characters.
var_dump(array_find_key($array, function (string $value) {
    return strlen($value) > 4;
})); // string(1) "e"
 
// Find the first animal whose name begins with f.
var_dump(array_find_key($array, function (string $value) {
    return str_starts_with($value, 'f');
})); // NULL
 
// Find the first animal where the array key is the first symbol of the animal.
var_dump(array_find_key($array, function (string $value, $key) {
   return $value[0] === $key;
})); // string(1) "c"
 
// Find the first animal where the array key matching a RegEx.
var_dump(array_find_key($array, function (string $value, $key) {
   return preg_match('/^([a-f])$/', $key);
})); // string(1) "a"
```

### array\_any

`array_any` returns `true`, if `$callback` returns `true` for any element. Otherwise the function returns `false`.

```php
function array_any(array $array, callable $callback): bool {
    foreach ($array as $key => $value) {
        if ($callback($value, $key)) {
            return true;
        }
    }
 
    return false;
}
```

#### Parameters

`array $array`

The array that should be searched.

`callable $callback`

The callback function to call to check each element. The first parameter contains the value, the second parameter contains the corresponding key. If this function returns `true`, `true` is returned from `array_any` and the callback will not be called for further elements.

#### Return Value

The function returns `true`, if there is at least one element for which `$callback` returns `true`. Otherwise the function returns `false`.

#### Examples

```php
$array = [
    'a' => 'dog',
    'b' => 'cat',
    'c' => 'cow',
    'd' => 'duck',
    'e' => 'goose',
    'f' => 'elephant'
];
 
// Check, if any animal name is longer than 5 letters.
var_dump(array_any($array, function (string $value) {
    return strlen($value) > 5;
})); // bool(true)
 
// Check, if any animal name is shorter than 3 letters.
var_dump(array_any($array, function (string $value) {
    return strlen($value) < 3;
})); // bool(false)
 
// Check, if any array key is not a string.
var_dump(array_any($array, function (string $value, $key) {
   return !is_string($key);
})); // bool(false)
```

### array\_all

`array_all` returns `true`, if `$callback` returns `true` for all elements. Otherwise the function returns `false`.

```php
function array_all(array $array, callable $callback): bool {
    foreach ($array as $key => $value) {
        if (!$callback($value, $key)) {
            return false;
        }
    }
 
    return true;
}
```

#### Parameters

`array $array`

The array that should be searched.

`callable $callback`

The callback function to call to check each element. The first parameter contains the value, the second parameter contains the corresponding key. If this function returns `false`, `false` is returned from `array_all` and the callback will not be called for further elements.

#### Return Value

The function returns `true`, if `$callback` returns `true` for all elements. Otherwise the function returns `false`.

#### Examples

```php
$array = [
    'a' => 'dog',
    'b' => 'cat',
    'c' => 'cow',
    'd' => 'duck',
    'e' => 'goose',
    'f' => 'elephant'
];
 
// Check, if all animal names are shorter than 12 letters.
var_dump(array_all($array, function (string $value) {
    return strlen($value) < 12;
})); // bool(true)
 
// Check, if all animal names are longer than 5 letters.
var_dump(array_all($array, function (string $value) {
    return strlen($value) > 5;
})); // bool(false)
 
// Check, if all array keys are strings.
var_dump(array_all($array, function (string $value, $key) {
   return is_string($key);
})); // bool(true)
```

## Backward Incompatible Changes

Functions created by the user and named `array_find`, `array_find_key`, `array_any` or `array_all` lead to a PHP error with the new version. A quick GitHub search shows, that there a [656 results](https://github.com/search?q=language%3Aphp%20symbol%3Aarray_find&type=code) defining the symbol `array_find`, [28 results](https://github.com/search?q=language%3Aphp%20symbol%3Aarray_find_key&type=code) defining the symbol `array_find_key`, [127 results](https://github.com/search?q=language%3Aphp%20symbol%3Aarray_any&type=code) defining the symbol `array_any` and [284 results](https://github.com/search?q=language%3Aphp%20symbol%3Aarray_all&type=code) defining the symbol `array_all` for the language PHP.

Looking at the search results I estimate about 30% of these results are functions that are not located in a namespace, are not part of a class and are not false-positvies (e.g. the symbol is `db_array_all` instead of `array_all`).

## Proposed PHP Version(s)

PHP 8.4

## RFC Impact

### To SAPIs

None.

### To Existing Extensions

None.

### To Opcache

None.

### New Constants

None.

### php.ini Defaults

None.

## Open Issues

This function behaves differently to `array_filter`, because it always passes the value and the key to the callback. `array_filter` has a parameter for this to set which parameters are to be passed to the callback. `array_map` does not support the pass of the key at all, but support using more than one array, to pass a various number of parameters to the callback. With closures, omitting a parameter is now possible without any problems, therefore, there is no reason to determine the choice of parameters for the callback.

## Unaffected PHP Functionality

This RFC only adds two new functions to PHP and only affects previously defined functions which are named as the proposed functions.

## Proposed Voting Choices

Each vote requires a 2/3 majority.

Voting started on 2024-05-15 and will end on 2024-05-29 15:00 UTC.

### array\_find()/array\_find\_key()

**Vote: Add array\_find() and array\_find\_key()?** — Yes: 21 · No: 0 (closed)

### array\_any()/array\_all()

**Vote: Add array\_any() and array\_all()?** — Yes: 20 · No: 0 (closed)

## Implementation

<https://github.com/php/php-src/pull/14108>

## References

- GitHub currently has [656 results](https://github.com/search?q=language%3Aphp%20symbol%3Aarray_find&type=code) for `array_find` and Laravel implements this feature by default with [Arr:first](https://github.com/laravel/framework/blob/08acc925f1ec8e1c41a54774a36720f506c5b5a8/src/Illuminate/Collections/Arr.php#L193).
- <https://en.cppreference.com/w/cpp/algorithm/find>
- [https://en.cppreference.com/w/cpp/algorithm/all\_any\_none\_of](https://en.cppreference.com/w/cpp/algorithm/all_any_none_of)
- [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/Array/find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find)
- [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/Array/every](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every)
- [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/Array/some](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some)
- <https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.find>
- <https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.all>
- <https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.any>
