Александр Некрасов · Автономное руководство

PHP: полный мануал с примерами, функциями и ООП

Разделы этой страницы
  1. Полный справочник функций массивов
  2. Массив → нужная операция → проверяемый результат
  3. Выбрать по задаче и увидеть весь состав категории
  4. Не перепутать новый массив, изменение и статус
  5. Все константы категории: какой функции они задают правило
  6. Полная таблица выбора сортировки и стабильность
  7. Ключ, значение, глубина и форма результата
  8. Стоимость, безопасные границы и последовательный маршрут
  9. Функции и методы этой темы
  10. Код и руководство с собой
PHP 8.5.11149 глав4458 карточек справочника
Дерево руководства

Глава 70 · От первого опыта к практике

Полный справочник функций массивов

Все 88 пунктов официальной категории Arrays: от первого элемента и преобразования до сравнений, сортировки, курсора и миграции удалённой each.

Массив → нужная операция → проверяемый результат

Наглядная модель

Выбрать товары и подготовить список для JSON

Фильтр оставляет ключи исходных ячеек. Перед передачей именно списка их нужно перенумеровать.

  1. [0 => Книга, 1 => Лампа, 2 => Стол]

    Исходный список из трёх товаров.

  2. array_filter

    Предположим, условию соответствуют только Книга и Стол.

  3. [0 => Книга, 2 => Стол]

    Ключи сохранены; образовался пропуск 1.

  4. array_values

    Получаем последовательные ключи 0 и 1 для договора списка.

  5. json_encode

    API получает JSON-массив, а не объект с числовыми именами полей.

Перенумерация нужна для списка. Если ключи являются артикулами или ID, сохраняйте их и выберите формат словаря осознанно.

В ответе API, строках SQL и данных формы часто уже есть массив. Прежде чем выбирать функцию, назовите задачу: оставить доступные товары, сложить суммы, найти ключ или изменить очередь. Одинаковое слово «массив» не означает одинаковую форму: список хранит порядок, словарь — связь идентификатора со значением, таблица — вложенные записи.

От ответа API к доступным товарам
  1. Создать обычные PHP-строки товаров p1 с остатком 2 и p2 с остатком 0
  2. Проверить форму строк и оставить положительный остаток
  3. Выдать список с одной строкой p1; формат ключей выбрать явно

Массив сам не знает, что поле stock означает остаток; это правило задаёт программа. Функции стандартной категории Arrays доступны в составе PHP; отдельный пакет для них не устанавливают. Новые функции всё же требуют своей версии: array_is_list — 8.1, array_all/any/find/find_key — 8.4, array_first/last — 8.5. each удалена в 8.0 и представлена для миграции.

Если синтаксис новый: переменная и присваивание → ключ, значение, чтение элемента → вызов, параметры, return → callback как переданная функция. Запись array $items в справочной сигнатуре описывает требуемый тип; она не создаёт массив. array ...$arrays означает несколько входов, &$array — изменение переданной переменной, : array — тип результата. Подробно: параметры и типы.

Выбрать по задаче и увидеть весь состав категории

Каждая ссылка ведёт к самостоятельной карточке с договором, схемой, первым опытом и применением. Ранее написанные карточки остаются на своих адресах в учебной главе «Массивы»; здесь собран общий вход. Сходное имя не означает одинаковое поведение: сначала сравните результат и правила ключей.

ЗадачаФункции
Создать и разобратьarray, list, range, array_fill, array_fill_keys, array_combine, compact, extract
Проверить, найти и прочитатьarray_all, array_any, array_find, array_find_key, array_first, array_last, array_key_first, array_key_last, array_is_list, array_key_exists, key_exists, in_array, array_search
Получить колонки, ключи и частотыarray_keys, array_values, array_column, array_count_values, array_flip, count, sizeof
Преобразовать и обойтиarray_change_key_case, array_filter, array_map, array_reduce, array_walk, array_walk_recursive, array_sum, array_product, array_unique
Объединить и обновитьarray_merge, array_merge_recursive, array_replace, array_replace_recursive
Разделить, вставить и удалитьarray_chunk, array_slice, array_splice, array_reverse, array_pad, array_push, array_pop, array_shift, array_unshift
Разностьarray_diff, array_diff_assoc, array_diff_key, array_diff_uassoc, array_diff_ukey, array_udiff, array_udiff_assoc, array_udiff_uassoc
Пересечениеarray_intersect, array_intersect_assoc, array_intersect_key, array_intersect_uassoc, array_intersect_ukey, array_uintersect, array_uintersect_assoc, array_uintersect_uassoc
Сортировкаsort, rsort, asort, arsort, ksort, krsort, natsort, natcasesort, usort, uasort, uksort, array_multisort
Указатель и случайный порядокcurrent, pos, key, next, prev, reset, end, each, array_rand, shuffle

Псевдонимы входят в официальный состав: key_exists = array_key_exists, pos = current, sizeof = count. array и list — конструкции языка, поэтому обычные правила callable применимы к ним не полностью. Этот каталог охватывает 88 пунктов ref.array, включая устаревшую each. Он не является утверждением, что здесь уже написан весь PHP Manual.

Не перепутать новый массив, изменение и статус

Операции чтения часто возвращают новый массив; операции сортировки, очереди и указателя работают с переданной переменной. Присваивание статуса вместо данных — отдельная частая ошибка.

ДоговорПримеры
Возвращает новый массивarray_filter, array_map, array_slice, array_merge, array_replace, array_diff
Меняет массив и возвращает статус/размерsort, usort, array_walk, array_push, array_unshift
Меняет массив и возвращает удалённоеarray_splice, array_pop, array_shift
Только читает / меняет указательcurrent и key читают; next, end меняют позицию, не удаляя данные.
Копия перед сортировкой
  1. original содержит [30,10,20]
  2. sorted получает значение массива; sort меняет sorted
  3. original остаётся прежним, статус равен true
Сохранить оригинальный порядокСамостоятельный пример
<?php
$original = [30, 10, 20];
$sorted = $original;
$status = sort($sorted, SORT_NUMERIC);
echo json_encode($original), "
";
echo json_encode($sorted), "
";
var_dump($status);
Ожидаемый результат
[30,10,20]
[10,20,30]
bool(true)

В выводе JSON здесь только способ показать массив. Обычное копирование массива не клонирует находящиеся внутри объекты; ссылки на элементы также требуют отдельного понимания: ссылки и владение данными.

Все константы категории: какой функции они задают правило

Константа — именованное значение без знака $. Используйте имя, а не случайно запомненное число. Знак | объединяет только совместимые флаги; не все режимы разрешено смешивать.

КонстантыНазначение
CASE_LOWER / CASE_UPPERarray_change_key_case: нижний/верхний регистр ключей. С PHP 8.2 преобразование только ASCII.
SORT_ASC / SORT_DESCarray_multisort: направление предыдущей колонки. Это не аргументы направления для sort.
SORT_REGULARОбычные правила сравнения PHP; смешанные типы могут дать неожиданный предметный порядок.
SORT_NUMERICСравнение числовых представлений.
SORT_STRINGСравнение строковых представлений. Это также режим по умолчанию у array_unique.
SORT_LOCALE_STRINGСравнение строк в текущей locale; результат зависит от окружения/setlocale.
SORT_NATURALЧисловые фрагменты строк идут естественным порядком: item2 перед item10.
SORT_FLAG_CASEДобавка через | к SORT_STRING или SORT_NATURAL; нечувствительность к ASCII-регистру с PHP 8.2.
ARRAY_FILTER_USE_KEYarray_filter: callback получает только ключ.
ARRAY_FILTER_USE_BOTHarray_filter: callback получает значение, затем ключ. Без режима — только значение.
COUNT_NORMAL / COUNT_RECURSIVEcount / sizeof: верхний уровень либо вложенные массивы с учётом контейнеров.
EXTR_OVERWRITEextract по умолчанию перезаписывает существующее имя.
EXTR_SKIPextract оставляет существующее имя нетронутым.
EXTR_PREFIX_SAMEПри коллизии extract добавляет prefix и подчёркивание.
EXTR_PREFIX_ALLextract добавляет prefix ко всем именам.
EXTR_PREFIX_INVALIDextract добавляет prefix только к недопустимым/числовым именам.
EXTR_IF_EXISTSextract изменяет только уже существующие имена.
EXTR_PREFIX_IF_EXISTSextract создаёт prefixed-имя только при наличии исходного имени.
EXTR_REFSДополнительный флаг extract: переменные связаны с элементами массива по ссылке. Может использоваться один или через | с основным режимом.

Подробные отказы, префиксы и область применения — в extract. Отбор существующих имён не делает недоверенные значения безопасными. SORT_NATURAL и SORT_FLAG_CASE не перечислены как режимы array_unique; не переносите все флаги сортировки в любую функцию с параметром flags.

Полная таблица выбора сортировки и стабильность

У выбора сортировки четыре независимых вопроса: что сравнивается, сохраняются ли ключи, какое направление и как определено равенство. Все функции в этой таблице изменяют переданный массив. Результат true нельзя выдавать за отсортированный список.

ФункцияСравнивает / сохраняет ключиПорядок
array_multisortЗначения нескольких колонок / Строковые да; числовые нетПервый критерий, затем следующие
asortЗначения / ДаВозрастание
arsortЗначения / ДаУбывание
krsortКлючи / ДаУбывание
ksortКлючи / ДаВозрастание
natcasesortЗначения / ДаЕстественный без ASCII-регистра
natsortЗначения / ДаЕстественный с регистром
rsortЗначения / НетУбывание
shuffleЗначения / НетСлучайный порядок
sortЗначения / НетВозрастание
uasortЗначения / ДаСвой компаратор
uksortКлючи / ДаСвой компаратор
usortЗначения / НетСвой компаратор

С PHP 8 сортировка стабильна: если два элемента равны по всем её критериям, их исходный взаимный порядок сохраняется. Это свойство не относится к случайному shuffle как к сравнению равных значений и не означает, что произвольный порядок входа уже подходит пользователю.

Равные приоритеты
  1. Заказы A и B имеют приоритет 1; C — 0
  2. Сравниваем только приоритет
  3. C перемещается вперёд, A остаётся перед B
Увидеть стабильность на одинаковом приоритетеСамостоятельный пример
<?php
$orders = [['id' => 'A', 'priority' => 1], ['id' => 'B', 'priority' => 1], ['id' => 'C', 'priority' => 0]];
usort($orders, function ($a, $b) { return $a['priority'] <=> $b['priority']; });
echo implode(',', array_column($orders, 'id')), "
";
Ожидаемый результат
C,A,B

function(...) передаёт сравнение, <=> возвращает -1/0/1. Когда приоритеты равны, callback отдаёт 0, не выбирая порядок по ID. Второй критерий добавляют явно, если он нужен задаче.

Ключ, значение, глубина и форма результата

Разность diff сохраняет элементы первого массива, отсутствующие во всех последующих. intersect требует совпадение в каждом последующем. Порядок аргументов важен, а количество повторов — не вычитание математических мультимножеств.

СемействоПравило
diff / intersectВстроенное равенство строковых представлений значений; ключи сравниваемых массивов не важны.
*_assocДолжны совпасть ключ и значение одной пары.
*_keyСравниваются только ключи, данные под ними могут различаться.
*_uassoc / *_ukeyПользовательское сравнение ключей.
array_udiff / array_uintersectПользовательское сравнение значений.
array_udiff_uassoc / array_uintersect_uassocДва callback: сначала значения, затем ключи.

Встроенное равенство значений этих diff/intersect — не режим === по исходным типам. Число 1 и строка "1" совпадут. Для строгой схемы сначала проверьте типы; для собственного правила нужен компаратор с целым отрицательным/нулевым/положительным результатом. Ни diff, ни intersect не спускаются по всему JSON-дереву автоматически. Как извлечь и проверить вложенные данные; как строить явный обход.

Мини-упражнение: есть [10 => "A", 20 => "B"] и [30 => "A"]. До запуска предскажите разность по значениям, разность по ключам и разность по парам. Затем откройте три карточки и объясните, почему ответы разные.

Стоимость, безопасные границы и последовательный маршрут

Операция над готовым массивом не делает источник потоковым. array_chunk и slice полезны для уже имеющихся небольших данных, но не отменяют загрузку миллиона строк до этого. Повторные merge с растущим результатом, shift больших очередей и дорогие callback сортировки требуют отдельного измерения на вашей нагрузке.

  • Нужен первый ответ: array_find/any/all могут завершить проверку раньше; полный filter создаёт весь результат.
  • Нужно много проверок уникального ID: заранее построенный словарь может заменить повторные линейные поиски; учтите преобразование ключей и память.
  • Нужно пройти данные один раз: foreach часто яснее цепочки временных map/filter/values.
  • Нужна непредсказуемость: array_rand/shuffle не подходят для секретов; выбирайте Randomizer с Secure либо random_int/random_bytes.
  • Нужны независимые объекты: копирование массива и array_fill одним объектом не клонируют экземпляры.

Маршрут после базы: array_filter → array_map → array_column → array_reduce → array_replace_recursive → usort. Практические продолжения: приём и проверка формы, интеграция с API, измерение стоимости вместо догадок.

Функции и методы этой темы

Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.

arrayСобрать несколько связанных значений в одно: список товаров или запись с именованными полями.

PHP 4+ · standard

array(key => value, ...) → array; короткая форма: [key => value, ...]

Собрать несколько связанных значений в одно: список товаров или запись с именованными полями.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
ЭлементыМежду скобками перечисляются значения через запятую. В key => value левая часть задаёт ключ, правая — значение.
КлючЦелое число или строка. Без явного ключа PHP выбирает следующий целочисленный индекс; в пустом массиве первый — 0.
Повтор ключаПозднее значение заменяет прежнее. Это словарь, а не место для нескольких значений под одним ключом.
ВозвратНовый массив в заданном порядке; array() и [] без элементов создают пустой массив.
Отказ и диагностикаНедопустимый тип ключа, например массив, вызывает TypeError. Преобразования допустимых ключей могут создать незаметную коллизию.

Это конструкция языка, а не обычная функция: её нельзя вызвать через строковое имя функции. array(...) и [...] — две записи одного значения; короткая форма доступна с PHP 5.4. = сохраняет массив в переменной, [0] справа читает элемент с ключом 0.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: ключ, значение и порядок массива.

Что происходит в первом опыте
  1. Создать [чай, кофе] с ключами 0 и 1.
  2. Прочитать обе позиции для подписи.
  3. Заменить drinks[1] на воду и прочитать новый заказ.
Записать две позиции и собрать подпись заказаСамостоятельный пример
<?php
$drinks = array('чай', 'кофе');
$firstDrink = $drinks[0];
$secondDrink = $drinks[1];
echo 'В заказе: ', $firstDrink, ' и ', $secondDrink, ".\n";
$drinks[1] = 'вода';
echo 'После изменения: ', $drinks[0], ' и ', $drinks[1], ".\n";
Ожидаемый результат
В заказе: чай и кофе.
После изменения: чай и вода.

Array — языковая конструкция создания массива. Круглые скобки ограничивают значения, запятая отделяет их; присваивание сохраняет весь массив в drinks. Первый автоматически назначенный ключ 0, следующий 1. Квадратные скобки после переменной читают или изменяют одну ячейку. Короткая запись ['чай', 'кофе'] создаёт тот же массив. Изменение ячейки не меняет ранее прочитанную secondDrink: это отдельное строковое значение.

Запись товара и замена повторного ключаСамостоятельный пример
<?php
$product = [
    'sku' => '0041',
    'stock' => 2,
    'stock' => 0,
];
echo $product['sku'], ':', $product['stock'], "\n";
$queue = [5 => 'paid', 'packed'];
echo json_encode($queue), "\n";
Ожидаемый результат
0041:0
{"5":"paid","6":"packed"}

Второй stock заменил первый; ноль сохранён как значение. После явного ключа 5 автоматический ключ равен 6. Последняя запятая разрешена и удобна в многострочной записи.

Нюансы и выбор. Вложенный массив создаётся теми же скобками, но уровень вложенности не добавляет проверку схемы. Строка-ключ "8" обычно становится int 8; "08" сохраняет строковую форму. Не путайте максимальный числовой ключ с количеством элементов. Для отрицательных автоматических ключей есть изменение PHP 8.3; оно подробно разобрано в правилах ключей и добавления. Массивы из результата SQL или json_decode используют те же правила, что литерал.

Сравните: list, array_fill, range, count. Выбрать операцию по задаче.

listРазложить строку отчёта в несколько понятных переменных одним присваиванием.

PHP 4+ · standard

list($first, $second, ...) = $array; также [$first, $second] = $array

Разложить строку отчёта в несколько понятных переменных одним присваиванием.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
Цели слеваПеременные, которым присваиваются элементы. Пустое место между запятыми пропускает соответствующий индекс. Полностью пустой list() недопустим.
КлючиБез явных ключей выбираются 0,1,…, а не первые элементы произвольного словаря. С PHP 7.1 можно указать ключ => переменная. Не смешивайте явную и неявную форму в одном списке.
Правая частьМассив или объект ArrayAccess. Это источник значений, а не переменные, которые нужно создать по динамическим именам.
ВозвратПрисваивает элементы целевым переменным; значение всего выражения присваивания — исходный массив.
Отказ и диагностикаОтсутствующий ключ даёт E_WARNING и null в PHP 8. Скаляр даёт null целям; с PHP 8.5 ненулевой не-массив дополнительно предупреждает. Обычный объект без ArrayAccess вызывает Error.

list($sku, $stock) = $row; читает row[0] и row[1]. Запись в квадратных скобках — тот же разбор, не создание нового списка слева. Сначала убедитесь, что строка имеет нужную форму.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: ключ, значение и порядок массива.

Что происходит в первом опыте
  1. В строке 0→0041, 1→3.
  2. List создаёт sku=0041 и quantity=3.
  3. Собрать из этих переменных понятную строку накладной.
Дать имена двум колонкам накладнойСамостоятельный пример
<?php
$row = ['0041', 3];
list($sku, $quantity) = $row;
$label = 'Артикул ' . $sku . ': ' . $quantity . ' упаковки';
echo $label, "\n";
[$sameSku, $sameQuantity] = $row;
echo 'Короткая запись: ', $sameSku, ', ', $sameQuantity, "\n";
Ожидаемый результат
Артикул 0041: 3 упаковки
Короткая запись: 0041, 3

Сначала PHP вычисляет правый массив row. List присваивает элемент с ключом 0 переменной sku, с ключом 1 переменной quantity. Это распаковка значений, а не перебор и не создание функции. Строковый артикул сохраняет начальные нули. Точка соединяет части подписи. Короткая форма слева [] делает то же. Форма строки заранее известна; отсутствие ключа потребовало бы проверки до распаковки.

Разобрать поля API независимо от их порядкаСамостоятельный пример
<?php
$row = ['stock' => 0, 'sku' => '0072'];
['sku' => $sku, 'stock' => $stock] = $row;
echo $sku, ':', $stock, "\n";
$slots = [4, 9];
[&$first] = $slots;
$first = 7;
unset($first);
echo json_encode($slots), "\n";
Ожидаемый результат
0072:0
[7,9]

Именованные ключи появились в PHP 7.1, ссылки в распаковке — в 7.3. & связал first с элементом slots[0]; unset разорвал связь. Для обычного чтения ссылка не нужна.

Увидеть отсутствующую колонку, а не принять её за нольСамостоятельный пример
<?php
set_error_handler(function ($severity, $message) {
    echo $severity === E_WARNING ? "Предупреждение\n" : "Другая диагностика\n";
    return true;
});
try {
    [$sku, $stock] = ['0041'];
    var_dump($stock);
} finally {
    restore_error_handler();
}
Ожидаемый результат
Предупреждение
NULL

Обработчик нужен только для наблюдения за диагностикой этого опыта и восстанавливается. В реальном импорте до распаковки проверяют наличие обязательной колонки; null не является корректным остатком.

Нюансы и выбор. Допускается вложенная распаковка и использование в foreach. Она выбирает значения, но не проверяет их типы и не ищет похожие имена. ArrayAccess означает специальный объект с договором чтения по ключу; обычный stdClass им не является. Ссылки и вложенность требуют внимательного владения данными; явные обращения $row["sku"] часто яснее для одной колонки. Не используйте трюки с порядком присваивания нескольким $array[] как переносимый договор между старыми версиями PHP.

Сравните: array, array_column, extract. Выбрать операцию по задаче.

rangeСоздать ограниченную последовательность: номера страниц, интервалы измерения или ASCII-метки.

PHP 4+ · standard

range(string|int|float $start, string|int|float $end, int|float $step = 1): array

Создать ограниченную последовательность: номера страниц, интервалы измерения или ASCII-метки.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
start / endНачало и последняя возможная граница. Направление выбирается по их соотношению; end входит только если шаг попадает точно.
stepРасстояние между соседними значениями. Ноль запрещён; отрицательный шаг допустим для убывания. Целочисленный float вроде 2.0 трактуется как int с PHP 8.3.
Строковые границыДля однобайтовых строк и целого шага получается последовательность байтов. Числовые строки длиной больше байта требуют отдельного внимания к типу результата (опыт ниже). Это не генератор букв Unicode.
ВозвратГотовый массив int, float или однобайтовых строк с числовыми ключами с нуля.
Отказ и диагностикаValueError: шаг 0, неконечные числовые значения (бесконечность INF или не-число NAN), отрицательный шаг для возрастания; в PHP 8.5.11 также шаг больше расстояния между различными числовыми границами. Равные границы допускают один элемент. С PHP 8.3 ужесточены типы границ; массив/объект/ресурс дают TypeError. Неподходящие строковые режимы могут предупреждать.

В range(1, 5, 2) числа означают начало 1, границу 5 и шаг 2. Функция сразу создаёт все элементы; цикл или генератор позволяет выдавать их постепенно.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Начало 1; шаг 2; верхняя граница 5.
  2. Получаются значения 1, затем 3, затем 5.
  3. Следующий кандидат 7 не входит; результат [1,3,5].
Номера с заданным шагомСамостоятельный пример
<?php
echo json_encode(range(1, 5, 2)), "\n";
echo json_encode(range(5, 1, 2)), "\n";
echo json_encode(range(1, 6, 2)), "\n";
Ожидаемый результат
[1,3,5]
[5,3,1]
[1,3,5]

Положительный размер шага подходит и убывающей последовательности. Последняя граница 6 не добавляется искусственно.

Метки небольших секций и страницыСамостоятельный пример
<?php
$sections = range('A', 'C');
echo implode(',', $sections), "\n";
$pages = range(1, 3);
foreach ($pages as $page) {
    echo '/catalog?page=', $page, "\n";
}
Ожидаемый результат
A,B,C
/catalog?page=1
/catalog?page=2
/catalog?page=3

Первая последовательность состоит из ASCII-байтов. Для русских букв или сложных Unicode-символов такой диапазон не подходит. URL здесь только выводятся, сетевых запросов нет.

Некорректный шаг — ошибка настройки, а не пустой списокСамостоятельный пример
<?php
foreach ([0, -1] as $step) {
    try {
        range(1, 3, $step);
    } catch (ValueError) {
        echo "Неверный шаг\n";
    }
}
echo json_encode(range(3, 1, -1)), "\n";
Ожидаемый результат
Неверный шаг
Неверный шаг
[3,2,1]

Для отрицательного шага возрастания ожидаемое поведение относится к PHP 8.3+. Не перехватывайте ошибку настройки, чтобы выдавать внешнему клиенту ложный успешный пустой результат.

Не вывести тип результата только из кавычекСамостоятельный пример
<?php
echo json_encode(range('1', '3')), "\n";
echo json_encode(range('10', '12')), "\n";
echo json_encode(range(10, 12)), "\n";
try { range(1, 2, 3); }
catch (ValueError) { echo "Шаг больше диапазона\n"; }
Ожидаемый результат
["1","2","3"]
[10,11,12]
[10,11,12]
Шаг больше диапазона

Проверено на PHP 8.5.11: однобайтовые числовые строки образуют строки-байты, многобайтовые числовые строки здесь образуют числа. Краткая формулировка Manual о двух строках не описывает этот частный случай достаточно точно; для числового договора задавайте проверенные int/float явно.

Нюансы и выбор. Память растёт с количеством созданных элементов: не передавайте пользовательский верхний предел без ограничения. С PHP 8.3 изменены правила строковых границ; нельзя считать, что любые две строки всегда дадут тот же тип элементов. Для числовых данных сначала явно проверьте и задайте числовой тип. Пустая строка предупреждает и трактуется как 0; многобайтовая нечисловая граница, смесь числа с приводимой строкой и нечисловые строки с дробным шагом тоже могут предупреждать. Float-диапазон использует двоичную арифметику, поэтому денежные шаги лучше задавать целыми копейками.

Сравните: array_fill, array_fill_keys, array_map. Выбрать операцию по задаче.

array_fillЗаранее подготовить одинаковые начальные значения: например четыре свободных места в расписании.

PHP 4.2+ · standard

array_fill(int $start_index, int $count, mixed $value): array

Заранее подготовить одинаковые начальные значения: например четыре свободных места в расписании.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
start_indexПервый целочисленный ключ. Последующие идут по одному, включая отрицательные в PHP 8.
countКоличество элементов, от 0 до 2147483647. Это предел типа API, не обещание доступной памяти.
valueЗначение для каждого элемента. Один переданный объект остаётся тем же объектом во всех ячейках.
ВозвратНовый заполненный массив; count=0 даёт []. Исходные переменные не заменяются.
Отказ и диагностикаВ PHP 8 недопустимый count вызывает ValueError; до PHP 8 были warning и false. Возможна нехватка памяти при чрезмерном размере.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Начать с ключа 9 и создать три одинаковых значения.
  2. Записать имя в ячейку 10.
  3. Вывести все часы, включая два свободных.
Подготовить и изменить три места в расписанииСамостоятельный пример
<?php
$slots = array_fill(9, 3, 'свободно');
$slots[10] = 'записана Анна';
foreach ($slots as $hour => $state) {
    echo $hour, ':00 — ', $state, "\n";
}
Ожидаемый результат
9:00 — свободно
10:00 — записана Анна
11:00 — свободно

Аргумент 9 — начальный ключ, 3 — число элементов, а не конечный час. Сначала возвращён массив с ключами 9, 10, 11 и одинаковой строкой «свободно». Затем меняется лишь значение ключа 10. Foreach берёт каждый час и его состояние для экрана расписания. Функция не знает календаря: интервалы здесь целые часы одного дня; реальное расписание с датами потребовало бы иной модели.

Отрицательные ключи и пустая заготовкаСамостоятельный пример
<?php
echo json_encode(array_fill(-2, 3, 0)), "\n";
echo json_encode(array_fill(0, 0, 'free')), "\n";
try {
    array_fill(0, -1, 'free');
} catch (ValueError) {
    echo "Количество не может быть отрицательным\n";
}
Ожидаемый результат
{"-2":0,"-1":0,"0":0}
[]
Количество не может быть отрицательным

В PHP 8 после −2 идёт −1, затем 0. В версиях до 8.0 после первого отрицательного ключа переходили к 0.

Три ссылки на один объект не являются тремя объектамиСамостоятельный пример
<?php
$prototype = (object) ['stock' => 0];
$rows = array_fill(0, 2, $prototype);
$rows[0]->stock = 3;
echo $rows[1]->stock, "\n";
Ожидаемый результат
3

(object) создаёт простой объект, ->stock обращается к его свойству. Обе ячейки держат один экземпляр. Для независимых объектов создавайте каждый отдельно; array_fill не является фабрикой и не клонирует значение.

Нюансы и выбор. Для списков обычно начинайте с 0. Если передать один объект, его состояние будет общим; это не относится к простой замене строковых ячеек первого опыта. При большом числе строк разумнее создавать данные порциями по мере необходимости.

Сравните: array_fill_keys, range, array_pad. Выбрать операцию по задаче.

array_fill_keysПодготовить словарь с известными ключами, например счётчики заказов по статусам.

PHP 5.2+ · standard

array_fill_keys(array $keys, mixed $value): array

Подготовить словарь с известными ключами, например счётчики заказов по статусам.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
keysЗначения массива становятся ключами результата; исходные ключи этого массива не используются.
valueОдинаковое стартовое значение для всех ключей. Объекты не клонируются.
ВозвратНовый словарь. Повторяющиеся или совпавшие после преобразования ключи объединяются.
Отказ и диагностикаНужен массив keys. Необычные типы ключей преобразуются в строки и могут дать диагностику или Error при невозможности строкового преобразования; передавайте заранее проверенные int/string.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Создать new=0, paid=0, sent=0.
  2. Пройти paid, new, paid: получить 1,2,0.
  3. Вывести полный отчёт, включая sent=0.
Показать все статусы заказов, включая нулевойСамостоятельный пример
<?php
$counts = array_fill_keys(['new', 'paid', 'sent'], 0);
$today = ['paid', 'new', 'paid'];
foreach ($today as $status) {
    $counts[$status]++;
}
foreach ($counts as $status => $quantity) {
    echo $status, ': ', $quantity, ' заказа', "\n";
}
Ожидаемый результат
new: 1 заказа
paid: 2 заказа
sent: 0 заказа

В первом аргументе значения new/paid/sent становятся ключами. Второй аргумент 0 задаёт начальное количество. Возвращённый словарь записан в counts; каждый ++ увеличивает выбранный счётчик на 1. Порядок отчёта определяется списком разрешённых статусов. Today здесь содержит только заранее проверенные коды: неизвестный код потребовал бы отдельной обработки, а не чтения отсутствующего счётчика.

Набор разрешённых кодов и повтор ключаСамостоятельный пример
<?php
$allowed = array_fill_keys(['A', 'B', 'A'], true);
var_dump(isset($allowed['B']));
var_dump(isset($allowed['C']));
echo count($allowed), "\n";
Ожидаемый результат
bool(true)
bool(false)
2

Повтор A не создаёт третьего элемента. Здесь значения всегда true, поэтому isset подходит; для словаря с null различайте отсутствие ключа через array_key_exists.

Нюансы и выбор. Это не проверка типа ключей. Числовые строки могут преобразоваться в int и совпасть с числовым ключом. Набор для множества повторных проверок может быть удобнее повторного сканирования in_array, но требует отдельной памяти и согласованной политики ключей.

Сравните: array_fill, array_combine, array_key_exists, in_array. Выбрать операцию по задаче.

array_combineСвязать заголовки и одну строку данных: превратить колонки CSV в именованные поля.

PHP 5+ · standard

array_combine(array $keys, array $values): array

Связать заголовки и одну строку данных: превратить колонки CSV в именованные поля.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
keysЗначения первого массива становятся ключами результата в порядке обхода.
valuesЗначения второго массива становятся соответствующими значениями, тоже по порядку. Ключи исходных массивов не сопоставляются.
ВозвратНовый массив ключ → значение. Два пустых массива дают []; одинаковые ключи оставляют позднее значение.
Отказ и диагностикаРазное число элементов в PHP 8 вызывает ValueError; ранее выдавались warning и false. Ключи должны быть осмысленными int/string; преобразование прочих типов может предупреждать или завершиться Error.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: параметры и результат вызова.

Что происходит в первом опыте
  1. Три имени и три значения идут в соответствующем порядке.
  2. Combine создаёт sku/quantity/priceKopecks.
  3. Прочитать количество и цену, вычислить 450 копеек.
Связать заголовки со значениями и рассчитать строкуСамостоятельный пример
<?php
$headers = ['sku', 'quantity', 'priceKopecks'];
$cells = ['0041', 3, 150];
$row = array_combine($headers, $cells);
$lineTotal = $row['quantity'] * $row['priceKopecks'];
echo 'Товар ', $row['sku'], ': ', $row['quantity'], ' × ', $row['priceKopecks'], ' = ', $lineTotal, ' коп.', "\n";
Ожидаемый результат
Товар 0041: 3 × 150 = 450 коп.

Первое имя sku связывается с первым значением 0041, затем quantity с 3 и priceKopecks со 150. Return функции — новый именованный массив row. После этого программа обращается к понятным именам колонок и получает 450. Combine не преобразует CSV-текст в числа и не проверяет цены; в этом минимальном опыте значения уже имеют нужные типы.

Отказать строке с потерянной колонкойСамостоятельный пример
<?php
function mapImportRow(array $headers, array $cells): array
{
    if (count($headers) !== count($cells)) {
        throw new UnexpectedValueException('Число колонок не совпало');
    }
    if (count(array_unique($headers)) !== count($headers)) {
        throw new UnexpectedValueException('Повтор заголовка');
    }
    return array_combine($headers, $cells);
}
try {
    mapImportRow(['sku', 'stock'], ['0041']);
} catch (UnexpectedValueException $error) {
    echo $error->getMessage(), "\n";
}
echo json_encode(array_combine(['sku', 'sku'], ['A', 'B'])), "\n";
Ожидаемый результат
Число колонок не совпало
{"sku":"B"}

В этом примере заголовки уже непустые строки из известной схемы. Обёртка даёт прикладное сообщение и предотвращает потерю дублирующейся колонки. Прямой второй вызов специально показывает позднюю замену.

Нюансы и выбор. Перед этой операцией проверьте допустимые имена колонок и их уникальность. После неё остаётся преобразование и проверка значений: текст из CSV не станет автоматически корректной ценой. Нельзя считать успешный combine доказательством полного совпадения формата поставщика.

Сравните: array_column, array_fill_keys, array_merge. Выбрать операцию по задаче.

compactСобрать уже существующие локальные переменные в массив для передачи шаблону.

PHP 4+ · standard

compact(array|string $var_name, array|string ...$var_names): array

Собрать уже существующие локальные переменные в массив для передачи шаблону.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
var_name / var_namesСтроки с именами переменных без $, либо массивы таких имён. Вложенные массивы имён обходятся рекурсивно.
Область поискаТекущая область переменных точки вызова. compact не загружает отсутствующие глобальные переменные внутрь функции.
ВозвратМассив имя переменной → её значение. Необъявленные имена пропускаются с диагностикой.
Отказ и диагностикаВ PHP 8 отсутствующая переменная вызывает E_WARNING; в 7.3–7.x это был E_NOTICE, раньше — молчаливый пропуск. Не путайте отсутствующую переменную с существующей переменной со значением null.

compact("title") получает имя, ищет локальную $title и создаёт поле title. В compact($title) содержимое title само стало бы искомым именем — это другая операция.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: параметры и результат вызова.

Что происходит в первом опыте
  1. В текущей области title=Каталог и total=2.
  2. По двум именам собрать новый массив view.
  3. Из его полей вывести подпись; позднее изменение title её не меняет.
Собрать данные для подписи страницыСамостоятельный пример
<?php
$title = 'Каталог';
$total = 2;
$view = compact('title', 'total');
echo $view['title'], ': найдено ', $view['total'], ' товара', "\n";
$title = 'Архив';
echo 'Сохранённый заголовок: ', $view['title'], "\n";
Ожидаемый результат
Каталог: найдено 2 товара
Сохранённый заголовок: Каталог

Строка title без знака $ сообщает имя искомой местной переменной. Compact прочитал её нынешнее значение «Каталог», добавил total=2 и вернул массив view. Echo затем читает поля из view. Присваивание «Архив» исходной строковой переменной не меняет уже собранное поле. Явная альтернатива: ['title' => $title, 'total' => $total].

Собрать значения внутри функции, включая nullСамостоятельный пример
<?php
function viewData(): array
{
    $title = 'Orders';
    $notice = null;
    return compact(['title', ['notice']]);
}
echo json_encode(viewData()), "\n";
Ожидаемый результат
{"title":"Orders","notice":null}

Вложен именно список имён, а результат остаётся плоским словарём. notice существует, поэтому null сохраняется. return передаёт массив вызывающему коду.

Нюансы и выбор. Связь со строковыми именами менее заметна инструментам переименования, чем ["title" => $title]. Не передавайте произвольный список имён от посетителя: он не должен выбирать, какие локальные данные уйдут наружу. Особенность dynamic variable lookup внутри функций мешает использовать так имена суперглобальных массивов; явно выбирайте необходимые безопасные поля.

Сравните: extract, array, array_combine. Выбрать операцию по задаче.

extractСоздать локальные переменные из заранее доверенного массива — в основном для границы старого шаблонизатора.

PHP 4+ · standard

extract(array &$array, int $flags = EXTR_OVERWRITE, string $prefix = ""): int

Создать локальные переменные из заранее доверенного массива — в основном для границы старого шаблонизатора.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayАссоциативный массив: ключ становится именем переменной, значение — её содержимым. Допустимость имени проверяется, но безопасность и тип значения не проверяются.
EXTR_OVERWRITE / EXTR_SKIPПо умолчанию существующее имя перезаписывается. SKIP сохраняет уже существующую переменную при коллизии.
EXTR_PREFIX_SAME / ALL / INVALIDДобавить prefix только при коллизии, ко всем именам либо к неверным/числовым именам. Итог всё равно должен быть допустимым именем переменной.
EXTR_IF_EXISTS / EXTR_PREFIX_IF_EXISTSИзменить лишь уже существующие имена либо создать их варианты с префиксом. Это фильтрация имён, а не проверка входных значений.
EXTR_REFSДобавочный флаг через | создаёт связи с элементами исходного массива. Изменение переменной меняет элемент.
prefixНужен для PREFIX-режимов. Между ним и ключом автоматически вставляется _. Для числовых ключей обычно требуется PREFIX_ALL или PREFIX_INVALID.
ВозвратКоличество действительно импортированных переменных. Возвращается число, а не исходный или изменённый массив.
Отказ и диагностикаНеверные значения flags/prefix могут вызвать ValueError. Недопустимые имена, которые не удалось исправить разрешённым префиксом, не импортируются. По ссылке передавайте переменную массива, а не результат выражения.

extract изменяет текущую область переменных. Именно поэтому нельзя распаковывать им напрямую $_GET, $_POST или ответ чужого API. В новом коде явные обращения к полям или list с перечисленными ключами обычно делают зависимость понятнее.

Что происходит в первом опыте
  1. Title уже существует: Каталог.
  2. SKIP пропускает title и создаёт stock=0.
  3. Прочитать переменные; отдельно вывести возвращённое число 1.
Перенести доверенные поля в переменные старого шаблонаСамостоятельный пример
<?php
$title = 'Каталог';
$view = ['title' => 'Склад', 'stock' => 0];
$created = extract($view, EXTR_SKIP);
echo 'Заголовок: ', $title, "\n";
echo 'Остаток: ', $stock, ' шт.', "\n";
echo 'Создано переменных: ', $created, "\n";
Ожидаемый результат
Заголовок: Каталог
Остаток: 0 шт.
Создано переменных: 1

EXTR_SKIP — именованная константа режима: существующий title сохраняется. Ключ stock создаёт новую местную переменную $stock со значением 0. Сам вызов возвращает 1 в created, потому что импортировано одно имя. Число не содержит данные шаблона: они уже записаны в title/stock. Доверенный view создан рядом; в новом шаблоне явное $view['stock'] обычно делает зависимость понятнее.

Отделить имена шаблона префиксомСамостоятельный пример
<?php
$data = ['sku' => '0041', 0 => 'first'];
$created = extract($data, EXTR_PREFIX_ALL, 'view');
echo $view_sku, ':', $view_0, ':', $created, "\n";
Ожидаемый результат
0041:first:2

view_0 — допустимое имя, хотя исходный ключ числовой. Префикс даёт различимые имена, но не заменяет разрешённый список полей.

Ссылка связывает переменную с элементомСамостоятельный пример
<?php
$data = ['stock' => 2];
extract($data, EXTR_PREFIX_ALL | EXTR_REFS, 'view');
$view_stock = 3;
unset($view_stock);
echo $data['stock'], "\n";
Ожидаемый результат
3

EXTR_REFS — явное изменение договора владения. unset разрывает локальную связь; значение массива уже изменилось. Для обычного вывода шаблона такая связь не нужна.

Нюансы и выбор. EXTR_IF_EXISTS не проверяет значение и может перезаписать важный локальный флаг. EXTR_SKIP тоже разрешает создание новых имён. Для шаблона ограничьте отдельной функцией область видимости, заранее сформируйте данные и перечислите разрешённые поля. Наличие этой функции в полном справочнике не означает рекомендацию массовой распаковки пользовательского ввода.

Сравните: compact, list, array_intersect_key. Выбрать операцию по задаче.

array_allПроверить, что каждый элемент подходит: например все выбранные товары доступны.

PHP 8.4+ · standard

array_all(array $array, callable $callback): bool

Для следующих четырёх функций нужен PHP 8.4+. Callback принимает значение и ключ и возвращает bool; all/any возвращают общий bool, find — выбранное значение, find_key — его ключ. Важно заранее решить, какая из этих четырёх форм результата нужна дальше.

Проверить, что каждый элемент подходит: например все выбранные товары доступны.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayМассив, который проверяется в его текущем порядке.
callbackПроверка callback(mixed $value, mixed $key): bool. Возвращайте осмысленный bool; передаются значение и ключ.
Возвратtrue/false; пустой массив даёт true.
Отказ и диагностикаНеверный тип массива или невызываемый callback даёт TypeError. Исключение callback передаётся вызывающему коду; оно не является результатом false/null.

Callback — функция, переданная другой функции. Здесь PHP вызывает её для очередного элемента: первый параметр получает значение, второй — ключ. function ($stock, $sku) { return $stock > 0; } объявляет такую проверку; return отдаёт bool. Короткая fn(...) => выражение автоматически возвращает результат одного выражения.

Для этого примера: передача функции как значения.

Что происходит в первом опыте
  1. stocks: A=2, B=0, C=4.
  2. Callback для A возвращает true, для B — false.
  3. Проверка останавливается; C не посещается, общий результат false.
Проследить первый решающий элементСамостоятельный пример
<?php
$stocks = ['A' => 2, 'B' => 0, 'C' => 4];
$ready = array_all($stocks, function ($stock, $sku) {
    echo $sku, "\n";
    return $stock > 0;
});
var_dump($ready);
Ожидаемый результат
A
B
bool(false)

Обход идёт по порядку массива и заканчивается, как только общий ответ уже известен.

Использовать результат array_all в задачеСамостоятельный пример
<?php
// PHP 8.4+.
$cart = [['sku' => 'A', 'quantity' => 1], ['sku' => 'B', 'quantity' => 2]];
$valid = $cart !== [] && array_all($cart, function ($row, $key) {
    return is_int($row['quantity']) && $row['quantity'] > 0;
});
if ($valid) {
    echo "Корзина принята\n";
    foreach ($cart as $row) {
        echo $row['sku'], ': ', $row['quantity'], ' шт.', "\n";
    }
}
$emptyPassesRule = array_all([], function ($value, $key) { return false; });
echo 'Правило каждого элемента для пустого массива: ', $emptyPassesRule ? 'выполнено' : 'нарушено', "\n";
Ожидаемый результат
Корзина принята
A: 1 шт.
B: 2 шт.
Правило каждого элемента для пустого массива: выполнено

Callback вернул true для количества 1 и 2; all вернул true, отдельная проверка непустоты тоже true. Общий valid разрешил показать готовый состав. У пустого массива нет нарушителя, поэтому all вернул true, даже не вызывая всегда ложный callback. Форма строк и наличие quantity здесь заранее известны; на внешнем входе их проверяют отдельно.

Нюансы и выбор. Для пустого массива результат true: нет элемента, нарушающего условие. Поэтому требование «корзина не пуста и каждая позиция корректна» состоит из двух проверок. Здесь форма строк уже известна; реальный API сначала проверяют на обязательные ключи. Для PHP 8.2/8.3 тот же договор выражается foreach с ранним return из функции; не стройте array_filter всех элементов, если нужен только первый ответ. Число вызовов callback зависит от места решающего элемента. Не меняйте проверяемый массив из callback и не прячьте в проверке отправку запросов.

Сравните: array_any, array_find, array_find_key, array_filter. Выбрать операцию по задаче.

array_anyУзнать, есть ли хотя бы один подходящий элемент: например доступный склад.

PHP 8.4+ · standard

array_any(array $array, callable $callback): bool

Узнать, есть ли хотя бы один подходящий элемент: например доступный склад.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayМассив, который проверяется в его текущем порядке.
callbackПроверка callback(mixed $value, mixed $key): bool. Возвращайте осмысленный bool; передаются значение и ключ.
Возвратtrue/false; пустой массив даёт false.
Отказ и диагностикаНеверный тип массива или невызываемый callback даёт TypeError. Исключение callback передаётся вызывающему коду; оно не является результатом false/null.

Callback — функция, переданная другой функции. Здесь PHP вызывает её для очередного элемента: первый параметр получает значение, второй — ключ. function ($stock, $sku) { return $stock > 0; } объявляет такую проверку; return отдаёт bool. Короткая fn(...) => выражение автоматически возвращает результат одного выражения.

Для этого примера: передача функции как значения.

Что происходит в первом опыте
  1. stocks: north=0, south=2, west=5.
  2. Callback для north ложен, для south истинен.
  3. Вернуть true; west для ответа уже не нужен.
Проследить первый решающий элементСамостоятельный пример
<?php
$stocks = ['north' => 0, 'south' => 2, 'west' => 5];
var_dump(array_any($stocks, function ($stock, $warehouse) {
    echo $warehouse, "\n";
    return $stock > 0;
}));
Ожидаемый результат
north
south
bool(true)

Обход идёт по порядку массива и заканчивается, как только общий ответ уже известен.

Использовать результат array_any в задачеСамостоятельный пример
<?php
// PHP 8.4+.
$orders = [['id' => 41, 'late' => false], ['id' => 42, 'late' => true]];
$hasLate = array_any($orders, function ($order, $key) {
    return $order['late'] === true;
});
if ($hasLate) {
    echo "Показать предупреждение: есть просроченные заказы\n";
}
$hasInEmptyList = array_any([], function ($value, $key) { return true; });
if (!$hasInEmptyList) {
    echo "В пустом списке подходящих заказов нет\n";
}
Ожидаемый результат
Показать предупреждение: есть просроченные заказы
В пустом списке подходящих заказов нет

Callback отклоняет заказ 41 и принимает 42. Any возвращает true в hasLate; это разрешает общее предупреждение, но не возвращает запись заказа 42. Для неё нужна find. Пустой вход возвращает false, не вызывая callback.

Нюансы и выбор. Пустой массив даёт false: подходящего элемента нет. Метод нужен для ответа да/нет; чтобы получить сам просроченный заказ, используйте array_find. Для PHP 8.2/8.3 тот же договор выражается foreach с ранним return из функции; не стройте array_filter всех элементов, если нужен только первый ответ. Число вызовов callback зависит от места решающего элемента. Не меняйте проверяемый массив из callback и не прячьте в проверке отправку запросов.

Сравните: array_all, array_find, array_find_key, array_filter. Выбрать операцию по задаче.

array_findПолучить первое подходящее значение, например товар с ненулевым остатком.

PHP 8.4+ · standard

array_find(array $array, callable $callback): mixed

Получить первое подходящее значение, например товар с ненулевым остатком.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayМассив, который проверяется в его текущем порядке.
callbackПроверка callback(mixed $value, mixed $key): bool. Возвращайте осмысленный bool; передаются значение и ключ.
ВозвратПервое подходящее значение; null, если совпадения нет.
Отказ и диагностикаНеверный тип массива или невызываемый callback даёт TypeError. Исключение callback передаётся вызывающему коду; оно не является результатом false/null.

Callback — функция, переданная другой функции. Здесь PHP вызывает её для очередного элемента: первый параметр получает значение, второй — ключ. function ($stock, $sku) { return $stock > 0; } объявляет такую проверку; return отдаёт bool. Короткая fn(...) => выражение автоматически возвращает результат одного выражения.

Для этого примера: передача функции как значения.

Что происходит в первом опыте
  1. stocks: A=0, B=2, C=4.
  2. Callback отклоняет A и принимает B.
  3. Возвращается значение 2, не ключ B; поиск прекращается.
Проследить первый решающий элементСамостоятельный пример
<?php
$stocks = ['A' => 0, 'B' => 2, 'C' => 4];
$stock = array_find($stocks, fn($value, $key) => $value > 0);
var_dump($stock);
Ожидаемый результат
int(2)

Обход идёт по порядку массива и заканчивается, как только общий ответ уже известен.

Использовать результат array_find в задачеСамостоятельный пример
<?php
// PHP 8.4+.
$products = [['sku' => 'A', 'stock' => 0], ['sku' => 'B', 'stock' => 3]];
$product = array_find($products, function ($row, $key) {
    return $row['stock'] > 0;
});
if ($product !== null) {
    echo 'Первый доступный товар: ', $product['sku'], "\n";
    echo 'Можно предложить: ', $product['stock'], ' шт.', "\n";
}
$nullValue = array_find(['A' => null], function ($value, $key) { return $key === 'A'; });
$absentValue = array_find([], function ($value, $key) { return true; });
echo 'Тип найденного null: ', get_debug_type($nullValue), "\n";
echo 'Тип результата отсутствующего совпадения: ', get_debug_type($absentValue), "\n";
Ожидаемый результат
Первый доступный товар: B
Можно предложить: 3 шт.
Тип найденного null: null
Тип результата отсутствующего совпадения: null

Return callback — только bool проверки. Return array_find — вся выбранная строка B; она используется для чтения sku и stock. Если значением может быть null, один результат null не различает успех и отсутствие. Тогда используйте find_key и прочитайте значение отдельно по найденному ключу.

Нюансы и выбор. Последние два результата одинаковы: найденный null неотличим от отсутствия результата по одному возвращённому значению. Если null допустим в данных, найдите ключ через array_find_key. Форма строк products здесь заранее задана. Для PHP 8.2/8.3 тот же договор выражается foreach с ранним return из функции; не стройте array_filter всех элементов, если нужен только первый ответ. Число вызовов callback зависит от места решающего элемента. Не меняйте проверяемый массив из callback и не прячьте в проверке отправку запросов.

Сравните: array_all, array_any, array_find_key, array_filter. Выбрать операцию по задаче.

array_find_keyНайти ключ первого элемента по правилу, чтобы затем обратиться именно к нему.

PHP 8.4+ · standard

array_find_key(array $array, callable $callback): mixed

Найти ключ первого элемента по правилу, чтобы затем обратиться именно к нему.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayМассив, который проверяется в его текущем порядке.
callbackПроверка callback(mixed $value, mixed $key): bool. Возвращайте осмысленный bool; передаются значение и ключ.
ВозвратПервое подходящее имя ключа; null, если совпадения нет.
Отказ и диагностикаНеверный тип массива или невызываемый callback даёт TypeError. Исключение callback передаётся вызывающему коду; оно не является результатом false/null.

Callback — функция, переданная другой функции. Здесь PHP вызывает её для очередного элемента: первый параметр получает значение, второй — ключ. function ($stock, $sku) { return $stock > 0; } объявляет такую проверку; return отдаёт bool. Короткая fn(...) => выражение автоматически возвращает результат одного выражения.

Для этого примера: передача функции как значения.

Что происходит в первом опыте
  1. stocks: A=0, B=2, C=4.
  2. Callback принимает первое положительное значение у B.
  3. Возвращается ключ B; само значение массива не заменяется.
Проследить первый решающий элементСамостоятельный пример
<?php
$stocks = ['A' => 0, 'B' => 2, 'C' => 4];
$sku = array_find_key($stocks, fn($value, $key) => $value > 0);
echo $sku, "\n";
Ожидаемый результат
B

Обход идёт по порядку массива и заканчивается, как только общий ответ уже известен.

Использовать результат array_find_key в задачеСамостоятельный пример
<?php
// PHP 8.4+.
$values = [0 => null, 1 => 'ready'];
$key = array_find_key($values, function ($value, $key) {
    return $value === null;
});
if ($key !== null) {
    $values[$key] = 'waiting';
    echo 'Незаполненная позиция ', $key, ' получила статус ', $values[$key], "\n";
}
$missing = array_find_key([], function ($value, $key) { return true; });
if ($missing === null) {
    echo "В пустом списке нечего изменять\n";
}
Ожидаемый результат
Незаполненная позиция 0 получила статус waiting
В пустом списке нечего изменять

Find_key возвращает ключ 0, и !== null правильно распознаёт его. По этому ключу программа записывает согласованный статус waiting. Пустой вход возвращает null. Ключ массива не хранится как null: при создании такой ключ преобразуется, поэтому null пригоден здесь как признак отсутствия.

Нюансы и выбор. Проверка !== null сохраняет успешный ключ 0. У PHP-массива null не хранится как отдельный тип ключа: он преобразуется; поэтому null здесь пригоден как маркер отсутствия. Документированный тип результата mixed; фактический найденный ключ — int или string. Для PHP 8.2/8.3 тот же договор выражается foreach с ранним return из функции; не стройте array_filter всех элементов, если нужен только первый ответ. Число вызовов callback зависит от места решающего элемента. Не меняйте проверяемый массив из callback и не прячьте в проверке отправку запросов.

Сравните: array_all, array_any, array_find, array_filter. Выбрать операцию по задаче.

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

PHP 7.3+ · standard

array_key_first(array $array): int|string|null

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

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayМассив. «Первый/последний» относится к порядку элементов, не к минимальному/максимальному ключу или значению.
ВозвратНайденный ключ; null для пустого массива.
Отказ и диагностикаДля аргумента другого типа PHP 8 выдаёт TypeError. Пустой массив допустим и не создаёт предупреждения.
Что происходит в первом опыте
  1. Массив хранит B=2, затем A=0.
  2. Вернуть B из текущей границы.
  3. Использовать возврат для подписи остатка; массив не меняется.
Использовать границу списка остатковСамостоятельный пример
<?php
$stocks = ['B' => 2, 'A' => 0];
$sku = array_key_first($stocks);
if ($sku !== null) {
    echo "Товар ", $sku, ": ", $stocks[$sku], " шт.\n";
}
Ожидаемый результат
Товар B: 2 шт.

В sku возвращается ключ B, а не остаток. После проверки !== null он используется в stocks[sku], чтобы прочитать соответствующее количество. Строгая проверка допускает полезный ключ 0 или пустую строку. Названия B/A специально записаны без сортировки: берётся граница текущего порядка.

Отделить чтение границы от состояния указателяСамостоятельный пример
<?php
$stocks = ['B' => 2, 'A' => 0];
next($stocks);
array_key_first($stocks);
echo key($stocks), "\n";
var_dump(array_key_first([]));
Ожидаемый результат
A
NULL

next передвинул указатель на A, чтение границы оставило его там. key читает позицию указателя; функция границы её не использует.

Нюансы и выбор. Ключ 0 или пустая строка — успешный результат; проверяйте !== null, а не if($key). Не создавайте весь array_keys ради единственного граничного ключа. reset/end тоже дают граничное значение, но меняют указатель; array_shift/array_pop ещё и удаляют элемент.

Сравните: array_key_last, array_first, array_last, reset, end. Выбрать операцию по задаче.

array_key_lastПрочитать последний ключ в порядке массива, не удаляя элемент и не переставляя внутренний указатель.

PHP 7.3+ · standard

array_key_last(array $array): int|string|null

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

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayМассив. «Первый/последний» относится к порядку элементов, не к минимальному/максимальному ключу или значению.
ВозвратНайденный ключ; null для пустого массива.
Отказ и диагностикаДля аргумента другого типа PHP 8 выдаёт TypeError. Пустой массив допустим и не создаёт предупреждения.
Что происходит в первом опыте
  1. Массив хранит B=2, затем A=0.
  2. Вернуть A из текущей границы.
  3. Использовать возврат для подписи остатка; массив не меняется.
Использовать границу списка остатковСамостоятельный пример
<?php
$stocks = ['B' => 2, 'A' => 0];
$sku = array_key_last($stocks);
if ($sku !== null) {
    echo "Товар ", $sku, ": ", $stocks[$sku], " шт.\n";
}
Ожидаемый результат
Товар A: 0 шт.

В sku возвращается ключ A, а не остаток. После проверки !== null он используется в stocks[sku], чтобы прочитать соответствующее количество. Строгая проверка допускает полезный ключ 0 или пустую строку. Названия B/A специально записаны без сортировки: берётся граница текущего порядка.

Отделить чтение границы от состояния указателяСамостоятельный пример
<?php
$stocks = ['B' => 2, 'A' => 0];
next($stocks);
array_key_last($stocks);
echo key($stocks), "\n";
var_dump(array_key_last([]));
Ожидаемый результат
A
NULL

next передвинул указатель на A, чтение границы оставило его там. key читает позицию указателя; функция границы её не использует.

Нюансы и выбор. Ключ 0 или пустая строка — успешный результат; проверяйте !== null, а не if($key). Не создавайте весь array_keys ради единственного граничного ключа. reset/end тоже дают граничное значение, но меняют указатель; array_shift/array_pop ещё и удаляют элемент.

Сравните: array_key_first, array_first, array_last, reset, end. Выбрать операцию по задаче.

array_firstПрочитать первое значение в порядке массива, не удаляя элемент и не переставляя внутренний указатель.

PHP 8.5+ · standard

array_first(array $array): mixed

Прочитать первое значение в порядке массива, не удаляя элемент и не переставляя внутренний указатель.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayМассив. «Первый/последний» относится к порядку элементов, не к минимальному/максимальному ключу или значению.
ВозвратНайденное значение; null для пустого массива.
Отказ и диагностикаДля аргумента другого типа PHP 8 выдаёт TypeError. Пустой массив допустим и не создаёт предупреждения.
Что происходит в первом опыте
  1. Массив хранит B=2, затем A=0.
  2. Вернуть 2 из текущей границы.
  3. Использовать возврат для подписи остатка; массив не меняется.
Использовать границу списка остатковСамостоятельный пример
<?php
$stocks = ['B' => 2, 'A' => 0];
$quantity = array_first($stocks);
echo "На границе списка: ", $quantity, " шт.\n";
if ($quantity === 0) { echo "Нужно пополнение\n"; }
Ожидаемый результат
На границе списка: 2 шт.

Значение 2 возвращается прямо в quantity. Здесь массив заведомо непустой и содержит только целые остатки. Число 0 — полезный остаток, по нему программа сообщает о пополнении; проверка if(quantity) смешала бы его с неудачей. В PHP 8.2–8.4 сначала получите соответствующий ключ, проверьте его на null и прочитайте значение по ключу.

Отделить чтение границы от состояния указателяСамостоятельный пример
<?php
$stocks = ['B' => 2, 'A' => 0];
next($stocks);
array_first($stocks);
echo key($stocks), "\n";
var_dump(array_first([]));
Ожидаемый результат
A
NULL

next передвинул указатель на A, чтение границы оставило его там. key читает позицию указателя; функция границы её не использует.

Нюансы и выбор. Null может быть настоящим значением непустого массива. Если важно отличить его от пустоты, проверьте $array !== [] либо сначала получите соответствующий ключ. В PHP 8.2–8.4 значение можно прочитать по array_key_first, проверив ключ на null. reset/end тоже дают граничное значение, но меняют указатель; array_shift/array_pop ещё и удаляют элемент.

Сравните: array_key_first, array_key_last, array_last, reset, end. Выбрать операцию по задаче.

array_lastПрочитать последнее значение в порядке массива, не удаляя элемент и не переставляя внутренний указатель.

PHP 8.5+ · standard

array_last(array $array): mixed

Прочитать последнее значение в порядке массива, не удаляя элемент и не переставляя внутренний указатель.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayМассив. «Первый/последний» относится к порядку элементов, не к минимальному/максимальному ключу или значению.
ВозвратНайденное значение; null для пустого массива.
Отказ и диагностикаДля аргумента другого типа PHP 8 выдаёт TypeError. Пустой массив допустим и не создаёт предупреждения.
Что происходит в первом опыте
  1. Массив хранит B=2, затем A=0.
  2. Вернуть 0 из текущей границы.
  3. Использовать возврат для подписи остатка; массив не меняется.
Использовать границу списка остатковСамостоятельный пример
<?php
$stocks = ['B' => 2, 'A' => 0];
$quantity = array_last($stocks);
echo "На границе списка: ", $quantity, " шт.\n";
if ($quantity === 0) { echo "Нужно пополнение\n"; }
Ожидаемый результат
На границе списка: 0 шт.
Нужно пополнение

Значение 0 возвращается прямо в quantity. Здесь массив заведомо непустой и содержит только целые остатки. Число 0 — полезный остаток, по нему программа сообщает о пополнении; проверка if(quantity) смешала бы его с неудачей. В PHP 8.2–8.4 сначала получите соответствующий ключ, проверьте его на null и прочитайте значение по ключу.

Отделить чтение границы от состояния указателяСамостоятельный пример
<?php
$stocks = ['B' => 2, 'A' => 0];
next($stocks);
array_last($stocks);
echo key($stocks), "\n";
var_dump(array_last([]));
Ожидаемый результат
A
NULL

next передвинул указатель на A, чтение границы оставило его там. key читает позицию указателя; функция границы её не использует.

Нюансы и выбор. Null может быть настоящим значением непустого массива. Если важно отличить его от пустоты, проверьте $array !== [] либо сначала получите соответствующий ключ. В PHP 8.2–8.4 значение можно прочитать по array_key_last, проверив ключ на null. reset/end тоже дают граничное значение, но меняют указатель; array_shift/array_pop ещё и удаляют элемент.

Сравните: array_key_first, array_key_last, array_first, reset, end. Выбрать операцию по задаче.

key_existsУзнать псевдоним array_key_exists в старом коде: договор проверки ключа полностью тот же.

PHP 4.0.6+ · standard

key_exists(string|int|float|bool|resource|null $key, array $array): bool

Узнать псевдоним array_key_exists в старом коде: договор проверки ключа полностью тот же.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
keyИскомый ключ. Для ясного договора используйте int или string; прочие допустимые типы преобразуются по правилам ключей. null как аргумент deprecated с PHP 8.5 — используйте пустую строку.
arrayМассив, проверяется только первый уровень. Объекты не поддерживаются с PHP 8.0; для свойства существует property_exists.
Возвратtrue, если ключ присутствует, включая значение null; false при отсутствии.
Отказ и диагностикаНеподдерживаемый тип ключа или аргумент не-массив вызывает TypeError. Преобразования некоторых ключей могут давать диагностику; не используйте ресурс как бизнес-ключ.
Что происходит в первом опыте
  1. В сохранённой записи есть текст комментария.
  2. Наличие ключа с null разрешает очистку.
  3. Пустой массив правки не меняет запись.
Различить очистку комментария и отсутствие измененияСамостоятельный пример
<?php
$saved = ['comment' => 'Позвонить заранее'];
$patch = ['comment' => null];
if (key_exists('comment', $patch)) {
    $saved['comment'] = $patch['comment'];
}
echo 'Комментарий: ', $saved['comment'] ?? 'не указан', "\n";
$patch = [];
if (key_exists('comment', $patch)) {
    $saved['comment'] = $patch['comment'];
}
echo 'После пустой правки: ', $saved['comment'] ?? 'не указан', "\n";
Ожидаемый результат
Комментарий: не указан
После пустой правки: не указан

По договору этой локальной правки null означает очистку. Проверка находит существующий ключ comment и возвращает true даже при null; присваивание действительно очищает значение. Во второй правке ключа нет: false пропускает присваивание. ?? выбирает текст для отсутствующего/null комментария. Isset дал бы false уже в первом случае и помешал бы очистить поле. Тип и разрешённые имена входных полей проверяют отдельно.

Вложенное поле требует перехода на нужный уровеньСамостоятельный пример
<?php
$payload = ['product' => ['stock' => 0]];
var_dump(key_exists('stock', $payload));
var_dump(key_exists('stock', $payload['product']));
echo $payload['product']['stock'], "\n";
Ожидаемый результат
bool(false)
bool(true)
0

Функция не ищет рекурсивно. Форма product здесь известна; для внешнего JSON сначала убедитесь, что product — массив.

Нюансы и выбор. Не заменяйте проверку наличия на empty: empty считает пустыми и 0, и "0", и false. Наличие поля не доказывает его тип и допустимость. В PHP 8.0 набор допустимых скалярных типов ключа расширен, но наиболее понятный контракт приложения — именованный строковый ключ или целочисленный индекс. В новом коде полное имя array_key_exists обычно читается яснее; иной производительности этот псевдоним не обещает.

Сравните: array_key_exists, in_array, array_keys. Выбрать операцию по задаче.

array_count_valuesСосчитать частоту строковых кодов или целых значений, например заказы по статусам.

PHP 4+ · standard

array_count_values(array $array): array

Сосчитать частоту строковых кодов или целых значений, например заказы по статусам.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayМассив значений; считаются только int и string. Исходные ключи не важны.
ВозвратСловарь значение → число его появлений. Новые ключи подчиняются правилам ключей PHP.
Отказ и диагностикаКаждое значение другого типа вызывает E_WARNING и пропускается. Это не рекурсивный счётчик вложенных записей.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Вход new,paid,new.
  2. Собрать частоты new=2 и paid=1.
  3. Показать отчёт и число ожидающих оплаты.
Посчитать и напечатать заказы по статусуСамостоятельный пример
<?php
$statuses = ['new', 'paid', 'new'];
$counts = array_count_values($statuses);
foreach ($counts as $status => $quantity) {
    echo 'Статус ', $status, ': ', $quantity, "\n";
}
$waiting = $counts['new'] ?? 0;
echo 'Ожидают оплаты: ', $waiting, "\n";
Ожидаемый результат
Статус new: 2
Статус paid: 1
Ожидают оплаты: 2

New встретился дважды и стал ключом со значением 2; paid — ключом со значением 1. Возвращённый словарь пригоден и для полного отчёта, и для обращения к одному статусу. Если new вообще не встретился, ключа не будет и ?? вернёт 0. Если необходимо заранее показывать все статусы, начните с array_fill_keys и прибавляйте количества обычным foreach.

Числовые строки могут совпасть с целыми ключамиСамостоятельный пример
<?php
echo json_encode(array_count_values([1, '1', '01'])), "\n";
$rows = [['status' => 'paid'], ['status' => 'new'], ['status' => 'paid']];
echo json_encode(array_count_values(array_column($rows, 'status'))), "\n";
Ожидаемый результат
{"1":2,"01":1}
{"paid":2,"new":1}

1 и строка "1" превращаются в один ключ; "01" остаётся отдельным. Во втором опыте сначала явно извлекается поле уже проверенных строк.

Нюансы и выбор. Для точного разделения разных типов задайте собственный ключ с меткой типа или используйте иной формат агрегации. Не приводите все входы к строке без договора: null и пустая строка могут начать означать одно и то же. Для сумм по категориям потребуется array_reduce или обычный foreach, а не подсчёт повторов.

Сравните: count, array_column, array_reduce, array_unique. Выбрать операцию по задаче.

array_flipПоменять направление уникального соответствия: из ID→код получить код→ID.

PHP 4+ · standard

array_flip(array $array): array

Поменять направление уникального соответствия: из ID→код получить код→ID.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayМассив, значения которого должны быть int/string, чтобы стать ключами.
ВозвратНовый массив: старые значения становятся ключами, старые ключи — значениями. Позднее повторяющееся значение побеждает.
Отказ и диагностикаДля каждого значения неподходящего типа выдаётся предупреждение, а пара пропускается. Другой тип array даёт TypeError.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Codes связывает 41→A и 72→B.
  2. Flip разворачивает B→72.
  3. Полученный 72 читает остаток 5 в другом словаре.
Найти ID товара по уникальному кодуСамостоятельный пример
<?php
$codes = [41 => 'A', 72 => 'B'];
$stockById = [41 => 0, 72 => 5];
$idByCode = array_flip($codes);
$requestedCode = 'B';
$id = $idByCode[$requestedCode];
echo 'Код ', $requestedCode, ' → ID ', $id, "\n";
echo 'Доступно: ', $stockById[$id], ' шт.', "\n";
Ожидаемый результат
Код B → ID 72
Доступно: 5 шт.

Flip возвращает новое соответствие A→41, B→72. Код B заранее известен и уникален; обращение idByCode[B] возвращает 72. Это число затем служит ключом в отдельном словаре остатков. Так показано, зачем нужен обратный индекс. Внешний неизвестный код сначала проверяют через array_key_exists, а повторы кодов запрещают либо хранят список ID; следующий опыт показывает потерю при повторе.

Дублирование теряет прежнее соответствиеСамостоятельный пример
<?php
$codes = [41 => 'A', 72 => 'A'];
echo json_encode(array_flip($codes)), "\n";
echo json_encode(array_flip(array_flip($codes))), "\n";
Ожидаемый результат
{"A":72}
{"72":"A"}

Двойной flip не восстановил запись 41: информация уже потеряна. Для одного кода с несколькими ID нужно явно собирать список ID под ключом.

Нюансы и выбор. Это не универсальное преобразование множества и не операция без потерь. Числовые строки могут стать целочисленными ключами; объекты, массивы, bool и null не являются допустимыми значениями для такого разворота. Для проверки принадлежности набору часто яснее array_fill_keys с фиксированным true.

Сравните: array_fill_keys, array_search, array_combine, array_unique. Выбрать операцию по задаче.

sizeofПрочитать псевдоним count: sizeof считает элементы, а не размер массива в байтах.

PHP 4+ · standard

sizeof(Countable|array $value, int $mode = COUNT_NORMAL): int

Прочитать псевдоним count: sizeof считает элементы, а не размер массива в байтах.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
valueМассив либо объект, реализующий Countable::count(). Не любая переменная или объект является countable.
modeCOUNT_NORMAL (0) считает верхний уровень. COUNT_RECURSIVE (1) дополнительно считает элементы вложенных массивов; вложенные контейнеры тоже учитываются.
ВозвратЦелое количество элементов. Для Countable вызывается его собственный метод count; это не обязательно число публичных свойств.
Отказ и диагностикаВ PHP 8 неподходящий тип даёт TypeError. В PHP 7.2 появилась диагностика для неподходящих типов; ранее не-null скаляр давал 1, null — 0. Рекурсивная ссылка при COUNT_RECURSIVE вызывает E_WARNING и не является корректным счётом листьев.
Что происходит в первом опыте
  1. Есть две строки: A с 3 упаковками и B с 1.
  2. Посчитать строки отдельно от суммы количеств.
  3. Показать 2 позиции и 4 упаковки.
Отличить число строк заказа от числа упаковокСамостоятельный пример
<?php
$cart = ['A' => 3, 'B' => 1];
$lineCount = sizeof($cart);
$packageCount = array_sum($cart);
echo 'Разных позиций: ', $lineCount, "\n";
echo 'Упаковок к сборке: ', $packageCount, "\n";
if ($lineCount === 0) { echo "Корзина пуста\n"; }
Ожидаемый результат
Разных позиций: 2
Упаковок к сборке: 4

sizeof возвращает 2, потому что на верхнем уровне две пары: A→3 и B→1. Этот результат отвечает за число разных строк; array_sum отдельно возвращает 4 упаковки. Наличие вложенных полей у строки не увеличило бы обычный count. Рекурсивный режим ниже считает также элементы контейнеров и не заменяет сумму количеств.

Вложенные контейнеры тоже входят в счётСамостоятельный пример
<?php
$groups = [['A', 'B'], ['C']];
echo sizeof($groups), "\n";
echo sizeof($groups, COUNT_RECURSIVE), "\n";
try {
    sizeof(null);
} catch (TypeError) {
    echo "Ожидался массив или Countable\n";
}
Ожидаемый результат
2
5
Ожидался массив или Countable

Рекурсивно получилось 2 контейнера + 3 значения. Это не число товаров-листьев. На границе API null сначала обрабатывают по договору, а не автоматически превращают в пустой список.

Нюансы и выбор. Обычный размер массива хранится в его структуре; не объявляйте count линейным обходом каждого элемента. Рекурсивный режим действительно обходит вложенные массивы, а пользовательский Countable может выполнять произвольную работу. Последний числовой ключ не равен количеству. Ссылки на собственный массив не превращают COUNT_RECURSIVE в безопасный универсальный обход графа. Название count обычно яснее: sizeof не измеряет память.

Сравните: count, array_sum, array_key_last. Выбрать операцию по задаче.

array_change_key_caseНормализовать регистр строковых ключей, не меняя значения.

PHP 4.2+ · standard

array_change_key_case(array $array, int $case = CASE_LOWER): array

Нормализовать регистр строковых ключей, не меняя значения.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИсходный массив; числовые ключи остаются прежними.
caseCASE_LOWER — нижний регистр, CASE_UPPER — верхний. С PHP 8.2 преобразуются только ASCII-буквы.
ВозвратНовый массив; при столкновении преобразованных ключей побеждает более позднее значение.
Отказ и диагностикаНеверный тип аргумента — TypeError. Допустимы документированные CASE_* режимы; функция не диагностирует потерю значения при столкновении.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Входные ключи Host, PORT, 7.
  2. Изменить строковые ключи на host/port, сохранить 7.
  3. Прочитать новый адрес; исходный Host по-прежнему доступен.
Привести согласованные имена настроек к одному региструСамостоятельный пример
<?php
$received = ['Host' => 'mail.local', 'PORT' => 587, 7 => 'служебная отметка'];
$settings = array_change_key_case($received, CASE_LOWER);
echo 'Сервер: ', $settings['host'], ':', $settings['port'], "\n";
echo 'Числовой ключ 7: ', $settings[7], "\n";
echo 'Исходное имя Host: ', $received['Host'], "\n";
Ожидаемый результат
Сервер: mail.local:587
Числовой ключ 7: служебная отметка
Исходное имя Host: mail.local

Case_lower — константа нижнего регистра. Возвращённый массив получает строковые ключи host/port; числовой 7 сохраняется. Значения не меняются. Echo строит адрес из унифицированных имён, а последняя строка показывает, что исходный массив received остался прежним. Здесь поставщик разрешает только ASCII-имена настроек; ниже разобрана коллизия имён, которую необходимо обнаружить до потери значения.

Проверить неоднозначность входных настроекСамостоятельный пример
<?php
$incoming = ['Token' => 'first', 'TOKEN' => 'second'];
$normalized = array_change_key_case($incoming, CASE_LOWER);
if (count($incoming) !== count($normalized)) {
    echo "Конфликт имён: требуется решение
";
}
echo json_encode(array_change_key_case(['mode' => 'test'], CASE_UPPER)), "
";
Ожидаемый результат
Конфликт имён: требуется решение
{"MODE":"test"}

В конфигурации нельзя молча считать Token и TOKEN двумя разными полями после нормализации. Здесь конфликт обнаружен до применения настроек.

Нюансы и выбор. Это не Unicode-преобразование русских ключей и не переименование вложенных полей. Предварительно решите, допустимы ли дубликаты без учёта регистра.

Сравните: array_keys, array_combine, array_replace. Выбрать операцию по задаче.

array_walkВыполнить действие над каждым элементом или изменить его значение на месте.

PHP 4+ · standard

array_walk(array|object &$array, callable $callback, mixed $arg = null): true

Задача и маршрут результата. Нужно изменить каждую цену в существующем прайсе. Callback получает связь с элементом через &$price; += пишет в массив. Возврат самой array_walk — статус true, полезные цены остаются в prices.

Выполнить действие над каждым элементом или изменить его значение на месте.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayМассив либо объект; функция обходит элементы независимо от текущего внутреннего указателя.
callbackcallback(value, key); для изменения значения объявите первый параметр как &$value. Возврат callback не заменяет элемент.
argЕсли передан, становится третьим аргументом callback.
ВозвратВсегда true; изменённые значения находятся в исходной переменной. С PHP 8.2 тип возврата уточнён с bool до true.
Отказ и диагностикаС PHP 7.1 нехватка аргументов callback — ArgumentCountError. С PHP 8 ссылка на второй/третий параметр callback вызывает E_WARNING. Менять ключи, добавлять, удалять или переставлять элементы при обходе нельзя: поведение не определено.

Знак & перед первым параметром в справочной сигнатуре означает изменение переданного массива. В самом вызове & не пишут: передают переменную, а не временное выражение. Запись function ($value) { return ...; } создаёт функцию, которую операция вызывает для каждого элемента; return передаёт ей результат. В объявлении function (&$value, $key) ссылка относится к значению элемента; ключ остаётся данными для чтения.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: передача функции как значения; что означает ссылка &.

Что происходит в первом опыте
  1. Метки red и blue
  2. Вызвать действие с value и key
  3. Напечатать пары, не строя новый массив
Прочитать ключ и значениеСамостоятельный пример
<?php
$labels = ['a' => 'red', 'b' => 'blue'];
$ok = array_walk($labels, function ($value, $key) {
    echo $key, '=', $value, "
";
});
var_dump($ok);
Ожидаемый результат
a=red
b=blue
bool(true)

Результат walk — признак завершения, а не собранный текст и не массив.

Использовать результат array_walk в задачеСамостоятельный пример
<?php
$prices = ['p1' => 100, 'p2' => 250];
$status = array_walk($prices, function (&$price, $key, $fee) {
    $price += $fee;
}, 20);
if ($status) {
    echo "Упаковка включена в каждую цену\n";
}
foreach ($prices as $id => $price) {
    echo $id, ': ', $price, ' коп.', "\n";
}
Ожидаемый результат
Упаковка включена в каждую цену
p1: 120 коп.
p2: 270 коп.

Третий аргумент 20 передаётся callback как fee для каждого элемента. Первый параметр &$price связан с его значением, поэтому += изменяет prices. Return у callback не нужен и не заменяет элемент. Status получает true, а дальнейший foreach читает изменённые цены из prices, не из status. Состав и порядок массива внутри walk не меняют.

Нюансы и выбор. Нельзя напрямую передать strtolower: walk передаёт также ключ, а многие встроенные функции отвергают лишние аргументы. Оберните нужный вызов в собственную функцию с подходящими параметрами. Возвращённый false не прекращает обход.

Сравните: array_map, array_walk_recursive, array_filter. Выбрать операцию по задаче.

array_walk_recursiveПройти листья вложенных массивов, например обработать текстовые поля разобранного JSON.

PHP 5+ · standard

array_walk_recursive(array|object &$array, callable $callback, mixed $arg = null): true

Пройти листья вложенных массивов, например обработать текстовые поля разобранного JSON.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayВложенный массив либо объект верхнего уровня, рассматриваемый как массив. Внутрь вложенных объектов функция не спускается.
callbackcallback(value, key): листья, не контейнеры-массивы. &$value позволяет менять лист. Ключ — локальный, не полный путь.
argНеобязательный третий аргумент callback.
Возвратtrue (точный тип с PHP 8.2); новый массив не возвращается.
Отказ и диагностикаОшибки callback распространяются наружу. Не меняйте структуру дерева при обходе; используйте конечное дерево без циклических ссылок. Неподходящие типы параметров callback могут приводить к TypeError.

Знак & перед первым параметром в справочной сигнатуре означает изменение переданного массива. В самом вызове & не пишут: передают переменную, а не временное выражение. Запись function ($value) { return ...; } создаёт функцию, которую операция вызывает для каждого элемента; return передаёт ей результат. Лист — значение, которое уже не является массивом. use (&$sum) ниже даёт функции доступ к внешнему накопителю по ссылке.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: передача функции как значения; рекурсивный обход и путь.

Что происходит в первом опыте
  1. Ветви left и right содержат qty
  2. Войти в каждый вложенный массив
  3. Получить листья qty=2 и qty=3
Увидеть локальные ключи листьевСамостоятельный пример
<?php
$tree = ['left' => ['qty' => 2], 'right' => ['qty' => 3]];
array_walk_recursive($tree, function ($value, $key) {
    echo $key, '=', $value, "
";
});
Ожидаемый результат
qty=2
qty=3

Ключи left/right в callback не пришли: они обозначают контейнеры. Если нужен путь left.qty, нужна собственная рекурсивная функция.

Сначала выше показан каждый локальный ключ листа. Теперь меняем только строковые значения. &$value связывает параметр с листом; is_string проверяет тип, trim возвращает очищенную строку. Ни callback, ни его return не возвращают новое дерево.

Очистить текст в подготовленной вложенной заявкеСамостоятельный пример
<?php
$payload = ['customer' => ['name' => ' Анна '], 'items' => [['code' => ' p1 ', 'qty' => 2]]];
$status = array_walk_recursive($payload, function (&$value, $key) {
    if (is_string($value)) {
        $value = trim($value);
    }
});
echo 'Получатель: [', $payload['customer']['name'], "]\n";
echo 'Артикул: [', $payload['items'][0]['code'], "]\n";
echo 'Количество: ', $payload['items'][0]['qty'], "\n";
if ($status) { echo "Обход завершён\n"; }
Ожидаемый результат
Получатель: [Анна]
Артикул: [p1]
Количество: 2
Обход завершён

Callback получает только листья: строку имени, строку артикула и число 2. Is_string допускает первые два; trim возвращает строку без крайних пробелов. Присваивание через &$value меняет соответствующий лист самого payload. Число пропускается и остаётся 2. Status содержит true — статус обхода; содержательные результаты читаются из payload. Квадратные скобки в выводе специально показывают отсутствие крайних пробелов. Ключ callback локальный и не сообщает путь родителя.

Накопить количество, не перепутав return walk с результатомСамостоятельный пример
<?php
$sum = 0;
$rows = [['qty' => 2], ['qty' => 3]];
array_walk_recursive($rows, function ($value, $key) use (&$sum) {
    if ($key === 'qty') { $sum += $value; }
});
echo $sum, "
";
Ожидаемый результат
5

Возврат callback не выходит из внешней функции и не останавливает весь walk. Когда нужно первое совпадение и ранний выход, явно пишите рекурсивный поиск.

Нюансы и выбор. Повторяющийся ключ name в разных ветках не идентифицирует одно поле. Нельзя восстановить родительский путь из одного callback(value,key); передавайте путь в своей рекурсии. Глубина и размер недоверенного JSON ограничиваются ещё при приёме.

Сравните: array_walk, array_map, array_reduce. Выбрать операцию по задаче.

array_merge_recursiveСобрать несколько значений одноимённых полей в общее дерево.

PHP 4.0.1+ · standard

array_merge_recursive(array ...$arrays): array

Собрать несколько значений одноимённых полей в общее дерево.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arraysНоль или больше массивов; обрабатываются слева направо. Без аргументов [] с PHP 7.4.
Правило совпаденияСовпавшие строковые ключи объединяются рекурсивно: два скаляра превращаются в массив. Числовые значения добавляются с перенумерацией, даже при совпавшем ключе.
ВозвратНовый массив; исходные массивы не изменяются. Это не глубокое клонирование объектов внутри значений.
Отказ и диагностикаНемассивный аргумент — TypeError. Рекурсивные варианты применяйте к конечным деревьям; циклические ссылки не являются поддержкой произвольного графа.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Tag равен red в одном источнике и blue в другом.
  2. Создать общий вложенный список двух меток.
  3. Перебрать каждую метку из combined[tag].
Собрать несколько меток одного поляСамостоятельный пример
<?php
$firstSource = ['tag' => 'red'];
$secondSource = ['tag' => 'blue'];
$combined = array_merge_recursive($firstSource, $secondSource);
foreach ($combined['tag'] as $tag) {
    echo 'Предложенная метка: ', $tag, "\n";
}
echo 'Первый источник всё ещё: ', $firstSource['tag'], "\n";
Ожидаемый результат
Предложенная метка: red
Предложенная метка: blue
Первый источник всё ещё: red

На одинаковом строковом ключе tag встретились две строки. Recursive merge возвращает под этим ключом вложенный массив [red,blue], поэтому следующий foreach проходит именно combined[tag]. Это полезно, когда по договору нужно собрать все варианты поля. Тип tag изменился со строки на массив; для одиночного порта/флага такой результат обычно непригоден. Следующий опыт сохраняет сравнение merge_recursive с replace_recursive.

Почему объединение не равно обновлению настройкиСамостоятельный пример
<?php
$base = ['mail' => ['host' => 'local', 'port' => 25]];
$patch = ['mail' => ['port' => 587]];
echo json_encode(array_merge_recursive($base, $patch)), "\n";
echo json_encode(array_replace_recursive($base, $patch)), "\n";
Ожидаемый результат
{"mail":{"host":"local","port":[25,587]}}
{"mail":{"host":"local","port":587}}

Два номера порта не являются корректным значением одного порта. Выбор операции определяется схемой данных.

Нюансы и выбор. Функция не удаляет дубликаты. Для объединения уникальных меток нужен отдельный шаг на известном уровне; для правки настроек обычно replace_recursive.

Сравните: array_merge, array_replace, array_replace_recursive. Выбрать операцию по задаче.

array_replace_recursiveПрименить частичный патч к вложенному словарю.

PHP 5.3+ · standard

array_replace_recursive(array $array, array ...$replacements): array

Применить частичный патч к вложенному словарю.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayОбязательный первый массив.
replacementsНоль или больше массивов-патчей, слева направо.
Правило совпаденияЕсли старое и новое значения оба массивы, рекурсивно обновляет их ключи. Во всех остальных случаях правое значение заменяет левое, даже при смене скаляра на массив или обратно.
ВозвратНовый массив; исходные массивы не изменяются. Это не глубокое клонирование объектов внутри значений.
Отказ и диагностикаНемассивный аргумент — TypeError. Рекурсивные варианты применяйте к конечным деревьям; циклические ссылки не являются поддержкой произвольного графа.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. В base есть mail.host и mail.port=25.
  2. Войти в mail и заменить только port на 587.
  3. Прочитать сохранённый host и новый port в строке адреса.
Изменить вложенный порт, сохранив имя сервераСамостоятельный пример
<?php
$base = ['mail' => ['host' => 'mail.local', 'port' => 25]];
$patch = ['mail' => ['port' => 587]];
$settings = array_replace_recursive($base, $patch);
echo 'Адрес для подключения: ', $settings['mail']['host'], ':', $settings['mail']['port'], "\n";
echo 'Исходный порт: ', $base['mail']['port'], "\n";
Ожидаемый результат
Адрес для подключения: mail.local:587
Исходный порт: 25

На ключе mail оба значения — массивы, поэтому функция входит внутрь. Там совпадает port: 25 заменяется на 587. Host в правке отсутствует, значит сохраняется. Возврат settings — целая новая структура; её два поля соединены в адрес, сетевого подключения этот пример не делает. При числовых ключах действует такое же замещение по ключу, поэтому список ролей требует отдельной политики: следующий опыт показывает этот крайний случай.

Не принять список ролей за атомарное значениеСамостоятельный пример
<?php
$base = ['roles' => ['reader','editor'], 'cache' => ['ttl' => 60]];
$patch = ['roles' => ['admin'], 'cache' => false];
echo json_encode(array_replace_recursive($base, $patch)), "\n";
Ожидаемый результат
{"roles":["admin","editor"],"cache":false}

roles[1] сохранился: список тоже массив с ключами. Если новый список должен полностью заменить старый, делайте явное присваивание roles после проверки.

Нюансы и выбор. Это не стандарт JSON Merge Patch: null не означает удаление, а числовые ключи списков обновляются по индексам. Для удаления и атомарных списков нужен явно описанный договор.

Сравните: array_merge, array_merge_recursive, array_replace. Выбрать операцию по задаче.

array_spliceЗаменить участок списка и отдельно получить удалённые элементы.

PHP 4+ · standard

array_splice(array &$array, int $offset, ?int $length = null, mixed $replacement = []): array

Задача и маршрут результата. Нужно заменить шаг процесса и отдельно сообщить, какой шаг удалён. Функция изменяет steps, а возвращает только удалённое; два результата должны быть прочитаны из разных мест.

Заменить участок списка и отдельно получить удалённые элементы.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемый исходный массив. Целочисленные ключи перенумеровываются.
offsetПозиция с нуля; отрицательная — от конца.
lengthnull/отсутствие: до конца; положительная: максимум удаляемых; отрицательная: оставить столько с конца; 0: только вставить. null поддержан с PHP 8.
replacementЗначения вставки; их ключи не сохраняются. Немассив преобразуется к массиву: чтобы вставить null/объект/массив одним элементом, оберните в [значение].
ВозвратМассив удалённых значений; изменённый список остаётся в первом аргументе.
Отказ и диагностикаПервый аргумент должен быть передаваемой переменной подходящего типа. Смещение за пределами списка не даёт ошибки; может получиться вставка у края.

Знак & перед первым параметром в справочной сигнатуре означает изменение переданного массива. В самом вызове & не пишут: передают переменную, а не временное выражение.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Список draft, review, done
  2. Убрать review и вставить approve
  3. Возврат [review], исходник draft, approve, done
Использовать результат array_splice в задачеСамостоятельный пример
<?php
$steps = ['draft', 'review', 'done'];
$removed = array_splice($steps, 1, 1, ['approve']);
foreach ($removed as $step) {
    echo 'Удалённый шаг: ', $step, "\n";
}
echo "Текущий маршрут\n";
foreach ($steps as $position => $step) {
    echo $position + 1, '. ', $step, "\n";
}
Ожидаемый результат
Удалённый шаг: review
Текущий маршрут
1. draft
2. approve
3. done

Первый аргумент steps меняется на месте. Со второй позиции удаляется один review, вместо него вставляется approve. Return содержит [review] и присваивается removed. Если присвоить результат обратно steps, дальнейший маршрут будет потерян. Позиция splice не равна id; для удаления ключа словаря подходит unset.

Вставить пустое поле, затем заменить хвостСамостоятельный пример
<?php
$cells = ['id','name'];
array_splice($cells, 1, 0, [null]);
echo json_encode($cells), "
";
array_splice($cells, -1, null, [['label' => 'title']]);
echo json_encode($cells), "
";
Ожидаемый результат
["id",null,"name"]
["id",null,{"label":"title"}]

[null] — один пустой элемент; null как replacement сам по себе преобразовался бы в пустой массив. Дополнительные скобки также удерживают вложенную запись одним элементом.

Нюансы и выбор. Не используйте splice как удаление по ID: offset означает позицию. Для словаря точнее unset($array[$id]); для неизменяющего среза — slice.

Сравните: array_slice, array_push, array_shift. Выбрать операцию по задаче.

array_reverseПолучить обратный порядок элементов, не сортируя их значения.

PHP 4+ · standard

array_reverse(array $array, bool $preserve_keys = false): array

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

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИсходный массив.
preserve_keystrue сохраняет числовые ключи, false перенумеровывает. Строковые ключи сохраняются в обоих режимах.
ВозвратНовый массив в обратном порядке; значения не меняются.
Отказ и диагностикаНеверный тип array — TypeError.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Порядок 10:A, 20:B
  2. Читать с конца
  3. B затем A; ключи выбирает preserve_keys
Перевернуть списокСамостоятельный пример
<?php
$items = [10 => 'A', 20 => 'B'];
echo json_encode(array_reverse($items)), "
";
echo json_encode(array_reverse($items, true)), "
";
Ожидаемый результат
["B","A"]
{"20":"B","10":"A"}

Обратный порядок ничего не говорит о цене, дате или алфавите.

Показать последние события первымиСамостоятельный пример
<?php
$log = ['evt-1' => 'open', 'evt-2' => 'save', 'evt-3' => 'close'];
foreach (array_reverse($log) as $id => $event) {
    echo $id, ':', $event, "
";
}
Ожидаемый результат
evt-3:close
evt-2:save
evt-1:open

Такой приём корректен, если исходный журнал уже расположен хронологически. Смешанные даты нужно сначала сортировать.

Нюансы и выбор. Для настоящего убывания по значениям нужна rsort/arsort. Reverse не выполняет сравнения.

Сравните: rsort, arsort, array_slice. Выбрать операцию по задаче.

array_padДополнить короткий ряд до нужного размера заданным значением.

PHP 4+ · standard

array_pad(array $array, int $length, mixed $value): array

Дополнить короткий ряд до нужного размера заданным значением.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИсходный массив.
lengthЦелевой размер по модулю; положительное число дополняет справа, отрицательное — слева. Если размер уже достаточен, ничего не удаляется.
valueКаждое добавленное значение. Объект остаётся одним и тем же экземпляром, а не клонируется.
ВозвратНовый массив. При дополнении числовые ключи перенумеровываются, строковые сохраняются.
Отказ и диагностикаПредельный размер ограничен возможностями массива и памятью. До PHP 8.3 за один вызов разрешалось добавить не более 1 048 576 элементов; теперь этот отдельный предел снят.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Ряд [7,9]
  2. Целевой размер 4, дополнение 0 справа
  3. Получить [7,9,0,0]
Дополнить справа и слеваСамостоятельный пример
<?php
echo json_encode(array_pad([7,9], 4, 0)), "
";
echo json_encode(array_pad([7,9], -4, 0)), "
";
echo json_encode(array_pad([7,9], 1, 0)), "
";
Ожидаемый результат
[7,9,0,0]
[0,0,7,9]
[7,9]

Целевой размер меньше исходного не обрезает вход.

Сделать три колонки отчёта без выдуманных измеренийСамостоятельный пример
<?php
$measurements = [12];
$cells = array_pad($measurements, 3, null);
foreach ($cells as $value) { echo $value === null ? "нет
" : $value . "
"; }
Ожидаемый результат
12
нет
нет

null здесь означает отсутствие измерения. Ноль значил бы реально измеренный ноль и исказил бы отчёт.

Нюансы и выбор. Не передавайте произвольный размер из запроса без верхнего ограничения. Для создания массива с нуля подходит fill, для обрезки slice.

Сравните: array_fill, array_slice, array_merge. Выбрать операцию по задаче.

array_pushДобавить несколько значений в конец списка.

PHP 4+ · standard

array_push(array &$array, mixed ...$values): int

Добавить несколько значений в конец списка.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемая переменная-массив.
valuesЗначения в порядке аргументов. Можно не передавать с PHP 7.3 — тогда возвращается текущий размер.
ВозвратНовое количество элементов, не новый массив. Существующие ключи сохраняются, новые получают следующий автоматический целочисленный индекс.
Отказ и диагностикаPHP 8: неверный тип первого аргумента — TypeError. В старых версиях могла быть warning; не используйте её как контракт современного PHP.

Знак & перед первым параметром в справочной сигнатуре означает изменение переданного массива. В самом вызове & не пишут: передают переменную, а не временное выражение.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Есть одна накладная под ключом 10.
  2. Добавить проверку адреса и упаковку после неё.
  3. Отдельно прочитать число 3 и каждое задание из изменённого tasks.
Добавить задания и прочитать изменившуюся очередьСамостоятельный пример
<?php
$tasks = [10 => 'выписать накладную'];
$size = array_push($tasks, 'проверить адрес', 'подготовить упаковку');
echo 'Заданий после добавления: ', $size, "\n";
foreach ($tasks as $position => $task) {
    echo $position, ': ', $task, "\n";
}
Ожидаемый результат
Заданий после добавления: 3
10: выписать накладную
11: проверить адрес
12: подготовить упаковку

Первый аргумент tasks меняется на месте. Два следующих — отдельные новые задания; между собой они сохраняют порядок. В size возвращено количество 3, а реальные задания читаются из tasks. При добавлении в конец старый ключ 10 сохранён, новые получили 11 и 12. Запись tasks = array_push(...) потеряла бы массив, заменив его числом.

Добавить партию в очередьСамостоятельный пример
<?php
$queue = ["report"];
$new = ["mail", "export"];
array_push($queue, ...$new);
echo implode(",", $queue), "\n";
echo array_push($queue), "\n";
Ожидаемый результат
report,mail,export
3

...$new разворачивает элементы в отдельные аргументы. Пустой набор значений не удаляет очередь.

Нюансы и выбор. Для одного значения обычное $array[] = $value проще и не требует вызова функции. Для вложенного массива без ... добавится один вложенный элемент.

Сравните: array_unshift, array_pop, array_shift, array_splice. Выбрать операцию по задаче.

array_unshiftДобавить несколько значений в начало списка.

PHP 4+ · standard

array_unshift(array &$array, mixed ...$values): int

Добавить несколько значений в начало списка.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемая переменная-массив.
valuesЗначения в порядке аргументов. Можно не передавать с PHP 7.3 — тогда возвращается текущий размер.
ВозвратНовое количество элементов, не новый массив. Числовые ключи перенумеровываются, строковые сохраняются; указатель сбрасывается в начало.
Отказ и диагностикаPHP 8: неверный тип первого аргумента — TypeError. В старых версиях могла быть warning; не используйте её как контракт современного PHP.

Знак & перед первым параметром в справочной сигнатуре означает изменение переданного массива. В самом вызове & не пишут: передают переменную, а не временное выражение.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Есть одна накладная под ключом 10.
  2. Добавить проверку адреса и упаковку перед ней.
  3. Отдельно прочитать число 3 и каждое задание из изменённого tasks.
Добавить задания и прочитать изменившуюся очередьСамостоятельный пример
<?php
$tasks = [10 => 'выписать накладную'];
$size = array_unshift($tasks, 'проверить адрес', 'подготовить упаковку');
echo 'Заданий после добавления: ', $size, "\n";
foreach ($tasks as $position => $task) {
    echo $position, ': ', $task, "\n";
}
Ожидаемый результат
Заданий после добавления: 3
0: проверить адрес
1: подготовить упаковку
2: выписать накладную

Первый аргумент tasks меняется на месте. Два следующих — отдельные новые задания; между собой они сохраняют порядок. В size возвращено количество 3, а реальные задания читаются из tasks. Добавление в начало перенумеровало числовые ключи: 0,1,2. Запись tasks = array_unshift(...) потеряла бы массив, заменив его числом.

Добавить срочную работу перед очередьюСамостоятельный пример
<?php
$queue = ["report"];
$new = ["mail", "export"];
array_unshift($queue, ...$new);
echo implode(",", $queue), "\n";
echo array_unshift($queue), "\n";
Ожидаемый результат
mail,export,report
3

...$new разворачивает элементы в отдельные аргументы. Пустой набор значений не удаляет очередь.

Нюансы и выбор. Частые вставки в начало требуют перемещения/перенумерации числовых элементов. Для большой очереди рассмотрите SplQueue или иной специализированный контейнер.

Сравните: array_push, array_pop, array_shift, array_splice. Выбрать операцию по задаче.

array_popИзвлечь и удалить последний элемент стека.

PHP 4+ · standard

array_pop(array &$array): mixed

Извлечь и удалить последний элемент стека.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayПеременная-массив, изменяемая на месте.
ВозвратУдалённое значение; для пустого массива null. Указатель сбрасывается в начало. Оставшиеся ключи сохраняются.
Отказ и диагностикаВ PHP 8 немассивный аргумент даёт TypeError, а не универсальное null. Возврат null может быть удалённым значением либо признаком пустоты.

Знак & перед первым параметром в справочной сигнатуре означает изменение переданного массива. В самом вызове & не пишут: передают переменную, а не временное выражение.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Три задания: адрес, упаковка, накладная.
  2. Извлечь накладную из конца.
  3. Возврат даёт одно задание; tasks хранит два оставшихся.
Получить одно задание и увидеть остаток очередиСамостоятельный пример
<?php
$tasks = [10 => 'адрес', 20 => 'упаковка', 30 => 'накладная'];
$task = array_pop($tasks);
echo 'Получено задание: ', $task, "\n";
echo "Осталось:\n";
foreach ($tasks as $position => $remaining) {
    echo $position, ': ', $remaining, "\n";
}
Ожидаемый результат
Получено задание: накладная
Осталось:
10: адрес
20: упаковка

Вызов удаляет последнее значение и возвращает только его в task. Дальнейший код мог бы выполнить полученное задание; здесь он сообщает название, затем отдельно читает остаток из tasks. Pop сохранил ключи остатка 10 и 20. Перед выбором из неизвестной очереди проверяют её непустоту; следующий опыт отделяет пустой массив от полезного значения null.

Различить пустую очередь и пустое значениеСамостоятельный пример
<?php
$items = [null];
while ($items !== []) {
    $value = array_pop($items);
    echo $value === null ? "Получен null\n" : "Получено значение\n";
}
var_dump(array_pop($items));
Ожидаемый результат
Получен null
NULL

Условие проверяет наличие элементов до удаления. Цикл while (($value = pop(...)) !== null) преждевременно закончился бы на полезном null.

Нюансы и выбор. Для чтения без удаления используйте array_last в PHP 8.5+ или array_key_last и чтение по ключу в прежних версиях.

Сравните: array_shift, array_first, array_last. Выбрать операцию по задаче.

array_shiftИзвлечь и удалить первый элемент очереди.

PHP 4+ · standard

array_shift(array &$array): mixed

Извлечь и удалить первый элемент очереди.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayПеременная-массив, изменяемая на месте.
ВозвратУдалённое значение; для пустого массива null. Указатель сбрасывается в начало. Оставшиеся числовые ключи перенумеровываются с нуля; строковые сохраняются.
Отказ и диагностикаВ PHP 8 немассивный аргумент даёт TypeError, а не универсальное null. Возврат null может быть удалённым значением либо признаком пустоты.

Знак & перед первым параметром в справочной сигнатуре означает изменение переданного массива. В самом вызове & не пишут: передают переменную, а не временное выражение.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Три задания: адрес, упаковка, накладная.
  2. Извлечь адрес из начала.
  3. Возврат даёт одно задание; tasks хранит два оставшихся.
Получить одно задание и увидеть остаток очередиСамостоятельный пример
<?php
$tasks = [10 => 'адрес', 20 => 'упаковка', 30 => 'накладная'];
$task = array_shift($tasks);
echo 'Получено задание: ', $task, "\n";
echo "Осталось:\n";
foreach ($tasks as $position => $remaining) {
    echo $position, ': ', $remaining, "\n";
}
Ожидаемый результат
Получено задание: адрес
Осталось:
0: упаковка
1: накладная

Вызов удаляет первое значение и возвращает только его в task. Дальнейший код мог бы выполнить полученное задание; здесь он сообщает название, затем отдельно читает остаток из tasks. Shift перенумеровал числовые ключи остатка 0 и 1. Перед выбором из неизвестной очереди проверяют её непустоту; следующий опыт отделяет пустой массив от полезного значения null.

Различить пустую очередь и пустое значениеСамостоятельный пример
<?php
$items = [null];
while ($items !== []) {
    $value = array_shift($items);
    echo $value === null ? "Получен null\n" : "Получено значение\n";
}
var_dump(array_shift($items));
Ожидаемый результат
Получен null
NULL

Условие проверяет наличие элементов до удаления. Цикл while (($value = pop(...)) !== null) преждевременно закончился бы на полезном null.

Нюансы и выбор. Повторный shift для большой очереди может быть дорогим из-за перенумерации. Если удаление не нужно, используйте foreach; для очереди — SplQueue.

Сравните: array_pop, array_first, array_last. Выбрать операцию по задаче.

array_sumСложить числовые значения, например суммы уже проверенных строк заказа.

PHP 4.0.4+ · standard

array_sum(array $array): int|float

Сложить числовые значения, например суммы уже проверенных строк заказа.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayЧисловые значения; ключи не участвуют. Числовые строки могут преобразовываться, но это не проверка входного формата.
ВозвратЦелое число или float. Пустой массив даёт 0 — нейтральное слагаемое.
Отказ и диагностикаС PHP 8.3 непреобразуемые в число значения вызывают E_WARNING. Раньше массивы/объекты игнорировались, другие значения преобразовывались; теперь объекты с числовым cast, например GMP, могут участвовать в расчёте.
Что происходит в первом опыте
  1. Числа 2, 3, 4
  2. Сложить начиная с 0
  3. Получить 9
Обычный и пустой входСамостоятельный пример
<?php
echo array_sum([2,3,4]), "\n";
echo array_sum([]), "\n";
Ожидаемый результат
9
0

Пустой вход не означает ошибку; бизнес-правило о минимальном числе позиций проверяется отдельно.

Использовать результат array_sum в задачеСамостоятельный пример
<?php
$lineTotals = ['p1' => 19900, 'p2' => 4500];
$itemsTotalKopecks = array_sum($lineTotals);
$deliveryKopecks = 30000;
$payableKopecks = $itemsTotalKopecks + $deliveryKopecks;
echo 'Товары: ', $itemsTotalKopecks, ' коп.', "\n";
echo 'С доставкой: ', $payableKopecks, ' коп.', "\n";
Ожидаемый результат
Товары: 24400 коп.
С доставкой: 54400 коп.

Sum складывает только значения 19900 и 4500; ключи p1/p2 в арифметике не участвуют. Return 24400 сохранён в itemsTotalKopecks, затем обычное + даёт 54400. Здесь уже заданы суммы строк в целых копейках: функция не перемножает price и quantity вложенной записи автоматически.

Нюансы и выбор. Функция не спускается рекурсивно по строкам заказа. Сначала извлеките/рассчитайте нужные числа. Float имеет погрешность, а превышение целочисленного диапазона может изменить тип результата; для точных больших денежных расчётов нужна подходящая числовая модель.

Сравните: array_product, array_reduce, array_column. Выбрать операцию по задаче.

array_productПеремножить числовые значения, например количества вариантов комплектации.

PHP 5.1+ · standard

array_product(array $array): int|float

Перемножить числовые значения, например количества вариантов комплектации.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayЧисловые значения; ключи не участвуют. Числовые строки могут преобразовываться, но это не проверка входного формата.
ВозвратЦелое число или float. Пустой массив даёт 1 — нейтральный множитель.
Отказ и диагностикаС PHP 8.3 непреобразуемые в число значения вызывают E_WARNING. Раньше массивы/объекты игнорировались, другие значения преобразовывались; теперь объекты с числовым cast, например GMP, могут участвовать в расчёте.
Что происходит в первом опыте
  1. Числа 2, 3, 4
  2. Умножить начиная с 1
  3. Получить 24
Обычный и пустой входСамостоятельный пример
<?php
echo array_product([2,3,4]), "\n";
echo array_product([]), "\n";
Ожидаемый результат
24
1

Пустой вход не означает ошибку; бизнес-правило о минимальном числе позиций проверяется отдельно.

Использовать результат array_product в задачеСамостоятельный пример
<?php
$choices = ['colors' => 3, 'sizes' => 4, 'packs' => 2];
$variants = array_product($choices);
echo 'Доступно сочетаний: ', $variants, "\n";
$choices['sizes'] = 0;
$variants = array_product($choices);
if ($variants === 0) {
    echo "Конструктор недоступен: нет размеров\n";
}
Ожидаемый результат
Доступно сочетаний: 24
Конструктор недоступен: нет размеров

Три независимых выбора дают 3 × 4 × 2 = 24. После нуля в sizes произведение 0 используется в ветке недоступности. Если цвет ограничивает размеры, варианты зависимы и такая формула неверна. Пустой массив дал бы 1 как нейтральный множитель, а не признак готовой комплектации.

Нюансы и выбор. Функция не спускается рекурсивно по строкам заказа. Сначала извлеките/рассчитайте нужные числа. Float имеет погрешность, а превышение целочисленного диапазона может изменить тип результата; для точных больших денежных расчётов нужна подходящая числовая модель.

Сравните: array_sum, array_reduce, array_column. Выбрать операцию по задаче.

array_diff_assocРазность массивов: оставить пары первого входа, для которых совпадение не найдено ни в одном из остальных массивов. Ключ и значение одновременно.

PHP 4.3+ · standard

array_diff_assoc(array $array, array ...$arrays): array

Разность массивов: оставить пары первого входа, для которых совпадение не найдено ни в одном из остальных массивов. Ключ и значение одновременно.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayПервый массив — источник возвращаемых ключей, значений и порядка.
arraysОстальные массивы для сравнения. Без них допустим вызов с PHP 8: возвращается исходное содержимое.
Что совпадаетКлюч и значение одновременно. Встроенное сравнение ключей проверяет одинаковое строковое представление. Значения равны, когда их строковые представления совпадают: 10 и "10" равны, 10 и "010" различаются. Это не строгое сравнение исходных типов.
ВозвратНовый массив с исходными ключами/значениями/порядком первого аргумента; повторы подходящих значений не убираются.
Отказ и диагностикаВложенные массивы здесь не сравниваются рекурсивно: приведение массива к строке вызывает warning, объект без строкового преобразования — Error. Немассивные входы — TypeError.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Первый массив задаёт кандидатов
  2. Сверить пары с остальными
  3. Сохранить пару, если совпадение не найдено ни в одном из остальных массивов
Увидеть, что именно сравниваетсяСамостоятельный пример
<?php
$a = ["a" => 10, "b" => 20, "c" => 10];
$b = ["a" => "10", "b" => 30, "z" => 10];
echo json_encode(array_diff_assoc($a, $b)), "\n";
Ожидаемый результат
{"b":20,"c":10}

Ключ и значение одновременно. Ключи результата взяты из $a.

Теперь применим правило первого опыта к данным задачи. Первый массив задаёт, какие значения и ключи можно вернуть. Следующие массивы служат только для сравнения; они не дополняют результат новыми записями.

Объяснить изменение настроек перед применениемСамостоятельный пример
<?php
$new = ['host' => 'mail.local', 'port' => 587, 'tls' => 'on'];
$old = ['host' => 'mail.local', 'port' => 25];
$selected = array_diff_assoc($new, $old);
foreach ($selected as $setting => $value) {
    echo "Изменённая или новая настройка: ", $setting, " = ", $value, "\n";
}
Ожидаемый результат
Изменённая или новая настройка: port = 587
Изменённая или новая настройка: tls = on

Для совпадения должны подойти и ключ, и значение одной пары. Host совпадает; port существует, но 587 отличается от 25; tls прежде отсутствовал. Return — словарь выбранных пар из new. Его foreach превращает в строки отчёта; настройки подключения здесь ещё не применяются. Значения сравниваются по строковому представлению: число 25 и строка "25" считались бы совпадением, поэтому это не аудит типов. Удалённые из new поля ищутся отдельным сравнением в обратную сторону.

Нюансы и выбор. Проверяется один уровень. Для вложенной записи выберите конкретное поле или собственный компаратор; не подменяйте структуру строкой "Array". Если нужна JSON-последовательность, явный array_values допустим только когда исходные ключи не несут смысла.

Сравните: array_diff, array_diff_key, array_udiff, array_unique. Выбрать операцию по задаче.

array_diff_keyРазность массивов: оставить пары первого входа, для которых совпадение не найдено ни в одном из остальных массивов. Только ключи; значения не сравниваются.

PHP 5.1+ · standard

array_diff_key(array $array, array ...$arrays): array

Разность массивов: оставить пары первого входа, для которых совпадение не найдено ни в одном из остальных массивов. Только ключи; значения не сравниваются.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayПервый массив — источник возвращаемых ключей, значений и порядка.
arraysОстальные массивы для сравнения. Без них допустим вызов с PHP 8: возвращается исходное содержимое.
Что совпадаетТолько ключи; значения не сравниваются. Встроенное сравнение ключей проверяет одинаковое строковое представление.
ВозвратНовый массив с исходными ключами/значениями/порядком первого аргумента; повторы подходящих значений не убираются.
Отказ и диагностикаНемассивные входы — TypeError.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Первый массив задаёт кандидатов
  2. Сверить ключи с остальными
  3. Сохранить пару, если совпадение не найдено ни в одном из остальных массивов
Увидеть, что именно сравниваетсяСамостоятельный пример
<?php
$a = ["name" => "Ada", "price" => 9];
$b = ["name" => null];
echo json_encode(array_diff_key($a, $b)), "\n";
Ожидаемый результат
{"price":9}

Только ключи; значения не сравниваются. Ключи результата взяты из $a.

Теперь применим правило первого опыта к данным задачи. Первый массив задаёт, какие значения и ключи можно вернуть. Следующие массивы служат только для сравнения; они не дополняют результат новыми записями.

Найти поля, которым не место в этой формеСамостоятельный пример
<?php
$incoming = ['name' => 'Анна', 'note' => 'Позвонить', 'role' => 'admin'];
$fields = ['name' => true, 'note' => true];
$selected = array_diff_key($incoming, $fields);
foreach ($selected as $field => $value) {
    echo "Неизвестное поле: ", $field, " = ", $value, "\n";
}
Ожидаемый результат
Неизвестное поле: role = admin

Словарь fields использует только ключи: значения true — заполнители и с «Анна» не сравниваются. Diff оставляет неизвестное role и его исходное значение admin, чтобы объяснить отказ пользователю. Функция не сохраняет данные и не назначает права. Сравниваются одинаковые имена ключей. Значение null в маске тоже обозначало бы присутствующий ключ.

Нюансы и выбор. Проверяется один уровень. Для вложенной записи выберите конкретное поле или собственный компаратор; не подменяйте структуру строкой "Array". Если нужна JSON-последовательность, явный array_values допустим только когда исходные ключи не несут смысла.

Сравните: array_diff, array_diff_assoc, array_udiff, array_unique. Выбрать операцию по задаче.

array_diff_uassocРазность массивов: оставить пары первого входа, для которых совпадение не найдено ни в одном из остальных массивов. Ключ и значение одновременно.

PHP 5+ · standard

array_diff_uassoc(array $array, array ...$arrays, callable $key_compare_func): array

Разность массивов: оставить пары первого входа, для которых совпадение не найдено ни в одном из остальных массивов. Ключ и значение одновременно.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayПервый массив — источник возвращаемых ключей, значений и порядка.
arraysОстальные массивы для сравнения. После массивов последним передаётся callback сравнения ключей. Не считайте его ещё одним массивом. В PHP 8.5.11 допускается только исходный массив и callback: результат сохраняет исходное содержимое.
Что совпадаетКлюч и значение одновременно. Значения равны, когда их строковые представления совпадают: 10 и "10" равны, 10 и "010" различаются. Это не строгое сравнение исходных типов.
key_compare_funccallback(keyA, keyB): int; 0 означает равные ключи. strcasecmp ниже сравнивает ASCII-регистр без различий.
ВозвратНовый массив с исходными ключами/значениями/порядком первого аргумента; повторы подходящих значений не убираются.
Отказ и диагностикаОшибки callback распространяются наружу; он обязан возвращать целое сравнение, float приводится к int и может ошибочно стать 0. Вложенные массивы здесь не сравниваются рекурсивно: приведение массива к строке вызывает warning, объект без строкового преобразования — Error. Немассивные входы — TypeError.

Компаратор — функция сравнения двух элементов. Она возвращает целое число: отрицательное — первый раньше, 0 — равны по выбранному признаку, положительное — первый позже. $a <=> $b даёт -1, 0 или 1. Это не проверка true/false; разность дробей нельзя возвращать вместо целого результата. function ($a, $b) { return ...; } передаёт правило операции, а не вызывает его немедленно. strcasecmp — встроенное сравнение двух строк без учёта ASCII-регистра.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: передача функции как значения.

Что происходит в первом опыте
  1. Первый массив задаёт кандидатов
  2. Сверить пары с остальными
  3. Сохранить пару, если совпадение не найдено ни в одном из остальных массивов
Увидеть, что именно сравниваетсяСамостоятельный пример
<?php
$a = ["A" => 10, "B" => 20, "C" => 10];
$b = ["a" => "10", "b" => 30, "z" => 10];
echo json_encode(array_diff_uassoc($a, $b, "strcasecmp")), "\n";
Ожидаемый результат
{"B":20,"C":10}

Ключ и значение одновременно. Ключи результата взяты из $a.

Теперь применим правило первого опыта к данным задачи. Первый массив задаёт, какие значения и ключи можно вернуть. Следующие массивы служат только для сравнения; они не дополняют результат новыми записями.

Объяснить изменение настроек перед применениемСамостоятельный пример
<?php
$new = ['host' => 'mail.local', 'port' => 587, 'tls' => 'on'];
$old = ['HOST' => 'mail.local', 'PORT' => 25];
$selected = array_diff_uassoc($new, $old, "strcasecmp");
foreach ($selected as $setting => $value) {
    echo "Изменённая или новая настройка: ", $setting, " = ", $value, "\n";
}
Ожидаемый результат
Изменённая или новая настройка: port = 587
Изменённая или новая настройка: tls = on

Для совпадения должны подойти и ключ, и значение одной пары. Host совпадает; port существует, но 587 отличается от 25; tls прежде отсутствовал. Return — словарь выбранных пар из new. Его foreach превращает в строки отчёта; настройки подключения здесь ещё не применяются. Ключи сравнивает strcasecmp без ASCII-регистра, а значения — встроенное строковое представление. Удалённые из new поля ищутся отдельным сравнением в обратную сторону.

Нюансы и выбор. Проверяется один уровень. Для вложенной записи выберите конкретное поле или собственный компаратор; не подменяйте структуру строкой "Array". Порядок callback не фиксирован; не рассчитывайте на вызов строго слева направо по исходному списку. Если нужна JSON-последовательность, явный array_values допустим только когда исходные ключи не несут смысла.

Сравните: array_diff, array_diff_assoc, array_diff_key, array_udiff, array_unique. Выбрать операцию по задаче.

array_diff_ukeyРазность массивов: оставить пары первого входа, для которых совпадение не найдено ни в одном из остальных массивов. Только ключи; значения не сравниваются.

PHP 5.1+ · standard

array_diff_ukey(array $array, array ...$arrays, callable $key_compare_func): array

Разность массивов: оставить пары первого входа, для которых совпадение не найдено ни в одном из остальных массивов. Только ключи; значения не сравниваются.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayПервый массив — источник возвращаемых ключей, значений и порядка.
arraysОстальные массивы для сравнения. После массивов последним передаётся callback сравнения ключей. Не считайте его ещё одним массивом. В PHP 8.5.11 допускается только исходный массив и callback: результат сохраняет исходное содержимое.
Что совпадаетТолько ключи; значения не сравниваются.
key_compare_funccallback(keyA, keyB): int; 0 означает равные ключи. strcasecmp ниже сравнивает ASCII-регистр без различий.
ВозвратНовый массив с исходными ключами/значениями/порядком первого аргумента; повторы подходящих значений не убираются.
Отказ и диагностикаОшибки callback распространяются наружу; он обязан возвращать целое сравнение, float приводится к int и может ошибочно стать 0. Немассивные входы — TypeError.

Компаратор — функция сравнения двух элементов. Она возвращает целое число: отрицательное — первый раньше, 0 — равны по выбранному признаку, положительное — первый позже. $a <=> $b даёт -1, 0 или 1. Это не проверка true/false; разность дробей нельзя возвращать вместо целого результата. function ($a, $b) { return ...; } передаёт правило операции, а не вызывает его немедленно. strcasecmp — встроенное сравнение двух строк без учёта ASCII-регистра.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: передача функции как значения.

Что происходит в первом опыте
  1. Первый массив задаёт кандидатов
  2. Сверить ключи с остальными
  3. Сохранить пару, если совпадение не найдено ни в одном из остальных массивов
Увидеть, что именно сравниваетсяСамостоятельный пример
<?php
$a = ["Name" => "Ada", "Price" => 9];
$b = ["name" => null];
echo json_encode(array_diff_ukey($a, $b, "strcasecmp")), "\n";
Ожидаемый результат
{"Price":9}

Только ключи; значения не сравниваются. Ключи результата взяты из $a.

Теперь применим правило первого опыта к данным задачи. Первый массив задаёт, какие значения и ключи можно вернуть. Следующие массивы служат только для сравнения; они не дополняют результат новыми записями.

Найти поля, которым не место в этой формеСамостоятельный пример
<?php
$incoming = ['name' => 'Анна', 'note' => 'Позвонить', 'role' => 'admin'];
$fields = ['NAME' => true, 'NOTE' => true];
$selected = array_diff_ukey($incoming, $fields, "strcasecmp");
foreach ($selected as $field => $value) {
    echo "Неизвестное поле: ", $field, " = ", $value, "\n";
}
Ожидаемый результат
Неизвестное поле: role = admin

Словарь fields использует только ключи: значения true — заполнители и с «Анна» не сравниваются. Diff оставляет неизвестное role и его исходное значение admin, чтобы объяснить отказ пользователю. Функция не сохраняет данные и не назначает права. Здесь договор явно допускает ASCII-регистр имён: strcasecmp возвращает 0 для name/NAME. Это готовая функция сравнения двух строк; строка "strcasecmp" передаёт её как callback.

Нюансы и выбор. Проверяется один уровень. Для вложенной записи выберите конкретное поле или собственный компаратор; не подменяйте структуру строкой "Array". Порядок callback не фиксирован; не рассчитывайте на вызов строго слева направо по исходному списку. Если нужна JSON-последовательность, явный array_values допустим только когда исходные ключи не несут смысла.

Сравните: array_diff, array_diff_assoc, array_diff_key, array_udiff, array_unique. Выбрать операцию по задаче.

array_udiffВычислить разность по собственному правилу значений.

PHP 5+ · standard

array_udiff(array $array, array ...$arrays, callable $value_compare_func): array

Вычислить разность по собственному правилу значений.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
array / array1Первый массив задаёт возвращаемые пары и порядок.
arraysОстальные массивы, затем callback-функции. Сохраняется элемент, для которого совпадение не найдено ни в одном из остальных массивов. В PHP 8.5.11 допустимо не передавать дополнительные массивы: с нужными callback возвращается содержимое первого.
value_compare_funccallback(valueA, valueB): int. Должен уметь сравнить любые два элемента любого из входов в любом порядке.
ВозвратНовый массив из подходящих элементов первого входа; ключи, значения и их исходный порядок сохранены.
Отказ и диагностикаFloat-результат компаратора приводится к int, дробь меньше 1 превратится в 0. Неподходящие типы входных элементов и ошибки callback могут привести к исключению. Не изменяйте сравниваемые данные из callback.

Компаратор — функция сравнения двух элементов. Она возвращает целое число: отрицательное — первый раньше, 0 — равны по выбранному признаку, положительное — первый позже. $a <=> $b даёт -1, 0 или 1. Это не проверка true/false; разность дробей нельзя возвращать вместо целого результата. function ($a, $b) { return ...; } передаёт правило операции, а не вызывает его немедленно. abs возвращает модуль числа: -3 и 3 дают одинаковое значение 3.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: передача функции как значения.

Что происходит в первом опыте
  1. Кандидаты -3, 8, 3
  2. Сравнить модули со значением 3
  3. Сохранить выбранные исходные пары, а не модули
Задать собственное равенствоСамостоятельный пример
<?php
$a = ["a" => -3, "b" => 8, "c" => 3];
$b = ["other" => 3];
$compare = function ($a, $b) { return abs($a) <=> abs($b); };
echo json_encode(array_udiff($a, $b, $compare)), "\n";
Ожидаемый результат
{"b":8}

Равенство выражено возвратом 0. Модуль нужен только для сравнения, исходные числа не заменяются.

Первый опыт уже показал три исхода компаратора: меньше, равно, больше. Теперь параметрами будут записи-массивы. Форма каждой записи проверена заранее; нельзя предполагать, что left всегда из local, а right всегда из remote.

Получить новые товары по IDСамостоятельный пример
<?php
$local = [['id' => 12, 'name' => 'Локальная карточка'], ['id' => 25, 'name' => 'Новый товар']];
$remote = [['id' => 12, 'name' => 'Иное название']];
$compareId = function ($left, $right) {
    return $left["id"] <=> $right["id"];
};
$selected = array_udiff($local, $remote, $compareId);
foreach ($selected as $record) {
    echo "ID ", $record["id"], ": ", $record["name"], "\n";
}
Ожидаемый результат
ID 25: Новый товар

Каждый параметр callback — одна запись с int-полем id. Возврат left[id]<=>right[id] равен 0 для одинакового ID независимо от name. Алгоритм получает этот знак для сравнения; selected получает массив подходящих записей local. ID 12 уже присутствует в remote; ID 25 отсутствует и попадает в план добавления. Ключи исходных списков не являются критерием. Такая операция не проверяет уникальность ID и не синхронизирует базу сама.

Нюансы и выбор. Внутри сравнения массивы могут предварительно сортироваться, поэтому нельзя предполагать: $a всегда из local, $b всегда из remote. Нужен согласованный полный порядок (транзитивность, противоположные знаки при обмене аргументов), не функция «похож/не похож». Обход одноуровневый; callback сам выбирает поля вложенных значений. Для больших наборов с точным уникальным ID явный индекс нередко проще повторных сравнений.

Сравните: array_diff, array_diff_assoc, array_udiff_assoc, array_udiff_uassoc. Выбрать операцию по задаче.

Реальная причина ошибки из вопроса о пропавших элементах: callback отдавал только 0/1 и не задавал согласованного порядка двух аргументов. Для отбора по одному признаку нужен array_filter; компаратор здесь обязан сравнить оба входа. Ответы обсуждения не служат нормативным правилом; договор проверен по PHP Manual.

array_udiff_assocВычислить разность по собственному правилу значений с проверкой ключа.

PHP 5+ · standard

array_udiff_assoc(array $array, array ...$arrays, callable $value_compare_func): array

Вычислить разность по собственному правилу значений с проверкой ключа.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
array / array1Первый массив задаёт возвращаемые пары и порядок.
arraysОстальные массивы, затем callback-функции. Сохраняется элемент, для которого совпадение не найдено ни в одном из остальных массивов. В PHP 8.5.11 допустимо не передавать дополнительные массивы: с нужными callback возвращается содержимое первого.
value_compare_funccallback(valueA, valueB): int. Должен уметь сравнить любые два элемента любого из входов в любом порядке.
КлючиПара должна иметь совпавший ключ по встроенному правилу; одного равенства значений недостаточно.
ВозвратНовый массив из подходящих элементов первого входа; ключи, значения и их исходный порядок сохранены.
Отказ и диагностикаFloat-результат компаратора приводится к int, дробь меньше 1 превратится в 0. Неподходящие типы входных элементов и ошибки callback могут привести к исключению. Не изменяйте сравниваемые данные из callback.

Компаратор — функция сравнения двух элементов. Она возвращает целое число: отрицательное — первый раньше, 0 — равны по выбранному признаку, положительное — первый позже. $a <=> $b даёт -1, 0 или 1. Это не проверка true/false; разность дробей нельзя возвращать вместо целого результата. function ($a, $b) { return ...; } передаёт правило операции, а не вызывает его немедленно. abs возвращает модуль числа: -3 и 3 дают одинаковое значение 3.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: передача функции как значения.

Что происходит в первом опыте
  1. Кандидаты -3, 8, 3
  2. Сравнить модули со значением 3 и ключи
  3. Сохранить выбранные исходные пары, а не модули
Задать собственное равенствоСамостоятельный пример
<?php
$a = ["a" => -3, "b" => 8, "c" => 3];
$b = ["a" => 3];
$compare = function ($a, $b) { return abs($a) <=> abs($b); };
echo json_encode(array_udiff_assoc($a, $b, $compare)), "\n";
Ожидаемый результат
{"b":8,"c":3}

Равенство выражено возвратом 0. Модуль нужен только для сравнения, исходные числа не заменяются.

Первый опыт уже показал три исхода компаратора: меньше, равно, больше. Теперь параметрами будут записи-массивы. Форма каждой записи проверена заранее; нельзя предполагать, что left всегда из local, а right всегда из remote.

Подготовить записи с отличающейся версиейСамостоятельный пример
<?php
$local = ['sku-a' => ['revision' => 2, 'label' => 'Карточка A'], 'sku-b' => ['revision' => 3, 'label' => 'Карточка B']];
$remote = ['sku-a' => ['revision' => 2, 'label' => 'Другое название A'], 'sku-b' => ['revision' => 1, 'label' => 'Старое название B']];
$compareRevision = function ($left, $right) {
    return $left["revision"] <=> $right["revision"];
};
$selected = array_udiff_assoc($local, $remote, $compareRevision);
foreach ($selected as $sku => $record) {
    echo $sku, ": ", $record["label"], ", версия ", $record["revision"], "\n";
}
Ожидаемый результат
sku-b: Карточка B, версия 3

Callback получает две целые записи, читает revision и возвращает знак сравнения. Для версий 2/2 это 0, для 3/1 — 1; алгоритм может дать их в обратном порядке или из одного входа. Дополнительно проверяются ключи по встроенному правилу. Для sku-a совпадают ключ и версия; для sku-b версия отличается. Return всей операции — выбранные исходные записи local, поэтому выводится его label, а не удалённый. Поле label намеренно не входит в критерий: равная версия здесь не доказывает побайтовое равенство всей карточки.

Нюансы и выбор. Внутри сравнения массивы могут предварительно сортироваться, поэтому нельзя предполагать: $a всегда из local, $b всегда из remote. Нужен согласованный полный порядок (транзитивность, противоположные знаки при обмене аргументов), не функция «похож/не похож». Обход одноуровневый; callback сам выбирает поля вложенных значений. Для больших наборов с точным уникальным ID явный индекс нередко проще повторных сравнений.

Сравните: array_diff, array_diff_assoc, array_udiff, array_udiff_uassoc. Выбрать операцию по задаче.

Реальная причина ошибки из вопроса о пропавших элементах: callback отдавал только 0/1 и не задавал согласованного порядка двух аргументов. Для отбора по одному признаку нужен array_filter; компаратор здесь обязан сравнить оба входа. Ответы обсуждения не служат нормативным правилом; договор проверен по PHP Manual.

array_udiff_uassocВычислить разность по собственному правилу значений с проверкой ключа.

PHP 5+ · standard

array_udiff_uassoc(array $array, array ...$arrays, callable $value_compare_func, callable $key_compare_func): array

Вычислить разность по собственному правилу значений с проверкой ключа.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
array / array1Первый массив задаёт возвращаемые пары и порядок.
arraysОстальные массивы, затем callback-функции. Сохраняется элемент, для которого совпадение не найдено ни в одном из остальных массивов. В PHP 8.5.11 допустимо не передавать дополнительные массивы: с нужными callback возвращается содержимое первого.
value_compare_funccallback(valueA, valueB): int. Должен уметь сравнить любые два элемента любого из входов в любом порядке.
КлючиПоследний key_compare_func(keyA,keyB): int сравнивает ключи. Порядок callback: сначала значения, потом ключи.
ВозвратНовый массив из подходящих элементов первого входа; ключи, значения и их исходный порядок сохранены.
Отказ и диагностикаFloat-результат компаратора приводится к int, дробь меньше 1 превратится в 0. Неподходящие типы входных элементов и ошибки callback могут привести к исключению. Не изменяйте сравниваемые данные из callback.

Компаратор — функция сравнения двух элементов. Она возвращает целое число: отрицательное — первый раньше, 0 — равны по выбранному признаку, положительное — первый позже. $a <=> $b даёт -1, 0 или 1. Это не проверка true/false; разность дробей нельзя возвращать вместо целого результата. function ($a, $b) { return ...; } передаёт правило операции, а не вызывает его немедленно. abs возвращает модуль числа: -3 и 3 дают одинаковое значение 3. strcasecmp во втором callback сравнивает ключи без учёта ASCII-регистра.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: передача функции как значения.

Что происходит в первом опыте
  1. Кандидаты -3, 8, 3
  2. Сравнить модули со значением 3 и ключи
  3. Сохранить выбранные исходные пары, а не модули
Задать собственное равенствоСамостоятельный пример
<?php
$a = ["A" => -3, "B" => 8, "C" => 3];
$b = ["a" => 3];
$compare = function ($a, $b) { return abs($a) <=> abs($b); };
echo json_encode(array_udiff_uassoc($a, $b, $compare, "strcasecmp")), "\n";
Ожидаемый результат
{"B":8,"C":3}

Равенство выражено возвратом 0. Модуль нужен только для сравнения, исходные числа не заменяются.

Первый опыт уже показал три исхода компаратора: меньше, равно, больше. Теперь параметрами будут записи-массивы. Форма каждой записи проверена заранее; нельзя предполагать, что left всегда из local, а right всегда из remote.

Подготовить записи с отличающейся версиейСамостоятельный пример
<?php
$local = ['SKU-A' => ['revision' => 2, 'label' => 'Карточка A'], 'SKU-B' => ['revision' => 3, 'label' => 'Карточка B']];
$remote = ['sku-a' => ['revision' => 2, 'label' => 'Другое название A'], 'sku-b' => ['revision' => 1, 'label' => 'Старое название B']];
$compareRevision = function ($left, $right) {
    return $left["revision"] <=> $right["revision"];
};
$selected = array_udiff_uassoc($local, $remote, $compareRevision, "strcasecmp");
foreach ($selected as $sku => $record) {
    echo $sku, ": ", $record["label"], ", версия ", $record["revision"], "\n";
}
Ожидаемый результат
SKU-B: Карточка B, версия 3

Callback получает две целые записи, читает revision и возвращает знак сравнения. Для версий 2/2 это 0, для 3/1 — 1; алгоритм может дать их в обратном порядке или из одного входа. Дополнительно проверяются ключи вторым callback strcasecmp; сначала передан callback значений, потом ключей. Для sku-a совпадают ключ и версия; для sku-b версия отличается. Return всей операции — выбранные исходные записи local, поэтому выводится его label, а не удалённый. Поле label намеренно не входит в критерий: равная версия здесь не доказывает побайтовое равенство всей карточки.

Нюансы и выбор. Внутри сравнения массивы могут предварительно сортироваться, поэтому нельзя предполагать: $a всегда из local, $b всегда из remote. Нужен согласованный полный порядок (транзитивность, противоположные знаки при обмене аргументов), не функция «похож/не похож». Обход одноуровневый; callback сам выбирает поля вложенных значений. Для больших наборов с точным уникальным ID явный индекс нередко проще повторных сравнений.

Сравните: array_diff, array_diff_assoc, array_udiff, array_udiff_assoc. Выбрать операцию по задаче.

Реальная причина ошибки из вопроса о пропавших элементах: callback отдавал только 0/1 и не задавал согласованного порядка двух аргументов. Для отбора по одному признаку нужен array_filter; компаратор здесь обязан сравнить оба входа. Ответы обсуждения не служат нормативным правилом; договор проверен по PHP Manual.

array_intersect_assocПересечение массивов: оставить пары первого входа, для которых совпадение найдено в каждом из остальных массивов. Ключ и значение одновременно.

PHP 4.3+ · standard

array_intersect_assoc(array $array, array ...$arrays): array

Пересечение массивов: оставить пары первого входа, для которых совпадение найдено в каждом из остальных массивов. Ключ и значение одновременно.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayПервый массив — источник возвращаемых ключей, значений и порядка.
arraysОстальные массивы для сравнения. Без них допустим вызов с PHP 8: возвращается исходное содержимое.
Что совпадаетКлюч и значение одновременно. Встроенное сравнение ключей проверяет одинаковое строковое представление. Значения равны, когда их строковые представления совпадают: 10 и "10" равны, 10 и "010" различаются. Это не строгое сравнение исходных типов.
ВозвратНовый массив с исходными ключами/значениями/порядком первого аргумента; повторы подходящих значений не убираются.
Отказ и диагностикаВложенные массивы здесь не сравниваются рекурсивно: приведение массива к строке вызывает warning, объект без строкового преобразования — Error. Немассивные входы — TypeError.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Первый массив задаёт кандидатов
  2. Сверить пары с остальными
  3. Сохранить пару, если совпадение найдено в каждом из остальных массивов
Увидеть, что именно сравниваетсяСамостоятельный пример
<?php
$a = ["a" => 10, "b" => 20, "c" => 10];
$b = ["a" => "10", "b" => 30, "z" => 10];
echo json_encode(array_intersect_assoc($a, $b)), "\n";
Ожидаемый результат
{"a":10}

Ключ и значение одновременно. Ключи результата взяты из $a.

Теперь применим правило первого опыта к данным задачи. Первый массив задаёт, какие значения и ключи можно вернуть. Следующие массивы служат только для сравнения; они не дополняют результат новыми записями.

Выделить настройки, совпадающие с прежнимиСамостоятельный пример
<?php
$new = ['host' => 'mail.local', 'port' => 587, 'tls' => 'on'];
$old = ['host' => 'mail.local', 'port' => 25];
$selected = array_intersect_assoc($new, $old);
foreach ($selected as $setting => $value) {
    echo "Неизменившаяся настройка: ", $setting, " = ", $value, "\n";
}
Ожидаемый результат
Неизменившаяся настройка: host = mail.local

Для совпадения должны подойти и ключ, и значение одной пары. Host совпадает; port существует, но 587 отличается от 25; tls прежде отсутствовал. Return — словарь выбранных пар из new. Его foreach превращает в строки отчёта; настройки подключения здесь ещё не применяются. Значения сравниваются по строковому представлению: число 25 и строка "25" считались бы совпадением, поэтому это не аудит типов. Удалённые из new поля ищутся отдельным сравнением в обратную сторону.

Нюансы и выбор. Проверяется один уровень. Для вложенной записи выберите конкретное поле или собственный компаратор; не подменяйте структуру строкой "Array". Если нужна JSON-последовательность, явный array_values допустим только когда исходные ключи не несут смысла.

Сравните: array_intersect, array_intersect_key, array_uintersect, array_unique. Выбрать операцию по задаче.

array_intersect_keyПересечение массивов: оставить пары первого входа, для которых совпадение найдено в каждом из остальных массивов. Только ключи; значения не сравниваются.

PHP 5.1+ · standard

array_intersect_key(array $array, array ...$arrays): array

Пересечение массивов: оставить пары первого входа, для которых совпадение найдено в каждом из остальных массивов. Только ключи; значения не сравниваются.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayПервый массив — источник возвращаемых ключей, значений и порядка.
arraysОстальные массивы для сравнения. Без них допустим вызов с PHP 8: возвращается исходное содержимое.
Что совпадаетТолько ключи; значения не сравниваются. Встроенное сравнение ключей проверяет одинаковое строковое представление.
ВозвратНовый массив с исходными ключами/значениями/порядком первого аргумента; повторы подходящих значений не убираются.
Отказ и диагностикаНемассивные входы — TypeError.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Первый массив задаёт кандидатов
  2. Сверить ключи с остальными
  3. Сохранить пару, если совпадение найдено в каждом из остальных массивов
Увидеть, что именно сравниваетсяСамостоятельный пример
<?php
$a = ["name" => "Ada", "price" => 9];
$b = ["name" => null];
echo json_encode(array_intersect_key($a, $b)), "\n";
Ожидаемый результат
{"name":"Ada"}

Только ключи; значения не сравниваются. Ключи результата взяты из $a.

Теперь применим правило первого опыта к данным задачи. Первый массив задаёт, какие значения и ключи можно вернуть. Следующие массивы служат только для сравнения; они не дополняют результат новыми записями.

Подготовить разрешённые поля формы для дальнейшей проверкиСамостоятельный пример
<?php
$incoming = ['name' => 'Анна', 'note' => 'Позвонить', 'role' => 'admin'];
$fields = ['name' => true, 'note' => true];
$selected = array_intersect_key($incoming, $fields);
foreach ($selected as $field => $value) {
    echo "Разрешённое поле: ", $field, " = ", $value, "\n";
}
Ожидаемый результат
Разрешённое поле: name = Анна
Разрешённое поле: note = Позвонить

Словарь fields использует только ключи: значения true — заполнители и с «Анна» не сравниваются. Intersect оставляет name и note с исходными значениями, которые далее можно проверять по типу и длине. Функция не сохраняет данные и не назначает права. Сравниваются одинаковые имена ключей. Значение null в маске тоже обозначало бы присутствующий ключ.

Нюансы и выбор. Проверяется один уровень. Для вложенной записи выберите конкретное поле или собственный компаратор; не подменяйте структуру строкой "Array". Если нужна JSON-последовательность, явный array_values допустим только когда исходные ключи не несут смысла.

Сравните: array_intersect, array_intersect_assoc, array_uintersect, array_unique. Выбрать операцию по задаче.

array_intersect_uassocПересечение массивов: оставить пары первого входа, для которых совпадение найдено в каждом из остальных массивов. Ключ и значение одновременно.

PHP 5+ · standard

array_intersect_uassoc(array $array, array ...$arrays, callable $key_compare_func): array

Пересечение массивов: оставить пары первого входа, для которых совпадение найдено в каждом из остальных массивов. Ключ и значение одновременно.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayПервый массив — источник возвращаемых ключей, значений и порядка.
arraysОстальные массивы для сравнения. После массивов последним передаётся callback сравнения ключей. Не считайте его ещё одним массивом. В PHP 8.5.11 допускается только исходный массив и callback: результат сохраняет исходное содержимое.
Что совпадаетКлюч и значение одновременно. Значения равны, когда их строковые представления совпадают: 10 и "10" равны, 10 и "010" различаются. Это не строгое сравнение исходных типов.
key_compare_funccallback(keyA, keyB): int; 0 означает равные ключи. strcasecmp ниже сравнивает ASCII-регистр без различий.
ВозвратНовый массив с исходными ключами/значениями/порядком первого аргумента; повторы подходящих значений не убираются.
Отказ и диагностикаОшибки callback распространяются наружу; он обязан возвращать целое сравнение, float приводится к int и может ошибочно стать 0. Вложенные массивы здесь не сравниваются рекурсивно: приведение массива к строке вызывает warning, объект без строкового преобразования — Error. Немассивные входы — TypeError.

Компаратор — функция сравнения двух элементов. Она возвращает целое число: отрицательное — первый раньше, 0 — равны по выбранному признаку, положительное — первый позже. $a <=> $b даёт -1, 0 или 1. Это не проверка true/false; разность дробей нельзя возвращать вместо целого результата. function ($a, $b) { return ...; } передаёт правило операции, а не вызывает его немедленно. strcasecmp — встроенное сравнение двух строк без учёта ASCII-регистра.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: передача функции как значения.

Что происходит в первом опыте
  1. Первый массив задаёт кандидатов
  2. Сверить пары с остальными
  3. Сохранить пару, если совпадение найдено в каждом из остальных массивов
Увидеть, что именно сравниваетсяСамостоятельный пример
<?php
$a = ["A" => 10, "B" => 20, "C" => 10];
$b = ["a" => "10", "b" => 30, "z" => 10];
echo json_encode(array_intersect_uassoc($a, $b, "strcasecmp")), "\n";
Ожидаемый результат
{"A":10}

Ключ и значение одновременно. Ключи результата взяты из $a.

Теперь применим правило первого опыта к данным задачи. Первый массив задаёт, какие значения и ключи можно вернуть. Следующие массивы служат только для сравнения; они не дополняют результат новыми записями.

Выделить настройки, совпадающие с прежнимиСамостоятельный пример
<?php
$new = ['host' => 'mail.local', 'port' => 587, 'tls' => 'on'];
$old = ['HOST' => 'mail.local', 'PORT' => 25];
$selected = array_intersect_uassoc($new, $old, "strcasecmp");
foreach ($selected as $setting => $value) {
    echo "Неизменившаяся настройка: ", $setting, " = ", $value, "\n";
}
Ожидаемый результат
Неизменившаяся настройка: host = mail.local

Для совпадения должны подойти и ключ, и значение одной пары. Host совпадает; port существует, но 587 отличается от 25; tls прежде отсутствовал. Return — словарь выбранных пар из new. Его foreach превращает в строки отчёта; настройки подключения здесь ещё не применяются. Ключи сравнивает strcasecmp без ASCII-регистра, а значения — встроенное строковое представление. Удалённые из new поля ищутся отдельным сравнением в обратную сторону.

Нюансы и выбор. Проверяется один уровень. Для вложенной записи выберите конкретное поле или собственный компаратор; не подменяйте структуру строкой "Array". Порядок callback не фиксирован; не рассчитывайте на вызов строго слева направо по исходному списку. Если нужна JSON-последовательность, явный array_values допустим только когда исходные ключи не несут смысла.

Сравните: array_intersect, array_intersect_assoc, array_intersect_key, array_uintersect, array_unique. Выбрать операцию по задаче.

array_intersect_ukeyПересечение массивов: оставить пары первого входа, для которых совпадение найдено в каждом из остальных массивов. Только ключи; значения не сравниваются.

PHP 5.1+ · standard

array_intersect_ukey(array $array, array ...$arrays, callable $key_compare_func): array

Пересечение массивов: оставить пары первого входа, для которых совпадение найдено в каждом из остальных массивов. Только ключи; значения не сравниваются.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayПервый массив — источник возвращаемых ключей, значений и порядка.
arraysОстальные массивы для сравнения. После массивов последним передаётся callback сравнения ключей. Не считайте его ещё одним массивом. В PHP 8.5.11 допускается только исходный массив и callback: результат сохраняет исходное содержимое.
Что совпадаетТолько ключи; значения не сравниваются.
key_compare_funccallback(keyA, keyB): int; 0 означает равные ключи. strcasecmp ниже сравнивает ASCII-регистр без различий.
ВозвратНовый массив с исходными ключами/значениями/порядком первого аргумента; повторы подходящих значений не убираются.
Отказ и диагностикаОшибки callback распространяются наружу; он обязан возвращать целое сравнение, float приводится к int и может ошибочно стать 0. Немассивные входы — TypeError.

Компаратор — функция сравнения двух элементов. Она возвращает целое число: отрицательное — первый раньше, 0 — равны по выбранному признаку, положительное — первый позже. $a <=> $b даёт -1, 0 или 1. Это не проверка true/false; разность дробей нельзя возвращать вместо целого результата. function ($a, $b) { return ...; } передаёт правило операции, а не вызывает его немедленно. strcasecmp — встроенное сравнение двух строк без учёта ASCII-регистра.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: передача функции как значения.

Что происходит в первом опыте
  1. Первый массив задаёт кандидатов
  2. Сверить ключи с остальными
  3. Сохранить пару, если совпадение найдено в каждом из остальных массивов
Увидеть, что именно сравниваетсяСамостоятельный пример
<?php
$a = ["Name" => "Ada", "Price" => 9];
$b = ["name" => null];
echo json_encode(array_intersect_ukey($a, $b, "strcasecmp")), "\n";
Ожидаемый результат
{"Name":"Ada"}

Только ключи; значения не сравниваются. Ключи результата взяты из $a.

Теперь применим правило первого опыта к данным задачи. Первый массив задаёт, какие значения и ключи можно вернуть. Следующие массивы служат только для сравнения; они не дополняют результат новыми записями.

Подготовить разрешённые поля формы для дальнейшей проверкиСамостоятельный пример
<?php
$incoming = ['name' => 'Анна', 'note' => 'Позвонить', 'role' => 'admin'];
$fields = ['NAME' => true, 'NOTE' => true];
$selected = array_intersect_ukey($incoming, $fields, "strcasecmp");
foreach ($selected as $field => $value) {
    echo "Разрешённое поле: ", $field, " = ", $value, "\n";
}
Ожидаемый результат
Разрешённое поле: name = Анна
Разрешённое поле: note = Позвонить

Словарь fields использует только ключи: значения true — заполнители и с «Анна» не сравниваются. Intersect оставляет name и note с исходными значениями, которые далее можно проверять по типу и длине. Функция не сохраняет данные и не назначает права. Здесь договор явно допускает ASCII-регистр имён: strcasecmp возвращает 0 для name/NAME. Это готовая функция сравнения двух строк; строка "strcasecmp" передаёт её как callback.

Нюансы и выбор. Проверяется один уровень. Для вложенной записи выберите конкретное поле или собственный компаратор; не подменяйте структуру строкой "Array". Порядок callback не фиксирован; не рассчитывайте на вызов строго слева направо по исходному списку. Если нужна JSON-последовательность, явный array_values допустим только когда исходные ключи не несут смысла.

Сравните: array_intersect, array_intersect_assoc, array_intersect_key, array_uintersect, array_unique. Выбрать операцию по задаче.

array_uintersectВычислить пересечение по собственному правилу значений.

PHP 5+ · standard

array_uintersect(array $array, array ...$arrays, callable $value_compare_func): array

Вычислить пересечение по собственному правилу значений.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
array / array1Первый массив задаёт возвращаемые пары и порядок.
arraysОстальные массивы, затем callback-функции. Сохраняется элемент, для которого совпадение найдено в каждом из остальных массивов. В PHP 8.5.11 допустимо не передавать дополнительные массивы: с нужными callback возвращается содержимое первого.
value_compare_funccallback(valueA, valueB): int. Должен уметь сравнить любые два элемента любого из входов в любом порядке.
ВозвратНовый массив из подходящих элементов первого входа; ключи, значения и их исходный порядок сохранены.
Отказ и диагностикаFloat-результат компаратора приводится к int, дробь меньше 1 превратится в 0. Неподходящие типы входных элементов и ошибки callback могут привести к исключению. Не изменяйте сравниваемые данные из callback.

Компаратор — функция сравнения двух элементов. Она возвращает целое число: отрицательное — первый раньше, 0 — равны по выбранному признаку, положительное — первый позже. $a <=> $b даёт -1, 0 или 1. Это не проверка true/false; разность дробей нельзя возвращать вместо целого результата. function ($a, $b) { return ...; } передаёт правило операции, а не вызывает его немедленно. abs возвращает модуль числа: -3 и 3 дают одинаковое значение 3.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: передача функции как значения.

Что происходит в первом опыте
  1. Кандидаты -3, 8, 3
  2. Сравнить модули со значением 3
  3. Сохранить выбранные исходные пары, а не модули
Задать собственное равенствоСамостоятельный пример
<?php
$a = ["a" => -3, "b" => 8, "c" => 3];
$b = ["other" => 3];
$compare = function ($a, $b) { return abs($a) <=> abs($b); };
echo json_encode(array_uintersect($a, $b, $compare)), "\n";
Ожидаемый результат
{"a":-3,"c":3}

Равенство выражено возвратом 0. Модуль нужен только для сравнения, исходные числа не заменяются.

Первый опыт уже показал три исхода компаратора: меньше, равно, больше. Теперь параметрами будут записи-массивы. Форма каждой записи проверена заранее; нельзя предполагать, что left всегда из local, а right всегда из remote.

Получить общие товары по IDСамостоятельный пример
<?php
$local = [['id' => 12, 'name' => 'Локальная карточка'], ['id' => 25, 'name' => 'Новый товар']];
$remote = [['id' => 12, 'name' => 'Иное название']];
$compareId = function ($left, $right) {
    return $left["id"] <=> $right["id"];
};
$selected = array_uintersect($local, $remote, $compareId);
foreach ($selected as $record) {
    echo "ID ", $record["id"], ": ", $record["name"], "\n";
}
Ожидаемый результат
ID 12: Локальная карточка

Каждый параметр callback — одна запись с int-полем id. Возврат left[id]<=>right[id] равен 0 для одинакового ID независимо от name. Алгоритм получает этот знак для сравнения; selected получает массив подходящих записей local. ID 12 есть в обоих входах и попадает в отчёт, причём имя взято из local. Ключи исходных списков не являются критерием. Такая операция не проверяет уникальность ID и не синхронизирует базу сама.

Нюансы и выбор. Внутри сравнения массивы могут предварительно сортироваться, поэтому нельзя предполагать: $a всегда из local, $b всегда из remote. Нужен согласованный полный порядок (транзитивность, противоположные знаки при обмене аргументов), не функция «похож/не похож». Обход одноуровневый; callback сам выбирает поля вложенных значений. Для больших наборов с точным уникальным ID явный индекс нередко проще повторных сравнений.

Сравните: array_intersect, array_intersect_assoc, array_uintersect_assoc, array_uintersect_uassoc. Выбрать операцию по задаче.

Реальная причина ошибки из вопроса о пропавших элементах: callback отдавал только 0/1 и не задавал согласованного порядка двух аргументов. Для отбора по одному признаку нужен array_filter; компаратор здесь обязан сравнить оба входа. Ответы обсуждения не служат нормативным правилом; договор проверен по PHP Manual.

array_uintersect_assocВычислить пересечение по собственному правилу значений с проверкой ключа.

PHP 5+ · standard

array_uintersect_assoc(array $array, array ...$arrays, callable $value_compare_func): array

Вычислить пересечение по собственному правилу значений с проверкой ключа.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
array / array1Первый массив задаёт возвращаемые пары и порядок.
arraysОстальные массивы, затем callback-функции. Сохраняется элемент, для которого совпадение найдено в каждом из остальных массивов. В PHP 8.5.11 допустимо не передавать дополнительные массивы: с нужными callback возвращается содержимое первого.
value_compare_funccallback(valueA, valueB): int. Должен уметь сравнить любые два элемента любого из входов в любом порядке.
КлючиПара должна иметь совпавший ключ по встроенному правилу; одного равенства значений недостаточно.
ВозвратНовый массив из подходящих элементов первого входа; ключи, значения и их исходный порядок сохранены.
Отказ и диагностикаFloat-результат компаратора приводится к int, дробь меньше 1 превратится в 0. Неподходящие типы входных элементов и ошибки callback могут привести к исключению. Не изменяйте сравниваемые данные из callback.

Компаратор — функция сравнения двух элементов. Она возвращает целое число: отрицательное — первый раньше, 0 — равны по выбранному признаку, положительное — первый позже. $a <=> $b даёт -1, 0 или 1. Это не проверка true/false; разность дробей нельзя возвращать вместо целого результата. function ($a, $b) { return ...; } передаёт правило операции, а не вызывает его немедленно. abs возвращает модуль числа: -3 и 3 дают одинаковое значение 3.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: передача функции как значения.

Что происходит в первом опыте
  1. Кандидаты -3, 8, 3
  2. Сравнить модули со значением 3 и ключи
  3. Сохранить выбранные исходные пары, а не модули
Задать собственное равенствоСамостоятельный пример
<?php
$a = ["a" => -3, "b" => 8, "c" => 3];
$b = ["a" => 3];
$compare = function ($a, $b) { return abs($a) <=> abs($b); };
echo json_encode(array_uintersect_assoc($a, $b, $compare)), "\n";
Ожидаемый результат
{"a":-3}

Равенство выражено возвратом 0. Модуль нужен только для сравнения, исходные числа не заменяются.

Первый опыт уже показал три исхода компаратора: меньше, равно, больше. Теперь параметрами будут записи-массивы. Форма каждой записи проверена заранее; нельзя предполагать, что left всегда из local, а right всегда из remote.

Подготовить записи с совпадающей версиейСамостоятельный пример
<?php
$local = ['sku-a' => ['revision' => 2, 'label' => 'Карточка A'], 'sku-b' => ['revision' => 3, 'label' => 'Карточка B']];
$remote = ['sku-a' => ['revision' => 2, 'label' => 'Другое название A'], 'sku-b' => ['revision' => 1, 'label' => 'Старое название B']];
$compareRevision = function ($left, $right) {
    return $left["revision"] <=> $right["revision"];
};
$selected = array_uintersect_assoc($local, $remote, $compareRevision);
foreach ($selected as $sku => $record) {
    echo $sku, ": ", $record["label"], ", версия ", $record["revision"], "\n";
}
Ожидаемый результат
sku-a: Карточка A, версия 2

Callback получает две целые записи, читает revision и возвращает знак сравнения. Для версий 2/2 это 0, для 3/1 — 1; алгоритм может дать их в обратном порядке или из одного входа. Дополнительно проверяются ключи по встроенному правилу. Для sku-a совпадают ключ и версия; для sku-b версия отличается. Return всей операции — выбранные исходные записи local, поэтому выводится его label, а не удалённый. Поле label намеренно не входит в критерий: равная версия здесь не доказывает побайтовое равенство всей карточки.

Нюансы и выбор. Внутри сравнения массивы могут предварительно сортироваться, поэтому нельзя предполагать: $a всегда из local, $b всегда из remote. Нужен согласованный полный порядок (транзитивность, противоположные знаки при обмене аргументов), не функция «похож/не похож». Обход одноуровневый; callback сам выбирает поля вложенных значений. Для больших наборов с точным уникальным ID явный индекс нередко проще повторных сравнений.

Сравните: array_intersect, array_intersect_assoc, array_uintersect, array_uintersect_uassoc. Выбрать операцию по задаче.

Реальная причина ошибки из вопроса о пропавших элементах: callback отдавал только 0/1 и не задавал согласованного порядка двух аргументов. Для отбора по одному признаку нужен array_filter; компаратор здесь обязан сравнить оба входа. Ответы обсуждения не служат нормативным правилом; договор проверен по PHP Manual.

array_uintersect_uassocВычислить пересечение по собственному правилу значений с проверкой ключа.

PHP 5+ · standard

array_uintersect_uassoc(array $array1, array ...$arrays, callable $value_compare_func, callable $key_compare_func): array

Вычислить пересечение по собственному правилу значений с проверкой ключа.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
array / array1Первый массив задаёт возвращаемые пары и порядок.
arraysОстальные массивы, затем callback-функции. Сохраняется элемент, для которого совпадение найдено в каждом из остальных массивов. В PHP 8.5.11 допустимо не передавать дополнительные массивы: с нужными callback возвращается содержимое первого.
value_compare_funccallback(valueA, valueB): int. Должен уметь сравнить любые два элемента любого из входов в любом порядке.
КлючиПоследний key_compare_func(keyA,keyB): int сравнивает ключи. Порядок callback: сначала значения, потом ключи.
ВозвратНовый массив из подходящих элементов первого входа; ключи, значения и их исходный порядок сохранены.
Отказ и диагностикаFloat-результат компаратора приводится к int, дробь меньше 1 превратится в 0. Неподходящие типы входных элементов и ошибки callback могут привести к исключению. Не изменяйте сравниваемые данные из callback.

Компаратор — функция сравнения двух элементов. Она возвращает целое число: отрицательное — первый раньше, 0 — равны по выбранному признаку, положительное — первый позже. $a <=> $b даёт -1, 0 или 1. Это не проверка true/false; разность дробей нельзя возвращать вместо целого результата. function ($a, $b) { return ...; } передаёт правило операции, а не вызывает его немедленно. abs возвращает модуль числа: -3 и 3 дают одинаковое значение 3. strcasecmp во втором callback сравнивает ключи без учёта ASCII-регистра.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: передача функции как значения.

Что происходит в первом опыте
  1. Кандидаты -3, 8, 3
  2. Сравнить модули со значением 3 и ключи
  3. Сохранить выбранные исходные пары, а не модули
Задать собственное равенствоСамостоятельный пример
<?php
$a = ["A" => -3, "B" => 8, "C" => 3];
$b = ["a" => 3];
$compare = function ($a, $b) { return abs($a) <=> abs($b); };
echo json_encode(array_uintersect_uassoc($a, $b, $compare, "strcasecmp")), "\n";
Ожидаемый результат
{"A":-3}

Равенство выражено возвратом 0. Модуль нужен только для сравнения, исходные числа не заменяются.

Первый опыт уже показал три исхода компаратора: меньше, равно, больше. Теперь параметрами будут записи-массивы. Форма каждой записи проверена заранее; нельзя предполагать, что left всегда из local, а right всегда из remote.

Подготовить записи с совпадающей версиейСамостоятельный пример
<?php
$local = ['SKU-A' => ['revision' => 2, 'label' => 'Карточка A'], 'SKU-B' => ['revision' => 3, 'label' => 'Карточка B']];
$remote = ['sku-a' => ['revision' => 2, 'label' => 'Другое название A'], 'sku-b' => ['revision' => 1, 'label' => 'Старое название B']];
$compareRevision = function ($left, $right) {
    return $left["revision"] <=> $right["revision"];
};
$selected = array_uintersect_uassoc($local, $remote, $compareRevision, "strcasecmp");
foreach ($selected as $sku => $record) {
    echo $sku, ": ", $record["label"], ", версия ", $record["revision"], "\n";
}
Ожидаемый результат
SKU-A: Карточка A, версия 2

Callback получает две целые записи, читает revision и возвращает знак сравнения. Для версий 2/2 это 0, для 3/1 — 1; алгоритм может дать их в обратном порядке или из одного входа. Дополнительно проверяются ключи вторым callback strcasecmp; сначала передан callback значений, потом ключей. Для sku-a совпадают ключ и версия; для sku-b версия отличается. Return всей операции — выбранные исходные записи local, поэтому выводится его label, а не удалённый. Поле label намеренно не входит в критерий: равная версия здесь не доказывает побайтовое равенство всей карточки.

Нюансы и выбор. Внутри сравнения массивы могут предварительно сортироваться, поэтому нельзя предполагать: $a всегда из local, $b всегда из remote. Нужен согласованный полный порядок (транзитивность, противоположные знаки при обмене аргументов), не функция «похож/не похож». Обход одноуровневый; callback сам выбирает поля вложенных значений. Для больших наборов с точным уникальным ID явный индекс нередко проще повторных сравнений.

Сравните: array_intersect, array_intersect_assoc, array_uintersect, array_uintersect_assoc. Выбрать операцию по задаче.

Реальная причина ошибки из вопроса о пропавших элементах: callback отдавал только 0/1 и не задавал согласованного порядка двух аргументов. Для отбора по одному признаку нужен array_filter; компаратор здесь обязан сравнить оба входа. Ответы обсуждения не служат нормативным правилом; договор проверен по PHP Manual.

sortУпорядочить значения по возрастанию, заменив все ключи индексами 0, 1….

PHP 4+ · standard

sort(array &$array, int $flags = SORT_REGULAR): true

Упорядочить значения по возрастанию, заменив все ключи индексами 0, 1….

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемая переменная-массив; удаляются и строковые, и числовые старые ключи.
flagsSORT_REGULAR — обычные правила PHP; SORT_NUMERIC — числовые; SORT_STRING — строковые; SORT_LOCALE_STRING — строки в текущей locale; SORT_NATURAL — естественный порядок числовых частей строк. SORT_FLAG_CASE добавляют через | только к SORT_STRING/SORT_NATURAL для нечувствительности к ASCII-регистру (с PHP 8.2 только ASCII).
Возвратtrue; тип объявлен как true с PHP 8.2, ранее bool. Сам результат сортировки находится в первом аргументе.
Отказ и диагностикаНеподходящий тип array — TypeError. Преобразование значений, несовместимых с режимом, может вызвать диагностику. SORT_REGULAR на смешанных типах часто не соответствует предметному правилу.

Все равные по правилу сравнения элементы сохраняют взаимный порядок с PHP 8.0; раньше он не гарантировался. Указатель массива сбрасывается на первый элемент. Массив меняется на месте: true — статус, не отсортированные данные. В сигнатуре & означает передачу изменяемой переменной; в вызове знак & не ставится.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Исходные цены A=300, B=100, C=200.
  2. Сравнить цены по возрастанию.
  3. Прочитать изменённый prices с новыми позициями 0/1/2.
Получить понятный упорядоченный отчётСамостоятельный пример
<?php
$prices = ['A' => 300, 'B' => 100, 'C' => 200];
$status = sort($prices, SORT_NUMERIC);
if ($status) { echo "Цены упорядочены\n"; }
foreach ($prices as $key => $price) { echo "Позиция ", $key, ": ", $price, " коп.\n"; }
Ожидаемый результат
Цены упорядочены
Позиция 0: 100 коп.
Позиция 1: 200 коп.
Позиция 2: 300 коп.

Сравниваются значения 300/100/200, а не подписи A/B/C. SORT_NUMERIC выбирает числовое сравнение. Все старые ключи A/B/C удалены и заменены позициями 0/1/2. Получен ряд цен; для каталога, которому нужны артикулы, выберите asort. Status получает true. Присвоить status переменной prices означало бы потерять сами отсортированные значения.

Упорядочить нумерованные части отчётаСамостоятельный пример
<?php
$files = ["ten" => "part10", "two" => "part2", "one" => "Part1"];
sort($files, SORT_NATURAL | SORT_FLAG_CASE);
echo json_encode($files), "\n";
Ожидаемый результат
["Part1","part2","part10"]

Часть 2 сравнивается как число и идёт перед частью 10 при возрастании. Флаг CASE убирает различие ASCII-регистра, а не меняет сами строки.

Нюансы и выбор. Для русских названий и языковых правил нужна подходящая locale/Collator, а не обещание универсального «алфавита». Не полагайтесь на конкретный алгоритм, число сравнений или скорость на любом входе. До сортировки нормализуйте сравниваемый тип; чтение БД уже в нужном порядке может быть выгоднее сортировки огромного PHP-массива.

Сравните: asort, ksort, usort, array_multisort. Выбрать операцию по задаче.

rsortУпорядочить значения по убыванию, заменив все ключи индексами 0, 1….

PHP 4+ · standard

rsort(array &$array, int $flags = SORT_REGULAR): true

Упорядочить значения по убыванию, заменив все ключи индексами 0, 1….

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемая переменная-массив; удаляются и строковые, и числовые старые ключи.
flagsSORT_REGULAR — обычные правила PHP; SORT_NUMERIC — числовые; SORT_STRING — строковые; SORT_LOCALE_STRING — строки в текущей locale; SORT_NATURAL — естественный порядок числовых частей строк. SORT_FLAG_CASE добавляют через | только к SORT_STRING/SORT_NATURAL для нечувствительности к ASCII-регистру (с PHP 8.2 только ASCII).
Возвратtrue; тип объявлен как true с PHP 8.2, ранее bool. Сам результат сортировки находится в первом аргументе.
Отказ и диагностикаНеподходящий тип array — TypeError. Преобразование значений, несовместимых с режимом, может вызвать диагностику. SORT_REGULAR на смешанных типах часто не соответствует предметному правилу.

Все равные по правилу сравнения элементы сохраняют взаимный порядок с PHP 8.0; раньше он не гарантировался. Указатель массива сбрасывается на первый элемент. Массив меняется на месте: true — статус, не отсортированные данные. В сигнатуре & означает передачу изменяемой переменной; в вызове знак & не ставится.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Исходные цены A=300, B=100, C=200.
  2. Сравнить цены по убыванию.
  3. Прочитать изменённый prices с новыми позициями 0/1/2.
Получить понятный упорядоченный отчётСамостоятельный пример
<?php
$prices = ['A' => 300, 'B' => 100, 'C' => 200];
$status = rsort($prices, SORT_NUMERIC);
if ($status) { echo "Цены упорядочены\n"; }
foreach ($prices as $key => $price) { echo "Позиция ", $key, ": ", $price, " коп.\n"; }
Ожидаемый результат
Цены упорядочены
Позиция 0: 300 коп.
Позиция 1: 200 коп.
Позиция 2: 100 коп.

Сравниваются значения 300/100/200, а не подписи A/B/C. SORT_NUMERIC выбирает числовое сравнение. Все старые ключи A/B/C удалены и заменены позициями 0/1/2. Получен ряд цен; для каталога, которому нужны артикулы, выберите arsort. Status получает true. Присвоить status переменной prices означало бы потерять сами отсортированные значения.

Упорядочить нумерованные части отчётаСамостоятельный пример
<?php
$files = ["ten" => "part10", "two" => "part2", "one" => "Part1"];
rsort($files, SORT_NATURAL | SORT_FLAG_CASE);
echo json_encode($files), "\n";
Ожидаемый результат
["part10","part2","Part1"]

Часть 2 сравнивается как число и идёт перед частью 10 при возрастании. Флаг CASE убирает различие ASCII-регистра, а не меняет сами строки.

Нюансы и выбор. Для русских названий и языковых правил нужна подходящая locale/Collator, а не обещание универсального «алфавита». Не полагайтесь на конкретный алгоритм, число сравнений или скорость на любом входе. До сортировки нормализуйте сравниваемый тип; чтение БД уже в нужном порядке может быть выгоднее сортировки огромного PHP-массива.

Сравните: sort, asort, ksort, usort, array_multisort. Выбрать операцию по задаче.

asortУпорядочить значения по возрастанию, сохранив связь ключей и значений.

PHP 4+ · standard

asort(array &$array, int $flags = SORT_REGULAR): true

Упорядочить значения по возрастанию, сохранив связь ключей и значений.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемая переменная-массив; ключи не теряются.
flagsSORT_REGULAR — обычные правила PHP; SORT_NUMERIC — числовые; SORT_STRING — строковые; SORT_LOCALE_STRING — строки в текущей locale; SORT_NATURAL — естественный порядок числовых частей строк. SORT_FLAG_CASE добавляют через | только к SORT_STRING/SORT_NATURAL для нечувствительности к ASCII-регистру (с PHP 8.2 только ASCII).
Возвратtrue; тип объявлен как true с PHP 8.2, ранее bool. Сам результат сортировки находится в первом аргументе.
Отказ и диагностикаНеподходящий тип array — TypeError. Преобразование значений, несовместимых с режимом, может вызвать диагностику. SORT_REGULAR на смешанных типах часто не соответствует предметному правилу.

Все равные по правилу сравнения элементы сохраняют взаимный порядок с PHP 8.0; раньше он не гарантировался. Указатель массива сбрасывается на первый элемент. Массив меняется на месте: true — статус, не отсортированные данные. В сигнатуре & означает передачу изменяемой переменной; в вызове знак & не ставится.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Исходные цены A=300, B=100, C=200.
  2. Сравнить цены по возрастанию.
  3. Прочитать изменённый prices с артикулами.
Получить понятный упорядоченный отчётСамостоятельный пример
<?php
$prices = ['A' => 300, 'B' => 100, 'C' => 200];
$status = asort($prices, SORT_NUMERIC);
if ($status) { echo "Цены упорядочены\n"; }
foreach ($prices as $key => $price) { echo "Артикул ", $key, ": ", $price, " коп.\n"; }
Ожидаемый результат
Цены упорядочены
Артикул B: 100 коп.
Артикул C: 200 коп.
Артикул A: 300 коп.

Сравниваются значения 300/100/200, а не подписи A/B/C. SORT_NUMERIC выбирает числовое сравнение. Связь каждого артикула с ценой сохранена, поэтому из результата можно строить список товаров. Status получает true. Присвоить status переменной prices означало бы потерять сами отсортированные значения.

Упорядочить нумерованные части отчётаСамостоятельный пример
<?php
$files = ["ten" => "part10", "two" => "part2", "one" => "Part1"];
asort($files, SORT_NATURAL | SORT_FLAG_CASE);
echo json_encode($files), "\n";
Ожидаемый результат
{"one":"Part1","two":"part2","ten":"part10"}

Часть 2 сравнивается как число и идёт перед частью 10 при возрастании. Флаг CASE убирает различие ASCII-регистра, а не меняет сами строки.

Нюансы и выбор. Для русских названий и языковых правил нужна подходящая locale/Collator, а не обещание универсального «алфавита». Не полагайтесь на конкретный алгоритм, число сравнений или скорость на любом входе. До сортировки нормализуйте сравниваемый тип; чтение БД уже в нужном порядке может быть выгоднее сортировки огромного PHP-массива.

Сравните: sort, ksort, usort, array_multisort. Выбрать операцию по задаче.

arsortУпорядочить значения по убыванию, сохранив связь ключей и значений.

PHP 4+ · standard

arsort(array &$array, int $flags = SORT_REGULAR): true

Упорядочить значения по убыванию, сохранив связь ключей и значений.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемая переменная-массив; ключи не теряются.
flagsSORT_REGULAR — обычные правила PHP; SORT_NUMERIC — числовые; SORT_STRING — строковые; SORT_LOCALE_STRING — строки в текущей locale; SORT_NATURAL — естественный порядок числовых частей строк. SORT_FLAG_CASE добавляют через | только к SORT_STRING/SORT_NATURAL для нечувствительности к ASCII-регистру (с PHP 8.2 только ASCII).
Возвратtrue; тип объявлен как true с PHP 8.2, ранее bool. Сам результат сортировки находится в первом аргументе.
Отказ и диагностикаНеподходящий тип array — TypeError. Преобразование значений, несовместимых с режимом, может вызвать диагностику. SORT_REGULAR на смешанных типах часто не соответствует предметному правилу.

Все равные по правилу сравнения элементы сохраняют взаимный порядок с PHP 8.0; раньше он не гарантировался. Указатель массива сбрасывается на первый элемент. Массив меняется на месте: true — статус, не отсортированные данные. В сигнатуре & означает передачу изменяемой переменной; в вызове знак & не ставится.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Исходные цены A=300, B=100, C=200.
  2. Сравнить цены по убыванию.
  3. Прочитать изменённый prices с артикулами.
Получить понятный упорядоченный отчётСамостоятельный пример
<?php
$prices = ['A' => 300, 'B' => 100, 'C' => 200];
$status = arsort($prices, SORT_NUMERIC);
if ($status) { echo "Цены упорядочены\n"; }
foreach ($prices as $key => $price) { echo "Артикул ", $key, ": ", $price, " коп.\n"; }
Ожидаемый результат
Цены упорядочены
Артикул A: 300 коп.
Артикул C: 200 коп.
Артикул B: 100 коп.

Сравниваются значения 300/100/200, а не подписи A/B/C. SORT_NUMERIC выбирает числовое сравнение. Связь каждого артикула с ценой сохранена, поэтому из результата можно строить список товаров. Status получает true. Присвоить status переменной prices означало бы потерять сами отсортированные значения.

Упорядочить нумерованные части отчётаСамостоятельный пример
<?php
$files = ["ten" => "part10", "two" => "part2", "one" => "Part1"];
arsort($files, SORT_NATURAL | SORT_FLAG_CASE);
echo json_encode($files), "\n";
Ожидаемый результат
{"ten":"part10","two":"part2","one":"Part1"}

Часть 2 сравнивается как число и идёт перед частью 10 при возрастании. Флаг CASE убирает различие ASCII-регистра, а не меняет сами строки.

Нюансы и выбор. Для русских названий и языковых правил нужна подходящая locale/Collator, а не обещание универсального «алфавита». Не полагайтесь на конкретный алгоритм, число сравнений или скорость на любом входе. До сортировки нормализуйте сравниваемый тип; чтение БД уже в нужном порядке может быть выгоднее сортировки огромного PHP-массива.

Сравните: sort, asort, ksort, usort, array_multisort. Выбрать операцию по задаче.

krsortУпорядочить ключи по убыванию, сохранив связь ключей и значений.

PHP 4+ · standard

krsort(array &$array, int $flags = SORT_REGULAR): true

Упорядочить ключи по убыванию, сохранив связь ключей и значений.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемая переменная-массив; ключи не теряются.
flagsSORT_REGULAR — обычные правила PHP; SORT_NUMERIC — числовые; SORT_STRING — строковые; SORT_LOCALE_STRING — строки в текущей locale; SORT_NATURAL — естественный порядок числовых частей строк. SORT_FLAG_CASE добавляют через | только к SORT_STRING/SORT_NATURAL для нечувствительности к ASCII-регистру (с PHP 8.2 только ASCII).
Возвратtrue; тип объявлен как true с PHP 8.2, ранее bool. Сам результат сортировки находится в первом аргументе.
Отказ и диагностикаНеподходящий тип array — TypeError. Преобразование значений, несовместимых с режимом, может вызвать диагностику. SORT_REGULAR на смешанных типах часто не соответствует предметному правилу.

Все равные по правилу сравнения элементы сохраняют взаимный порядок с PHP 8.0; раньше он не гарантировался. Указатель массива сбрасывается на первый элемент. Массив меняется на месте: true — статус, не отсортированные данные. В сигнатуре & означает передачу изменяемой переменной; в вызове знак & не ставится. В PHP 8.2 сравнение числовых строковых ключей SORT_REGULAR приведено к стандартным правилам PHP 8.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Исходный порядок ID 30,10,20.
  2. Сравнить только ключи по убыванию.
  3. Пройти изменённый invoices и показать накладные по ID.
Получить понятный упорядоченный отчётСамостоятельный пример
<?php
$invoices = [30 => 'накладная C', 10 => 'накладная A', 20 => 'накладная B'];
$status = krsort($invoices, SORT_NUMERIC);
if ($status) { echo "Накладные упорядочены\n"; }
foreach ($invoices as $id => $title) { echo "ID ", $id, ": ", $title, "\n"; }
Ожидаемый результат
Накладные упорядочены
ID 30: накладная C
ID 20: накладная B
ID 10: накладная A

Сравниваются числовые ключи 30/10/20; текст накладной в сравнении не участвует. SORT_NUMERIC явно выбирает числовой порядок. Значение перемещается вместе со своим ID. Возврат status — true; результат сортировки находится в изменившемся invoices и сразу используется для отчёта.

Упорядочить нумерованные части отчётаСамостоятельный пример
<?php
$files = ["part10" => "ten", "part2" => "two", "Part1" => "one"];
krsort($files, SORT_NATURAL | SORT_FLAG_CASE);
echo json_encode($files), "\n";
Ожидаемый результат
{"part10":"ten","part2":"two","Part1":"one"}

Часть 2 сравнивается как число и идёт перед частью 10 при возрастании. Флаг CASE убирает различие ASCII-регистра, а не меняет сами строки.

Нюансы и выбор. Для русских названий и языковых правил нужна подходящая locale/Collator, а не обещание универсального «алфавита». Не полагайтесь на конкретный алгоритм, число сравнений или скорость на любом входе. До сортировки нормализуйте сравниваемый тип; чтение БД уже в нужном порядке может быть выгоднее сортировки огромного PHP-массива.

Сравните: sort, asort, ksort, usort, array_multisort. Выбрать операцию по задаче.

natsortОтсортировать числовые части строк естественным порядком, учитывая регистр.

PHP 4+ · standard

natsort(array &$array): true

Отсортировать числовые части строк естественным порядком, учитывая регистр.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемый массив строк. Ключи и их связь со значениями сохраняются. Дополнительных flags нет.
Возвратtrue (тип уточнён в PHP 8.2); значения переставлены в исходном массиве.
Отказ и диагностикаНеверный тип array — TypeError; неоднородные и непреобразуемые к строке значения не являются подходящим входом.

Все равные по правилу сравнения элементы сохраняют взаимный порядок с PHP 8.0; раньше он не гарантировался. Указатель массива сбрасывается на первый элемент. Массив меняется на месте: true — статус, не отсортированные данные. В сигнатуре & означает передачу изменяемой переменной; в вызове знак & не ставится.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Значения в порядке part10,part2,part1.
  2. Числовые части сравниваются как 10,2,1.
  3. Вывести part1,part2,part10 вместе с сохранёнными ID.
Показать части инструкции в порядке номеровСамостоятельный пример
<?php
$pages = ['ten' => 'part10', 'two' => 'part2', 'one' => 'part1'];
natsort($pages);
foreach ($pages as $id => $file) {
    echo 'Раздел ', $id, ': ', $file, ".txt\n";
}
Ожидаемый результат
Раздел one: part1.txt
Раздел two: part2.txt
Раздел ten: part10.txt

Функция сравнивает числовые части строк: 1,2,10. Возврат — статус true, поэтому его не присваивают pages. Изменённый массив сохраняет связь one/two/ten с соответствующими именами файлов; следующий foreach готовит порядок списка инструкции. Файлы здесь не читаются и не создаются. Для одних и тех же строчных имён обе natural-функции дают одинаковый порядок; следующий опыт показывает, что меняется при разном регистре.

Сравнить договоры регистрозависимой и независимой сортировкиСамостоятельный пример
<?php
$sensitive = ['x2', 'X10', 'x1'];
$insensitive = $sensitive;
natsort($sensitive);
natcasesort($insensitive);
echo json_encode(array_values($sensitive)), "
";
echo json_encode(array_values($insensitive)), "
";
Ожидаемый результат
["X10","x1","x2"]
["x1","x2","X10"]

Два режима дают разный результат на одном списке; выберите правило до сортировки. array_values здесь только делает вывод списком.

Нюансы и выбор. «Естественный» не означает понимание версий, дат, дробей или всех языков. Ведущие нули и формат чисел важны; для SemVer нужен его собственный договор сравнения. Для обратного результата можно array_reverse(..., true), если хотите сохранить ключи; это также перевернёт порядок равных элементов.

Сравните: natcasesort, asort, array_reverse. Выбрать операцию по задаче.

natcasesortОтсортировать числовые части строк естественным порядком без учёта ASCII-регистра.

PHP 4+ · standard

natcasesort(array &$array): true

Отсортировать числовые части строк естественным порядком без учёта ASCII-регистра.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемый массив строк. Ключи и их связь со значениями сохраняются. Дополнительных flags нет.
Возвратtrue (тип уточнён в PHP 8.2); значения переставлены в исходном массиве.
Отказ и диагностикаНеверный тип array — TypeError; неоднородные и непреобразуемые к строке значения не являются подходящим входом.

Все равные по правилу сравнения элементы сохраняют взаимный порядок с PHP 8.0; раньше он не гарантировался. Указатель массива сбрасывается на первый элемент. Массив меняется на месте: true — статус, не отсортированные данные. В сигнатуре & означает передачу изменяемой переменной; в вызове знак & не ставится.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Значения в порядке part10,part2,part1.
  2. Числовые части сравниваются как 10,2,1.
  3. Вывести part1,part2,part10 вместе с сохранёнными ID.
Показать части инструкции в порядке номеровСамостоятельный пример
<?php
$pages = ['ten' => 'part10', 'two' => 'part2', 'one' => 'part1'];
natcasesort($pages);
foreach ($pages as $id => $file) {
    echo 'Раздел ', $id, ': ', $file, ".txt\n";
}
Ожидаемый результат
Раздел one: part1.txt
Раздел two: part2.txt
Раздел ten: part10.txt

Функция сравнивает числовые части строк: 1,2,10. Возврат — статус true, поэтому его не присваивают pages. Изменённый массив сохраняет связь one/two/ten с соответствующими именами файлов; следующий foreach готовит порядок списка инструкции. Файлы здесь не читаются и не создаются. Для одних и тех же строчных имён обе natural-функции дают одинаковый порядок; следующий опыт показывает, что меняется при разном регистре.

Сравнить договоры регистрозависимой и независимой сортировкиСамостоятельный пример
<?php
$sensitive = ['x2', 'X10', 'x1'];
$insensitive = $sensitive;
natsort($sensitive);
natcasesort($insensitive);
echo json_encode(array_values($sensitive)), "
";
echo json_encode(array_values($insensitive)), "
";
Ожидаемый результат
["X10","x1","x2"]
["x1","x2","X10"]

Два режима дают разный результат на одном списке; выберите правило до сортировки. array_values здесь только делает вывод списком.

Нюансы и выбор. «Естественный» не означает понимание версий, дат, дробей или всех языков. Ведущие нули и формат чисел важны; для SemVer нужен его собственный договор сравнения. Для обратного результата можно array_reverse(..., true), если хотите сохранить ключи; это также перевернёт порядок равных элементов.

Сравните: natsort, asort, array_reverse. Выбрать операцию по задаче.

uasortЗадать своё правило порядка значений, сохранив исходные ключи.

PHP 4+ · standard

uasort(array &$array, callable $callback): true

Задать своё правило порядка значений, сохранив исходные ключи.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемый массив; связь ключ–значение сохранена.
callbackcallback(a,b): int сравнивает значения. Допустим любой отрицательный/нулевой/положительный int, не только -1/0/1.
Возвратtrue; тип уточнён с bool в PHP 8.2. Массив находится в первом аргументе.
Отказ и диагностикаС PHP 8 параметры callback по ссылке вызывают E_WARNING. Float приводится к int, например 0.6 превращается в 0. Булевый компаратор не задаёт три исхода; возврат bool устарел с PHP 8. Ошибки callback распространяются наружу.

Все равные по правилу сравнения элементы сохраняют взаимный порядок с PHP 8.0; раньше он не гарантировался. Указатель массива сбрасывается на первый элемент. Массив меняется на месте: true — статус, не отсортированные данные. В сигнатуре & означает передачу изменяемой переменной; в вызове знак & не ставится. Компаратор — функция сравнения двух элементов. Она возвращает целое число: отрицательное — первый раньше, 0 — равны по выбранному признаку, положительное — первый позже. $a <=> $b даёт -1, 0 или 1. Это не проверка true/false; разность дробей нельзя возвращать вместо целого результата. function ($a, $b) { return ...; } передаёт правило операции, а не вызывает его немедленно.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: передача функции как значения; оператор <=> и условный выбор.

Что происходит в первом опыте
  1. Есть массы 2.7,2.1,2.4.
  2. Callback сравнивает пару масс и возвращает знак целым числом.
  3. В weights получен порядок 2.1,2.4,2.7; его показывает foreach.
Упорядочить массы собственным правилом сравненияСамостоятельный пример
<?php
$weights = ['large' => 2.7, 'small' => 2.1, 'middle' => 2.4];
uasort($weights, function ($left, $right) {
    return $left <=> $right;
});
foreach ($weights as $key => $weight) {
    echo 'Упаковка ', $key, ': ', $weight, " кг\n";
}
Ожидаемый результат
Упаковка small: 2.1 кг
Упаковка middle: 2.4 кг
Упаковка large: 2.7 кг

Первый аргумент — изменяемый массив, второй — функция как значение. Алгоритм сам многократно передаёт в left/right две массы; конкретный порядок вызовов не обещан. Оператор <=> возвращает int: например, для 2.1 и 2.7 это -1, для обратной пары 1, для одинаковых значений 0. Этот return поступает в алгоритм сортировки, а не в weights. После завершения внешний foreach читает массы в новом порядке. Исходные имена упаковок сохранены. Дробную разность left-right возвращать нельзя: приведение к int превратило бы 0.6 в 0.

Сортировка заказов с явным вторым критериемСамостоятельный пример
<?php
$orders = ["c" => ["priority" => 2, "id" => 30], "a" => ["priority" => 1, "id" => 20], "b" => ["priority" => 1, "id" => 10]];
uasort($orders, function ($a, $b) {
    $byPriority = $a["priority"] <=> $b["priority"];
    return $byPriority !== 0 ? $byPriority : $a["id"] <=> $b["id"];
});
echo json_encode(array_column($orders, "id")), "\n";
echo json_encode(array_keys($orders)), "\n";
Ожидаемый результат
[10,20,30]
["b","a","c"]

Сначала сравниваем приоритет, при равенстве — ID. ?: выбирает один результат; <=> вычисляет целое сравнение даже для float.

Нюансы и выбор. Компаратор должен задавать согласованный порядок, а не решать «эти похожи»: нарушенная транзитивность делает результат ненадёжным. Не выполняйте внутри каждого сравнения сетевой запрос или дорогое преобразование; предварительно вычислите сортировочные поля. Два поля с равным критерием сохраняют исходный порядок в PHP 8, но порядок исходного ответа БД сам по себе может быть не определён без ORDER BY.

Сравните: usort, uksort, sort, array_multisort. Выбрать операцию по задаче.

uksortЗадать своё правило порядка ключей, сохранив исходные ключи.

PHP 4+ · standard

uksort(array &$array, callable $callback): true

Задать своё правило порядка ключей, сохранив исходные ключи.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемый массив; связь ключ–значение сохранена.
callbackcallback(a,b): int сравнивает ключи. Допустим любой отрицательный/нулевой/положительный int, не только -1/0/1.
Возвратtrue; тип уточнён с bool в PHP 8.2. Массив находится в первом аргументе.
Отказ и диагностикаС PHP 8 параметры callback по ссылке вызывают E_WARNING. Float приводится к int, например 0.6 превращается в 0. Булевый компаратор не задаёт три исхода; возврат bool устарел с PHP 8. Ошибки callback распространяются наружу.

Все равные по правилу сравнения элементы сохраняют взаимный порядок с PHP 8.0; раньше он не гарантировался. Указатель массива сбрасывается на первый элемент. Массив меняется на месте: true — статус, не отсортированные данные. В сигнатуре & означает передачу изменяемой переменной; в вызове знак & не ставится. Компаратор — функция сравнения двух элементов. Она возвращает целое число: отрицательное — первый раньше, 0 — равны по выбранному признаку, положительное — первый позже. $a <=> $b даёт -1, 0 или 1. Это не проверка true/false; разность дробей нельзя возвращать вместо целого результата. function ($a, $b) { return ...; } передаёт правило операции, а не вызывает его немедленно.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Для этого примера: передача функции как значения; оператор <=> и условный выбор.

Что происходит в первом опыте
  1. Части документа пришли footer,main,header.
  2. Таблица rank задаёт header=0,main=1,footer=2.
  3. Сравнить ранги ключей и вывести Заголовок,Текст,Подпись.
Показать части документа в заданном редактором порядкеСамостоятельный пример
<?php
$sections = ['footer' => 'Подпись', 'main' => 'Текст', 'header' => 'Заголовок'];
$rank = ['header' => 0, 'main' => 1, 'footer' => 2];
uksort($sections, function ($left, $right) use ($rank) {
    return $rank[$left] <=> $rank[$right];
});
foreach ($sections as $name => $text) {
    echo $name, ': ', $text, "\n";
}
Ожидаемый результат
header: Заголовок
main: Текст
footer: Подпись

Uksort передаёт callback ключи header/main/footer, а не содержимое «Заголовок/Текст/Подпись». Use ($rank) сохраняет доступ к таблице порядка при создании callback. Например, сравнение header/footer получает 0<=>2 и возвращает -1, ставя header раньше. Значение переносится вместе с ключом. Все имена в этом примере присутствуют в rank; следующий опыт показывает запасное место для неизвестного имени.

Показать разделы в предметном порядкеСамостоятельный пример
<?php
$sections = ['footer' => 'F', 'main' => 'M', 'header' => 'H'];
$rank = ['header' => 0, 'main' => 1, 'footer' => 2];
uksort($sections, function ($a, $b) use ($rank) {
    return ($rank[$a] ?? 99) <=> ($rank[$b] ?? 99);
});
echo implode(',', array_keys($sections)), "
";
Ожидаемый результат
header,main,footer

use ($rank) захватывает таблицу при создании callback; ?? задаёт место неизвестного ключа. Сортируется имя раздела, а не его содержимое.

Нюансы и выбор. Компаратор должен задавать согласованный порядок, а не решать «эти похожи»: нарушенная транзитивность делает результат ненадёжным. Не выполняйте внутри каждого сравнения сетевой запрос или дорогое преобразование; предварительно вычислите сортировочные поля. Здесь значения callback не передаются; захватывайте отдельную проверенную таблицу через use, если порядок ключей зависит от неё.

Сравните: usort, uasort, sort, array_multisort. Выбрать операцию по задаче.

array_multisortСинхронно переставить несколько колонок, применяя следующие как дополнительные критерии.

PHP 4+ · standard

array_multisort(array &$array1, mixed $array1_sort_order = SORT_ASC, mixed $array1_sort_flags = SORT_REGULAR, mixed ...$rest): true

Синхронно переставить несколько колонок, применяя следующие как дополнительные критерии.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
array1Первая изменяемая колонка.
array1_sort_orderSORT_ASC или SORT_DESC для предыдущей колонки; по умолчанию ASC. Можно поменять местами с flags либо опустить.
array1_sort_flagsSORT_REGULAR — обычные правила PHP; SORT_NUMERIC — числовые; SORT_STRING — строковые; SORT_LOCALE_STRING — строки в текущей locale; SORT_NATURAL — естественный порядок числовых частей строк. SORT_FLAG_CASE добавляют через | только к SORT_STRING/SORT_NATURAL для нечувствительности к ASCII-регистру (с PHP 8.2 только ASCII). По умолчанию REGULAR; можно поменять местами с order либо опустить.
restСледующие изменяемые массивы той же длины, у каждого свои необязательные order/flags. Следующая колонка сравнивается только при равенстве всех предыдущих; это лексикографический порядок.
Возвратtrue (точный тип с PHP 8.5, ранее bool). Все переданные массивы переставлены; строковые ключи сохранены, числовые перенумерованы.
Отказ и диагностикаРазная длина массивов — ValueError; неподходящие аргументы/флаги — TypeError или ValueError в зависимости от нарушения. Для каждого передаваемого массива нужна переменная.

Все равные по правилу сравнения элементы сохраняют взаимный порядок с PHP 8.0; раньше он не гарантировался. Указатель массива сбрасывается на первый элемент. Массив меняется на месте: true — статус, не отсортированные данные. В сигнатуре & означает передачу изменяемой переменной; в вызове знак & не ставится. Колонки соединяются по позиции. Они должны описывать одни и те же строки до сортировки, а не просто иметь одинаковую длину.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Три пары: 20↔90,10↔90,30↔70.
  2. Баллы по убыванию; при равенстве ID по возрастанию.
  3. Прочитать обе изменённые колонки по общей позиции.
Построить рейтинг, сохранив соответствие ID и балловСамостоятельный пример
<?php
$scores = [90, 90, 70];
$ids = [20, 10, 30];
array_multisort($scores, SORT_DESC, SORT_NUMERIC, $ids, SORT_ASC, SORT_NUMERIC);
foreach ($ids as $position => $id) {
    echo 'Место ', $position + 1, ': ID ', $id, ' — ', $scores[$position], ' баллов', "\n";
}
Ожидаемый результат
Место 1: ID 10 — 90 баллов
Место 2: ID 20 — 90 баллов
Место 3: ID 30 — 70 баллов

До вызова позиции связывают 20↔90, 10↔90, 30↔70. После scores идут её флаги: DESC убывание и NUMERIC числовое сравнение. Затем ids и её ASC/NUMERIC. ID сравнивается только при одинаковых баллах, поэтому 10 стоит раньше 20. Обе переменные переставлены синхронно; foreach берёт ID и баллы одной новой позиции. Возврат самой функции — true, не таблица рейтинга.

Сохранить порядок равных цен в таблице товаровСамостоятельный пример
<?php
$rows = [['id' => 20, 'price' => 100], ['id' => 10, 'price' => 100], ['id' => 30, 'price' => 50]];
$prices = array_column($rows, 'price');
$positions = array_keys($rows);
array_multisort($prices, SORT_ASC, SORT_NUMERIC, $positions, SORT_ASC, SORT_NUMERIC, $rows);
echo json_encode(array_column($rows, 'id')), "
";
Ожидаемый результат
[30,20,10]

Если передать только prices и rows, сами строки станут следующим критерием. Явные исходные позиции перед rows исключают такой скрытый порядок.

Обнаружить повреждённые параллельные колонкиСамостоятельный пример
<?php
$prices = [100, 200];
$ids = [10];
try { array_multisort($prices, $ids); }
catch (ValueError $error) { echo "Разная длина колонок
"; }
Ожидаемый результат
Разная длина колонок

Проверка count до сортировки позволяет объяснить ошибку импорта на своей границе. В отличие от array_map отсутствующие позиции не дополняются null.

Нюансы и выбор. Для небольшого массива записей usort с явным callback может быть понятнее параллельных колонок. Стабильность PHP 8 относится к равенству по всем переданным критериям, а не только первому. Не теряйте числовые ID, используя их как ключи сортируемого массива без отдельного поля.

Сравните: usort, uasort, array_column, array_map. Выбрать операцию по задаче.

currentпрочитать текущее значение без перемещения указателя.

PHP 4+ · standard

current(array|object $array): mixed

прочитать текущее значение без перемещения указателя.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayМассив с текущей позицией. Историческая поддержка объектов устарела; в новом коде передавайте массив.
ВозвратЗначение элемента; false для пустого массива или позиции за его пределами. Сам элемент тоже может содержать false.
Отказ и диагностикаНеверный тип — TypeError; объект вызывает E_DEPRECATED с PHP 8.1. Строгое сравнение с false отличает 0/"" от false, но не отличает элемент false от конца: проверяйте key(...) !== null.

Внутренний указатель — сохранённая позиция внутри массива, а не его числовой ключ. Изначально он указывает на первый добавленный элемент. current/pos и key читают позицию, next/prev/reset/end её меняют. foreach имеет собственный механизм обхода и обычно понятнее для обычного списка.

Что происходит в первом опыте
  1. Позиция стоит на address→Проверить адрес.
  2. Два чтения дают одинаковую подпись.
  3. Next перемещает позицию к pack→Упаковать.
Прочитать текущую операцию и отдельно перейти к следующейСамостоятельный пример
<?php
$steps = ['address' => 'Проверить адрес', 'pack' => 'Упаковать'];
$caption = current($steps);
echo 'Сейчас: ', $caption, "\n";
echo 'Повторное чтение: ', current($steps), "\n";
next($steps);
echo 'После перехода: ', current($steps), "\n";
Ожидаемый результат
Сейчас: Проверить адрес
Повторное чтение: Проверить адрес
После перехода: Упаковать

У нового steps внутренняя позиция стоит на address. Возврат current — строка текущего значения; присваивание caption сохраняет её для подписи. Повторное чтение возвращает ту же строку. Только next меняет позицию на pack. Это чтение плана: вывод названия не означает, что адрес проверен или упаковка выполнена. Pos — полное другое имя current с тем же договором.

Прочитать реальный false без ложного концаСамостоятельный пример
<?php
$states = ["ready" => false, "count" => 0];
while (key($states) !== null) {
    echo key($states), "=";
    var_dump(current($states));
    next($states);
}
var_dump(current($states));
Ожидаемый результат
ready=bool(false)
count=int(0)
bool(false)

key вернул имя ready, поэтому false был настоящими данными. После последнего next ключ становится null, а значение-чтение — false.

Нюансы и выбор. Вызовы этих функций на объектах устарели с PHP 8.1. Для свойств объекта сначала явно выберите представление массива, например get_mangled_object_vars; для Iterator используйте его методы. С PHP 7.4 SPL-объекты здесь рассматриваются как объекты без свойств, а не как команда вызвать одноимённый метод Iterator. Не передавайте результат current в if как единственный признак наличия элемента. Для первого значения без влияния чужих перемещений есть array_first в PHP 8.5+.

Сравните: pos, key, next, reset, array_first. Выбрать операцию по задаче.

posПсевдоним current: прочитать текущее значение без перемещения указателя.

PHP 4+ · standard

pos(array|object $array): mixed

Псевдоним current: прочитать текущее значение без перемещения указателя.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayМассив с текущей позицией. Историческая поддержка объектов устарела; в новом коде передавайте массив.
ВозвратЗначение элемента; false для пустого массива или позиции за его пределами. Сам элемент тоже может содержать false.
Отказ и диагностикаНеверный тип — TypeError; объект вызывает E_DEPRECATED с PHP 8.1. Строгое сравнение с false отличает 0/"" от false, но не отличает элемент false от конца: проверяйте key(...) !== null.

Внутренний указатель — сохранённая позиция внутри массива, а не его числовой ключ. Изначально он указывает на первый добавленный элемент. current/pos и key читают позицию, next/prev/reset/end её меняют. foreach имеет собственный механизм обхода и обычно понятнее для обычного списка.

Что происходит в первом опыте
  1. Позиция стоит на address→Проверить адрес.
  2. Два чтения дают одинаковую подпись.
  3. Next перемещает позицию к pack→Упаковать.
Прочитать текущую операцию и отдельно перейти к следующейСамостоятельный пример
<?php
$steps = ['address' => 'Проверить адрес', 'pack' => 'Упаковать'];
$caption = pos($steps);
echo 'Сейчас: ', $caption, "\n";
echo 'Повторное чтение: ', pos($steps), "\n";
next($steps);
echo 'После перехода: ', pos($steps), "\n";
Ожидаемый результат
Сейчас: Проверить адрес
Повторное чтение: Проверить адрес
После перехода: Упаковать

У нового steps внутренняя позиция стоит на address. Возврат pos — строка текущего значения; присваивание caption сохраняет её для подписи. Повторное чтение возвращает ту же строку. Только next меняет позицию на pack. Это чтение плана: вывод названия не означает, что адрес проверен или упаковка выполнена. Pos — полное другое имя current с тем же договором.

Прочитать реальный false без ложного концаСамостоятельный пример
<?php
$states = ["ready" => false, "count" => 0];
while (key($states) !== null) {
    echo key($states), "=";
    var_dump(pos($states));
    next($states);
}
var_dump(pos($states));
Ожидаемый результат
ready=bool(false)
count=int(0)
bool(false)

key вернул имя ready, поэтому false был настоящими данными. После последнего next ключ становится null, а значение-чтение — false.

Нюансы и выбор. Вызовы этих функций на объектах устарели с PHP 8.1. Для свойств объекта сначала явно выберите представление массива, например get_mangled_object_vars; для Iterator используйте его методы. С PHP 7.4 SPL-объекты здесь рассматриваются как объекты без свойств, а не как команда вызвать одноимённый метод Iterator. Не передавайте результат current в if как единственный признак наличия элемента. Для первого значения без влияния чужих перемещений есть array_first в PHP 8.5+.

Сравните: current, key, next, reset, array_first. Выбрать операцию по задаче.

keyПрочитать ключ в текущей позиции; null показывает отсутствие позиции.

PHP 4+ · standard

key(array|object $array): int|string|null

Прочитать ключ в текущей позиции; null показывает отсутствие позиции.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayМассив с текущей позицией; объектный режим устарел с PHP 8.1.
ВозвратКлюч int/string, либо null для пустого массива или указателя вне элементов. Указатель не сдвигается.
Отказ и диагностикаНеверный тип — TypeError; объекты дают E_DEPRECATED с PHP 8.1. Ключ 0 или пустая строка — допустимый результат, не признак конца.

Внутренний указатель — сохранённая позиция внутри массива, а не его числовой ключ. Изначально он указывает на первый добавленный элемент. current/pos и key читают позицию, next/prev/reset/end её меняют. foreach имеет собственный механизм обхода и обычно понятнее для обычного списка.

Что происходит в первом опыте
  1. Текущий ключ 10 открывает Накладную A.
  2. После next ключ 50 открывает Накладную B.
  3. За краем key возвращает null; показать завершение.
Узнать ID выбранной накладной и открыть её подписьСамостоятельный пример
<?php
$documents = [10 => 'Накладная A', 50 => 'Накладная B'];
$id = key($documents);
if ($id !== null) { echo 'Выбрано ID ', $id, ': ', $documents[$id], "\n"; }
next($documents);
$id = key($documents);
if ($id !== null) { echo 'Выбрано ID ', $id, ': ', $documents[$id], "\n"; }
next($documents);
if (key($documents) === null) { echo "Больше накладных нет\n"; }
Ожидаемый результат
Выбрано ID 10: Накладная A
Выбрано ID 50: Накладная B
Больше накладных нет

Key возвращает ключ текущей позиции, сначала 10. Он сохранён в id и использован в documents[id]; функция не возвращала весь документ. Next переходит к следующему элементу 50, а не к арифметическому ключу 11. После второго перехода позиции нет: key возвращает null. Строгая проверка сохраняет допустимый ключ 0. Чтение key само не двигает позицию.

Не потерять допустимый пустой ключСамостоятельный пример
<?php
$fields = ['' => 'empty-name', 0 => 'zero'];
while (key($fields) !== null) {
    echo '[', key($fields), ']=', current($fields), "
";
    next($fields);
}
Ожидаемый результат
[]=empty-name
[0]=zero

Условие if (key(...)) пропустило бы оба ключа; строгое сравнение решает именно проверку позиции.

Нюансы и выбор. Вызовы этих функций на объектах устарели с PHP 8.1. Для свойств объекта сначала явно выберите представление массива, например get_mangled_object_vars; для Iterator используйте его методы. С PHP 7.4 SPL-объекты здесь рассматриваются как объекты без свойств, а не как команда вызвать одноимённый метод Iterator. Это ключ внутреннего указателя, не переменная $key из отдельно выполняемого foreach. Для края без перемещения используйте array_key_first/last.

Сравните: current, next, array_key_first, array_key_last. Выбрать операцию по задаче.

nextПереместить внутренний указатель вперёд на один элемент и прочитать новое значение.

PHP 4+ · standard

next(array|object &$array): mixed

Переместить внутренний указатель вперёд на один элемент и прочитать новое значение.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемая переменная-массив: значения остаются, меняется позиция. Поэтому нельзя передавать временный литерал/результат выражения как by-reference аргумент.
ВозвратЗначение новой позиции; false, если её нет. Для reset/end пустой массив даёт false; для next/prev — также выход за край. Элемент false остаётся неоднозначным без key.
Отказ и диагностикаНеподходящий тип — TypeError; объектный вызов устарел с PHP 8.1. Требуется реальная переменная для аргумента по ссылке.

Внутренний указатель — сохранённая позиция внутри массива, а не его числовой ключ. Изначально он указывает на первый добавленный элемент. current/pos и key читают позицию, next/prev/reset/end её меняют. foreach имеет собственный механизм обхода и обычно понятнее для обычного списка. Знак & в сигнатуре обозначает изменяемый аргумент, а не необходимость писать & в вызове.

Что происходит в первом опыте
  1. Документы имеют ключи 10,50,90.
  2. Переместить позицию к ID 50 и получить его название.
  3. Показать выбор, затем все три сохранённых документа.
Переместить выбор и использовать возвращённое названиеСамостоятельный пример
<?php
$documents = [10 => 'Накладная A', 50 => 'Накладная B', 90 => 'Накладная C'];
$title = next($documents);
if (key($documents) !== null) {
    echo "Текущий документ ID ", key($documents), ": ", $title, "\n";
}
echo "Все документы сохранены:\n";
foreach ($documents as $id => $item) { echo $id, ": ", $item, "\n"; }
Ожидаемый результат
Текущий документ ID 50: Накладная B
Все документы сохранены:
10: Накладная A
50: Накладная B
90: Накладная C

Позиция нового массива начинается с ID 10. next перемещает её к ID 50 и возвращает значение новой позиции в title. Key проверяет существование позиции и даёт ID для подписи. Дальнейший foreach показывает все три документа с исходными ключами: перемещение не удалило ни один. Его обход не начинается с текущего курсора. False от функции могло бы быть настоящим значением, поэтому признак наличия читается через key !== null.

Отличить false в данных от отсутствующей позицииСамостоятельный пример
<?php
$states = ["start" => 1, "present" => false];
next($states);
var_dump(current($states));
echo key($states) !== null ? "Элемент существует\n" : "Нет позиции\n";
$empty = [];
var_dump(next($empty));
Ожидаемый результат
bool(false)
Элемент существует
bool(false)

После перемещения нужно проверить key !== null. Сравнение значения с false само по себе не даёт ответа.

Нюансы и выбор. Вызовы этих функций на объектах устарели с PHP 8.1. Для свойств объекта сначала явно выберите представление массива, например get_mangled_object_vars; для Iterator используйте его методы. С PHP 7.4 SPL-объекты здесь рассматриваются как объекты без свойств, а не как команда вызвать одноимённый метод Iterator. Для обычного обхода foreach проще ручного управления позицией. Если массив меняется структурно в процессе, пересмотрите договор обхода.

Сравните: prev, reset, end, current, key. Выбрать операцию по задаче.

prevПереместить внутренний указатель назад на один элемент и прочитать новое значение.

PHP 4+ · standard

prev(array|object &$array): mixed

Переместить внутренний указатель назад на один элемент и прочитать новое значение.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемая переменная-массив: значения остаются, меняется позиция. Поэтому нельзя передавать временный литерал/результат выражения как by-reference аргумент.
ВозвратЗначение новой позиции; false, если её нет. Для reset/end пустой массив даёт false; для next/prev — также выход за край. Элемент false остаётся неоднозначным без key.
Отказ и диагностикаНеподходящий тип — TypeError; объектный вызов устарел с PHP 8.1. Требуется реальная переменная для аргумента по ссылке.

Внутренний указатель — сохранённая позиция внутри массива, а не его числовой ключ. Изначально он указывает на первый добавленный элемент. current/pos и key читают позицию, next/prev/reset/end её меняют. foreach имеет собственный механизм обхода и обычно понятнее для обычного списка. Знак & в сигнатуре обозначает изменяемый аргумент, а не необходимость писать & в вызове.

Что происходит в первом опыте
  1. Документы имеют ключи 10,50,90.
  2. Переместить позицию к ID 50 и получить его название.
  3. Показать выбор, затем все три сохранённых документа.
Переместить выбор и использовать возвращённое названиеСамостоятельный пример
<?php
$documents = [10 => 'Накладная A', 50 => 'Накладная B', 90 => 'Накладная C'];
end($documents);
$title = prev($documents);
if (key($documents) !== null) {
    echo "Текущий документ ID ", key($documents), ": ", $title, "\n";
}
echo "Все документы сохранены:\n";
foreach ($documents as $id => $item) { echo $id, ": ", $item, "\n"; }
Ожидаемый результат
Текущий документ ID 50: Накладная B
Все документы сохранены:
10: Накладная A
50: Накладная B
90: Накладная C

Начальное end ставит позицию на ID 90. prev перемещает её к ID 50 и возвращает значение новой позиции в title. Key проверяет существование позиции и даёт ID для подписи. Дальнейший foreach показывает все три документа с исходными ключами: перемещение не удалило ни один. Его обход не начинается с текущего курсора. False от функции могло бы быть настоящим значением, поэтому признак наличия читается через key !== null.

Отличить false в данных от отсутствующей позицииСамостоятельный пример
<?php
$states = ["present" => false, "end" => 1];
end($states);
prev($states);
var_dump(current($states));
echo key($states) !== null ? "Элемент существует\n" : "Нет позиции\n";
$empty = [];
var_dump(prev($empty));
Ожидаемый результат
bool(false)
Элемент существует
bool(false)

После перемещения нужно проверить key !== null. Сравнение значения с false само по себе не даёт ответа.

Нюансы и выбор. Вызовы этих функций на объектах устарели с PHP 8.1. Для свойств объекта сначала явно выберите представление массива, например get_mangled_object_vars; для Iterator используйте его методы. С PHP 7.4 SPL-объекты здесь рассматриваются как объекты без свойств, а не как команда вызвать одноимённый метод Iterator. Для обычного обхода foreach проще ручного управления позицией. Если массив меняется структурно в процессе, пересмотрите договор обхода.

Сравните: next, reset, end, current, key. Выбрать операцию по задаче.

resetПереместить внутренний указатель на первый элемент и прочитать новое значение.

PHP 4+ · standard

reset(array|object &$array): mixed

Переместить внутренний указатель на первый элемент и прочитать новое значение.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемая переменная-массив: значения остаются, меняется позиция. Поэтому нельзя передавать временный литерал/результат выражения как by-reference аргумент.
ВозвратЗначение новой позиции; false, если её нет. Для reset/end пустой массив даёт false; для next/prev — также выход за край. Элемент false остаётся неоднозначным без key.
Отказ и диагностикаНеподходящий тип — TypeError; объектный вызов устарел с PHP 8.1. Требуется реальная переменная для аргумента по ссылке.

Внутренний указатель — сохранённая позиция внутри массива, а не его числовой ключ. Изначально он указывает на первый добавленный элемент. current/pos и key читают позицию, next/prev/reset/end её меняют. foreach имеет собственный механизм обхода и обычно понятнее для обычного списка. Знак & в сигнатуре обозначает изменяемый аргумент, а не необходимость писать & в вызове.

Что происходит в первом опыте
  1. Документы имеют ключи 10,50,90.
  2. Переместить позицию к ID 10 и получить его название.
  3. Показать выбор, затем все три сохранённых документа.
Переместить выбор и использовать возвращённое названиеСамостоятельный пример
<?php
$documents = [10 => 'Накладная A', 50 => 'Накладная B', 90 => 'Накладная C'];
end($documents);
$title = reset($documents);
if (key($documents) !== null) {
    echo "Текущий документ ID ", key($documents), ": ", $title, "\n";
}
echo "Все документы сохранены:\n";
foreach ($documents as $id => $item) { echo $id, ": ", $item, "\n"; }
Ожидаемый результат
Текущий документ ID 10: Накладная A
Все документы сохранены:
10: Накладная A
50: Накладная B
90: Накладная C

Начальное end ставит позицию на ID 90. reset перемещает её к ID 10 и возвращает значение новой позиции в title. Key проверяет существование позиции и даёт ID для подписи. Дальнейший foreach показывает все три документа с исходными ключами: перемещение не удалило ни один. Его обход не начинается с текущего курсора. False от функции могло бы быть настоящим значением, поэтому признак наличия читается через key !== null.

Отличить false в данных от отсутствующей позицииСамостоятельный пример
<?php
$states = ["present" => false, "end" => 1];
end($states);
reset($states);
var_dump(current($states));
echo key($states) !== null ? "Элемент существует\n" : "Нет позиции\n";
$empty = [];
var_dump(reset($empty));
Ожидаемый результат
bool(false)
Элемент существует
bool(false)

После перемещения нужно проверить key !== null. Сравнение значения с false само по себе не даёт ответа.

Нюансы и выбор. Вызовы этих функций на объектах устарели с PHP 8.1. Для свойств объекта сначала явно выберите представление массива, например get_mangled_object_vars; для Iterator используйте его методы. С PHP 7.4 SPL-объекты здесь рассматриваются как объекты без свойств, а не как команда вызвать одноимённый метод Iterator. Для безопасного начала повторного обхода явно reset; не рассчитывайте, что копирование массива обязано переместить чужой указатель.

Сравните: next, prev, end, current, key. Выбрать операцию по задаче.

endПереместить внутренний указатель на последний элемент и прочитать новое значение.

PHP 4+ · standard

end(array|object &$array): mixed

Переместить внутренний указатель на последний элемент и прочитать новое значение.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемая переменная-массив: значения остаются, меняется позиция. Поэтому нельзя передавать временный литерал/результат выражения как by-reference аргумент.
ВозвратЗначение новой позиции; false, если её нет. Для reset/end пустой массив даёт false; для next/prev — также выход за край. Элемент false остаётся неоднозначным без key.
Отказ и диагностикаНеподходящий тип — TypeError; объектный вызов устарел с PHP 8.1. Требуется реальная переменная для аргумента по ссылке.

Внутренний указатель — сохранённая позиция внутри массива, а не его числовой ключ. Изначально он указывает на первый добавленный элемент. current/pos и key читают позицию, next/prev/reset/end её меняют. foreach имеет собственный механизм обхода и обычно понятнее для обычного списка. Знак & в сигнатуре обозначает изменяемый аргумент, а не необходимость писать & в вызове.

Что происходит в первом опыте
  1. Документы имеют ключи 10,50,90.
  2. Переместить позицию к ID 90 и получить его название.
  3. Показать выбор, затем все три сохранённых документа.
Переместить выбор и использовать возвращённое названиеСамостоятельный пример
<?php
$documents = [10 => 'Накладная A', 50 => 'Накладная B', 90 => 'Накладная C'];
$title = end($documents);
if (key($documents) !== null) {
    echo "Текущий документ ID ", key($documents), ": ", $title, "\n";
}
echo "Все документы сохранены:\n";
foreach ($documents as $id => $item) { echo $id, ": ", $item, "\n"; }
Ожидаемый результат
Текущий документ ID 90: Накладная C
Все документы сохранены:
10: Накладная A
50: Накладная B
90: Накладная C

Позиция нового массива начинается с ID 10. end перемещает её к ID 90 и возвращает значение новой позиции в title. Key проверяет существование позиции и даёт ID для подписи. Дальнейший foreach показывает все три документа с исходными ключами: перемещение не удалило ни один. Его обход не начинается с текущего курсора. False от функции могло бы быть настоящим значением, поэтому признак наличия читается через key !== null.

Отличить false в данных от отсутствующей позицииСамостоятельный пример
<?php
$states = ["start" => 1, "present" => false];
end($states);
var_dump(current($states));
echo key($states) !== null ? "Элемент существует\n" : "Нет позиции\n";
$empty = [];
var_dump(end($empty));
Ожидаемый результат
bool(false)
Элемент существует
bool(false)

После перемещения нужно проверить key !== null. Сравнение значения с false само по себе не даёт ответа.

Нюансы и выбор. Вызовы этих функций на объектах устарели с PHP 8.1. Для свойств объекта сначала явно выберите представление массива, например get_mangled_object_vars; для Iterator используйте его методы. С PHP 7.4 SPL-объекты здесь рассматриваются как объекты без свойств, а не как команда вызвать одноимённый метод Iterator. Если нужно только крайнее значение без изменения позиции, используйте array_first/last в PHP 8.5+ либо чтение по array_key_first/last в прежних версиях.

Сравните: next, prev, reset, current, key. Выбрать операцию по задаче.

eachИсторическая функция чтения пары и перемещения указателя: удалена из PHP 8; нужна для понимания и миграции старого кода.

PHP 4–7; deprecated 7.2, removed 8.0 · standard

Исторически each(array|object &$array): array|false; в PHP 8 отсутствует

Историческая функция чтения пары и перемещения указателя: удалена из PHP 8; нужна для понимания и миграции старого кода.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИсторически изменяла внутренний указатель переданного массива, переходя к следующему элементу после чтения текущего.
ВозвратВ PHP 7 возвращала четыре поля: 0 и key содержали ключ; 1 и value — значение. За пределами массива false. Для повторного обхода требовался reset.
Отказ и диагностикаDeprecated с PHP 7.2, удалена в PHP 8.0. Вызов в PHP 8 приводит к Error: Call to undefined function each(). Историческая работа с объектами могла давать неожиданные результаты.

Внутренний указатель — сохранённая позиция внутри массива, а не его числовой ключ. Изначально он указывает на первый добавленный элемент. current/pos и key читают позицию, next/prev/reset/end её меняют. foreach имеет собственный механизм обхода и обычно понятнее для обычного списка. Ниже сначала виден старый шаблон, затем два самостоятельных способа переноса. Исторические предупреждения о копировании массива относятся к старому коду each, не являются обещанием современных правил копирования.

Что происходит в первом опыте
  1. Старый each читал текущую пару
  2. Сам перемещал указатель дальше
  3. Миграция выбирает foreach либо явный курсор
Исторический шаблон: не запускать в PHP 8Фрагмент или команда
<?php
$items = ['x' => 4, 'y' => 9];
while (list($key, $value) = each($items)) {
    echo $key, '=', $value, "
";
}

Негативный фрагмент для распознавания: PHP 8 выдаст Error об отсутствующей each. list распределял два позиционных поля исторического ответа.

Современный перенос полного обходаСамостоятельный пример
<?php
$items = ['x' => 4, 'y' => 9];
foreach ($items as $key => $value) { echo $key, '=', $value, "
"; }
Ожидаемый результат
x=4
y=9

Если задача — просто пройти все элементы, foreach выражает её прямо и допускает false в значениях.

Перенос, когда старый код продолжал с текущей позицииСамостоятельный пример
<?php
$items = ['x' => 4, 'y' => 9, 'z' => 12];
next($items);
while (key($items) !== null) {
    $key = key($items);
    $value = current($items);
    next($items);
    echo $key, '=', $value, "
";
}
Ожидаемый результат
y=9
z=12

Простая замена на полный foreach изменила бы смысл: он начал бы с x. Здесь воспроизведено чтение с текущей позиции с перемещением перед телом обработки.

Нюансы и выбор. При миграции найдите, зависело ли тело от позиции после each, изменяло ли массив, прерывало ли обход и продолжало позднее. Историческое присваивание массива в цикле могло сбрасывать указатель и зацикливать each; нельзя механически обещать эквивалентность для всех таких программ.

Сравните: current, key, next, reset, list. Выбрать операцию по задаче.

array_randВыбрать один или несколько случайных ключей, сохранив исходный массив.

PHP 4+ · standard

array_rand(array $array, int $num = 1): int|string|array

Выбрать один или несколько случайных ключей, сохранив исходный массив.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayНепустой массив.
numЧисло выбранных элементов, от 1 до count(array) включительно.
ВозвратПри num=1 один ключ int/string; иначе массив различных ключей в их исходном порядке. Возвращаются ключи, а не значения и не случайная перестановка выбранного.
Отказ и диагностикаPHP 8: ValueError при пустом входе, num<1 или num>count. Раньше E_WARNING и null.

array_rand и shuffle используют общую глобальную Mt19937-последовательность (с PHP 7.1 вместо libc rand); вызовы других функций с тем же генератором сдвигают её независимо от области видимости. mt_srand/srand с фиксированным seed делают последовательность повторяемой, но не защищённой. Для нового кода PHP Manual рекомендует Random\Randomizer; для непредсказуемости нужен Random\Engine\Secure, а простые безопасные альтернативы — random_int/random_bytes. Это не алгоритм выдачи секретных токенов. Ниже показаны сами выбранные карточки. Фиксированный seed относится только к самостоятельному учебному запуску на указанной версии.

Что происходит в первом опыте
  1. Для воспроизводимого опыта установить seed 12345.
  2. Получить ключ a, затем прочитать cards[a].
  3. Показать человеку текст выбранной карточки.

Здесь нужен видимый выбранный текст. Для проверяемого учебного результата мы явно фиксируем начальное состояние генератора через mt_srand(12345). В самостоятельном файле показанный вывод воспроизведён на PHP 8.5.11; в реальной случайной выдаче фиксированное начальное состояние не задают.

Выбрать карточку дня и показать её текстСамостоятельный пример
<?php
mt_srand(12345);
$cards = ['a' => 'Руководство', 'b' => 'Пример'];
$key = array_rand($cards);
$title = $cards[$key];
echo 'Выбран ключ: ', $key, "\n";
echo 'Карточка дня: ', $title, "\n";
Ожидаемый результат
Выбран ключ: a
Карточка дня: Руководство

Array_rand возвращает один ключ, здесь a; чтение cards[key] получает текст «Руководство». Именно он показывается человеку. Mt_srand(12345) устанавливает начальное состояние общего генератора, чтобы самостоятельный учебный запуск повторялся на проверенной PHP 8.5.11. До выбора нет других случайных вызовов. В обычной карточке дня фиксированный seed убирают; не обещайте этот конкретный ключ на любой версии или после чужих случайных вызовов.

Выбрать две разные карточки и показать обеСамостоятельный пример
<?php
mt_srand(12345);
$cards = ['a' => 'Руководство', 'b' => 'Практика', 'c' => 'Задача'];
$keys = array_rand($cards, 2);
foreach ($keys as $key) {
    echo 'Карточка ', $key, ': ', $cards[$key], "\n";
}
try { array_rand($cards, 4); }
catch (ValueError $error) { echo "Нельзя выбрать четыре из трёх\n"; }
Ожидаемый результат
Карточка b: Практика
Карточка c: Задача
Нельзя выбрать четыре из трёх

Второй аргумент 2 меняет тип возврата: keys получает массив двух различных ключей. Foreach берёт каждый ключ и показывает его карточку. Порядок выбранных ключей соответствует исходному массиву, а не новой случайной перестановке. Вызов с 4 отвергается ValueError; catch выводит понятное сообщение. Два отдельных вызова num=1 не гарантировали бы две разные карточки. Указанный seed нужен только воспроизводимому учебному опыту.

Нюансы и выбор. Выбор рекламной карточки может допускать такой генератор, токен восстановления — нет. Seed не гарантирует одинаковые последовательности между любыми версиями PHP/алгоритмами. Для перемешанного порядка выбранной группы нужна отдельная операция или Randomizer с явным договором.

Сравните: shuffle, array_keys, array_intersect_key. Выбрать операцию по задаче.

shuffleПеремешать значения на месте, заменив все ключи числовыми индексами.

PHP 4+ · standard

shuffle(array &$array): true

Перемешать значения на месте, заменив все ключи числовыми индексами.

Обозначения перед первым опытом: ключ, значение и чтение через [ ]; вызов, параметры и результат. var_dump показывает тип и значение; echo выводит текст, а "\n" переносит строку. try/catch в опытах с отказом отделяют успешный результат от исключения: разбор обработки ошибок.

Вход или результатДоговор
arrayИзменяемая переменная-массив, в том числе пустой. Старые ключи удаляются; если ID важен, храните его внутри записи.
Возвратtrue; изменённый список находится в array. Указатель сбрасывается в начало. Перемешивание может случайно оставить прежний порядок.
Отказ и диагностикаНеверный тип — TypeError. Операция не гарантирует криптографической непредсказуемости или обязательного изменения порядка.

array_rand и shuffle используют общую глобальную Mt19937-последовательность (с PHP 7.1 вместо libc rand); вызовы других функций с тем же генератором сдвигают её независимо от области видимости. mt_srand/srand с фиксированным seed делают последовательность повторяемой, но не защищённой. Для нового кода PHP Manual рекомендует Random\Randomizer; для непредсказуемости нужен Random\Engine\Secure, а простые безопасные альтернативы — random_int/random_bytes. Это не алгоритм выдачи секретных токенов. Знак & в сигнатуре означает изменение переданной переменной. Учебный seed позволяет увидеть точный порядок в самостоятельном запуске; без такого условия единственного заранее известного порядка нет.

В выводе примеров json_encode только показывает форму результата: [...] — список, {...} — именованные поля. Это отдельное преобразование в текст; как читать такой вывод.

Что происходит в первом опыте
  1. Исходные значения Адрес,Упаковка,Накладная.
  2. Установить seed 12345 и перемешать tasks.
  3. Прочитать полученный порядок с новыми позициями 0/1/2.
Получить и сразу показать порядок заданийСамостоятельный пример
<?php
mt_srand(12345);
$tasks = ['a' => 'Адрес', 'b' => 'Упаковка', 'c' => 'Накладная'];
$status = shuffle($tasks);
if ($status) { echo "Порядок подготовлен\n"; }
foreach ($tasks as $position => $task) {
    echo 'Позиция ', $position, ': ', $task, "\n";
}
Ожидаемый результат
Порядок подготовлен
Позиция 0: Накладная
Позиция 1: Упаковка
Позиция 2: Адрес

Shuffle меняет tasks на месте, удаляет ключи a/b/c и назначает 0/1/2. Status получает только true; foreach читает реальный новый порядок из tasks. Установленный seed делает этот самостоятельный опыт повторяемым на PHP 8.5.11. Случайная перестановка в общем случае может совпасть с исходной, поэтому функция не обещает обязательного изменения. Здесь задачи независимы: этапы реального процесса с зависимостями перемешивать нельзя.

Сохранить ID внутри перемешанных карточекСамостоятельный пример
<?php
mt_srand(12345);
$questions = [['id' => 40, 'text' => 'Что такое переменная?'], ['id' => 70, 'text' => 'Что возвращает функция?']];
shuffle($questions);
foreach ($questions as $position => $question) {
    echo 'Вопрос ', $position + 1, ' [ID ', $question['id'], ']: ', $question['text'], "\n";
}
$empty = [];
shuffle($empty);
if ($empty === []) { echo "Пустая подборка осталась пустой\n"; }
Ожидаемый результат
Вопрос 1 [ID 70]: Что возвращает функция?
Вопрос 2 [ID 40]: Что такое переменная?
Пустая подборка осталась пустой

Весь массив каждой карточки перемещается как одно значение, поэтому id и text остаются вместе. Позиция 0/1 — номер выдачи, id 70/40 — постоянный идентификатор для проверки ответа позже. Нельзя было полагаться на прежний внешний ключ карточки: shuffle его заменяет. Пустой массив допустим. Это учебная подборка с фиксированным seed; экзаменационный или конкурсный выбор требует отдельного договора непредсказуемости.

Нюансы и выбор. Не присваивайте $items = shuffle($items): получите true вместо списка. Для сохранения внешних ключей можно перемешать отдельный список ключей и читать исходный словарь по нему. Randomizer удобен для отдельного экземпляра генератора без скрытого общего состояния.

Сравните: array_rand, array_keys, array_values. Выбрать операцию по задаче.

Источники и обсуждения

Код и руководство с собой

Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.