最近在做php,发现添加了自定义404页面模板后没反应,仍然使用默认异常模板,查了一下源码才知道问题所在,都是自己惯性思维惹的祸。
文档说明:
异常处理 · ThinkPHP5.1完全开发手册 · 看云 (kancloud.cn)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| if (!function_exists('abort')) {
function abort($code, $message = null, $header = []) { if ($code instanceof Response) { throw new HttpResponseException($code); } else { throw new HttpException($code, $message, null, $header); } } }
|
调用thinkphp
的abort
函数可以方便地创建HTTP异常,从这里入手,看一下thinkphp
是怎么处理http异常的。
这里通过$code
区分了一下,相当于是实现了函数重载,$code
参数是404,走HttpException
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class HttpException extends \RuntimeException { private $statusCode; private $headers;
public function __construct($statusCode, $message = null, \Exception $previous = null, array $headers = [], $code = 0) { $this->statusCode = $statusCode; $this->headers = $headers;
parent::__construct($message, $code, $previous); } }
|
初始化之后,会自动被think\exception\Handle
处理,调用内部render
方法,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| <?php namespace think\exception;
class Handle {
public function render(Exception $e) { if ($this->render && $this->render instanceof \Closure) { $result = call_user_func_array($this->render, [$e]); if ($result) { return $result; } }
if ($e instanceof HttpException) { return $this->renderHttpException($e); } else { return $this->convertExceptionToResponse($e); } }
protected function renderHttpException(HttpException $e) { $status = $e->getStatusCode(); $template = Config::get('http_exception_template'); if (!App::$debug && !empty($template[$status])) { return Response::create($template[$status], 'view', $status)->assign(['e' => $e]); } else { return $this->convertExceptionToResponse($e); } }
}
|
此时通过异常类型的判断,继续走renderHttpException
,这个方法已经能够说明问题了,如果当前不是debug模式并且能够匹配到有对应模板,则会去找对应模板输出。显然我这里是走了else了,输出App::$debug
值为'1'
,但是我明明设置了$debug=false
。继续查看$debug
来源,发现初始化$debug
是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?php class App { public static function initCommon() { $config = self::init(); self::$suffix = $config['class_suffix'];
self::$debug = Env::get('app_debug', Config::get('app_debug')); } }
|
先读取env
,再读取config.php
,哦原来是我config.php
写死之后,.env
文件没有删掉。
在thinkphp
官方文档其实有写:
环境变量中设置的APP_DEBUG
和APP_TRACE
参数会自动生效(优先于应用的配置文件),其它参数则必须通过Env::get
方法才能读取。