Intereting Posts
Как узнать, какая версия Symfony у меня есть? Изменить размер, затем обрезать PHP Добавление в переменную среды $ PATH в скрипте PHP PHP – установка унаследованного статического свойства также установит его в других классах, наследующих его проверьте, действительно ли соединение mysql Как создать порог для подобных строк, используя расстояние Левенштейна и учет опечаток? codeigniter разрешает «http: //» в переменной get Как определить, где эта вставка и извлечение базы данных ломается? как заменить адрес электронной почты из html innertext Использование API Google Directory для извлечения всех пользователей в домене Представление PHP-формы, проверка переменных phpass возвращает разные результаты PHP отправляет var в AS3 с помощью AJAX или POST Доступ к относительным файлам CSS / JS с правилом перезаписи htaccess Многопоточный запрос PHP PDO, последовательно отбрасывающий последний набор строк

Тип жонглирования при проведении свободного сравнения дает нежелательный результат

Я отвечал на этот вопрос сегодня, используя array_walk_recursive() , и, учитывая array_walk_recursive() образец выборки OP, мой ответ был на месте. Однако, когда OP использовал его на более крупном, реальном массиве, было обнаружено некоторое нежелательное поведение при условной проверке ключей с помощью == . В конце концов, использование === было достаточно, чтобы исправить проблему.

Вот минимальная демонстрация ( Demo Link ):

 $array=[ 'key1'=>[ ['key1A'=>'v1'], ['key1B'=>'v2'], ['key1C'=>'v3'] ], 'key2'=>[ [0=>'v4'], [1=>'v5'], [2=>'v6'] ], 'key3'=>[ ["0"=>'v7'], ["1"=>'v8'], ["2"=>'v9'] ] ]; echo "Leafy nodes:\n-----\n"; array_walk_recursive($array,function($v,$k)use(&$result1){ echo "$k => $v\n"; if($k=='key1B'){ // buggy behavior with == if(!isset($result1[$v])){$result1[$v]=0;} ++$result1[$v]; } }); array_walk_recursive($array,function($v,$k)use(&$result2){ //echo "$k => $v\n"; if($k==='key1B'){ // no trouble with === if(!isset($result2[$v])){$result2[$v]=0;} ++$result2[$v]; } }); echo "\nIncorrect key-matching with ==\n"; var_export($result1); echo "\nCorrect key-matching with ===\n"; var_export($result2); 

Вывод:

 Leafy nodes: ----- key1A => v1 key1B => v2 key1C => v3 0 => v4 1 => v5 2 => v6 0 => v7 1 => v8 2 => v9 Incorrect key-matching with == array ( 'v2' => 1, 'v4' => 1, 'v7' => 1, ) Correct key-matching with === array ( 'v2' => 1, ) 

Поведение, похоже, состоит в том, что клавиши «нуль-иш» соответствуют key1B . Если [0=>'v4'] закомментирован, то v5 не вставляется в $result1 ; поэтому речь идет не о ключевой позиции в подмассиве, а о бремени на нулевом ключе.

Я хотел бы знать:

  • Это ошибка, или я просто что-то недопонимаю? Если это не ошибка, объясните, почему это правильное поведение.
  • Должен ли я опубликовать комментарий по адресу http://php.net/manual/en/function.array-walk-recursive.php ? Единственный комментарий, похожий на то, что я говорю, находится на самом дне (от 10 лет назад), что говорит о несуществующем плакате.

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

Это происходит потому, что преобразование типа php не выполняется, когда сравнение ===, но в == сравнение происходит после манипуляции типа.

для получения дополнительной информации ознакомьтесь с руководством ..
Операторы сравнения: http://www.php.net/manual/en/language.operators.comparison.php

введите описание изображения здесь

введите описание изображения здесь

PHP-тип указывает член в правой части оператора == на тип элемента с левой стороны. Так как $k иногда равно целому числу, key1B в целое число, равное 0.

Из руководства по PHP …

введите описание изображения здесь

При использовании == (свободное сравнение) и одним из операндов является число, php выполняет манипуляцию типа в качестве предназначенной функции. Эффект в этом случае означает, что строка key1B преобразуется в 0 когда $k является числовой.

Это таблица свободных сравнений из таблицы таблиц сравнения типов PHP : введите описание изображения здесь

Это говорит о том, что при свободном сравнении строки и нуля результат будет TRUE .

Вот еще одна демонстрация с использованием массива с циклом foreach:

Код:

 $array=['v1','key1'=>'v2']; var_export($array); echo "\n"; foreach($array as $k=>$v){ echo "$k => $v"; echo ' ($k = ',gettype($k),")"; if($k=='key1'){ echo " loosely equal"; } echo "\n"; } 

Вывод:

 array ( 0 => 'v1', 'key1' => 'v2', ) 0 => v1 ($k = integer) loosely equal key1 => v2 ($k = string) loosely equal 

* Заметьте, функция жонглирования типа запрещена, когда $k присваивается тип: if((string)$k=='key1'){ Это сравнение не приведет к TRUE когда $k равно 0 .

Урок, который нужно убрать, заключается в том, что вы не на 100% уверены, что операнды, которые вы сравниваете, будут одного типа, лучше всего использовать строгое сравнение ( === ).