tp6 路由bug

浏览:1726 发布日期:2019/07/05 分类:ThinkPHP6专区 关键字: tp6 bug反馈
以下问题在多级控制器时会发生

现在我有一个控制器,其目录为app\controller\v1\File,其命名空间为
namespace app\controller\v1;
该控制器有一个test方法public function test()
    {
        echo 1;
    }
定义路由为Route::rule('file','v1.File/test');正常情况下访问www.servername.com/file 页面上会输出一个 1,而实际上我得到一个报错:[0] HttpException in Controller.php line 69
控制器不存在:app\controller\V1\File
注意看这里的报错V1是大写的V,而我定义的路由v1为小写的v ,经翻看源码(命名空间为 think\route\dispatch的类Controller    public function init(App $app)
    {
        parent::init($app);

        $result = $this->dispatch;

        if (is_string($result)) {
            $result = explode('/', $result);
        }

        // 获取控制器名
        $controller = strip_tags($result[0] ?: $this->rule->config('default_controller'));

        $this->controller = App::parseName($controller, 1);
        
        // 获取操作名
        $this->actionName = strip_tags($result[1] ?: $this->rule->config('default_action'));
        // 设置当前请求的控制器、操作
        $this->request
            ->setController($this->controller)
            ->setAction($this->actionName);
    }
发现在第54行调用的App::parseName($controller, 1)执行过程中使用ucfirst将v1的首字母强制转换为了大写而导致了访问时的bug /**
     * 字符串命名风格转换
     * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
     * @access public
     * @param string  $name    字符串
     * @param integer $type    转换类型
     * @param bool    $ucfirst 首字母是否大写(驼峰规则)
     * @return string
     */
    public static function parseName(string $name = null, int $type = 0, bool $ucfirst = true): string
    {
        if ($type) {
            $name = preg_replace_callback('/_([a-zA-Z])/', function ($match) {
                return strtoupper($match[1]);
            }, $name);
            return $ucfirst ? ucfirst($name) : lcfirst($name);
        }

        return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
    }
测试中源码断点  public function init(App $app)
    {
        parent::init($app);

        $result = $this->dispatch;

        if (is_string($result)) {
            $result = explode('/', $result);
        }

        // 获取控制器名
        $controller = strip_tags($result[0] ?: $this->rule->config('default_controller'));

        $this->controller = App::parseName($controller, 1);
        // 断点输出检测
        halt($controller,$this->controller);
        // 获取操作名
        $this->actionName = strip_tags($result[1] ?: $this->rule->config('default_action'));
        // 设置当前请求的控制器、操作
        $this->request
            ->setController($this->controller)
            ->setAction($this->actionName);
    }
断点输出"v1.File"
"V1.File"
问题修复方案
在这个问题中,可以将Controller中的代码修改为 public function init(App $app)
    {
        parent::init($app);

        $result = $this->dispatch;

        if (is_string($result)) {
            $result = explode('/', $result);
        }

        // 获取控制器名
        $controller = strip_tags($result[0] ?: $this->rule->config('default_controller'));
        // 原代码
        //$this->controller = App::parseName($controller, 1);
        
        // 修复1:
        $this->controller = App::parseName($controller, 1,false);
        // 修复2:
        $this->controller = $controller;
        
        // 获取操作名
        $this->actionName = strip_tags($result[1] ?: $this->rule->config('default_action'));
        // 设置当前请求的控制器、操作
        $this->request
            ->setController($this->controller)
            ->setAction($this->actionName);
    }
来修复这个问题,使得路由正常访问 。具体修复方式@thinkphp
最佳答案
评论( 相关
后面还有条评论,点击查看>>