Ответ 1
Решение (короче):
Используйте in_array()
всегда с третьим параметром strict true
:
$arrayWithTrue = ['Andreas', 'Philipp', true];
$arrayWithNull = [1, 2, 3, null];
$arrayWithMinusOne = [-1];
var_dump(in_array('Gary', $arrayWithTrue, true)); // returns bool(false)
var_dump(in_array(0, $arrayWithNull, true)); // returns bool(false)
var_dump(in_array(true, [-1], true)); // returns bool(false)
Поэтому, когда вы используете in_array()
с true
в качестве третьего параметра, сравнение между искомым значением и массивом выполняется строго, значение in_array()
работает так, как вы ожидали бы этого.
(Параметр strict также описан в документации php.net.)
Описание
Без параметра strict, установленного в true, сравнение найденного значения и каждого значения массива выполняется с помощью равенства, а не идентификатора. Это означает, что тип значения не имеет значения, и, таким образом, PHP преобразует значения внутри одного и того же типа данных, чтобы иметь возможность их сравнивать.
Это означает, что в первом примере искомое значение 'Gary'
преобразуется в булево, когда оно сравнивается с true
, поэтому оно приводит к сравнению true
с true
, что, очевидно, true
.
То же самое происходит со вторым массивом, где 0
, наконец, сравнивается с null
, что приводит к true
, хотя 0
, очевидно, не совпадает с null
(это может быть особенно сложно, если вы работаете с числами и/или результатами функций, например, где null
может выразить пустое значение, а не 0
).
Третий массив выглядит действительно странно, потому что мы проверяем значение true
в массиве, которое содержит только -1
, но in_array()
все еще возвращает true
для сравнения. В этом случае -1
преобразуется в boolean true
. Таким образом, проблема в обоих направлениях одинакова.
Вы можете найти больше примеров проблемы сравнения в PHP (потому что это то же самое, что ==
/===
) в этом ответе.
К сожалению, по умолчанию для строкового параметра при вызове in_array()
есть... ну, да, false
.: -/PHP и он печатает...
Последствия
Вы никогда не должны называть in_array()
без строгой настройки параметра true
. Если у вас нет массивов смешанных типов, и вы проверяете только значения одного типа, in_array()
работает так, как ожидалось. См. Этот пример:
$arrayWithStrings = ['Andreas', 'Philipp', 'Friedrich'];
var_dump(in_array('Gary', $arrayWithStrings)); // returns bool(false)
Итак, по крайней мере, это работает так, как ожидалось. Но, на мой взгляд, гораздо проще просто называть in_array()
строгим true
. (Совместим с "проблемой впрыска SQL"... Всегда используйте PDO и подготовленные операторы, чтобы вы были в безопасности, даже если это запрос без переменных параметров. В любом случае вы всегда в безопасности.)
Будьте осторожны, хотя
Вы должны обязательно называть in_array()
строгим true
. Но есть один недостаток, хотя я хочу упомянуть (хотя это очевидно). Вы должны обязательно использовать правильные типы при вызове in_array()
, а затем:
$arrayWithNumbers = [1, 2, 3];
var_dump(in_array('1', $arrayWithNumbers, true)); // returns bool(false)
Но вы можете просто использовать Type Casting, когда знаете, что сравниваете числа:
$arrayWithNumbers = [1, 2, 3];
var_dump(in_array((int)'1', $arrayWithNumbers, true)); // returns bool(true)
Bonus
// Comparing false with an empty array
var_dump(in_array(false, [[]])); // returns bool(true)
Ну, да... Просто используйте его со строгим набором true
.; -)