PHP 數據類型轉換與常量完整指南
類型轉換是 PHP 弱類型系統的核心特性。掌握強制轉換、自動轉換規則、常量定義與魔術常量,能避免隱式轉換導致的邏輯 Bug。
一、強制類型轉換
| 語法 | 目標類型 | 別名 | 說明 |
(int) $x / (integer) $x | int | int | 截斷小數,非數字字符串為 0 |
(float) $x / (double) $x / (real) $x | float | double/real | 保留小數 |
(bool) $x / (boolean) $x | bool | boolean | 按真假值規則 |
(string) $x | string | - | 對象需實現 __toString() |
(array) $x | array | - | 標量→單元素數組,對象→屬性數組 |
(object) $x | object | - | 數組→stdClass,其他→stdClass{scalar:值} |
(unset) $x | null | - | PHP 7.2+ 棄用,用 null |
關鍵行為差異
<?php
$a = "123abc";
// 1. 強制轉換(臨時,不改變原變量)
$b = (int)$a; // 123
var_dump($a); // string(6) "123abc" (原值不變)
var_dump($b); // int(123)
// 2. settype() 永久改變原變量
settype($a, 'int'); // true
var_dump($a); // int(123) (原值已變)
// 3. 內存溢出風險
$big = '999999999999999999999999999999999999';
var_dump((int)$big); // float(9.999...E+35) - 超出 int 範圍自動變 float
// 64位系統 int 範圍:-9223372036854775808 ~ 9223372036854775807
?>
二、自動類型轉換(類型演算規則)
算術運算符規則
<?php
// 任一操作數為 float → 結果為 float
var_dump(1 + 1.0); // float(2)
var_dump(1 + "2.5"); // float(3.5)
// 兩操作數均為 int(或可轉為 int 的字符串) → 結果為 int
var_dump(1 + 2); // int(3)
var_dump("10" + "5"); // int(15)
var_dump("10 apples" + "5 oranges"); // int(15) + 警告
// 字符串連接符 . 強制轉字符串
var_dump("5" . 2); // string(2) "52"
?>
比較運算符規則(== 鬆散比較)
| 操作數類型 | 比較規則 | 示例 |
| bool vs 任意 | bool 轉 int (true=1, false=0) | true == 1 → true |
| null vs 任意 | null 轉 false/0/'' | null == false → true |
| string vs number | string 轉 number | "5" == 5 → true |
| object vs 任意 | object 轉 int (1) + 警告 | new StdClass == 1 → true |
| array vs 任意 | array 總是大於非 array | [] > 0 → true |
=== 全等比較(推薦)
// 類型+值同時相等
1 === 1; // true
1 === '1'; // false (類型不同)
true === 1; // false
null === false; // false
[] === []; // true (同鍵同值同序)
?>
三、類型檢測函數
<?php
// is_* 系列
is_int($x); is_float($x); is_bool($x); is_string($x);
is_array($x); is_object($x); is_null($x); is_resource($x);
is_scalar($x); // int/float/bool/string
is_callable($x); // 可調用
is_iterable($x); // array 或 Traversable (PHP 7.1+)
is_countable($x); // 可 count() (PHP 7.3+)
is_numeric($x); // 數字或數字字符串(含十六進制、科學計數法)
// gettype() 返回類型字符串
gettype(123); // 'integer'
gettype(1.2); // 'double'
gettype(true); // 'boolean'
gettype("str"); // 'string'
gettype([]); // 'array'
gettype(null); // 'NULL'
// PHP 8+ 更精確
get_debug_type(123); // 'int'
get_debug_type(1.2); // 'float'
get_debug_type([]); // 'array'
get_debug_type(fn()=>1); // 'Closure'
?>
四、常量定義與使用
define() 運行時定義
<?php
// 基本定義
define('APP_NAME', 'MyApp');
define('MAX_UPLOAD_SIZE', 10 * 1024 * 1024); // 表達式求值
// 大小寫不敏感(PHP 8.0+ 棄用,不推薦)
define('VERSION', '1.0', true); // 第三參數 true
echo version; // 也能訪問
// 檢查常量是否存在
defined('APP_NAME'); // true
defined('NOT_EXIST'); // false
// 常量值只能是標量/數組 (PHP 7+)
define('ALLOWED_EXT', ['jpg', 'png', 'gif']);
define('DB_CONFIG', ['host'=>'localhost', 'port'=>3306]); // PHP 7+
?>
const 編譯時定義(類/命名空間/文件頂層)
<?php
namespace App\Config;
const API_TIMEOUT = 30;
const RETRY_TIMES = 3;
const ENDPOINTS = [
'user' => '/api/user',
'order' => '/api/order'
];
class Constants {
public const STATUS_OK = 200;
public const STATUS_ERROR = 500;
// 類常量可被繼承覆蓋
}
// 訪問
echo \App\Config\API_TIMEOUT;
echo Constants::STATUS_OK;
?>
五、魔術常量(編譯時解析)
| 常量 | 含義 | 示例輸出 |
__LINE__ | 當前行號 | 15 |
__FILE__ | 完整文件路徑(已解析符號鏈接) | /var/www/app/index.php |
__DIR__ | 文件所在目錄(等同 dirname(__FILE__)) | /var/www/app |
__FUNCTION__ | 函數名(含命名空間) | App\Controllers\UserController::index |
__CLASS__ | 類名(含命名空間) | App\Models\User |
__TRAIT__ | Trait 名 | App\Traits\Loggable |
__METHOD__ | 類方法名 | UserController::index |
__NAMESPACE__ | 當前命名空間 | App\Controllers |
ClassName::class | 類完全限定名 (PHP 5.5+) | App\Models\User |
六、常見陷阱與最佳實踐
- "0" == false 為 true:表單驗證用 `=== ''` 或 `empty()` 而非 `== false`。
- 浮點數精度:`0.1 + 0.7 === 0.8` 為 false,金額計算用整數(分)或 BCMath。
- 常量 vs 變量:常量無 `$` 前綴,全局可訪問,不可修改,不可銷毀。
- define() 陣列值:PHP 7+ 支援,PHP 5.6 僅標量。
- 類常量訪問:`self::CONST`(靜態綁定)vs `static::CONST`(晚期靜態綁定)。
嚴格區分類型、善用 `===`、理解轉換規則,是寫出可靠 PHP 代碼的基石。