修复 ThinkPHP3.2.3 抛出异常模块的一个BUG,关闭字段缓存功能
2016-12-04 12:07
591 查看
使用 ThinkPHP3.2.3 遇到一个奇怪的问题,正式环境上报错,提示
“页面错误!请稍后再试~”
为了查看到底出啥错误,哪里出错,于是在入口文件中加了一段代码,开启调试:
再运行程序,页面又正常显示,这就奇怪了!
翻了下 ThinkPHP 框架的源代码,看了下其具体实现,得到如下几点认识:
模板不存在:/home/jianbao/52php.com/Echo/View/Index2/chargelogintype.html
好吧,至少让我看到了问题的根本!
奇怪的是,页面的 ACTION 是 chargeLoginType,咋就全部转成小写的呢?如果转成小写,视图文件肯定是找不到了哦,因为 Linux 服务器是区分文件名大小写的。
找到视图功能的文件 ./ThinkPHP/Library/Think/View.class.php,里面有段计算 视图文件路径的代码:
当没有传 视图文件名时,取跟 ACTION_NAME 同名的视图文件。
再找到路由分发功能的文件 ./ThinkPHP/Library/Think/Dispatcher.class.php,里面有段计算 ACTION_NAME 的代码:
也就是说,当你配置了 URL_CASE_INSENSITIVE = true; // 默认false 表示URL区分大小写 true则表示不区分大小写,ACTION_NANE 会被强制转为小写。
总结:
当未开启调试 define('APP_DEBUG', false); 且 URL_CASE_INSENSITIVE = false; 时,就会报错,提示找不到视图文件
看到没,里面有个 URL_CASE_INSENSITIVE = false,表示 URL区分大小写,即 ACTION_NAME 不会被系统篡改为小写,保持原样。
在计算 视图文件时,文件名正确,文件也存在,所以不报错!
小技巧:
在 入口文件中,增加是否开启 调试模式的开关变量,参考代码如下:
(2) 找到配置文件 ./ThinkPHP/Conf/convention.php,配置如下:
(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) {...},在以下代码
之前,增加代码:
“页面错误!请稍后再试~”
为了查看到底出啥错误,哪里出错,于是在入口文件中加了一段代码,开启调试:
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/jianbao/52php.com/Echo/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); 不然的话,会显示详细的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']));
相关文章推荐
- 解决ThinkPHP3.2.3框架,PDO驱动类“抛出异常”不起作用的bug
- Thinkphp 开启字段缓存后,生成字段缓存文件bug修改
- 关于UDP消息服务抛出“远程主机强迫关闭了一个现有的连接”的异常说明及处理方法
- DC.Web.HttpCompress (采用原作者最新版,修复2处Bug,增加缓存功能)
- erlang关闭一个socket进入死循环的bug修复过程
- 1 开发一个注重性能的JDBC应用程序不是一件容易的事. 当你的代码运行很慢的时候JDBC驱动程序并不会抛出异常告诉你。 本系列的性能提示将为改善JDBC应用程序的性能介绍一些基本的指导原则,这其中的原则已经被许多现有的JDBC应用程序编译运行并验证过。 这些指导原则包括: 正确的使用数据库MetaData方法 只获取需要的数据 选用最佳性能的功能 管理连
- thinkphp 3.2.3 在项目中需要做的一个发送邮件的功能
- 一个很深的bug - 句柄被异常关闭
- DC.Web.HttpCompress 压缩模块发布(采用原作者最新版,修复2处Bug,增加缓存功能)!
- 关于UDP消息服务抛出“远程主机强迫关闭了一个现有的连接”的异常说明及处理方法
- 解决ThinkPHP3.2.3框架,PDO驱动查询出来的字段名全是小写的bug
- DC.Web.HttpCompress 压缩模块发布(采用原作者最新版,修复2处Bug,增加缓存功能)!(更新源码)
- ThinkPHP 3.2.3+ORACLE插入数据BUG修复及支持获取自增Id的上次记录
- (原)CfileDialog 为何抛出异常,其实这是mfc 的一个bug
- uubox.net 网站的第二阶段完成,修复了部分的bug,增加了图片浏览和mp3在线播放等功能
- 一个模块如何处理异常
- hibernate3.2.6终于修复一个bug
- msn上的tab功能Firefox对childNodes处理的一个BUG
- 一个小型即时通讯项目的开发经验3--模块设计与功能分配
- 为Unreal添加一个定时运行的功能模块