preg_replace 的 /e 修飾符 (PREG_REPLACE_EVAL) 自 PHP 5.5 棄用,7.0 移除。它將替換字串視為 PHP 代碼執行,極易導致注入漏洞且難以除錯。現代專案必須遷移至 preg_replace_callback。
/e',
"\$this->ifTag('\\1')", $template);
// 新寫法 (安全、標準)
$template = preg_replace_callback('//',
[$this, 'ifTag'], $template);
?>
mixed preg_replace_callback(
mixed $pattern,
callable $callback,
mixed $subject,
int $limit = -1,
int &$count = null
)
$callback 接收 array $matches 參數:$matches[0] 完整匹配,$matches[1] 第一個捕獲組...
yyyzzz'; // /e 模式輸出 // xxxyyyzzz // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 雙引號被加上反斜線,導致語法錯誤 ?>
/',
[$this, 'ifTag'],
$template
);
}
protected function ifTag(array $matches): string {
// $matches[1] 直接是原始字串,無任何轉義問題
return '';
}
}
$tpl = new Template();
echo $tpl->compile($template);
// 輸出:xxxyyyzzz
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 完美保留原始引號
?>
pattern, [$this, 'replace'], $text);
// PHP 5.3+ 風格 (推薦)
// return preg_replace_callback($this->pattern, 'self::replace', $text);
}
protected function replace(array $m): string {
return method_exists($this, $m[1]) ? $this->{$m[1]}($m[2]) : '';
}
}
?>
/',
'//',
'//',
];
$callbacks = [
fn($m) => '',
fn($m) => '',
fn($m) => '',
];
$compiled = $template;
foreach ($patterns as $i => $p) {
$compiled = preg_replace_callback($p, $callbacks[$i], $compiled);
}
?>
$this->pattern = '/.../'; 避免重複編譯$limit 防止失控&$count 監控處理量null → 該匹配處變空字串s (DOTALL) 修飾符 → 跨行匹配失效$matches[0] 是整個匹配,非第一組preg_replace_callback 串聯,而非單一巨大正則preg_replace_callback 是現代 PHP 正則替換的標準作法:關注點分離(模式與邏輯分離)、型別安全(回傳字串而非執行代碼)、除錯友善(可在回調打斷點)。所有舊專案的 /e 用法務必優先重構。