Циклы и массивы (включая ассоциативные)
Массивы в PHP - как карман: туда можно положить всё. Главное потом не искать ключи в стиральной машине.
Обычные массивы
<?php
$numbers = [10, 20, 30];
echo $numbers[0]; // 10
echo count($numbers); // 3
Добавить элемент:
<?php
$numbers[] = 40; // добавить в конец
array_push($numbers, 50); // то же самое, но длиннее
Удалить элемент:
<?php
unset($numbers[1]); // удалит элемент с индексом 1
// Осторожно: индексы НЕ пересчитываются!
// Чтобы пересчитать: $numbers = array_values($numbers);
Ассоциативные массивы
Ассоциативный массив - это словарь: ключ → значение. Именно так обычно представляют JSON-объекты после json_decode (см. урок про JSON) и строки из БД через PDO.
<?php
$user = [
'id' => 1,
'name' => 'Иван',
'role' => 'student',
];
echo $user['name']; // Иван
Проверить, есть ли ключ:
<?php
if (array_key_exists('email', $user)) {
echo $user['email'];
} else {
echo 'Email не указан';
}
// Короче (но не различает null и «нет ключа»):
echo $user['email'] ?? 'Email не указан';
foreach - лучший друг массива
<?php
$nums = [1, 2, 3];
foreach ($nums as $n) {
echo $n . "\n";
}
// С ключами:
foreach ($user as $key => $value) {
echo "$key = $value\n";
}
Изменить элемент прямо в цикле - через ссылку &:
<?php
$prices = [100, 200, 300];
foreach ($prices as &$price) {
$price *= 1.1; // +10% к каждой цене
}
unset($price); // обязательно: убираем ссылку после цикла
Циклы for / while
<?php
for ($i = 0; $i < 3; $i++) {
echo $i; // 012
}
while - когда количество итераций заранее неизвестно:
<?php
$line = '';
while (($line = fgets(STDIN)) !== false) {
echo "Прочитано: $line";
}
Сортировка
<?php
$nums = [3, 1, 4, 1, 5];
sort($nums); // [1, 1, 3, 4, 5] - по возрастанию
rsort($nums); // [5, 4, 3, 1, 1] - по убыванию
Для ассоциативных массивов - asort / ksort (сохраняют ключи):
<?php
$ages = ['Иван' => 25, 'Анна' => 22, 'Пётр' => 30];
asort($ages); // сортировка по значению: Анна, Иван, Пётр
ksort($ages); // сортировка по ключу: Анна, Иван, Пётр
Кастомная сортировка - usort:
<?php
$users = [
['name' => 'Иван', 'age' => 25],
['name' => 'Анна', 'age' => 22],
];
usort($users, fn($a, $b) => $a['age'] - $b['age']);
// Теперь: Анна (22), Иван (25)
// fn() => - стрелочная функция, подробнее в [уроке про функции](./05-functions.md)
Полезные функции
<?php
$items = [1, 2, 3, 4, 5];
// array_map - преобразовать каждый элемент
$doubled = array_map(fn($n) => $n * 2, $items);
// [2, 4, 6, 8, 10]
// array_filter - оставить только подходящие
$even = array_filter($items, fn($n) => $n % 2 === 0);
// [2, 4]
// array_reduce - свернуть в одно значение
$sum = array_reduce($items, fn($carry, $n) => $carry + $n, 0);
// 15
Объединение массивов
<?php
$a = [1, 2];
$b = [3, 4];
// array_merge - объединить
$c = array_merge($a, $b); // [1, 2, 3, 4]
// Spread-оператор (PHP 7.4+)
$c = [...$a, ...$b]; // [1, 2, 3, 4]
Для ассоциативных массивов array_merge перезаписывает одинаковые ключи (последний побеждает):
<?php
$defaults = ['color' => 'blue', 'size' => 'M'];
$custom = ['color' => 'red'];
$result = array_merge($defaults, $custom);
// ['color' => 'red', 'size' => 'M']
Деструктуризация (list)
<?php
$coords = [55.75, 37.62];
[$lat, $lon] = $coords;
echo "Широта: $lat, Долгота: $lon";
// С ассоциативным массивом:
$user = ['name' => 'Иван', 'age' => 25];
['name' => $name, 'age' => $age] = $user;
echo "$name, $age лет";
Многомерные массивы
<?php
$matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
echo $matrix[1][2]; // 6
// Массив объектов (массивов):
$orders = [
['id' => 1, 'items' => ['Молоко', 'Хлеб']],
['id' => 2, 'items' => ['Кофе']],
];
foreach ($orders as $order) {
echo "Заказ #{$order['id']}: " . implode(', ', $order['items']) . "\n";
}
in_array и array_search
<?php
$roles = ['admin', 'editor', 'viewer'];
if (in_array('admin', $roles, true)) {
echo 'Есть админ';
}
$index = array_search('editor', $roles, true);
// $index === 1
Типичные ошибки
in_arrayбезstrict=true.in_array(0, ['admin'])вернётtrueиз-за юглинга типов: строка кастуется к0. Всегда передавай третий аргументtrue, чтобы получить сравнение через===.array_mergeдля числовых ключей.array_merge([1, 2], [3, 4])объединяет как[1, 2, 3, 4], а оператор+оставит только первый массив:[1, 2] + [3, 4] === [1, 2]. Для ассоциативных наоборот:+сохраняет левые ключи,array_mergeперезаписывает их правыми.issetпротивarray_key_exists.isset($arr['key'])вернётfalse, если значениеnull- и ты не отличишь «ключа нет» от «ключ есть, ноnull». Если эта разница важна (например, в конфиге) - используйarray_key_exists.unsetрушит порядок индексов. Послеunset($arr[1])массив[10, 20, 30]превращается в[0 => 10, 2 => 30]. Следующийforeachотработает, но$arr[1]уже не существует. Если нужны последовательные индексы -array_values($arr).- Изменение массива через
&безunsetпосле цикла.foreach ($items as &$item)оставляет$itemпривязанным к последнему элементу. Любое присваивание$item = ...ниже по коду молча перезапишет последний элемент массива. Всегда делайunset($item)сразу после такого цикла.
Best practices
- Используй
array_key_existsдля проверок наличия ключа в данных, гдеnull- валидное значение (конфиги, JSON-ответы). - Для слияния списков по индексам -
array_mergeили spread[...$a, ...$b]. Оператор+оставляй для defaults:$options = $userOptions + $defaults. - Передавай большие массивы в функции, только если не собираешься их мутировать. Copy-on-write бесплатен на чтение, но первая же мутация скопирует весь массив.
- Сортируй ассоциативные массивы через
asort/ksort/uasort- обычныйsortсбросит ключи в0, 1, 2, ...и потеряет связь «ключ → значение». - Типизируй параметры как
arrayв сигнатуре функции, а внутри сразу валидируй структуру (array_key_exists,is_string) - PHP не проверит «массив строк» за тебя.
Мини-задание
- Создай массив товаров (
name,price), выведи список - Посчитай сумму цен через
array_reduce - С помощью
array_filterвыбери товары дороже 100 - Отсортируй товары по цене (по возрастанию) через
usort - Объедини два массива товаров через spread-оператор