2010-11-04 3 views
7

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

Для проверки части запроса 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. Если вышеприведенный код получил питание в качестве его целого числа, он всегда будет следовать за первым путь выполнения, доступный для него.

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

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

ответ

12

Это связано с тем, как 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.

Ресурсы:
String conversion to numbers
Type comparison tables


придираться время. Когда вы делаете простые операторы 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] и вместо этого вернул бы ваш случай по умолчанию.

+4

+1 dang! Это опасное поведение. –

+1

PHP может быть чистым злом. Это автоматическое преобразование int вызвало больше разочарований, чем «спасенное» время. – GWW

+1

По крайней мере, в случае, если вы можете использовать === и предотвратить это, но, к сожалению, переключатель/case равен == – UnkwnTech

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){ 
    // ... 
} 
Смежные вопросы