修復 ThinkPHP3.2.3 拋出異常模塊的一個BUG,關閉字段緩存功能

使用 ThinkPHP3.2.3 遇到一個奇怪的問題,正式環境上報錯,提示php

「頁面錯誤!請稍後再試~」html

爲了查看到底出啥錯誤,哪裏出錯,因而在入口文件中加了一段代碼,開啓調試:緩存

defined('APP_DEBUG') or define('APP_DEBUG', true); 

再運行程序,頁面又正常顯示,這就奇怪了!服務器

 

翻了下 ThinkPHP 框架的源代碼,看了下其具體實現,獲得以下幾點認識:框架

一、當 define('APP_DEBUG', false); 時,發生錯誤顯示效果以下圖所示,只展現一句很籠統的提示語:

二、當 define('APP_DEBUG', true); 時,發生錯誤顯示效果以下圖所示,會顯示出什麼錯?哪裏出錯?具體的上下文(TRACE)是什麼?

三、疑問(1):當我未開啓調試 define('APP_DEBUG', false); 時,如何顯示簡要的出錯信息,而不是默認的籠統的信息「頁面錯誤!請稍後再試~」呢?

先找到默認配置文件 ./ThinkPHP/Conf/convention.php,把 SHOW_ERROR_MSG 選項設置爲 true,再運行一下頁面,顯示函數

模板不存在:/home/jianbao/52php.com/Echo/View/Index2/chargelogintype.htmlthis

好吧,至少讓我看到了問題的根本!url

奇怪的是,頁面的 ACTION 是 chargeLoginType,咋就所有轉成小寫的呢?若是轉成小寫,視圖文件確定是找不到了哦,由於 Linux 服務器是區分文件名大小寫的。spa

找到視圖功能的文件 ./ThinkPHP/Library/Think/View.class.php,裏面有段計算 視圖文件路徑的代碼:debug

$templateFile = $this->parseTemplate($templateFile);

當沒有傳 視圖文件名時,取跟 ACTION_NAME 同名的視圖文件。

再找到路由分發功能的文件 ./ThinkPHP/Library/Think/Dispatcher.class.php,裏面有段計算 ACTION_NAME 的代碼:

$urlCase =  C('URL_CASE_INSENSITIVE');
define('ACTION_NAME', defined('BIND_ACTION') ? BIND_ACTION : self::getAction($varAction, $urlCase));

 也就是說,當你配置了 URL_CASE_INSENSITIVE = true; // 默認false 表示URL區分大小寫 true則表示不區分大小寫ACTION_NANE 會被強制轉爲小寫。

總結:

當未開啓調試 define('APP_DEBUG', false); 且 URL_CASE_INSENSITIVE = false; 時,就會報錯,提示找不到視圖文件

四、疑問(2):當我開啓調試 define('APP_DEBUG', true); 時,爲什麼頁面又正常了?

當爲調試模式,系統會加載配置文件 ./ThinkPHP/Conf/debug.php,內容以下:

// 調試模式下面默認設置 能夠在應用配置目錄下從新定義 debug.php 覆蓋
return  array(
    'LOG_RECORD'            =>  true,    // 進行日誌記錄
    'LOG_EXCEPTION_RECORD'  =>  true,    // 是否記錄異常信息日誌
    'LOG_LEVEL'             =>  'EMERG,ALERT,CRIT,ERR,WARN,NOTIC,INFO,DEBUG,SQL',  // 容許記錄的日誌級別
    'DB_FIELDS_CACHE'       =>  false,  // 字段緩存信息
    'DB_DEBUG'				=>  true,   // 開啓調試模式 記錄SQL日誌
    'TMPL_CACHE_ON'         =>  false,  // 是否開啓模板編譯緩存,設爲false則每次都會從新編譯
    'TMPL_STRIP_SPACE'      =>  false,  // 是否去除模板文件裏面的html空格與換行
    'SHOW_ERROR_MSG'        =>  true,   // 顯示錯誤信息
    'URL_CASE_INSENSITIVE'  =>  false,  // URL區分大小寫
);

看到沒,裏面有個 URL_CASE_INSENSITIVE = false,表示 URL區分大小寫,即 ACTION_NAME 不會被系統篡改成小寫,保持原樣。

在計算 視圖文件時,文件名正確,文件也存在,因此不報錯!

五、最後的建議:

(1) 正式環境 define('APP_DEBUG', false); 否則的話,會顯示詳細的TRACE信息,而且會記錄大量的日誌信息,好多不是想要記錄的。

小技巧:

在 入口文件中,增長是否開啓 調試模式的開關變量,參考代碼以下:

if ((CUR_ENV != 'production') || (isset($_GET['debug']) && ($_GET['debug'] == '52php'))) {
	define('APP_DEBUG', TRUE);
}

(2) 找到配置文件 ./ThinkPHP/Conf/convention.php,配置以下:

'LOG_RECORD' => false,              // 關閉日誌功能
'URL_CASE_INSENSITIVE'  =>  false,  // 默認false 表示URL區分大小寫,true則表示不區分大小寫
'SHOW_ERROR_MSG' => true,          // 顯示錯誤信息,
'DB_FIELDS_CACHE' => false,        // 關閉數據表字段緩存
'TMPL_CACHE_ON' => false,          // 關閉模板緩存

(3) 儘管在正式環境 沒有開啓 DEBUG 模式,可是由於開啓了 SHOW_ERROR_MSG = true,因此當有錯誤時,仍是會顯示(簡要的)錯誤信息,信息當中可能會暴露 服務器絕對路徑等敏感信息,

模板不存在:/home/jianbao/52php.com/Echo/View/Index2/chargelogintype.html

因此須要作些過濾操做,把絕對路徑去掉,展現爲相對路徑。

找到文件 ./ThinkPHP/Library/Think/Think.class.php,找到函數 static public function halt($error) {...},在如下代碼

// 包含異常頁面模板
$exceptionFile = C('TMPL_EXCEPTION_FILE', null, THINK_PATH . 'Tpl/think_exception.tpl' );

以前,增長代碼:

// 過濾掉 服務絕對路徑信息
isset($e['message']) && ($e['message'] = str_replace(ROOT_PATH, '', $e['message']));
相關文章
相關標籤/搜索