其他地方沒有提到:intval(NULL) 也會傳回 0。
(PHP 4、PHP 5、PHP 7、PHP 8)
intval — 取得變數的整數值
value
要轉換為整數的純量值
base
轉換的進位
注意:
如果
base
為 0,則使用的進位由value
的格式決定
- 如果字串包含 "0x"(或 "0X")前綴,則進位被視為 16(十六進位);否則,
- 如果字串以 "0b"(或 "0B")開頭,則進位被視為 2(二進位);否則,
- 如果字串以 "0" 開頭,則進位被視為 8(八進位);否則,
- 進位被視為 10(十進位)。
成功時傳回 value
的整數值,失敗時傳回 0。空陣列傳回 0,非空陣列傳回 1。
最大值取決於系統。32 位元系統的最大帶號整數範圍為 -2147483648 到 2147483647。因此,例如在這樣的系統上,intval('1000000000000')
將會傳回 2147483647。64 位元系統的最大帶號整數值為 9223372036854775807。
字串很可能會傳回 0,儘管這取決於字串最左邊的字元。適用整數轉換的通用規則。
範例 #1 intval() 範例
以下範例基於 64 位元系統。
<?php
echo intval(42); // 42
echo intval(4.2); // 4
echo intval('42'); // 42
echo intval('+42'); // 42
echo intval('-42'); // -42
echo intval(042); // 34
echo intval('042'); // 42
echo intval(1e10); // 10000000000
echo intval('1e10'); // 10000000000
echo intval(0x1A); // 26
echo intval('0x1A'); // 0
echo intval('0x1A', 0); // 26
echo intval(42000000); // 42000000
echo intval(420000000000000000000); // -4275113695319687168
echo intval('420000000000000000000'); // 9223372036854775807
echo intval(42, 8); // 42
echo intval('42', 8); // 34
echo intval(array()); // 0
echo intval(array('foo', 'bar')); // 1
echo intval(false); // 0
echo intval(true); // 1
?>
注意:
除非
value
參數是字串,否則base
參數沒有作用。
請小心
<?php
$n="19.99";
print intval($n*100); // 印出 1998
print intval(strval($n*100)); // 印出 1999
?>
看來 intval 在 PHP 5.6 和 7.0 與 PHP 7.1 之間,對於有效的數字字串有不同的解讀方式。
<?php
echo intval('1e5');
?>
在 PHP 5.6 和 PHP 7.0 上會傳回 1,
但在 PHP 7.1 上會傳回 100000。
intval 會將雙精度浮點數透過截斷數字的小數部分來轉換為整數。
當處理某些值時,這可能會產生奇怪的結果。請考慮以下程式碼
print intval ((0.1 + 0.7) * 10);
這很可能會印出 7,而不是預期的值 8。
更多資訊,請參閱 PHP 手冊中有關浮點數的章節 (https://php.dev.org.tw/manual/language.types.double.php)
另請注意,如果您嘗試將字串轉換為整數,結果通常會是 0。
但是,如果字串最左邊的字元看起來像有效的數值,那麼 PHP 會持續讀取字串,直到遇到不屬於有效數字的字元為止。
例如
"101 Dalmations" 將轉換為 101
"$1,000,000" 將轉換為 0 (第一個字元不是有效的數字起始字元)
"80,000 leagues ..." 將轉換為 80
"1.4e98 microLenats were generated when..." 將轉換為 1.4e98
另請注意,字串中只會識別十進制數字。
"099" 將轉換為 99,而 "0x99" 將轉換為 0。
關於 intval 行為的另一個注意事項。如果您指定 base 參數,則 var 參數應該是字串 - 否則 base 將不會被應用。
例如
print intval (77, 8); // 印出 77
print intval ('77', 8); // 印出 63
各位一定會喜歡這個。我發現了一些令我相當不安的事情。
$test1 = intVal(1999);
$amount = 19.99 * 100;
$test2 = intVal($amount);
$test3 = intVal("$amount");
echo $test1 . "<br />\n";
echo $test2 . "<br />\n";
echo $test3 . "<br />\n";
預期輸出
1999
1999
1999
實際輸出
1999
1998
1999
看起來像是浮點數問題,但 1999 是我唯一能讓它發生這種情況的數字。 19.99 是許多東西的價格,而為了我們的目的,我們必須傳遞 1999 而不是 19.99。
這是一個非常有用的未公開功能
您可以讓它自動從字串的前綴推斷數字的進位,方法是傳遞 base 為 0 給 intval(),其使用與 PHP 中整數字面值相同的語法(十六進制為 "0x",八進制為 "0",十進制為非 "0")。
<?php
echo intval("0x1a", 0), "\n"; // 十六進制;印出 "26"
echo intval("057", 0), "\n"; // 八進制;印出 "47"
echo intval("42", 0), "\n"; // 十進制;印出 "42"
?>
如果您想從字串中提取數字,無論它可能包含什麼,這是一個很好的解決方案
<?php
function int($s){return(int)preg_replace('/[^\-\d]*(\-?\d*).*/','$1',$s);}
echo int('j18ugj9hu0gj5hg');
//輸出:18
?>
這個範例會回傳一個整數,所以它會遵循整數規則,並且支援負值。
<?php
function int($s){return($a=preg_replace('/[^\-\d]*(\-?\d*).*/','$1',$s))?$a:'0';}
echo int('j-1809809808908099878758765ugj9hu0gj5hg');
//輸出:-1809809808908099878758765
?>
這一個只會回傳包含數值的字串。
它也支援負值。
當您擁有 32 位元的系統,並且想要大於 PHP_MAX_INT 的巨大整數時,後者更好。
二進制表示法在 php7.2 之前不支援。
<?php
// PHP <7.2 | PHP >=7.2
echo intval(0b11); // 3 | 3
echo intval(-0b11); // -3 | -3
echo intval('0b11'); // 0 | 0
echo intval('-0b11'); // 0 | 0
echo intval('0b11', 0); // 0 | 3
echo intval('-0b11', 0); // 0 | -3
?>
有時 intval 就是不夠用。例如,如果您想使用不帶正負號的 32 位元整數,並且需要全部 32 位元。最近,我寫了一個小腳本,它會接收一個整數並將其轉換為 IP 位址。在意識到我不能只是對整個東西取餘數(因為正負號位會將其偏移並做補償)之後,我們遇到了問題,如果將其輸入到表單中,該值在某種程度上沒有正確地轉換為整數,至少不是隱式地。解決方案是這樣,也是我建議將字串轉換為整數的方式,是
$num = $num + 0;
而 PHP 會保持您的數字不變;它只會知道它是一個數字。這就是鬆散類型語言的樂趣。 :)
作為警告,請勿單獨使用此函數進行輸入驗證。
存在漏洞的範例
<?php
if(isset($_GET['id']) && intval($_GET['id']) > 0){
echo $id;
}
?>
下列請求將會通過這個篩選器
/page.php?id=10
/page.php?id=10oops
/page.php?id=10<script>alert(1)</script>
/page.php?id=1' OR '1'='1
/page.php?id[]=<script>alert(1)</script>
請改用 is_numeric() 函數進行整數驗證
<?php
echo intval("10oops"); // 10
echo is_numeric("10oops"); // false
?>
安全範例
<?php
if(isset($_GET['id']) && is_numeric($_GET['id']) && intval($_GET['id']) > 0){
echo $id;
}
?>
PHP 7.2
$test = intval(150.20*100); //15019
$test2 = intval(15020); //15020
$test3 = intval(15020.0); //15020
$test4 = 150.20*100; //15020.0
當您真正想要 round() 時,請勿使用 intval()。這是由於 PHP 如何處理精度。
echo number_format(8.20*100, 20), "<br />";
echo intval(8.20*100), "<br />";
echo floor(8.20*100), "<br />";
echo round(8.20*100), "<br />";
819.99999999999988631316
819
819
820
當提供進位時,intval() 的行為很有趣,您最好檢查您的 intval 基底表示式,因為它違反直覺。
如範例所示
<?php
intval('42', 8); // => 34
intval(42, 8); // => 42 !
?>
PHP 認為 42 已經是一個整數,因此不進行任何轉換。並且提供
<?php
intval(49, 8); // => 49 !
?>
不會產生錯誤或警告。
請注意
<?php
// 請觀察以下情況
echo intval( strval( -0.0001 ) ); // 0
echo intval( strval( -0.00001 ) ); // -1
// 這是因為
echo strval( -0.0001 ); // -.0001
echo strval( -0.00001 ); // -1.0E-5
// 因此在使用時請注意
function trunc2_bad( $n ) {
return intval( strval( $n * 100 ) / 100 );
}
// 請改用以下方式
function trunc2_good( $n ) {
return intval( floatval( strval( $n * 100 ) ) / 100 );
}
?>
補充一點,encode 函式中的 "if ($int > 0)" 檢查是多餘的。保持它並不會有什麼壞處,因為當執行到該點時,它總是會成立,但這樣做是一個沒有意義的條件判斷。這是當我嘗試用位元位移來撰寫這個函式時留下來的,如果第 32 位元被設定(而不是使用 >> 時總是補 0,而是補 1 導致負整數),這樣在位移時可能會導致負整數。
警告:intval() 會解析科學記號,例如 "12.3e7"。
當你使用 intval() 從字串中截取第一個整數值時,這會突然出現;乍看之下沒有任何問題,如果你有 "123.jeff",它會給你 123,但在解析帶有十六進位數字的第二個區段的罕見情況下,你很容易遇到這個問題。(我們不要開始「為什麼你要這樣解析字串」的爭論。)
所以如果你沒有準備,這些結果可能會讓你感到驚訝
intval("123.ee-2") - 給你 123
intval("123.e2-e") - 給你 12300
intval("123.a2-e") - 給你 123
intval("123.e-22") - 給你 0
intval("123.e-a2") - 給你 123
intval("123.e-2a") - 給你 1
intval("123.2e2a") - 給你 12320
intval("123.22e2") - 給你 12322
intval("123.22ea") - 給你 123
再次強調,一旦你知道它會解釋科學記號,這某種程度上是預期的行為。但這似乎是一個不太廣為人知的事實,而且我只有在使用了 PHP 20 多年後才遇到這個問題。