標籤:action 系統 編譯 stat html 提示 視圖 back 上下
使用 ThinkPHP3.2.3 遇到一個奇怪的問題,正式環境上報錯,提示
“分頁錯誤!請稍後再試~”
為了查看到底出啥錯誤,哪裡出錯,於是在入口檔案中加了一段代碼,開啟調試:
defined(‘APP_DEBUG‘) or define(‘APP_DEBUG‘, true);
再運行程式,頁面又正常顯示,這就奇怪了!
翻了下 ThinkPHP 架構的原始碼,看了下其具體實現,得到如下幾點認識:
1、當 define(‘APP_DEBUG‘, false); 時,發生錯誤顯示效果如所示,只展示一句很籠統的提示:2、當 define(‘APP_DEBUG‘, true); 時,發生錯誤顯示效果如所示,會顯示出什麼錯?哪裡出錯?具體的上下文(TRACE)是什嗎?3、疑問(1):當我未開啟調試 define(‘APP_DEBUG‘, false); 時,如何顯示簡要的出錯資訊,而不是預設的籠統的資訊“分頁錯誤!請稍後再試~”呢?
先找到預設設定檔 ./ThinkPHP/Conf/convention.php,把 SHOW_ERROR_MSG 選項設定為 true,再運行一下頁面,顯示
模板不存在:/home/wwwroot/52php.com/jck/Economic/View/Index2/chargelogintype.html
好吧,至少讓我看到了問題的根本!
奇怪的是,頁面的 ACTION 是 chargeLoginType,咋就全部轉成小寫呢?如果轉成小寫,視圖檔案肯定是找不到了哦,因為 Linux 伺服器是區分檔案名稱大小寫。
找到視圖功能的檔案 ./ThinkPHP/Library/Think/View.class.php,裡面有段計算 視圖檔案路徑的代碼:
$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; 時,就會報錯,提示找不到視圖檔案
4、疑問(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 不會被系統篡改為小寫,保持原樣。
在計算 視圖檔案時,檔案名稱正確,檔案也存在,所以不報錯!
5、最後的建議:
(1) 正式環境 define(‘APP_DEBUG‘, false); 不然的話,系統會記錄大量的日誌資訊,好多不是自己想要記錄的。
小技巧:
在 入口檔案中,增加是否開啟 偵錯模式的開關變數,參考代碼如下:
if ((CUR_ENV != ‘production‘) || (isset($_GET[‘debug‘]) && ($_GET[‘debug‘] == ‘52php‘))) {define(‘APP_DEBUG‘, TRUE);}
(2) 找到設定檔 ./ThinkPHP/Conf/convention.php,配置如下:
‘URL_CASE_INSENSITIVE‘ => false, // 預設false 表示URL區分大小寫,true則表示不區分大小寫‘SHOW_ERROR_MSG‘ => true, // 顯示錯誤資訊
(3) 儘管在正式環境 沒有開啟 DEBUG 模式,但是因為開啟了 SHOW_ERROR_MSG = true,所有當有錯誤時,還是會顯示(簡要的)錯誤資訊,資訊當中可能會暴露 伺服器絕對路徑等敏感資訊,
模板不存在:/home/wwwroot/52php.com/jck/Economic/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‘]));
修複 ThinkPHP3.2.3 拋出異常模組的一個BUG