Нечетное поведение оператора switch

Я пишу код для сортируемой таблицы, где щелчок по ссылкам в заголовке изменяет ORDER BY, выполняемый при генерации набора результатов поиска (случай, когда там нет действительного порядка, заставляя запрос не запускаться с порядком и просто верните результаты в том порядке, в котором возвращается база данных, как это было предусмотрено). Код записывается в рамках, предоставленных моим работодателем.

Чтобы проверить часть запроса ORDER BY, я запускаю вход через следующую функцию проверки.

<?php function sortMode ($name) { $mode = ''; switch ($name) { case 'resnum' : $mode = 'b_resnum'; break; case 'state' : $mode = 'st_id'; break; case 'name' : $mode = 'lastname, firstname'; break; case 'phone' : $mode = 'phone'; break; case 'email' : $mode = 'email'; break; case 'opened' : $mode = 'cs_created'; break; default : $mode = ''; break; } return ($mode); } ?> 

При тестировании я обнаружил, что если параметр не был предоставлен, порядок сортировки будет resnum. После некоторых экспериментов я обнаружил, что фильтрация, встроенная в фреймворк, вызовет запрос для неинициализированной переменной, такой как параметр unset GET, для возврата целого числа 0. Если вышеприведенный код получил питание в качестве его целого числа, он всегда будет следовать за первым путь выполнения, доступный для него.

В качестве эксперимента я попытался переупорядочить порядок дел в инструкции switch и нашел, что было наверху, это то, что было выполнено, если эта функция была передана 0.

Решение проблемы заключалось в использовании switch (strval($name)) поэтому конкретная проблема решена, но теперь мне любопытно switch (strval($name)) к общему поведению операторов переключения PHP. Является ли поведение я свидетелем правильного поведения для PHP? Есть ли какая-то ошибка в PHP, которая вызывает это, или я сделал ошибку в своем коде, о котором я не знаю?

Это связано с тем, как php передает строки в ints. Когда вы передаете значение 0 , вы просите его выполнить целочисленное сравнение, поэтому оно преобразует все ваши ключи к целым. Когда php выводит string в int , она ищет фактическое число в начале строки и накапливает номер до тех пор, пока он не попадет в не-число. Так как строка «resnum» не имеет чисел, она возвращает 0. См. Здесь:

 php > echo (int)"100"; 100 php > echo (int)"300 dogs"; 300 php > echo (int)"resnum"; 0 php > echo (int)"resnum 100"; 0 

Поскольку все эти строки переданы в 0, первый случай будет оцениваться как true так как 0 == 0 .

Ресурсы:
Преобразование строк в номера
Таблицы сравнения типов


Время Nitpick. Когда вы делаете простые операторы case, которые отображают строку в строку, используйте массив. Это намного яснее и быстрее:

 function sortMode ($name) { $modeMap = array( 'resnum' => 'b_resnum', 'state' => 'st_id', 'name' => 'lastname, firstname', 'phone' => 'phone', 'email' => 'email', 'opened' => 'cs_created' ); return isset($modeMap[$name]) ? $modeMap[$name] : ''; } 

Если на карте задано $name , мы возвращаем значение, к которому привязан ключ. В противном случае мы возвращаем пустую строку, которая заменяет случай по default .

В качестве бонуса вы бы заметили ошибку раньше, если вы сделали вышеупомянутый метод, потому что он пытался получить доступ к $modeMap[0] и вместо этого вернул бы ваш случай по умолчанию.

Ключевым моментом является то, что оператор switch () выполняет сравнение между параметром и метками. Это означает, что вам приходится иметь дело с правилами сравнения и выбора типов PHP. Просто посмотрите несколько примеров:

 <?php var_dump( ''==0 ); // bool(true) var_dump( 'foo'==0 ); // bool(true) var_dump( '0'==0 ); // bool(true) var_dump( '0m'==0 ); // bool(true) var_dump( '01'==0 ); // bool(false) 

Ссылка может быть найдена по адресу:

Инициализация не заданного параметра GET до 0 – довольно странное дизайнерское решение. Вы должны разобраться с этим конкретным делом в отдельности, чтобы было ясно, что это особая ситуация:

 if( $name===0 ){ return ''; } switch($name){ // ... }