• 修复 ThinkPHP3.2.3 抛出异常模块的一个BUG,关闭字段缓存功能


    使用 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/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']));
    
  • 相关阅读:
    HCIA_R&S-学习_Day05(PPPoE、DHCP、ACL、NAT)
    HCIA_R&S-学习_Day04(链路状态协议OSPF & PPP)
    HCIA_R&S-学习_Day03(路由协议基础与实现)
    【详谈 Delta Lake 】系列技术专题 之 湖仓一体( Lakehouse )
    工作7年,我的10条经验总结
    Hologres揭秘:优化COPY,批量导入性能提升5倍+
    谈谈JVM内部锁升级过程
    如何帮用户管好云账本?阿里云数据库助力收钱吧 | 甲子光年
    重磅 | 数据库自治服务DAS论文入选全球顶会SIGMOD,领航“数据库自动驾驶”新时代
    同程旅行基于 RocketMQ 高可用架构实践
  • 原文地址:https://www.cnblogs.com/52php/p/6128997.html
Copyright © 2020-2023  润新知