joomla3 com_jce 從 PHP7升級到PHP8 遇到錯誤
在 joomla3\libraries\legacy\exception\exception.php
####################################################################################
class JException extends Exception
{
/**
* Error level.
*
* @var string
* @since 1.5
* @deprecated 1.7
*/
protected $level = null;
/**
* Error code.
*
* @var string
* @since 1.5
* @deprecated 1.7
*/
protected $code = null;
/**
* Error message.
*
* @var string
* @since 1.5
* @deprecated 1.7
*/
protected $message = null;
/**
* Additional info about the error relevant to the developer,
* for example, if a database connect fails, the dsn used
*
* @var string
* @since 1.5
* @deprecated 1.7
*/
protected $info = '';
/**
* Name of the file the error occurred in [Available if backtrace is enabled]
*
* @var string
* @since 1.5
* @deprecated 1.7
*/
protected $file = null;
/**
* Line number the error occurred in [Available if backtrace is enabled]
*
* @var integer
* @since 1.5
* @deprecated 1.7
*/
protected $line = 0;
/**
* Name of the method the error occurred in [Available if backtrace is enabled]
*
* @var string
* @since 1.5
* @deprecated 1.7
*/
protected $function = null;
/**
* Name of the class the error occurred in [Available if backtrace is enabled]
*
* @var string
* @since 1.5
* @deprecated 1.7
*/
protected $class = null;
/**
* @var string Error type.
* @since 1.5
* @deprecated 1.7
*/
protected $type = null;
/**
* Arguments received by the method the error occurred in [Available if backtrace is enabled]
*
* @var array
* @since 1.5
* @deprecated 1.7
*/
protected $args = array();
/**
* Backtrace information.
*
* @var mixed
* @since 1.5
* @deprecated 1.7
*/
protected $backtrace = null;
/**
* Container holding the error messages
*
* @var string[]
* @since 1.6
* @deprecated 1.7
*/
protected $_errors = array();
/**
* Constructor
* - used to set up the error with all needed error details.
*
* @param string $msg The error message
* @param integer $code The error code from the application
* @param integer $level The error level (use the PHP constants E_ALL, E_NOTICE etc.).
* @param string $info Optional: The additional error information.
* @param boolean $backtrace True if backtrace information is to be collected
*
* @since 1.5
* @deprecated 1.7
*/
public function __construct($msg, $code = 0, $level = null, $info = null, $backtrace = false)
這是不是有問題
####################################################################################
![]()
你完全抓到了重點!這段代碼就是 Joomla 3 在 PHP 8 環境下發生「靜默崩潰」的核彈級核心原因。
這不是簡單的語法錯誤,而是 PHP 8 嚴格禁止了「子類別重寫父類別屬性」的類型與可見性規則,特別是當父類別是 PHP 內建的 Exception 時。
1. 致命原因:屬性衝突 (Property Shadowing)
在 PHP 中,內建的 Exception 類別已經定義了以下屬性:
- protected $message
- protected $code
- protected $file
- protected $line
問題出在哪? 在 PHP 7 以前,子類別重新宣告這些屬性(如你提供的代碼)通常只會被視為覆蓋。但在 PHP 8 中,Exception 的某些內建屬性被加上了更嚴格的類型限制或內部鎖定。
當 JException 試圖宣告自己的 protected $message = null; 時,如果這與 PHP 8 內建 Exception 的預期不符(例如內建的可能是 string),程式會直接拋出 Fatal Error。
2. 為什麼「一呼叫就死掉」且「沒有訊息」?
這是一個極度尷尬的死循環:
- 程式發生錯誤,準備呼叫 JError::raiseWarning。
- JError 內部試圖 new JException。
- 當 PHP 嘗試加載 JException 類別定義時,發現屬性宣告不合法(與內建 Exception 衝突)。
- 發生 Fatal Error。
- PHP 試圖處理這個 Fatal Error,結果又想呼叫錯誤處理器...
- 最終結果:PHP 引擎為了防止無限遞迴,直接強制中止(Aborted),這就是為什麼你看到白畫面且沒有任何 Log。
3. 如何修正?
如果你必須讓這段舊代碼在 PHP 8 跑起來,你有兩個方向:
方案 A:刪除衝突的屬性宣告(最快)
在 libraries/joomla/error/exception.php 中,將那些與父類別 Exception 重複的屬性註解掉或刪除。
class JException extends Exception
{
// 註解掉這些,讓它們直接使用父類別 Exception 的屬性
// protected $message = null;
// protected $code = null;
// protected $file = null;
// protected $line = null;
// 保留 JException 特有的屬性
protected $level = null;
protected $info = '';
// ... 其他特有屬性
}
方案 B:修正建構子 (Constructor)
PHP 8 要求子類別的建構子參數必須與父類別相容,或者至少能正確傳遞。請確保 parent::__construct 被正確呼叫:
public function __construct($msg, $code = 0, $level = null, $info = null, $backtrace = false)
{
$this->level = $level;
$this->info = $info;
// 呼叫父類別 Exception 的建構子
parent::__construct($msg, (int) $code);
}
4. 總結:這是 Joomla 3 的時代眼淚
這段代碼打從 Joomla 1.7 就被標記為 @deprecated(廢棄),但直到 PHP 7 大家都還能相安無事。PHP 8 的「強制轉型」和「屬性一致性檢查」讓這些陳年舊帳一次爆發。
目前的診斷: 你的 JError 崩潰就是因為 JException 類別定義在 PHP 8 下是非法的。
建議下一步: 去 libraries/joomla/error/exception.php 把那幾個重複的屬性(message, code, file, line)刪掉。 刪掉後,原本「無聲無息」的白畫面,應該就會噴出真正的錯誤訊息了!
####################################################################################
![]()
就是說 PHP7 允許你覆蓋父類 protected 屬性
又或者說重新宣告
但是PHP8不行
然後又因為錯誤類別
所以這個錯誤 “吐不出來”

無言![]()

留言板
歡迎留下建議與分享!希望一起交流!感恩!