Нечетное поведение оператора 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))
, поэтому конкретная проблема решена, но теперь мне любопытно относиться к общему поведению операторов переключения PHP. Является ли поведение я свидетелем правильного поведения для PHP? Есть ли какая-то ошибка в PHP, которая вызывает это, или я сделал ошибку в своем коде, о котором я не знаю?
Ответы
Ответ 1
Это из-за того, как php передает строки в int. Когда вы передаете 0
, вы просите его выполнить целочисленное сравнение, поэтому он преобразует все ваши ключи к целым. Когда php отправляет a 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]
и вместо этого вернул бы ваш случай по умолчанию.
Ответ 2
Ключевым моментом является то, что оператор 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){
// ...
}