Глиф Учебники

Урок 4. Массивы и foreach

Курс «PHP» · урок 4 из 10 · 3 минуты чтения

Массив хранит много значений под одним именем: список товаров, оценки ученика, строки из базы данных. Каждое значение в массиве лежит под своим ключом — номером или именем.

Список

PHP
<?php
$fruits = ["яблоко", "груша", "слива"];
echo $fruits[0] . "\n";
echo count($fruits) . "\n";
$fruits[] = "вишня";
echo $fruits[3] . "\n";
Вывод
яблоко
3
вишня

Номера элементов начинаются с нуля: первый — $fruits[0], третий — $fruits[2]. count возвращает число элементов, а пустые скобки $fruits[] = … добавляют элемент в конец. В старом коде вместо квадратных скобок встречается array("яблоко", "груша") — это то же самое.

$fruits [0] "яблоко" [1] "груша" [2] "слива" [3] "вишня" count($fruits) → 3 в конец $fruits[] = "вишня";
Номера элементов списка $fruits идут с нуля: "яблоко" — номер 0, "слива" — номер 2; count даёт 3, а пустые скобки добавляют "вишня" в конец под номером 3.

Ассоциативный массив

Вместо номеров ключами могут быть строки. Такой массив похож на карточку с полями:

PHP
<?php
$user = [
    "name" => "Иван",
    "city" => "Гродно",
    "age" => 30,
];
echo $user["name"] . " из города " . $user["city"] . "\n";
$user["age"] = 31;
echo "Возраст: {$user['age']}\n";
Вывод
Иван из города Гродно
Возраст: 31

Пара пишется как ключ => значение. Запятая после последней пары разрешена и удобна: новую строку можно дописать, не трогая предыдущую. Внутри строки в двойных кавычках элемент массива берут в фигурные скобки: {$user['age']}.

Если ключа в массиве нет, PHP выводит предупреждение Undefined array key. Как его избежать — в справке Undefined variable и Undefined array key.

Цикл foreach

foreach проходит по всем элементам массива по порядку:

PHP
<?php
$stock = ["яблоки" => 12, "груши" => 7, "сливы" => 0];
$total = 0;
foreach ($stock as $fruit => $count) {
    if ($count === 0) {
        echo "$fruit: нет в наличии\n";
    } else {
        echo "$fruit: $count кг\n";
    }
    $total += $count;
}
echo "Всего: $total кг\n";
Вывод
яблоки: 12 кг
груши: 7 кг
сливы: нет в наличии
Всего: 19 кг

На каждом шаге в $fruit попадает ключ, в $count — значение. Если ключ не нужен, пишут короче: foreach ($fruits as $fruit).

$stock ключ значение $fruit $count $total шаг "яблоки" => 12 1 "яблоки" 12 12 "груши" => 7 2 "груши" 7 19 "сливы" => 0 3 "сливы" 0 19 foreach ($stock as $fruit => $count) {
На каждом шаге foreach берёт следующую пару массива $stock: ключ попадает в $fruit, значение — в $count, а $total после трёх шагов равен 19.

Посмотреть массив целиком

Для отладки массив выводят функцией print_r (или var_dump — с типами):

PHP
<?php
$colors = ["красный", "зелёный"];
print_r($colors);
Вывод
Array
(
    [0] => красный
    [1] => зелёный
)

Полезные функции

PHP
<?php
$marks = [7, 9, 4, 10, 8];
echo "Оценок: " . count($marks) . "\n";
echo "Сумма: " . array_sum($marks) . "\n";
echo "Лучшая: " . max($marks) . "\n";
echo "Средняя: " . round(array_sum($marks) / count($marks), 1) . "\n";
sort($marks);
echo implode(", ", $marks) . "\n";
var_dump(in_array(10, $marks));
Вывод
Оценок: 5
Сумма: 38
Лучшая: 10
Средняя: 7.6
4, 7, 8, 9, 10
bool(true)
ФункцияЧто делает
count($a)число элементов
in_array($x, $a)есть ли значение в массиве
array_search($x, $a)ключ найденного значения или false
array_keys($a), array_values($a)только ключи / только значения
sort($a), rsort($a)сортировка по возрастанию / убыванию, ключи заново с нуля
asort($a), ksort($a)сортировка по значениям / по ключам с сохранением ключей
array_merge($a, $b)склеить массивы
array_slice($a, 0, 3)первые три элемента
implode(", ", $a)склеить элементы в строку
explode(",", $s)разбить строку на массив

Функции сортировки меняют сам массив и ничего полезного не возвращают. Запись $sorted = sort($marks) — частая ошибка: в $sorted окажется true, а не массив.

Строка ↔ массив

PHP
<?php
$line = "Минск,Брест,Гомель";
$cities = explode(",", $line);
echo count($cities) . "\n";
echo implode(" | ", $cities) . "\n";
Вывод
3
Минск | Брест | Гомель

explode режет строку по разделителю, implode склеивает обратно. Подробнее и с подводными камнями — в справке Как разбить строку на массив.

Массив массивов

Строки таблицы обычно хранят как список ассоциативных массивов — так их возвращает и база данных (урок 9):

PHP
<?php
$users = [
    ["name" => "Анна", "role" => "администратор"],
    ["name" => "Олег", "role" => "редактор"],
];
foreach ($users as $user) {
    echo $user["name"] . " — " . $user["role"] . "\n";
}
echo $users[1]["name"] . "\n";
Вывод
Анна — администратор
Олег — редактор
Олег

$users[1]["name"] — сначала второй элемент списка, затем поле name в нём.

Удаление элемента

unset($fruits[1]) удаляет элемент, но номера остальных не сдвигаются: после удаления останутся ключи 0, 2, 3. Чтобы снова пронумеровать с нуля, используют $fruits = array_values($fruits).

Массив $fruits после добавления «вишни» 0 "яблоко" 1 "груша" 2 "слива" 3 "вишня" unset($fruits[1]); номера остальных не сдвинулись 0 "яблоко" ключа 1 нет 2 "слива" 3 "вишня" $fruits = array_values($fruits); 0 "яблоко" 1 "слива" 2 "вишня" снова по порядку с 0
После unset у массива $fruits остаются ключи 0, 2 и 3 — номера не сдвигаются, а array_values заново нумерует элементы подряд: 0, 1, 2.

Частые ошибки

Коротко

Проверьте себя

1. Как добавить элемент в конец массива $list?
2. Что выведет программа?
PHP
<?php
$a = [10, 20, 30];
echo $a[1];
3. Что окажется в $sorted после $sorted = sort($a);?
4. Какая запись обходит массив и даёт ключ и значение?