发现了一个在ThinkPHP6路由使用上的坑,而且还是觉得像之前ThinkPHP3那种解析对应的控制器方法的好…
好了,言归正传,说一下到底是什么坑
首先我们安装一个新的Thinkphp代码来测试
composer create-project topthink/think tp
然后我们来定义两个路由
Route::get('user/:id', 'Index/read');
Route::get('user/resetPwd', 'Index/resetPwd');
在Index
控制器中写入以下两个方法
public function read($id)
{
return sprintf('%s %s', __METHOD__, $id);
}
public function resetPwd()
{
$id = request()->get('id', 666);
return sprintf('%s %s', __METHOD__, $id);
}
先猜一下,当我们请求http://127.0.0.1:8000/user/1
和http://127.0.0.1:8000/user/resetPwd?id=1
时会输出什么结果?
是不是app\controller\Index::read 1
和app\controller\Index::resetPwd 1
呢?
答案是不。
进入到tp目录,执行php think run
运行起来看一下
会发现结果是:app\controller\Index::read 1
和app\controller\Index::read resetPwd
咦,为什么呢?我们路由不是定义的是resetPwd
方法吗?为什么还走到了read
方法中呢?
这个坑就是ThinkPHP中的变量规则,系统默认的变量规则设置是[\w\.]+
,只会匹配字母、数字、中文和下划线字符
当我们请求/user/resetPwd?id=1
就会匹配到所定义的user/:id
,也就说把/resetPwd?id=1
这一串当成了/:id
匹配
那么如何解决这个问题呢?有两种解决方案。
1. 可以调整优先级,将user/resetPwd
放到前面去
Route::get('user/resetPwd', 'Index/resetPwd');
Route::get('user/:id', 'Index/read');
2. 增加局部变量规则
我们可以给user/:id
增加变量规则,限制它只能为数字
Route::get('user/:id', 'Index/read')
->pattern(['id' => '\d+']);
这时候再去请求的话,就会输出我们想要的结果了
app\controller\Index::read 1
和app\controller\Index::resetPwd 1
还好,坑不大,去年还是前年,我被那个多对多关联的坑,坑的不轻~