PHP 作為解釋型語言,微觀寫法差異在高併發下會被放大。本文透過五組對比範例,展示常見效能陷阱;並彙整 30 條經實戰驗證的優化法則,助你寫出高效能 PHP 程式碼。
// ❌ 低效:每次迴圈都呼叫 count()
$arr = range(1, 10000);
for ($i = 0; $i < count($arr); $i++) {
echo $arr[$i];
}
// ✅ 高效:預先快取長度
$arr = range(1, 10000);
$len = count($arr);
for ($i = 0; $i < $len; $i++) {
echo $arr[$i];
}
// ✅ 更優:foreach(語意清晰、內部最佳化)
foreach ($arr as $val) {
echo $val;
}
// ❌ 低效:explode 分割再取第一段
$date = '2012-06-04 10:43:00';
$parts = explode(' ', $date);
echo $parts[0];
// ✅ 高效:substr 直接截取(已知固定格式)
echo substr($date, 0, 10);
// ✅ 更優:DateTime 物件(語意化、可擴充)
echo (new DateTime($date))->format('Y-m-d');
$str = '變數值';
// ❌ 雙引號:引擎需掃描變數
echo "這是雙引號字串{$str}";
// ✅ 單引號 + 串接:無變數解析,速度更快
echo '這是單引號字串' . $str;
// ✅ 多參數 echo:避免字串串接記憶體分配
echo '這是單引號字串', $str;
// ❌ 多餘變數
function multiply($a, $b) {
$c = $a * $b;
return $c;
}
$result = multiply(10, 16);
echo $result;
// ✅ 直接回傳
function multiply($a, $b) {
return $a * $b;
}
echo multiply(10, 16);
// ❌ 多層 if-else:條件判斷由上而下,平均比較次數多
if ($a == 1) { /* ... */ }
elseif ($a == 2) { /* ... */ }
elseif ($a == 3) { /* ... */ }
// ...
// ✅ switch:跳躍表優化,O(1) 平均查找
switch ($a) {
case 1: /* ... */ break;
case 2: /* ... */ break;
case 3: /* ... */ break;
// ...
default: /* ... */
}
static 的方法盡量靜態化,呼叫速度提升 ~4 倍。echo 為語言結構,無回傳值,比 print 快。echo 'a', 'b', $var;,避免字串串接(點號)產生臨時字串。for ($i=0, $len=count($arr); $i<$len; $i++) 避免重複 count()。unset($largeArray) 釋放記憶體,尤其在迴圈中處理大量資料時。__get, __set, __autoload 有額外開銷,能用存取器/Composer 自動載入替代則替代。require 效能更好(架構上確保不重複載入即可)。require '/var/www/lib/config.php' 避免系統搜尋 include_path。time() 函式開銷。strpos, strstr, parse_url 解決的,不用 preg_match。strtr(4x str_replace),陣列替換用 str_replace,複雜模式才用 preg_replace。@ 會改變錯誤處理流程,極度低效,改用條件判斷或 error_reporting 控制。wait_timeout。$row['id'] 比 $row[id] 快 ~7 倍(後者會先嘗試常數查找並觸發 Notice)。display_errors,改記錄 log。$i++ ≈ 函式內局部變數速度。$GLOBALS['x']++ 比局部變數慢 ~2 倍。$this->prop++ 比局部變數慢 ~3 倍。$undefined++ 比預定義局部變數慢 9-10 倍(觸發 Notice + 查找符號表)。若需讀取大檔案(如 GB 級日誌),避免一次性 file_get_contents() 載入記憶體,改用:
fopen() + fgets() 逐行處理SplFileObject 物件導向介面yield 實現惰性讀取function readLargeFile($path) {
$fp = fopen($path, 'r');
while (($line = fgets($fp)) !== false) {
yield $line; // 惰性產出,記憶體常數級
}
fclose($fp);
}
foreach (readLargeFile('huge.log') as $line) {
// 處理單行
}
效能優化無銀彈,但「良好的編碼習慣」是低成本、高回報的投資。從微觀寫法開始,配合 Profiling 工具(Xdebug, Blackfire, Tideways)定位真正瓶頸,再針對性優化—— 這才是專業 PHP 開發者的成長之路。