PHP 數據類型與變量核心概念全解析
PHP 是一門弱類型、動態類型的語言。變量無需聲明類型,由上下文自動推斷。理解類型系統、作用域規則與特殊機制,是編寫健壯 PHP 代碼的基石。
1. 八大標量/複合類型
| 分類 | 類型 | 說明 | 範例 |
| 標量類型 | boolean | 布爾值 | true, false |
| integer | 整數 (平台相關,通常 64 位) | 42, -10, 0x1A (十六進制), 075 (八進制) |
| float/double | 浮點數 | 3.14, 1.2e3, 7E-10 |
| string | 字串 (位元組序列,無編碼限制) | 'hello', "world", << |
| 複合類型 | array | 有序映射 (鍵值對) | [1,2,3], ['a'=>1, 'b'=>2] |
| object | 類實例 | new DateTime() |
| 特殊類型 | resource | 外部資源句柄 | fopen(), mysql_connect() |
| NULL | 無值狀態 | null, 未定義變量 |
2. 類型檢測與判斷函數
<?php
$vars = [
'str' => 'hello',
'int' => 42,
'float' => 3.14,
'bool' => true,
'arr' => [1,2,3],
'obj' => new stdClass(),
'null' => null,
'res' => fopen('php://memory', 'r')
];
echo "<table border=1><tr><th>變量</th><th>gettype()</th><th>is_* 判斷</th></tr>";
foreach ($vars as $name => $val) {
$type = gettype($val);
$checks = [];
foreach (['bool','int','float','string','array','object','null','resource','scalar','callable'] as $fn) {
if (($f = 'is_'.$fn) && $f($val)) $checks[] = $fn;
}
echo "<tr><td>$name</td><td>$type</td><td>".implode(', ', $checks)."</td></tr>";
}
echo "</table>";
fclose($vars['res']);
?>
3. 顯式類型轉換 (C 風格)
| 轉換運算子 | 目標類型 | 別名 |
| (int) | integer | (integer) |
| (float) | float | (double), (real) |
| (string) | string | |
| (bool) | boolean | (boolean) |
| (array) | array | |
| (object) | object | |
| (unset) | NULL | PHP 7.2+ 棄用 |
轉換規則重點
<?php
// 字串轉數字:從開頭解析數字字符
echo (int)"123abc"; // 123
echo (float)"3.14pi"; // 3.14
echo (int)"abc"; // 0
// 布爾轉換:只有 false, 0, 0.0, "", "0", [], null 為 false
var_dump((bool)"0"); // false (字串 "0" 特例!)
var_dump((bool)"false"); // true (非空字串)
// 陣列轉物件
$arr = ['a' => 1, 'b' => 2];
$obj = (object)$arr;
echo $obj->a; // 1
// 物件轉陣列 (僅公開屬性)
class Test { public $x=1; protected $y=2; private $z=3; }
$obj = new Test();
print_r((array)$obj); // 只包含 'x' => 1
?>
4. 函數參數傳遞:值傳遞 vs 引用傳遞
<?php
// 值傳遞 (預設) - 複製副本
function swap1($x, $y) {
$t = $x; $x = $y; $y = $t;
}
// 引用傳遞 - 操作同一記憶體地址
function swap2(&$x, &$y) {
$t = $x; $x = $y; $y = $t;
}
$a = 3; $b = 5;
swap1($a, $b);
echo "swap1 後: a=$a, b=$b\n"; // a=3, b=5 (未變)
swap2($a, $b);
echo "swap2 後: a=$a, b=$b\n"; // a=5, b=3 (交換成功)
// 實際應用:大陣列引用傳遞節省記憶體
function processLargeArray(&$data) {
// 直接修改原陣列,避免複製 100MB 數據
$data['processed'] = true;
}
?>
5. 函數預設參數
<?php
function calculatePrice($price, $taxRate = 0.05, $discount = 0) {
return $price * (1 + $taxRate) * (1 - $discount);
}
echo calculatePrice(100); // 105 (用預設稅率 5%)
echo calculatePrice(100, 0.08); // 108 (指定稅率 8%)
echo calculatePrice(100, 0.05, 0.1); // 94.5 (稅率 5% + 折扣 10%)
// 注意:預設值必須是常量表達式,不能是變量或函數調用
// 錯誤: function foo($x = time()) {}
// 正確: function foo($x = null) { $x ??= time(); }
?>
6. 變量作用域四大類別
| 作用域 | 定義位置 | 訪問範圍 | 生命週期 |
| 局部變量 | 函數內部 | 僅該函數內 | 函數執行期間 |
| 函數參數 | 函數簽名 | 僅該函數內 | 函數執行期間 |
| 全局變量 | 函數外部 | 全腳本 (需 global 關鍵字) | 腳本執行期間 |
| 靜態變量 | 函數內部 (static 關鍵字) | 僅該函數內 | 腳本執行期間 (保持值) |
全局變量陷阱與正確用法
<?php
$taxRate = 0.03; // 全局變量
function change1() {
$taxRate += 1; // 創建同名局部變量,遮蔽全局
}
function change2() {
global $taxRate; // 顯式聲明使用全局
$taxRate += 1;
}
function change3() {
$GLOBALS['taxRate'] += 1; // 替代寫法:超全局陣列
}
change1(); echo $taxRate . "\n"; // 0.03 (全局未變)
change2(); echo $taxRate . "\n"; // 1.03 (全局被修改)
change3(); echo $taxRate . "\n"; // 2.03
?>
靜態變量:保持狀態的計數器
<?php
function counter() {
static $count = 0; // 只初始化一次
$count++;
return $count;
}
echo counter(); // 1
echo counter(); // 2
echo counter(); // 3
// 遞歸函數中的靜態變量
function recursive($n) {
static $depth = 0;
$depth++;
if ($n <= 0) return $depth;
$result = recursive($n - 1);
$depth--;
return $result;
}
?>
7. 超全局變量 - 系統預定義環境訪問
| 變量 | 用途 | 典型鍵值 |
| $GLOBALS | 所有全局變量的引用 | $GLOBALS['var'] 等同 $var |
| $_SERVER | 伺服器與執行環境資訊 | REQUEST_URI, HTTP_HOST, SERVER_ADDR |
| $_GET | URL 查詢字串參數 | ?id=1&name=test → ['id'=>1,'name'=>'test'] |
| $_POST | POST 請求體數據 | 表單提交數據 |
| $_FILES | 上傳文件資訊 | ['tmp_name', 'name', 'size', 'error'] |
| $_COOKIE | 客戶端 Cookie | session_id, preferences |
| $_SESSION | 會話數據 (需 session_start()) | 用戶登入狀態、購物車 |
| $_REQUEST | $_GET + $_POST + $_COOKIE 合併 | 不推薦使用 (安全性、效能) |
| $_ENV | 環境變量 | PATH, APP_ENV |
8. 變量變量 - 動態變量名
<?php
$name = 'hello';
$$name = 'world'; // 等同 $hello = 'world';
echo $hello; // world
// 實際應用:批量創建變量
$fields = ['title', 'content', 'author', 'date'];
foreach ($fields as $field) {
$$field = $_POST[$field] ?? '';
}
// 現在可直接使用 $title, $content 等
?>
9. 流程控制語句差異
elseif (單詞) vs C 語言 else if (兩詞)
: / endif; 替代大括號語法 (模板常用)
foreach 專為陣列/物件遍歷設計
declare(ticks=1) 等進階控制結構
<?php
// 替代語法範例 (適合 HTML 模板混編)
if ($user->isAdmin()):
echo "管理員面板";
elseif ($user->isEditor()):
echo "編輯器";
else:
echo "普通用戶";
endif;
// foreach 替代語法
foreach ($items as $item):
echo "<li>$item</li>";
endforeach;
?>
掌握 PHP 的類型系統、作用域規則與特殊機制,能避免大量常見 Bug,編寫出更可預測、可維護的代碼。建議配合 declare(strict_types=1) (PHP 7+) 強制模式使用,在關鍵業務邏輯中明確類型預期。