Особенности условных конструкции со строками в PHP
Операции сравнения, операторы if и switch могут вести себя неожиданно в присутствии строковых переменных. Незнание поведения данных операторов может приводить к ошибкам безопасности приложения.
Что есть истина?
Какие строки истинны? Рассмотрим пример:
echo '"0" is ' . ('0'?'true':'false') . "\n";
echo '"-0" is ' . ('-0'?'true':'false') . "\n";
echo '"0.0" is ' . ('0.0'?'true':'false') . "\n";
echo '"00" is ' . ('00'?'true':'false') . "\n";
echo '"A" is ' . ('A'?'true':'false') . "\n";
Имеем:
"" is false "0" is false "-0" is true "0.0" is true "00" is true "A" is true
Итак истинны все непустые строки, кроме строки "0". Логика такого поведения для меня не ясна. На практике часто с помощью оператора if проверяется заполнено ли поле формы, например:
Такая проверка примет поле, в котором указан 0 за незаполненное. Чтобы избежать возможного недоразумения, следует использовать проверку в виде:
Сравнение с участием строк
В PHP два оператора сравнения == и ===. Второй оператор сравнивает совпадение типов и значений, первый производит преобразование типа, а затем выполняет сравнение. Особенность оператора == в том, что при сравнении числа и строки, просходит преобразование строки в число. Если строка не представляет собой число, то она преобразуется в числовое значение 0. Рассмотрим пример:
echo '"A"===0 is ' . ('A'===0?'true':'false') . "\n";
echo '"A"==0.0 is ' . ('A'==0?'true':'false') . "\n";
echo '"A"===0.0 is ' . ('A'===0?'true':'false') . "\n";
Результат работы скрипта: "A"==0 is true "A"===0 is false "A"==0.0 is true "A"===0.0 is false
Если ваша функция сравнивает строку, переданную в качестве аргумента с заданной строкой, то следует предварительно проверить, что в качестве аргумента передана строка, а не число. Пример будет приведен далее, при рассмотрении оператора switch.
Оператор switch
Мы ожидаем, что оператор switch сравнивает переданное значение с заданными константами. Особенность реализации switch в php в том, что он производит сравнение с помощью оператора ==, то есть не производит сравнение типов. В качестве примера рассмотрим вымышленную функцию, которая возвращает зарплату сотрудника, получая его имя на входе:
function get_salary($name) {
switch($name) {
case 'John':
return 3400;
break;
case 'Mary':
return 4600;
break;
default:
return 0;
}
}
echo "John's salary is " . get_salary('John') . "\n";
echo "Mary's salary is " . get_salary('Mary') . "\n";
echo "Peter's salary is " . get_salary('Peter') . "\n";
echo "0's salary is " . get_salary(0) . "\n";
?>
Результат работы скрипта: John's salary is 3400 Mary's salary is 4600 Peter's salary is 0 0's salary is 3400
На примере видно, что безопасность функции скомпрометирована путем передачи числового значения вместо строкового. Чтобы защитить функцию от нежелательного использования, требуется проверять тип входного значения.
function get_salary($name) {
if(!is_string($name)) return 0;
switch($name) {
case 'John':
return 3400;
break;
case 'Mary':
return 4600;
break;
default:
return 0;
}
}
echo "John's salary is " . get_salary('John') . "\n";
echo "Mary's salary is " . get_salary('Mary') . "\n";
echo "Peter's salary is " . get_salary('Peter') . "\n";
echo "0's salary is " . get_salary(0) . "\n";
?>
Результат работы скрипта: John's salary is 3400 Mary's salary is 4600 Peter's salary is 0 0's salary is 0
Итак, некоторые операции сравнения ведут себя контринтуитивно. Кто предупрежден, тот вооружен.
Статья написана по материалам онлайн-курса «Программирование на PHP».
© Все права на данную статью принадлежат порталу webew.ru. Перепечатка в интернет-изданиях разрешается только с указанием автора и прямой ссылки на оригинальную статью. Перепечатка в печатных изданиях допускается только с разрешения редакции.