Новые функции массива в PHP 8.4

Источник: «New Array Functions in PHP 8.4»
Узнайте, как использовать новые функции PHP 8.4 array_find, array_find_key, array_all и array_any. Кроме того, приведены аналоги в Laravel, для достижения тех же результатов.

Введение

PHP 8.4 выйдет в ноябре 2024 года и представит несколько новых функций для работы с массивами:

Кратко рассмотрим эти новые функции и как их использовать в проектах на PHP 8.4.

Если вы Laravel разработчик, то возможно заметили, что уже есть подобные функции в классах Illuminate\Support\Collection и Illuminate\Support\Arr. Но мне нравится, что эти функции будут встроенными в PHP и поэтому будут доступны в любом PHP-проекте.

Для тех кто разрабатывает в Laravel, я покажу эквиваленты новых функций массивов PHP 8.4 в Laravel, чтобы можно было реализовать тот же функционал в своих Laravel проектах, не дожидаясь выхода PHP 8.4.

Функция array_find

Функция array_find возвращает значение первого элемента, соответствующего критериям, заданным в обратном вызове. Если ни один элемент не соответствует запросу, функция возвращает null.

Рассмотрим простой пример. Представим, что есть массив товаров, и нужно найти товар со штрих-кодом 123456:

$products = [
[
'name' => 'Macbook Pro',
'type' => 'Laptop',
'barcode' => 123456,
],
[
'name' => 'Framework Laptop 13',
'type' => 'Laptop',
'barcode' => 789012,
],
[
'name' => 'Samsung Galaxy S24',
'type' => 'Phone',
'barcode' => 135791,
],
];

// Поиск товара со штрих-кодом 123456
$findProduct = array_find(
array: $products,
callback: function (array $product): bool {
return $product['barcode'] == 123456;
},
);

После выполнения вышеприведённого кода значение $findProduct станет равным:

[
'name'=> 'Macbook Pro',
'type' => 'Laptop',
'barcode' => 123456,
]

Можно сделать код ещё немного чище, используя в качестве второго аргумента стрелочную функцию:

$findProduct = array_find(
array: $products,
callback: fn (array $product): bool => $product['barcode'] === 123456,
);

Код, вернёт тот же результат, что и в предыдущем примере.

Если ни один элемент не удовлетворяет требованиям обратного вызова, функция вернёт null. Давайте посмотрим на примере:

$nonExistentProduct = array_find(
array: $products,
callback: fn (array $product): bool => $product['barcode'] === 'invalid',
);

В этом случае $nonExistentProduct будет равен null.

Эквивалент array_find в Laravel

В Laravel аналогичного результата можно добиться с помощью метода Arr::first:

use Illuminate\Support\Arr;

$findProduct = Arr::first(
$products,
fn (array $product): bool => $product['barcode'] === 123456,
);

Функция array_find_key

Эта функция аналогична функции array_find, но вместо возвращения значения первого элемента, соответствующего обратному вызову, она возвращает ключ первого элемента, соответствующего обратному вызову.

Возьмём массив $products из предыдущего примера. На этот раз нужно найти ключ товара со штрих-кодом 789012:

$products = [
[
'name' => 'Macbook Pro',
'type' => 'Laptop',
'barcode' => 123456,
],
[
'name' => 'Framework Laptop 13',
'type' => 'Laptop',
'barcode' => 789012,
],
[
'name' => 'Samsung Galaxy S24',
'type' => 'Phone',
'barcode' => 135791,
],
];

// Поиск ключа к товару со штрих-кодом 789012
$findProduct = array_find_key(
array: $products,
callback: fn (array $product): bool => $product['barcode'] === 789012,
);

После выполнения вышеприведённого кода $findProduct будет равен 1, поскольку товар является вторым элементом в массиве.

Если ни один элемент не удовлетворяет условиям обратного вызова, функция вернёт null. Давайте рассмотрим это на примере:

$nonExistentProduct = array_find_key(
array: $products,
callback: fn (array $product): bool => $product['barcode'] === 'invalid',
);

В этом случае $nonExistentProduct будет равен null.

Эквивалент array_find_key в Laravel

В Laravel можно добиться аналогичного результата, используя комбинацию методов array_keys и Arr::first:

use Illuminate\Support\Arr;

$firstProductKey = Arr::first(
array_keys($products),
fn (int $key): bool => $products[$key]['barcode'] === 789012,
);

В приведённом выше коде сначала используется array_keys для получения массива ключей массива $products. Затем с помощью Arr::first находится первый ключ, соответствующий обратному вызову. Это немного более многословный способ, чем встроенная функция PHP, но результат тот же.

Функция array_any

Функция array_any позволяет проверить, что хотя бы один элемент массива соответствует критериям, заданным в обратном вызове. Если какой-либо элемент соответствует обратному вызову, функция возвращает true. Если ни один элемент не соответствует обратному вызову, функция возвращает false.

Используя массив $products, проверим, имеет ли какой-либо из товаров тип Laptop:

$anyProductsAreLaptops = array_any(
array: $products,
callback: fn (array $product): bool => $product['type'] === 'Laptop',
);

В данном случае $anyProductsAreLaptops будет равно true, потому что хотя бы один из продуктов в массиве является ноутбуком.

Если ни один элемент не соответствует обратному вызову, функция вернёт false. Давайте рассмотрим это на примере:

$anyProductsAreInvalid = array_any(
array: $products,
callback: fn (array $product): bool => $product['type'] === 'Invalid',
);

В этом случае $anyProductsAreInvalid будет равно false.

Эквивалент array_any в Laravel

В Laravel можно получить тот же результат, используя метод contains на коллекции:

use Illuminate\Support\Collection;

$anyProductsAreLaptops = Collection::make($products)->contains(
fn (array $product): bool => $product['type'] === 'Laptop',
);

В приведённом выше коде из массива $products создаётся коллекция, а затем с помощью метода contains проверяется, является ли какой-либо из продуктов в коллекции ноутбуком.

Функция array_all

Функция array_all аналогична функции array_any, но вместо того, чтобы проверять, соответствует ли хотя бы один элемент обратному вызову, она проверяет, соответствуют ли все элементы обратному вызову. Если все элементы соответствуют обратному вызову, функция возвращает true. Если какой-либо элемент не соответствует обратному вызову, функция возвращает false.

Давайте проверим, все ли товары в массиве $products являются ноутбуками:

$allProductsAreLaptops = array_all(
array: $products,
callback: fn (array $product): bool => $product['type'] === 'Laptop',
);

В этом случае $allProductsAreLaptops будет равно false, потому что не все товары в массиве являются ноутбуками.

Эквивалент array_all в Laravel

В Laravel можно получить тот же результат, используя метод every на коллекции:

use Illuminate\Support\Collection;

$allProductsAreLaptops = Collection::make($products)->every(
fn (array $product): bool => $product['type'] === 'Laptop',
);

В приведённом выше коде из массива $products создаётся коллекция, а затем с помощью метода every проверяется, все ли товары в коллекции являются ноутбуками.

Заключение

Надеюсь, эта статья продемонстрировала, как можно использовать новые функции массивов, представленные в PHP 8.4. Она также должна была дать представление, как можно достичь аналогичной функциональности в Laravel, используя классы Illuminate\Support\Collection и Illuminate\Support\Arr.

Дополнительные материалы

Предыдущая Статья

Когда использовать if, switch и match в PHP

Следующая Статья

CSS свойство contain