В PHP 8.4 планируется добавить новые функции массива: array_find, array_find_key, array_any и array_all, которые являются вспомогательными функциями для общих шаблонов проверки массива на наличие элементов, соответствующих определенному условию.

В настоящее время существует несколько функций, обрабатывающих массивы с использованием обратного вызова. Однако по-прежнему отсутствуют функции для поиска отдельного элемента, соответствующего условию, и тесно связанные функции проверки наличия элементов, соответствующих условию. Реализовать эти функции в среде пользователей относительно просто, но они часто требуются, что приводит к тому, что колесо изобретается снова и снова. Кроме того, функции такого типа реализованы и в других языках программирования, таких как Rust, JavaScript или C++. Поэтому есть причина включить эти функции в стандартную комплектацию следующей версии PHP. Кроме того, реализация этих функций очень похожа на array_filter и относительно проста в реализации, поэтому затраты на обслуживание должны быть низкими.

array_find

array_find возвращает значение первого элемента, для которого функция $callback возвращает значение true. Если соответствующий элемент не найден, функция возвращает значение NULL.

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

Давайте рассмотрим работу этой функции на примерах.

$array = [
    'a' => 'dog',
    'b' => 'cat',
    'c' => 'cow',
    'd' => 'duck',
    'e' => 'goose',
    'f' => 'elephant'
];
 
// Поиск первого животного с именем, длина которого превышает 4 символа.
var_dump(array_find($array, function (string $value) {
    return strlen($value) > 4;
})); // string(5) "goose"
 
// Поиск первого животного с именем, которое начинается на f.
var_dump(array_find($array, function (string $value) {
    return str_starts_with($value, 'f');
})); // NULL
 
// Поиск первого животного, в котором ключ массива является первым символом животного.
var_dump(array_find($array, function (string $value, $key) {
   return $value[0] === $key;
})); // string(3) "cow"
 
// Поиск первого животного, у которого ключ массива соответствует регулярному выражению.
var_dump(array_find($array, function ($value, $key) {
   return preg_match('/^([a-f])$/', $key);
})); // string(3) "dog"

array_find_key

array_find_key возвращает ключ первого элемента, для которого функция $callback возвращает значение true. Если соответствующий элемент не найден, функция возвращает значение NULL.

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

Давайте рассмотрим работу этой функции на примерах.

$array = [
    'a' => 'dog',
    'b' => 'cat',
    'c' => 'cow',
    'd' => 'duck',
    'e' => 'goose',
    'f' => 'elephant'
];
 
// Поиск первого животного с именем, длина которого превышает 4 символа.
var_dump(array_find_key($array, function (string $value) {
    return strlen($value) > 4;
})); // string(1) "e"
 
// Поиск первого животного с именем, которое начинается на f.
var_dump(array_find_key($array, function (string $value) {
    return str_starts_with($value, 'f');
})); // NULL
 
// Поиск первого животного, в котором ключ массива является первым символом животного.
var_dump(array_find_key($array, function (string $value, $key) {
   return $value[0] === $key;
})); // string(1) "c"
 
// Поиск первого животного, у которого ключ массива соответствует регулярному выражению.
var_dump(array_find_key($array, function (string $value, $key) {
   return preg_match('/^([a-f])$/', $key);
})); // string(1) "a"

array_any

array_any возвращает значение true, если $callback возвращает значение true для любого элемента. В противном случае функция возвращает значение false.

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

Давайте рассмотрим работу этой функции на примерах.

$array = [
    'a' => 'dog',
    'b' => 'cat',
    'c' => 'cow',
    'd' => 'duck',
    'e' => 'goose',
    'f' => 'elephant'
];
 
// Проверяет, не содержит ли название какого-либо животного более 5 букв.
var_dump(array_any($array, function (string $value) {
    return strlen($value) > 5;
})); // bool(true)
 
// Проверяет, не содержит ли название какого-либо животного более 3 букв.
var_dump(array_any($array, function (string $value) {
    return strlen($value) < 3;
})); // bool(false)
 
// Проверяет, не является ли какой-либо ключ массива строкой.
var_dump(array_any($array, function (string $value, $key) {
   return !is_string($key);
})); // bool(false)

array_all

array_all возвращает значение true, если $callback возвращает значение true для всех элементов. В противном случае функция возвращает значение false.

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

Давайте рассмотрим работу этой функции на примерах.

$array = [
    'a' => 'dog',
    'b' => 'cat',
    'c' => 'cow',
    'd' => 'duck',
    'e' => 'goose',
    'f' => 'elephant'
];
 
// Проверяет, все ли названия животных короче 12 букв.
var_dump(array_all($array, function (string $value) {
    return strlen($value) < 12;
})); // bool(true)
 
// Проверяет, все ли названия животных длиннее 5 букв.
var_dump(array_all($array, function (string $value) {
    return strlen($value) > 5;
})); // bool(false)
 
// Проверяет, все ли ключи массива являются строками.
var_dump(array_all($array, function (string $value, $key) {
   return is_string($key);
})); // bool(true)

Полезность этих методов очевидна, но давайте посмотрим, как много раз были написаны эти функции самостоятельно людьми.

Функции, созданные пользователем и названные array_find, array_find_key, array_any или array_all, приводят к ошибке PHP в новой версии. Быстрый поиск на GitHub показывает, что есть 656 результатов, определяющих символ array_find, 28 результатов, определяющих символ array_find_key, 127 результатов, определяющих символ array_any и 284 результата, определяющих символ array_all для языка PHP.

Глядя на результаты поиска, я оцениваю, что около 30% этих результатов — это функции, которые не находятся в пространстве имен, не являются частью класса и не являются ложными выводами (например, символ — db_array_all вместо array_all).

Еще больше статей, юмора и жизненны моментов во ВКонтакте Пихта DEV и Телеграмм канале Пихта DEV

Комментарии (2)


  1. Daniel217D
    10.07.2024 08:03
    +2

    После того как привык к функциональному походу в js, в пыхе подобных функций очень не хватало. Юзаю полифил от симфони https://github.com/symfony/polyfill-php84 Скоро от него можно будет отказаться)


    1. mepihin Автор
      10.07.2024 08:03
      +1

      Там еще добавили сеттеры и геттеры прям в свойства классов. Это прям тебе зайдёт)