1

我遇到了一些奇怪的事情,我不知道为什么会这样!

我有一个像这样的网址:

http://mysite.com/users/USER_ID

此用户 ID 可能是INT并且可能是STRING,类似于 Facebook 页面地址,如果您使用页面 ID 调用页面,它会加载它,您也可以使用页面名称(例如“my_page_name”)调用它

所以想象一个用户,它的 ID 是1,它的地址是my_name 在我的 php 页面上我需要查询数据库,但在此之前我需要知道要查看哪一列,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!

为什么会这样?

提前致谢。

4

5 回答 5

5

PHP 真正与所谓的类型杂耍“联系在一起”。它是大多数 PHP 脚本中最容易出错的部分。因此,您应该始终保持安全并使用最可靠的检查。例如intval("twelve")将返回 0,这是一个有效的整数。但也被认为是“假”: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

edit As commentor points out, there was a logical flaw in my code, stemming form the fact I tested it in phpsh only. I refactored it from using is_int() to intval and > 0. In a web-environment, $_GET["id"] is always a string; no matter what. Hence is_int() will always return FALSE.

于 2012-12-08T11:34:23.103 回答
4

要检查是否请求了数值,请使用is_numeric.

于 2012-12-08T11:19:47.717 回答
2

来自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。

如果您使用===而不是==不使用类型进行测试,则将执行杂耍。

于 2012-12-08T11:13:26.130 回答
2

PHP 在类型方面有点奇怪。

基本上,您所做的是将字符串解析为数字(因此'abcdef'返回 0,因为它根本不是数字),然后将原始字符串与数字进行比较。

现在,我明白为什么你会认为它应该是错误的,但 PHP 试图变得聪明。基本上,==将强制类型,并且如果其中一个值是数字,则几乎总是强制为数字。因此,它使用您对字符串所做的相同转换,然后进行比较。

使用===which 也检查类型是一个更好的主意。

于 2012-12-08T11:14:52.283 回答
1

成功时 var 的整数值,失败时为 0。空数组返回 0,非空数组返回 1。(来自 php.net intval()。)

intval('abcdefg') 将触发错误并且函数返回 0。

于 2012-12-08T11:11:14.170 回答