運算子是程式邏輯的基石。PHP 提供七大類運算子,理解其優先序、結合性、短路行為與型別轉換規則,能避免大量隱性 Bug。本文系統整理並附上實戰範例與避坑指南。
| 類別 | 運算子 | 關鍵特性 |
|---|---|---|
| 算術 | + - * / % ** | ** 指數 (PHP 5.6+);% 取餘,雙方先轉 int |
| 字串 | . .= | 連接,優先序高於算術 |
| 指派 | = += -= *= /= %= .= | 右結合,回傳賦值結果 |
| 比較 | == === != !== < > <= >= <=> | <=> 太空船 (PHP 7+) 回傳 -1/0/1 |
| 邏輯 | && || ! and or xor | &&/|| 短路;and/or 優先序極低 |
| 位元 | & | ^ ~ << >> | 作用於整數,雙方先轉 int |
| 其他 | ?: ?? => -> :: @ ` | ?? Null 合併 (PHP 7);` 執行 Shell |
1. clone new [非結合]
2. ** [右]
3. ++ -- ~ (int) (float) (string) ... [右]
4. instanceof [非結合]
5. * / % [左]
6. + - . [左]
7. << >> [左]
8. < <= > >= [非結合]
9. == != === !== <> <=> [非結合]
10. & [左]
11. ^ [左]
12. | [左]
13. && [左]
14. || [左]
15. ? : [右]
16. ?? [右]
17. = += -= *= /= %= .= &= |= ^= <<= >>= [右]
18. and [左]
19. xor [左]
20. or [左]
黃金法則:不確定時加括號 (),提高可讀性並消除歧義。
&& 與 ||(短路)$a = 10;
if ($a > 5 || $a++ < 100) { } // $a 保持 10,右側未執行
echo $a; // 10
$b = 10;
if ($b > 5 | $b++ < 100) { } // | 不短路,右側執行
echo $b; // 11
&&:左側 false → 直接回傳 false,右側不執行。||:左側 true → 直接回傳 true,右側不執行。$db = connect() || throw new Exception('DB down');、$user = getCache($id) ?? fetchFromDB($id);(PHP 7 ?? 亦為短路)。& |(非短路,位元/邏輯雙重身分)作用於 bool 時為邏輯運算,兩側皆會執行,可用於需執行副作用函數的場景:
function logA() { echo 'A'; return true; }
function logB() { echo 'B'; return false; }
logA() && logB(); // 輸出 A(短路)
logA() & logB(); // 輸出 AB(非短路)
const READ = 1 << 0; // 1 (0001)
const WRITE = 1 << 1; // 2 (0010)
const EXEC = 1 << 2; // 4 (0100)
const ADMIN = 1 << 3; // 8 (1000)
$userPerm = READ | WRITE; // 3 (0011)
// 檢查權限
function hasPerm($user, $perm) {
return ($user & $perm) === $perm;
}
hasPerm($userPerm, READ); // true
hasPerm($userPerm, ADMIN); // false
// 新增權限
$userPerm |= EXEC; // 7 (0111)
// 移除權限
$userPerm &= ~WRITE; // 5 (0101)
// 切換權限
$userPerm ^= ADMIN; // 13 (1101)
$x = 17;
$x << 1; // 34 (x * 2)
$x << 2; // 68 (x * 4)
$x >> 1; // 8 (intdiv(x, 2))
$x >> 2; // 4 (intdiv(x, 4))
?: 與 Null 合併 ??$b = $a > 5 ? $a : 5; // 傳統三元
$c = $a ?? 'default'; // $a 存在且非 null 取 $a,否則 'default'
$d = $a ?: 'fallback'; // $a 為真取 $a,否則 'fallback' (PHP 5.3+)
$e = $a ?? $b ?? 'last'; // 串聯
@$content = @file_get_contents('missing.txt'); // 隱藏 Warning
// 生產環境慎用,會吞沒所有錯誤,導致除錯困難
` `(反引號)$output = `ipconfig /all`; // Windows
$output = `ls -la`; // Linux
// 等同 shell_exec(),回傳完整輸出字串
| 程式碼 | 結果 | 原因 |
|---|---|---|
| 15 (int) | 算術運算自動轉數字 | |
| '105' (string) | 字串連接 | |
| true | 字串轉數字為 0 | |
| false | 型別不同 | |
| true | 空陣列為假值 | |
| 2 (int) | bool 轉 1/0 | |
| 0 (int) | 字串十六進位不自動解析,需 hexdec() |
function isLeapYear(int $year): bool {
return ($year % 4 === 0 && $year % 100 !== 0) || $year % 400 === 0;
}
// 原文範例有語法錯誤:%year%100、$year%400=0(指派而非比較)
結語:運算子看似基礎,實則暗藏型別轉換、優先序、短路等細節。養成「加括號、用嚴格比較、善用短路、位元操作權限」習慣,能大幅降低邏輯錯誤機率。