使用场景
tp6连接除database.php配置外的数据库(临时数据库等)
使用方式
1 | //use think\facade\Config; |
tp6连接除database.php配置外的数据库(临时数据库等)
1 | //use think\facade\Config; |
get()/all()
方法find()/select()
来作为替换get()
参数使用的不是主键,则需配合where()->find()
使用think\Db | think\Session
等需要使用门面
think\facade\Session
等,具体可查看此处init()
方法的模型事件self::beforeInsert(function ($obj) { })
等无法使用public static function onBeforeInsert($obj) {}
$this->redirect('/path'); return true;
无法使用return redirect('/path');
Session
需设置为中间件使用ROOT_PATH | TEMP_PATH | DS
等全局变量不可使用app()->getRootPath() | app()->getRuntimePath()
等validate
方法不可用$this->validate()
或validate()->check($file)
原项目使用tp5多应用模式,未使用强制路由,且url参数是按照顺序解析url_param_type = 1
想尝试能不能从tp5升级到tp6,虽然有官方升级文档,但tp6的url参数方式只能按照名称成对解析,无法满足需求,于是看了下源码看看能不能处理
顺序参数模式(config.php
文件中设置'url_param_type' => 1
)
文件路径:application/index/controller/TestController.php
1 | public function test($a = '', $b = '') |
执行curl http://localhost/index/test/test/111/222
输出
1 | 参数a:111 |
同样代码输出
1 | 参数a:222 |
推荐方式:curl http://localhost/index/test/test/a/111/b/222
或者其实:curl http://localhost/index/test/test/fff/111/fff/222
也行,具体可以打印request()->param()
看看就知道了
think\route\dispatch\Url->parseUrl(string $url): array
更改parseUrl
方法可以处理,但对框架有影响,所以建议从项目内部替换Url类
可以直接引入我写的包
composer require aichenk/tp6-route-param
在config/route.php
中添加参数'url_param_type' => 1
即可(0即为关闭)
tp6输出
1 | 参数a:111 |
使用php自带的ZipArchive来解压带中文文件名压缩包时会造成乱码,现象如下:
1 | $zip = new \ZipArchive(); |
默认windows,mac打压缩包时编码为简体中文,解压时未作文件转化导致解压结果与预期不符
打开压缩包后先将内部文件名及目录进行转码,转码后需关闭压缩包并重新打开解压
实现如下:
1 | $zipName = './钱学森班.zip'; |
tp6是一个封装度很高的框架,在大部分场景下都能做到开箱即用
本次遇到情况为,当请求消息体为索引数组时,路由参数无法正常获取
路由定义
1 | Route::post('test/:a/:b', 'index/test'); |
Index控制器输出参数
1 | public function test($a, $b) |
启动服务php think run -p 8080
请求测试,如下我们得到了我们所需要的结果
1 | ➜ ~ curl -X POST http://localhost:8080/test/1/2 |
将IndexController->test
中$a, $b
参数调换位置(路由不变)
1 | public function test($b, $a) |
重新请求,得到的结果依然不变
1 | ➜ ~ curl -X POST http://localhost:8080/test/1/2 |
那么我们是否可以得到结论:tp6控制器参数会根据路由参数名自动匹配?
看以上结果好像是没问题,但是有个大坑!
路由,控制器输出方法都不变,仅增加requestBody
,得到如下结果
1 | ➜ ~ curl -X POST -H "content-type:application/json" -d "[3, 4]" http://localhost:8080/test/1/2 |
说好的路由匹配呢!
在方法中打印出request->param()
可查看到刚才的请求最终得到的参数
1 | array:4 [ |
可以看到消息体中参数是索引数组部分,而路由参数a,b为关联数组部分
tp在最终匹配action参数的时候,按照先分配索引,再分配关联的顺序进行了参数传入,导致没有得到我们想要的效果
若消息体内增加键值,我们重新尝试,如下依然是我们想要的结果
1 | ➜ ~ curl -X POST -H "content-type:application/json" -d "{\"a\":3}" http://localhost:8080/test/1/2 |
所以大概得到结论:param()参数的来源为先获取query、body等参数,再覆盖上路由参数
既然已经知道原因,那么解决方案就比较好处理了
更改消息体,避免直接使用索引数组传递,如
1 | ➜ ~ curl -X POST -H "content-type:application/json" -d "{\"data\":[3, 4]}" http://localhost:8080/test/1/2 |
我们在方法内根据键值data即可获取想要的数据
不需要更改结构体,但action参数不通过传入参数获取,由内部自己获取
1 | // action代码如下 |
使用原消息体测试
1 | ➜ ~ curl -X POST -H "content-type:application/json" -d "[3, 4]" http://localhost:8080/test/1/2 |
根据结果,不能说这是tp的BUG,可以说这次问题是不熟悉导致,但也算是一个坑吧,在遇到这种情况下确实容易摸不着头脑
大家项目内使用时多多注意即可~