现在我有一个控制器,其目录为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 最佳答案