Деструктуризация массива в PHP

Деструктуризация массива в PHP

Языковая конструкция list()

В 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);


Ну что, я вас убедил в полезности использования list в своем коде?

Сергей Мухин

Веб-разработчик со стажем программирования более 6 лет, постоянно учусь, люблю делать новые проекты.

Есть вопросы?

Я почти всегда в режиме онлайн

Связаться со мной