2012-12-08 49 views
1

我遇到了奇怪的事情,我不知道它为什么会发生!PHP intval()奇怪的结果

我有这样一个URL:

http://mysite.com/users/USER_ID

该用户ID可能是INT和可STRING,它像Facebook页面的地址,如果调用页面ID它加载到页面,你也可以用网页名称称呼它“my_page_name”

所以,想象一下它的ID是1用户,它的地址是my_name 在我的PHP页面,我需要查询数据库,而T3之前帽子我需要知道看哪一列,idpage_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'); 
?> 

所以我测试了它,但结果是怪异,即使我把这个网址:

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! 

为什么发生这种情况?

在此先感谢。

+1

祝贺管理始终拼错怪异,因为有线... – Aatch

+0

@Aatch恭喜您接近问题的要点! :-D – behz4d

+1

我也回答了这个问题。我只是惊讶于你设法写了'有线'而不是'怪异'4次。 – Aatch

回答

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'); 

阿苏注意$ _GET [“id”]可能没有设置,这会在您的代码中发出通知。

最后但肯定不是最不重要的:SQL-injection?id=LittleBobby';Drop table users

编辑作为评注者指出的,在我的代码逻辑漏洞,制止形成我phpsh只测试了它的事实。我使用is_int()intval> 0来重构它。在Web环境中,$ _GET [“id”]总是一个字符串;无论。因此is_int()将始终返回FALSE

+0

我使用mysql_real_escape_string($ id),这足以防止SQL注入吗? – behz4d

+0

它[可能是](http://stackoverflow.com/questions/1220182/does-mysql-real-escape-string-fully-protect-against-sql-injection?rq=1) – berkes

+1

'is_int'检查类型变量和'$ _GET'只包含字符串,所以它会一直返回false。 –

1

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

INTVAL( 'ABCDEFG')将触发一个错误,并用0

+0

确实,这是真的,但为什么它的价值与字符串一样!?上述问题的解决方案是什么? – behz4d

+0

类型杂耍PHP的类型会将字符串转换为与intval-ed变体相匹配的类型。 –

+1

这实际上并没有回答这个问题。 – Aatch

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

这就解释了为什么您的代码中的计算结果为true。

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

+0

'==='解决了这个问题,谢谢,但我仍然不要得到我的代码回声“奇怪!”的逻辑,因此我的字符串在注册后将为0,但为什么if()语句会转到第一个回显?即使用你的答案,0!='abcdefg' – behz4d

2

当谈到类型时,PHP有点奇怪。

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

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

使用===也是一个好主意,它也检查类型。

4

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