PHP intval()奇怪的结果


PHP intval() weird results

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

我有一个类似的网址:

http://mysite.com/users/ USER_ID

此用户ID可以为INT,也可以为STRING,类似于Facebook页面地址,如果您调用具有页面ID的页面,则会加载该页面,也可以使用页面名称(如" my_page_name")进行调用

因此,假设一个用户的ID为1,其地址为my_name
在我的php页面上,我需要查询db,但是在此之前,我需要知道要看哪一列,idpage_name

所以我想到了这个解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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';

我打开了一个新的测试页面:

1
2
3
4
5
6
7
<?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...";
?>

结果:

1
2
3
Real String is: abcdefg
The same string as int is: 0
Weird!

为什么会这样呢?

提前致谢。


PHP确实与所谓的"类型变戏法""连接"在一起。它是大多数PHP脚本中最容易出错的部分。因此,您应始终保持安全,并使用最可靠的检查方法。例如,intval("twelve")将返回0,这是一个有效的整数。但也被视为"假":print if (intval("one")) ?"yup" :"nope"将打印" nope"。

在这种情况下,应结合使用intval和检查整数是否大于零的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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');
?>

或者,更短:

1
2
3
4
$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

1
2
3
4
5
6
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。