ECSHOP 2.x/3.x 核心模板引擎大量使用 preg_replace('/pattern/e', 'code', $str) 的 /e 修飾符,PHP 5.5 棄用、7.0 移除,導致直接報錯 Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead。本文提供最小侵入性修復方案,保持原有模板語法行為不變。
檔案:includes/cls_template.php,方法 fetch() 中:
// 原始碼 (約第 300 行)
return preg_replace("/\{([^\}\{\n]*)\}/e", "\$this->select('\\1');", $source);
/e 使替換字串作為 PHP 代碼執行,\\1 為捕獲組內容,直接呼叫 $this->select()。
// 替換為:
return preg_replace_callback(
"/\{([^\}\{\n]*)\}/",
function ($matches) {
return $this->select($matches[1]);
},
$source
);
關鍵點:
e。$matches 陣列,$matches[1] 對應第一個捕獲組。$this 在 Closure 中自動綁定 (PHP 5.4+),無需 use ($this)。includes/cls_template.php。preg_replace (約 3-4 處)。preg_replace_callback 寫法:// 1. 主模板標籤解析 (最關鍵)
return preg_replace_callback(
"/\{([^\}\{\n]*)\}/",
function ($m) { return $this->select($m[1]); },
$source
);
// 2. 如果有其他 /e 用法 (如庫存、價格格式化),同理修改
// 例:
// preg_replace("/\[amount\](.*)\[\/amount\]/e", "format_price('\\1')", $str)
// →
// preg_replace_callback("/\[amount\](.*)\[\/amount\]/", fn($m) => format_price($m[1]), $str)
temp/caches/ 下所有快取檔。若專案多處使用 /e,可在 includes/lib_base.php 或獨立檔案定義:
if (!function_exists('preg_replace_e')) {
function preg_replace_e($pattern, $callback, $subject, $limit = -1, &$count = null) {
return preg_replace_callback($pattern, $callback, $subject, $limit, $count);
}
}
// 使用:preg_replace_e("/\{([^\}]+)\}/", fn($m) => $this->select($m[1]), $source);
| PHP 版本 | /e 修飾符 | preg_replace_callback | 建議 |
|---|---|---|---|
| 5.3 - 5.4 | 支援 | 支援 | 可不改,但建議統一遷移 |
| 5.5 - 5.6 | Deprecated 警告 | 支援 | **必須修復** |
| 7.0 - 7.4 | **已移除**,致命錯誤 | 支援 | **必須修復** |
| 8.0+ | 不支援 | 支援 (支援箭頭函數 fn) | **必須修復** |
mysql_* 函數 → 改用 mysqli_* 或 PDO (ECSHOP 3.6+ 已內建 cls_mysql.php 兼容層)。create_function() → 改用匿名函數 fn() 或 function()。each()、split() 等棄用函數 → 現代替代寫法。public $var; 或 #[AllowDynamicProperties]。