Я встречаюсь с чем-то странным, и я не знаю, почему это происходит!
У меня есть URL-адрес:
http://mysite.com/users/ USER_ID
этот идентификатор пользователя может быть INT
и может быть STRING
, это что-то вроде адресов страниц Facebook, если вы вызываете страницу с идентификатором страницы, который она загружает, вы также можете назвать ее с именем страницы, например «my_page_name»,
Итак, представьте себе, что пользователь, которому он равен 1
и его адрес – my_name
На моей php-странице мне нужен запрос db, но перед этим мне нужно знать, какой столбец искать, id
или page_name
Поэтому я пришел с таким решением:
<?php $id = $_GET['id']; $id_inted = intval($_GET['id']); if($id == $id_inted){ // The column which I should look into is id $column = 'id'; }else{ // The column which I should look into is page_name $column = 'page_name'; } $query = mysql_qyery(SELECT * FROM members WHERE $column = '$id'); ?>
Поэтому я тестировал его, но результаты были странными, даже если я называю этот URL:
http://mysite.com/users/ page_name
Это происходит: $column = 'id';
Я открыл новую тестовую страницу:
<?php $real_string = 'abcdefg'; $string_inted = intval($real_string); echo "Real String is: " . $real_string . "<br />"; echo "The same string as int is: " . $string_inted . "<br />"; if($real_string == $string_inted) echo "Weird!"; else echo "Fine..."; ?>
и результаты:
Real String is: abcdefg The same string as int is: 0 Weird!
Почему это происходит?
Заранее спасибо.
PHP действительно «подключен» с так называемым манипулятором типа. Это наиболее подверженная ошибкам часть большинства PHP-скриптов. Таким образом, вы всегда должны оставаться на безопасной стороне и использовать самую надежную проверку. Например, intval("twelve")
вернет 0, что является действительным целым числом. Но также считается «ложным»: print if (intval("one")) ? "yup" : "nope"
print if (intval("one")) ? "yup" : "nope"
напечатает «nope».
В этом случае использование intval
в сочетании с проверкой, если целое число больше нуля, должно сделать трюк:
<?php $id = intval($_GET['id']); if($id > 0){ // The column which I should look into is id $column = 'id'; }else{ // The column which I should look into is page_name $column = 'page_name'; } $query = mysql_qyery(SELECT * FROM members WHERE $column = '$id'); ?>
Или, короче:
$id = intval($_GET['id']); $column = ($id > 0) ? "id" : "page_name"; $query = mysql_qyery(SELECT * FROM members WHERE $column = '$id');
Aso обратите внимание, что $ _GET ["id"] не может быть установлен, что вызовет уведомление в вашем коде.
И последнее, но, конечно, не в последнюю очередь: SQL-инъекция ?id=LittleBobby';Drop table users
Как замечает комментатор, в моем коде есть логический недостаток, связанный с тем, что я тестировал его только в phpsh . Я реорганизовал его с использованием is_int()
для intval
и > 0
. В веб-среде $ _GET ["id"] всегда является строкой; не важно что. Следовательно is_int()
всегда возвращает FALSE
.
Чтобы проверить, запрашивается ли числовое значение, используйте is_numeric
.
PHP немного странный, когда дело касается типов.
В основном, то, что вы делаете, это разбор строки на число (поэтому 'abcdef'
возвращает 0, потому что это не номер вообще), а затем сравнивает исходную строку с номером.
Теперь я могу понять, почему вы предполагаете, что это должно быть ложным, но PHP пытается быть умным. В принципе, ==
будет принуждать типы и почти всегда прибегает к номерам, если одно из его значений – это число. Таким образом, он использует то же преобразование, что и в строке, а затем сравнение.
Лучше использовать ===
который также проверяет типы.
С http://php.net/manual/en/language.operators.comparison.php
Example Name Result $a == $b Equal TRUE if $a is equal to $b after type juggling. $a === $b Identical TRUE if $a is equal to $b, and they are of the same type.
Ваша строка заливается в целое число из-за манипуляции типа в операторе ==
и intval()
строки возвращает 0
Это объясняет, почему $id == $id_inted
в вашем коде оценивается как true.
Если вы сделаете свой тест с ===
вместо ==
не будет выполняться жонглирование.
Целое значение var для успеха, или 0 при ошибке. Пустые массивы возвращают 0, возвращаются непустые массивы 1. (Из php.net intval () .)
intval ('abcdefg') вызовет ошибку, а функция вернется с 0.