PHPFlowPHP, MySQL, Laravel и JavaScript

Массивы в PHP: создание, перебор, сортировка и поиск

Обновлено:

Коротко

PHP массив - это набор пар "ключ → значение", который создают квадратными скобками: $a = ['php', 'mysql']. Элемент добавляют записью $a[] = $x, удаляют через unset(), перебирают циклом foreach, сортируют функциями sort(), asort() и usort(), ищут через in_array() и array_search().

Содержание
  1. Что такое массив в PHP и как его создать
  2. Индексированные, ассоциативные и многомерные массивы
  3. Как вывести массив на экран
  4. Добавить элемент в массив
  5. Удалить элемент массива
  6. Первый и последний элемент массива
  7. Длина массива и проверка на массив
  8. Перебор массива
  9. Сортировка массива
  10. Поиск в массиве
  11. Сравнение массивов
  12. Массив в строку и JSON
  13. Распаковка массива в переменные

Что такое массив в PHP и как его создать

Массив в PHP - упорядоченный набор пар "ключ → значение". Ключом может быть целое число или строка, значением - что угодно: числа, строки, объекты, другие массивы. Один и тот же тип array в PHP играет роль и списка, и словаря, и стека, и очереди.

Схема устройства массива PHP
Массив хранит пары ключ - значение; ключ бывает числом или строкой, значение - любым

Современная запись массива - квадратные скобки. Старая форма array() тоже работает, но в новом коде её почти не используют.

<?php
$empty = [];                          // пустой массив
$fruits = ['яблоко', 'груша', 'слива']; // ключи 0, 1, 2 - автоматически
$old = array(1, 2, 3);                // устаревшая запись, то же самое

$numbers = range(1, 10);              // [1, 2, ..., 10]
$zeros = array_fill(0, 5, 0);         // [0, 0, 0, 0, 0]
$map = array_combine(['a', 'b'], [1, 2]); // ['a' => 1, 'b' => 2]

Индексированные, ассоциативные и многомерные массивы

По виду ключей массивы условно делят на три типа. Для PHP это один и тот же тип данных, разница только в том, как вы их используете.

ВидКлючиПример
Индексированный (список)0, 1, 2... по порядку['php', 'js']
АссоциативныйСтроки['name' => 'Ольга']
МногомерныйЛюбые, значения - массивы[['id' => 1], ['id' => 2]]

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

Ассоциативный массив хранит данные под именованными ключами - как запись из базы или настройки. Обращаются к элементу по ключу в квадратных скобках.

<?php
$user = [
    'id'    => 15,
    'name'  => 'Ольга',
    'email' => 'olga@example.com',
];

echo $user['name'];          // Ольга
$user['role'] = 'admin';     // добавить новый ключ
echo $user['phone'] ?? '-';  // значение по умолчанию, если ключа нет

Строковые ключи, похожие на целые числа, PHP приводит к int: $a['5'] и $a[5] - один и тот же элемент. Ключи true и false превращаются в 1 и 0, а null - в пустую строку.

Многомерный массив

Многомерный массив - массив, элементы которого тоже массивы. Так обычно выглядят строки, полученные из базы через fetchAll() (подробнее в статье про PDO в PHP), или дерево категорий.

<?php
$products = [
    ['id' => 1, 'title' => 'Ноутбук', 'price' => 72000, 'tags' => ['it', 'sale']],
    ['id' => 2, 'title' => 'Мышь',    'price' => 1500,  'tags' => ['it']],
    ['id' => 3, 'title' => 'Кресло',  'price' => 18900, 'tags' => []],
];

echo $products[0]['title'];      // Ноутбук
echo $products[0]['tags'][1];    // sale
$products[2]['tags'][] = 'home'; // добавить тег третьему товару

Как вывести массив на экран

echo для массива выведет только слово "Array" и предупреждение "Array to string conversion". Чтобы посмотреть содержимое при отладке, есть три функции:

  • print_r($a) - компактно показывает ключи и значения;
  • var_dump($a) - дополнительно выводит типы и длины строк;
  • var_export($a) - печатает массив как валидный PHP-код, который можно вставить в конфиг.

В браузере оборачивайте вывод в <pre>, иначе все строки сольются в одну:

<?php
$cfg = ['debug' => true, 'langs' => ['ru', 'en']];

echo '<pre>';
print_r($cfg);
echo '</pre>';

// Вернуть результат строкой, а не выводить - например, в лог
$dump = print_r($cfg, true);
error_log($dump);
Вывод массива через print_r в браузере
Так print_r внутри тега pre показывает массив в браузере

Для вывода пользователю перебирайте массив в цикле и формируйте HTML, а для API отдавайте JSON - об этом ниже.

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

Чтобы добавить элемент в конец списка, пишут пустые квадратные скобки: $a[] = $value. PHP возьмёт ключ на единицу больше максимального целого. Для ассоциативного массива указывают ключ явно.

<?php
$cart = ['хлеб'];

$cart[] = 'молоко';                 // в конец
array_push($cart, 'сыр', 'масло');  // несколько в конец
array_unshift($cart, 'кофе');       // в начало, ключи пересчитаются
// ['кофе', 'хлеб', 'молоко', 'сыр', 'масло']

$prices = [];
$prices['хлеб'] = 65;               // по ключу
array_splice($cart, 2, 0, ['чай']); // вставить на позицию 2

Объединить массивы

Объединить массивы PHP позволяет тремя способами, и они по-разному обходятся с совпадающими ключами:

<?php
$defaults = ['lang' => 'ru', 'theme' => 'light', 'limit' => 20];
$custom   = ['theme' => 'dark'];

array_merge($defaults, $custom); // theme = dark: строковые ключи перезаписываются
$custom + $defaults;             // theme = dark: левый массив главнее
[...$defaults, ...$custom];      // распаковка, с PHP 8.1 и для строковых ключей

array_merge([1, 2], [3, 4]);     // [1, 2, 3, 4] - числовые ключи пересчитаны
[1, 2] + [3, 4, 5];              // [1, 2, 5] - совпавшие ключи 0 и 1 не тронуты

Удалить элемент массива

Чтобы удалить элемент массива по ключу, используйте unset(). Важная деталь: ключи после этого не пересчитываются, в списке появится "дыра". Если нужен список с ключами по порядку, вызовите array_values().

<?php
$list = ['a', 'b', 'c', 'd'];

unset($list[1]);              // [0 => 'a', 2 => 'c', 3 => 'd']
$list = array_values($list);  // [0 => 'a', 1 => 'c', 2 => 'd']

array_shift($list);           // удалить первый элемент и вернуть его
array_pop($list);             // удалить последний элемент
array_splice($list, 0, 1);    // удалить 1 элемент с позиции 0

Удалить элемент по значению можно через поиск ключа или через array_diff(), если таких значений несколько:

<?php
$tags = ['php', 'spam', 'mysql', 'spam'];

// Одно вхождение
$key = array_search('mysql', $tags, true);
if ($key !== false) {
    unset($tags[$key]);
}

// Все вхождения
$tags = array_values(array_diff($tags, ['spam']));

// Удалить пустые элементы массива: '', null, false, [] (и 0 тоже)
$clean = array_filter(['a', '', null, 'b', 0]);          // ['a', 'b']
$keepZero = array_filter([0, '', 5], fn($v) => $v !== '' && $v !== null);
Удаление элемента массива через unset
После unset в списке остаётся пропуск, array_values пересчитывает ключи

Первый и последний элемент массива

Индекс [0] подходит только для списков: в ассоциативном массиве или после unset() элемента с ключом 0 может не быть. Надёжный способ - функции array_key_first() и array_key_last(), а в PHP 8.5 появились array_first() и array_last(), которые сразу возвращают значение (или null для пустого массива).

<?php
$rates = ['usd' => 92.4, 'eur' => 100.1, 'cny' => 12.8];

// PHP 7.3+
$firstKey = array_key_first($rates);  // 'usd'
$first = $rates[$firstKey];           // 92.4
$last = $rates[array_key_last($rates)]; // 12.8

// PHP 8.5+
$first = array_first($rates);         // 92.4
$last = array_last($rates);           // 12.8

Функции reset() и end() тоже возвращают первый и последний элементы, но сдвигают внутренний указатель массива и требуют переменную, а не результат функции. В новом коде их лучше не применять.

Длина массива и проверка на массив

Количество элементов в массиве возвращает count() (её синоним - sizeof()). С флагом COUNT_RECURSIVE она посчитает элементы и всех вложенных массивов.

<?php
$matrix = [[1, 2], [3, 4, 5]];

count($matrix);                   // 2
count($matrix, COUNT_RECURSIVE);  // 7 - 2 вложенных массива + 5 чисел

is_array($matrix);                // true - проверка на массив
array_is_list([10, 20]);          // true - ключи 0, 1 по порядку (PHP 8.1+)
array_is_list([1 => 'a']);        // false
empty([]);                        // true - массив пустой

С PHP 8.0 count() для не-массива (например, null) выбрасывает TypeError. Если значение может отсутствовать, проверяйте его заранее или пишите count($items ?? []).

Перебор массива

Основной способ перебрать массив - цикл foreach. Он работает с любыми ключами и не требует знать длину.

<?php
$stock = ['Ноутбук' => 4, 'Мышь' => 0, 'Кресло' => 7];

foreach ($stock as $title => $qty) {
    echo "$title: $qty шт." . PHP_EOL;
}

// Изменить элементы на месте - через ссылку &
foreach ($stock as &$qty) {
    $qty *= 2;
}
unset($qty); // обязательно разорвать ссылку после цикла

Если после foreach по ссылке не сделать unset(), переменная продолжит ссылаться на последний элемент. Следующий цикл с тем же именем незаметно перезапишет его.

Для преобразований без циклов есть функции высшего порядка:

<?php
$prices = [1500, 72000, 18900];

$withVat = array_map(fn(int $p): float => $p * 1.2, $prices);   // каждому элементу
$cheap = array_filter($prices, fn(int $p): bool => $p < 20000); // отобрать
$total = array_sum($prices);                                    // сумма элементов: 92400
$max = max($prices);                                            // 72000
$sum = array_reduce($products, fn($c, $p) => $c + $p['price'], 0); // сумма по полю
Перебор ассоциативного массива в PHP
foreach перебирает пары ключ - значение, array_filter оставляет нужные элементы

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

В PHP много функций сортировки, и их легко перепутать. Все они меняют исходный массив и возвращают true, а не отсортированную копию.

ФункцияПо чему сортируетКлючи
sort / rsortПо значению, по возрастанию / убываниюПересчитываются
asort / arsortПо значениюСохраняются
ksort / krsortПо ключуСохраняются
usort / uasort / uksortПо своей функции сравненияПересчитываются / сохраняются
<?php
$files = ['img12.png', 'img10.png', 'img2.png'];
sort($files, SORT_NATURAL);  // img2, img10, img12 - "человеческий" порядок

$cities = ['Омск' => 1100, 'Казань' => 1300, 'Сочи' => 450];
arsort($cities);  // по населению, от большего; названия-ключи на месте
ksort($cities);   // сортировка массива по ключу: по алфавиту

// Сортировка многомерного массива по полю
usort($products, fn(array $a, array $b): int => $a['price'] <=> $b['price']);

// По двум полям: сначала по категории, потом по цене убыванию
usort($products, fn($a, $b) => [$a['cat'], $b['price']] <=> [$b['cat'], $a['price']]);

Оператор "космический корабль" <=> возвращает -1, 0 или 1 - именно то, что ждёт функция сравнения. Для кириллицы в ключах учитывайте, что ksort сравнивает байты: "Ё" окажется раньше "А". Если это важно, используйте класс Collator из расширения intl.

Поиск в массиве

Для поиска по значению есть in_array() (есть ли элемент) и array_search() (какой у него ключ). Всегда передавайте третий аргумент true - строгое сравнение. Без него in_array('abc', [0]) в старых версиях давал true, а in_array('1e1', ['10']) даёт true и сейчас.

<?php
$roles = ['editor', 'admin', 'viewer'];

in_array('admin', $roles, true);       // true
array_search('viewer', $roles, true);  // 2 (или false, если не найдено)

$user = ['name' => 'Ольга', 'phone' => null];
isset($user['phone']);                 // false - ключ есть, но значение null
array_key_exists('phone', $user);      // true - проверяет именно ключ

// Найти элемент многомерного массива по полю (PHP 8.4+)
$item = array_find($products, fn(array $p): bool => $p['id'] === 2);
$hasSale = array_any($products, fn($p) => in_array('sale', $p['tags'], true));

До PHP 8.4 вместо array_find() используют комбинацию с array_column(): она вытаскивает из многомерного массива одну колонку и может сразу сделать её ключом.

<?php
$titles = array_column($products, 'title');       // ['Ноутбук', 'Мышь', 'Кресло']
$byId = array_column($products, null, 'id');      // ключи - id товаров
$mouse = $byId[2] ?? null;                        // быстрый поиск по ключу

Если по большому массиву приходится искать много раз, один раз переиндексируйте его по нужному полю через array_column($rows, null, 'id'). Поиск по ключу работает мгновенно, а in_array() каждый раз перебирает все элементы.

Сравнение массивов

<?php
$old = ['php', 'mysql', 'jquery'];
$new = ['php', 'mysql', 'vue'];

array_diff($new, $old);       // ['vue'] - что добавилось
array_diff($old, $new);       // ['jquery'] - что пропало
array_intersect($old, $new);  // ['php', 'mysql'] - общие значения
array_diff_key($a, $b);       // разница по ключам

['a' => 1, 'b' => 2] == ['b' => 2, 'a' => 1];  // true - те же пары
['a' => 1, 'b' => 2] === ['b' => 2, 'a' => 1]; // false - важен порядок и типы

Массив в строку и JSON

Перевести PHP массив в строку можно по-разному, в зависимости от цели. Для простого списка через запятую подходит implode(), для передачи в JavaScript или API - json_encode().

<?php
$tags = ['php', 'mysql', 'docker'];
echo implode(', ', $tags);   // php, mysql, docker

$order = ['id' => 77, 'items' => $tags, 'paid' => true];
echo json_encode($order, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
// {"id":77,"items":["php","mysql","docker"],"paid":true}

// Обратно: JSON → ассоциативный массив
$data = json_decode('{"city":"Пермь"}', true, flags: JSON_THROW_ON_ERROR);
echo $data['city']; // Пермь
Массив в JSON с кириллицей
Флаг JSON_UNESCAPED_UNICODE сохраняет русские буквы при переводе массива в JSON

Флаг JSON_UNESCAPED_UNICODE оставляет кириллицу читаемой вместо последовательностей П. Остальные флаги и разбор ошибок описаны в статье про JSON в PHP. Обратная задача - строку в массив - решается через explode() и preg_split(), они разобраны в статье "Строки в PHP".

Объект в массив и обратно

Объект превращают в массив приведением типа (array) или функцией get_object_vars(), которая вернёт только доступные свойства. Вложенные объекты при этом не преобразуются - для полного перевода удобен приём через JSON.

<?php
$point = new stdClass();
$point->x = 10;
$point->y = 20;

$arr = (array) $point;              // ['x' => 10, 'y' => 20]
$obj = (object) ['x' => 1, 'y' => 2]; // массив в объект stdClass

// Глубокое преобразование вложенных объектов
$deep = json_decode(json_encode($response), true);

Распаковка массива в переменные

Квадратные скобки слева от знака = раскладывают массив по переменным. Так удобно возвращать из функции несколько значений и перебирать пары.

<?php
[$width, $height] = [1920, 1080];
['name' => $name, 'email' => $email] = $user;  // по ключам

foreach ($products as ['title' => $title, 'price' => $price]) {
    echo "$title - $price ₽" . PHP_EOL;
}

[$a, $b] = [$b, $a]; // поменять значения местами

Полный список функций для массивов с описанием параметров есть в документации php.net. Как подставлять элементы массива прямо в строки - "{$user['name']}" - разобрано в статье об интерполяции строк.

Частые вопросы

Как добавить элемент в массив PHP?

В конец - $a[] = $value или array_push($a, $value), в начало - array_unshift($a, $value), по ключу - $a['key'] = $value.

Как удалить элемент массива по ключу?
unset($a[$key]). Чтобы после этого ключи списка шли по порядку, выполните $a = array_values($a).
Как узнать длину массива в PHP?

Функцией count($a). Для подсчёта вместе с вложенными массивами - count($a, COUNT_RECURSIVE).

Как получить первый элемент массива?

В PHP 8.5 - array_first($a). В более ранних версиях - $a[array_key_first($a)], этот способ работает и для ассоциативных массивов.

Как перевести массив в строку?

Список через разделитель - implode(', ', $a), вся структура для API или хранения - json_encode($a, JSON_UNESCAPED_UNICODE).

Чем isset отличается от array_key_exists?
isset() вернёт false, если ключ есть, но значение равно null. array_key_exists() проверяет только наличие ключа.