Перейти к содержимому
Теория · Массивы · урок 1 из 8

Списки

Чему вы научитесь

Чему вы научитесь:

  • добавлять, заменять и удалять элементы списков и ассоциативных массивов;
  • предсказывать, какой ключ получит новый элемент и во что PHP превратит ключ '8';
  • обходить вложенные массивы двумя циклами foreach;
  • объяснять, почему после $b = $a изменение $b не меняет $a.
Стена гардероба с крючками [0] и [1] с пальто и новое пальто на следующем свободном крючке $list[]

В теме о циклах вы уже встречали список [10, 20, 30]: элементы хранятся по порядку, индексы начинаются с 0, а count возвращает число элементов. Тогда список только читали. Теперь научимся его менять: добавлять элементы, заменять их и печатать весь список целиком.

Представьте гардероб в театре. Вдоль стены висят крючки с номерами 0, 1, 2, и на каждом — одна вещь. Гардеробщик находит вещь по номеру крючка, может повесить на крючок другую, а новую вещь вешает на следующий свободный крючок.

В PHP такой гардероб называют массивом: одна переменная хранит много значений, и у каждого есть свой номер. Список — это массив, в котором номера идут подряд с нуля. Посмотрим, как список гостей меняется по ходу программы:

PHP
<?php

$guests = ['Anna', 'Boris'];
$guests[] = 'Vera';
$guests[1] = 'Gleb';
echo count($guests), "\n"; // 3
echo $guests[0], ' ', $guests[1], ' ', $guests[2], "\n"; // Anna Gleb Vera

Давайте разберём по строкам:

  1. $guests = ['Anna', 'Boris']; создаёт список из двух гостей: 'Anna' висит на крючке 0, 'Boris' — на крючке 1.
  2. $guests[] = 'Vera'; вешает 'Vera' на следующий свободный крючок, 2.
  3. $guests[1] = 'Gleb'; снимает с крючка 1 прежнее значение и вешает туда 'Gleb'.
  4. count($guests) возвращает 3: замена не добавила новый элемент.
  5. Последний echo печатает Anna Gleb Vera.

Добавить или заменить

Обе записи похожи: имя списка, квадратные скобки и присваивание. Разница в том, что стоит внутри скобок.

Пустые скобки: $a[] = …

Запись $guests[] = 'Vera' добавляет элемент в конец списка. Номер PHP выбирает сам: следующий за самым большим номером, который уже занят. Считать индексы вручную не нужно.

Так удобно собирать список по одному значению. Начинают с пустого списка [], а потом в цикле добавляют элементы: $squares[] = $i * $i;. После трёх витков с $i от 1 до 3 в $squares лежат 1, 4 и 9.

Индекс в скобках: $a[1] = …

Запись $guests[1] = 'Gleb' пишет значение под индексом 1. Если элемент там уже есть, новое значение заменяет старое, и count не меняется.

Это то же присваивание, что и для обычной переменной. Только место для значения задаёт не одно имя, а имя списка вместе с индексом.

Индекса нет

Что будет, если попросить вещь с крючка, которого нет? В списке из трёх гостей есть индексы 0, 1 и 2, а индекса 3 нет:

PHP
echo $guests[3] ?? 'nobody', "\n"; // nobody
echo $guests[3], "\n"; // ✗
TEXT
Warning: Undefined array key 3

Разберём обе строки:

  1. $guests[3] ?? 'nobody' печатает nobody. Как вы уже знаете, ?? сначала проверяет, есть ли значение, и с элементом массива он работает так же — без предупреждения.
  2. $guests[3] без ?? читает отсутствующий элемент. PHP выдаёт предупреждение, читает вместо элемента null, и echo печатает пустую строку.

Как и с незаданной переменной, это предупреждение, а не остановка: строки ниже выполняются дальше. Но в коде оно говорит об ошибке, поэтому отсутствующий индекс читают через ??.

Здесь картинка с гардеробом расходится с PHP. В театре пустые крючки висят на стене и ждут вещей, а в массиве крючок появляется только вместе с вещью. Индекса 3 в списке нет совсем, а не «крючок пуст».

Напечатать весь список

Для печати всего списка в PHP есть две функции:

PHP
echo implode(', ', $guests), "\n"; // Anna, Gleb, Vera
print_r($guests);
// Array
// (
//     [0] => Anna
//     [1] => Gleb
//     [2] => Vera
// )

implode

implode(', ', $guests) склеивает элементы в одну строку. Первый аргумент — разделитель: его PHP ставит между соседними элементами. Список при этом не меняется: implode возвращает новую строку.

print_r($guests) печатает массив вместе с индексами: слева от => номер, справа значение. Её вывод занимает несколько строк, поэтому print_r берут, чтобы заглянуть внутрь массива во время отладки, а не для красивого вывода.

Частая ошибка

Весь список пытаются напечатать через echo:

PHP
echo $guests, "\n"; // ✗
TEXT
Warning: Array to string conversion

echo печатает строки, а массив сам в строку не превращается. PHP выдаёт предупреждение и печатает вместо элементов слово Array. Чтобы увидеть элементы, склейте их через implode или загляните внутрь через print_r.

Главное

  • Массив хранит много значений в одной переменной; в списке индексы идут подряд с 0.
  • $a[] = x добавляет элемент в конец, а $a[1] = y заменяет элемент с индексом 1.
  • Чтение отсутствующего индекса даёт Warning: Undefined array key и null, а $a[3] ?? 'nobody' читает без предупреждения.
  • implode(', ', $a) склеивает список в строку, print_r($a) показывает его с индексами, а echo $a печатает только Array.