常見程式碼片段:
<?php
// 寫法 A:if 語句
if (!defined('APP_PATH')) {
// do something
}
// 寫法 B:邏輯或運算子
defined('APP_PATH') or 1;
原文測試顯示 `or` 寫法較快。我們來深入分析原因與實際意義。
PHP 的邏輯運算子 `||`、`or`、`&&`、`and` 都具備**短路求值**特性:
expr1 || expr2:若 expr1 為 true,**不執行** expr2expr1 or expr2:同 ||,但優先序較低expr1 && expr2:若 expr1 為 false,**不執行** expr2expr1 and expr2:同 &&,但優先序較低<?php
// || 優先序高於 =
$result = false || true; // $result = true
// or 優先序低於 =
$result = false or true; // $result = false (!) 等同於 ($result = false) or true
// 正確用法:加括號
($result = false) or true; // $result = false
$result = (false or true); // $result = true
結論:賦值語境**必須用 `||`**,或加括號。`or` 適用於獨立語句(如 `doSomething() or die()`)。
<?php
function benchmark(callable $fn, int $iterations = 1_000_000): float {
$start = hrtime(true);
for ($i = 0; $i < $iterations; $i++) {
$fn();
}
return (hrtime(true) - $start) / 1e9; // 秒
}
// 測試常數檢查
$iterations = 1_000_000;
$t1 = benchmark(fn() => !defined('APP_PATH'));
$t2 = benchmark(fn() => defined('APP_PATH') || true);
$t3 = benchmark(fn() => defined('APP_PATH') or true);
echo "if (!defined): {$t1}s\n";
echo "defined || true: {$t2}s\n";
echo "defined or true: {$t3}s\n";
// 典型輸出 (PHP 8.2, JIT 關閉):
// if (!defined): 0.045s
// defined || true: 0.038s
// defined or true: 0.037s
| 寫法 | 相對速度 | 原因 |
|---|---|---|
!defined() 在 if 中 | 基準 | 條件判斷 + 分支預測 |
defined() || true | ~15-20% 較快 | 單一運算式、無分支、Opcode 較少 |
defined() or true | ~15-20% 較快 | 同上,優先序不同但獨立語句相同 |
關鍵發現:差異極微(百萬次僅差幾毫秒),屬於**微優化**範疇。
// if (!defined('APP_PATH'));
// JMPZ (ISSET_ISEMPTY_CONST) -> JMP
// 共 ~4-5 opcodes
// defined('APP_PATH') || 1;
// ISSET_ISEMPTY_CONST -> JMPZ_EX -> QM_ASSIGN -> FREE
// 共 ~4 opcodes,無條件跳轉
<?php
// ✅ 推薦:語意清晰
if (!defined('APP_PATH')) {
define('APP_PATH', __DIR__);
}
// ❌ 不推薦:晦澀難懂
defined('APP_PATH') or define('APP_PATH', __DIR__);
<?php
function process(User $user): void {
// 早期返回,減少巢狀
if (!$user->isActive()) return;
if (!$user->hasPermission('write')) return;
// 核心邏輯
doWork();
}
| 優化層級 | 影響幅度 | 範例 |
|---|---|---|
| 演算法/資料結構 | 指數級 | O(n²) → O(n log n)、避免 N+1 查詢 |
| I/O 減少 | 數量級 | 快取、批次查詢、連線池 |
| 記憶體管理 | 顯著 | 生成器、釋放大變數、opcache |
| 語法微優化 | 微乎其微 | if vs or、單雙引號、++$i vs $i++ |
<?php
// ✅ 適用:資源獲取失敗時的預設值
$cache = $redis->get($key) || $db->query($sql) || [];
// ✅ 適用:函式呼叫鏈的錯誤處理
connect() || throw new ConnectionException();
// ✅ 適用:腳本執行守衛
defined('IN_APP') or die('Access denied');
// ❌ 不適合:複雜邏輯判斷
if ($user->isAdmin() || $user->hasRole('editor') || $post->isPublished()) {
// 難以除錯、難以加日誌
}
這個經典的「if vs or」效能爭論,本質上是**過早優化**的典型案例。理解短路求值原理與優先序差異固然重要,但在實際開發中,選擇最能表達意圖、最易維護的寫法才是正道。