top-think / framework

ThinkPHP Framework
http://www.thinkphp.cn
Other
2.71k stars 1.05k forks source link

异常处理需要进一步优化 #3028

Closed ichynul closed 3 weeks ago

ichynul commented 1 month ago

所属功能组件

异常(Exception)

ThinkPHP 版本

6.1

操作系统

linux

错误信息

原因,tp6以后session驱动只支持[file/cache]两种类型了。 问题就出在这里,如果你填了这两个个之外的值,比如填个redis,那么框架又是白屏+无日志。 错误日志:

InvalidArgumentException: Driver [File1] not supported. in D:\doc\php\tpextdev\myadmin6\vendor\topthink\framework\src\think\Manager.php:104 Stack trace: 
#0 D:\doc\php\tpextdev\myadmin6\vendor\topthink\framework\src\think\Manager.php(137): think\Manager->resolveClass() 
#1 D:\doc\php\tpextdev\myadmin6\vendor\topthink\framework\src\think\Session.php(34): think\Manager->createDriver() 
#2 D:\doc\php\tpextdev\myadmin6\vendor\topthink\framework\src\think\Manager.php(66): think\Session->createDriver() 
#3 D:\doc\php\tpextdev\myadmin6\vendor\topthink\framework\src\think\Manager.php(56): think\Manager->getDriver() 
#4 D:\doc\php\tpextdev\myadmin6\vendor\topthink\framework\src\think\Manager.php(175): think\Manager->driver() 
#5 D:\doc\php\tpextdev\myadmin6\vendor\topthink\framework\src\think\exception\Handle.php(178): think\Manager->__call() 
#6 D:\doc\php\tpextdev\myadmin6\vendor\topthink\framework\src\think\exception\Handle.php(222): think\exception\Handle->convertExceptionToArray() 
#7 D:\doc\php\tpextdev\myadmin6\vendor\topthink\framework\src\think\exception\Handle.php(206): think\exception\Handle->renderExceptionContent() 
#8 D:\doc\php\tpextdev\myadmin6\vendor\topthink\framework\src\think\exception\Handle.php(111): think\exception\Handle->convertExceptionToResponse() 
#9 D:\doc\php\tpextdev\myadmin6\vendor\topthink\framework\src\think\Middleware.php(185): think\exception\Handle->render() 
#10 [internal function]: think\Middleware->handleException() 
#11 D:\doc\php\tpextdev\myadmin6\vendor\topthink\framework\src\think\Pipeline.php(102): call_user_func() 
#12 D:\doc\php\tpextdev\myadmin6\vendor\topthink\framework\src\think\Pipeline.php(87): think\Pipeline->handleException() 
#13 D:\doc\php\tpextdev\myadmin6\vendor\topthink\framework\src\think\Pipeline.php(66): think\Pipeline->think\{closure}() 
#14 D:\doc\php\tpextdev\myadmin6\vendor\topthink\framework\src\think\Http.php(217): think\Pipeline->then() 
#15 D:\doc\php\tpextdev\myadmin6\vendor\topthink\framework\src\think\Http.php(176): think\Http->runWithRequest() 
#16 D:\doc\php\tpextdev\myadmin6\public\index.php(20): think\Http->run() 
#17 {main}

原因分析: Session初始化驱动时调用Manager创建Driver 但填的类型找不到类,抛出异常。 进入ErrorHandle渲染错误页面。 错误信息收集session信息,又触发了session驱动调用

protected function convertExceptionToArray(Throwable $exception): array
{
      //...................
      'Session'   => $this->app->exists('session') ? $this->app->session->all() : [],
      //...................
}

直接抛出异常导致白屏。 也就是说渲染异常的时候又出现异常了。

处理方案: 修改:think\Session


 protected function createDriver(string $name)
   {
        if (!in_array(strtolower($name), ['cache', 'file'])) {
            // $name = 'file'; 驱动不对,强制设为file,或者下面抛出异常
            $this->app->delete('session');//删除Session,使异常处理时 $this->app->exists('session') 为假。
            throw new \InvalidArgumentException("Driver [$name] not supported.");
        }
        $handler = parent::createDriver($name);

        return new Store($this->getConfig('name') ?: 'PHPSESSID', $handler, $this->getConfig('serialize'));
   }

其它说明

为什么我遇到这个问题,因为程序是买来的,它的session配置可能是复制了tp5的 //驱动方式 支持redis memcache memcached

我以前说的一个问题,还打算修复吗?我就奇怪是不是只有我一个人会遇到这些蛋疼问题??每次遇到都是花费半天时间去修改框架源码调试出来。 (#2999)

ichynul commented 1 month ago

经过观察如果think\Session::createDriver()里面抛异常,think\initializer\Error::appException()调用http->end()调用think\middleware\SessionInit::end();又会触发报错。 然后走到框架的http->end()又重复一次。 一个页面渲染了多次错误。 检测驱动类型不是那两种就强制为file,这中方案简单有效些。

liu21st commented 3 weeks ago

初始化阶段的异常改成采用内置的异常处理机制了