2012-12-08 62 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