in_array($needle, $haystack) возвращает true, если значение есть где-то в массиве, и false, если нет. Передайте true третьим аргументом, in_array($needle, $haystack, true), чтобы требовать ещё и совпадения типа; именно эту строгую форму стоит использовать по умолчанию.
in_array() смотрит только на значения. Чтобы проверить, есть ли ключ, используйте array_key_exists() или isset().
Параметр strict
Без третьего аргумента in_array() сравнивает через ==, которое приводит типы перед сравнением. С true сравнение идёт через ===: должны совпасть и значение, и тип. Разница проявляется, как только в массиве смешаны числа и строки, а это обычное дело для данных из форм, URL и CSV-файлов.
Каждая ячейка ниже показывает, что возвращают == и === для этой пары значений в PHP 8.3. in_array() отвечает true, если игла и любой элемент дают true в таблице для выбранного режима. Переключайтесь между вкладками и смотрите на строки null, true и числовых строк.
| $a == $b | true | false | null | 0 | 1 | "0" | "1" | "" | "abc" | "10" | "1e1" | 10 | [] |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| true | |||||||||||||
| false | |||||||||||||
| null | |||||||||||||
| 0 | |||||||||||||
| 1 | |||||||||||||
| "0" | |||||||||||||
| "1" | |||||||||||||
| "" | |||||||||||||
| "abc" | |||||||||||||
| "10" | |||||||||||||
| "1e1" | |||||||||||||
| 10 | |||||||||||||
| [] |
В PHP 8 изменилось одно правило: нечисловая строка больше не равна 0, поэтому in_array('abc', [0]) сегодня даёт false, а в PHP 7 давало true. Код, написанный для PHP 7, иногда на это полагался, и это ещё одна причина передавать true, а не зависеть от правил приведения. Подробно они объяснены на странице об операторах сравнения.
in_array без учёта регистра
in_array() сравнивает строки точно, поэтому 'PHP' и 'php' разные. Приведите к нижнему регистру и иглу, и массив перед проверкой. mb_strtolower() справляется и с буквами с диакритикой и нелатинскими буквами.
Проверка нескольких значений сразу
in_array() принимает одну иглу. Для нескольких сравнивайте массивы как множества: array_diff() возвращает недостающие иглы, поэтому пустой результат значит, что есть все, а array_intersect() возвращает найденные.
array_diff() и array_intersect() сравнивают значения как строки, поэтому 1 и '1' там считаются равными.
in_array в многомерном массиве
in_array() не ищет внутри вложенных массивов. Чтобы проверить, есть ли в какой-то строке поле с нужным значением, сначала извлеките это поле через array_column(), а потом ищите в плоском списке.
Последняя строка показывает, что игла сама может быть массивом: она совпадает со строкой, которая идентична ей, с теми же ключами, значениями и порядком.
in_array, array_search и isset
Все три отвечают на вопрос "есть ли?", но возвращают разное и работают с разной скоростью:
| Вызов | Возвращает | Скорость на большом массиве |
|---|---|---|
in_array($v, $arr, true) | true или false | просматривает каждый элемент |
array_search($v, $arr, true) | ключ или false | просматривает каждый элемент |
isset($set[$v]) | true или false | один поиск по хешу |
Используйте array_search(), когда нужно знать, где находится значение. Когда проверяете много значений по одному большому списку, один раз переверните список, чтобы его значения стали ключами, и используйте isset().
Время меняется от запуска к запуску, а разрыв нет: поиск через isset() остаётся постоянным, а in_array() растёт вместе с размером списка. array_flip() работает только со строковыми и целочисленными значениями, а дубликаты схлопываются в один ключ, что для проверки наличия не важно.
Часто задаваемые вопросы
Что делает третий параметр in_array?
Он включает строгое сравнение. in_array($x, $arr, true) сравнивает через ===, поэтому должны совпадать и значение, и тип: in_array('1', [1, 2], true) даёт false. Без него PHP сравнивает через == и сначала приводит типы.
Всегда ли использовать строгий режим в in_array?
Обычно да. В нестрогом режиме in_array(null, [0]), in_array(true, ['any string']) и in_array('1e1', ['10']) все возвращают true. Выключайте его, только когда сознательно хотите, чтобы '5' из формы совпадало с целым 5.
Как сделать in_array без учёта регистра?
Приведите обе стороны к нижнему регистру: in_array(strtolower($needle), array_map('strtolower', $haystack), true). Используйте mb_strtolower, когда в тексте могут быть не-ASCII буквы.
Как проверить, что в массиве есть несколько значений?
Чтобы требовать все, проверьте, что ничего не осталось: !array_diff($needles, $haystack). Чтобы требовать хотя бы одно, проверьте пересечение: (bool) array_intersect($needles, $haystack).
Медленная ли функция in_array?
Она просматривает массив элемент за элементом, поэтому медленна для больших массивов, которые проверяют много раз. Один раз переверните массив через $set = array_flip($haystack); и используйте isset($set[$value]), это один поиск по хешу.