Деструктуризация массива в PHP
Содержание
В PHP list является такой же «языковой конструкцией», как и array(). Эта языковая конструкция используется для «разложения» массива на переменные
Я никогда не видел слишком частого использования list()
в "дикой природе", но он позволяет вам писать довольно интересные вещи.
Синтаксис: list или []
Вот как это выглядит:
$array = [1, 2, 3]; //использование Oldschool: list($a, $b, $c) = $array; // или короткий вариант, начиная с PHP 7.1: [$a, $b, $c] = $array; // $a = 1 // $b = 2 // $c = 3
Можно использовать list
или его короткий вариант []
, как вам удобно. Есть мнение, что []
это неоднозначное использование с синтаксисом сокращенного массива, и поэтому предпочитают list
. Я обычно использую сокращенную версию в примерах кода.
Так что еще можно сделать с list
?
Пропуск элементов в массиве
Скажем, вам нужен только третий элемент массива, первые два можно пропустить, просто не указав переменную.
[, , $c] = $array; // $c = 3
Также стоит обратить внимание, что list
всегда начинается с индекса 0. Возьмем, к примеру, следующий массив:
$array = [ 1 => 'a', 2 => 'b', 3 => 'c', ];
Значение первой переменной, которое вытащит list
будет null
, потому что нет элемента с индексом 0. Это может показаться недостатком, но, к счастью, имеет большие перспективы.
В PHP5
list()
присваивает значения начиная с самого правого значения. В PHP7 - с самого левого значения. Если вы используете обычные переменные, можете не думать об этом, но, если вы используете массивы с индексами, вы ожидаете, что порядок элементов в массиве будет ровно таким, как вы его определили вlist()
, слева направо, но в PHP5 вы получите обратный порядок.
Вообще говоря, желательно не полагаться на конкретный порядок операций, так как в будущем это поведение может быть изменено.
Работа с ассоциативным массивом
PHP 7.1 позволяет list
использовать ассоциативный массив. Это открывает много возможностей:
$array = [ 'a' => 1, 'b' => 2, 'c' => 3, ];
Присвоение можно сделать так:
['c' => $c, 'a' => $a] = $array;
Как видите, вы можете изменить порядок, какой хотите, а также полностью пропустить элементы.
Или другой пример:
$person = [ 'name' => 'Sergey', 'job' => 'Developer', ]; list('job' => $job) = $person; echo $job; // "Developer"
Разбор адреса или пути файла
Часто list
применяют с такими функциями как parse_url()
и pathinfo()
. Поскольку эти функции возвращают массив с именованными параметрами, можно использовать list
для извлечения нужной нам информации:
[ 'basename' => $file, 'dirname' => $directory, ] = pathinfo('/products/001/product-1.png');
Как видно из примера, переменные не нуждаются в том же имени, что и ключ. Также обратите внимание, что разложение массива с неизвестным ключом вызовет предупреждение:
[ 'path' => $path, 'query' => $query, ] = parse_url('https://sergeymukhin.com/blog'); // PHP Notice: Undefined index: query
В этом случае $query
будет null
. Еще одна деталь: с именованными деструкторами допускаются конечные запятые, так же как это делается в обычных массивах.
Использование Explode строки
Если после explode
строки вы хотите сразу представить результат как две отдельные переменные:
[$user, $repository] = explode('/', 'sinbadxiii/my-repo', 2);
Создание нескольких объектов
Итак, вы создали несколько объектов одновременно, например с помощью фабрики, и хотите, чтобы они все были отдельными переменными:
[$userA, $userB, $userC] = factory(User::class, 3)->create();
Обмен значений переменных
И мое любимое, это просто шедевр в синтаксисе PHP, например, вы хотите поменять местами две переменные:
$a = 'hello'; $b = 'world'; [$a, $b] = [$b, $a]; echo $a; // "world" echo $b; // "hello"
Что-то похожее есть в Python:
a, b = b, a
Использование деструктуризации в циклах
Вы также можете использовать конструкцию списка в циклах:
$array = [ [ 'name' => 'a', 'id' => 1 ], [ 'name' => 'b', 'id' => 2 ], ]; foreach ($array as ['id' => $id, 'name' => $name]) { // … }
Это может быть полезно при разборе файла, например, JSON
или CSV
. Но нужно быть осторожным, неопределенные ключи могут вызывать предупреждения.
Несколько возвращаемых значений
Некоторые языки допускают возвращение нескольких значений. Рассмотрим функцию, у которой в качестве параметра целое число и возвращает она два целых числа, одно из которых является $int + 5
, другое $int - 5
. Вот как это будет выглядеть в Go:
func addAndRemoveFive(i int) (int, int) { return i + 5, i - 5 } func main() { x, y := addAndRemoveFive(10) }
Мы могли бы достичь что-то подобного, возвращая массив в PHP и немедленно его уничтожая:
function addAndRemoveFive(int $i): array { return [$i + 5, $i - 5]; } [$x, $y] = addAndRemoveFive(10); echo $x; // 15 echo $y; // 5
Более реальная ситуация, когда несколько возвращаемых значений могут быть полезны, - это случаи, когда вы ожидаете статус и сообщение, например валидация:
[$valid, $reason] = $validator->validate($data); if (! $valid) { return new JsonResponse(422, ['reason' => $reason]); } return new JsonResponse(200);
Источник: sergeymukhin.com
2 комментария
Cocoder
11 декабря 2022 в 09:45Спасибо, полезно!
Олег Десятников
12 декабря 2022 в 22:45Пожалуйста 🙂