
别慌,这篇文章就是你的“Request对象实用手册”。我们把ThinkPHP5中Request请求对象的常用方法全收录——从基础的GET/POST参数获取、Header信息读取,到请求类型(AJAX/POST/GET)判断、IP地址获取,再到文件上传的完整流程;更贴心加了实战避坑技巧:比如如何安全过滤参数防止注入、多端请求的兼容性处理、大文件上传的优化方法。
不管你是刚入门的新手(怕记不住方法),还是熟手(想提升效率),这篇“大全”都能帮你把Request的知识点串成体系。不用再零散查文档,遇到请求问题直接翻,省时间更省心。赶紧往下看,把这些实用技巧收进你的开发工具箱!
做ThinkPHP5开发的你,是不是常遇到这些麻烦?想拿POST参数,记混了post()
和input()
;判断AJAX请求,写了isAjax()
又怕不兼容;处理文件上传,明明传了文件却拿不到参数?我之前做过3个TP5项目,光请求处理就踩了不下10个坑,后来把Request对象的常用方法和避坑技巧整理成了这套“速查表”,今天分享给你,看完至少省你半天查文档的时间。
Request对象最常用的10个方法,帮你解决80%的请求问题
先抛个 TP5的Request对象里,80%的需求都能用10个方法解决——我去年帮朋友做电商系统时,把这些方法贴在桌面,3个月没再查过文档。接下来一个个说,每个都结合我踩过的坑。
第一个必须说param()
方法。你是不是也试过,用get('id')
拿URL里的id,用post('name')
拿表单里的name,结果遇到路由传参(比如/user/:id
)就蒙了?我之前做用户详情页时,就是因为用get('id')
没拿到路由参数,导致页面报错。后来查官方文档才知道(https://www.thinkphp.cn/doc/nofollow),param()
会自动合并GET、POST、路由参数,而且会自动过滤非法字符(比如标签),比单独用
get()
或post()
安全多了。比如你要拿用户ID,直接写$id = request()->param('id');
,不管参数是从URL来的还是表单来的,都能拿到,省得你一个个判断。
第二个常用方法是isPost()
和isAjax()
。做登录功能时,你肯定要判断是不是POST请求吧?isPost()
就是干这个的,但要注意:它只判断请求的方法类型,不判断内容类型——比如如果前端用POST传了JSON数据,isPost()
还是会返回true,但post()
方法拿不到参数(因为JSON数据要用水input('put')
或者raw()
)。我之前做API接口时就踩过这坑:前端用POST传JSON,我用isPost()
判断后用post()
拿参数,结果啥也没拿到,后来换成param()
才解决。再说说isAjax()
,它是判断是不是AJAX请求,但有些手机浏览器的AJAX请求没带X-Requested-With: XMLHttpRequest
头,这时候isAjax()
会返回false。我做点赞功能时就遇到过:安卓端的WebView发的AJAX没带这个头,导致点赞失败,后来改成if (request()->isAjax() || request()->header('X-Requested-With') == 'XMLHttpRequest')
,才算兼容了所有情况——这是TP5官方文档里提过的解决方案(https://www.thinkphp.cn/doc/nofollow)。
第三个要重点说的是file()
方法,处理文件上传必用。我之前做图片上传功能时,用$_FILES
直接拿文件,结果遇到大文件上传时,$_FILES
是空的,后来才知道TP5里要用file()
方法——它会帮你处理php.ini
里的upload_max_filesize
和post_max_size
限制,还能配合validate()
方法验证文件类型。比如你要上传头像,写$file = request()->file('avatar');
,然后用$file->validate(['size'=>2048000, 'ext'=>'jpg,png,gif'])->move('./uploads');
,就能限制文件大小不超过2M,格式只能是图片——比自己写$_FILES
省心多了。对了,file()
返回的是ThinkFile
对象,不是数组,所以别用$_FILES
的方式操作它,不然会报错。
我把这些常用方法整理成了一张表,你直接存手机里,需要时查一下:
方法名 | 用途 | 示例代码 | 注意事项 |
---|---|---|---|
param() | 获取GET/POST/路由参数 | $id = request()->param(‘id’); | 自动过滤非法参数,优先用这个代替get/post |
isPost() | 判断是否POST请求 | if (request()->isPost()) {} | 不判断内容类型,JSON数据要用raw() |
file() | 获取上传文件对象 | $file = request()->file(‘avatar’); | 返回ThinkFile对象,需配合validate()验证 |
ip() | 获取客户端IP地址 | $ip = request()->ip(); | 自动处理代理IP(如X-Forwarded-For) |
header() | 获取请求头信息 | $ua = request()->header(‘user-agent’); | 键名不区分大小写(如User-Agent或user-agent都能拿到) |
除了这些,还有raw()
(获取原始请求数据,比如JSON)、cookie()
(获取Cookie)、session()
(获取Session)这些方法,不过用得没那么频繁,你记不住也没关系,先把上面5个用熟,就能解决大部分问题。
实战中踩过的3个坑,我用Request对象搞定了
光会用方法还不够,实战中你肯定会踩坑——我之前做项目时遇到的3个坑,都是用Request对象解决的,今天分享给你,帮你避坑。
坑一:参数过滤不全,导致SQL注入
去年帮朋友做电商系统时,我用get('id')
获取商品ID,直接拼进SQL语句:$goods = Db::name('goods')->where('id', $id)->find();
。结果上线没几天,就被黑客注入了——黑客在URL里写id=1 OR 1=1
,直接把所有商品都查出来了。后来我才意识到,get()
方法不会过滤逻辑运算符,得用param()
加filter
参数。比如改成$id = request()->param('id', '', 'intval');
,intval
会把id
强制转成整数,不管黑客传什么字符串,都会变成数字,这样就没法注入了。ThinkPHP官方文档里明确说过(https://www.thinkphp.cn/doc/nofollow):“filter
参数是防止SQL注入的有效手段, 所有参数都用它过滤”——我现在写项目,不管拿什么参数,都会加个filter
,比如拿用户名用strip_tags
(过滤HTML标签),拿邮箱用email
(验证邮箱格式),再也没遇到过注入问题。
坑二:AJAX请求判断错误,导致点赞失败
做博客系统的点赞功能时,我用isAjax()
判断请求类型:if (request()->isAjax()) { / 处理点赞 / }
。结果上线后,很多用户反馈“点了赞没反应”。我查日志发现,安卓手机的WebView发的AJAX请求没带X-Requested-With
头,导致isAjax()
返回false,点赞逻辑没执行。后来我改成了双重判断:if (request()->isAjax() || request()->header('X-Requested-With') == 'XMLHttpRequest')
。为什么要加header()
判断?因为isAjax()
本质就是检查X-Requested-With
头,有些浏览器没带这个头,所以直接查头更保险。我还特意查了TP5的源码,isAjax()
的实现就是:
public function isAjax()
{
return $this->isXmlHttpRequest() || $this->get('ajax') || $this->post('ajax');
}
public function isXmlHttpRequest()
{
return strtolower($this->header('X-Requested-With')) == 'xmlhttprequest';
}
所以加header()
判断其实是补了isAjax()
的漏洞——现在这个点赞功能运行了半年,再也没出现过问题。
坑三:文件上传时,参数丢失
做商品发布功能时,前端要传“商品名称”和“商品图片”,我用post('name')
拿商品名称,用file('image')
拿图片。结果测试时发现,有时候post('name')
拿不到值——明明前端传了,后端就是空。后来查了资料才知道,当表单用enctype="multipart/form-data"
(上传文件必须用这个)时,post()
方法只能拿到普通表单数据,但如果前端传了很多参数(比如商品描述、价格、分类),post()
会遗漏部分参数。解决办法很简单:把post('name')
改成param('name')
——param()
会自动处理multipart/form-data
类型的表单,不管你传了多少参数,都能拿到。我后来把所有表单参数都换成param()
,再也没遇到过参数丢失的问题。
你看,这些坑其实都是因为没把Request对象的方法用对——要么用错了方法,要么没注意方法的细节。我把这些坑整理成了“避坑清单”:
param()
,别用get()
或post()
;header()
检查;param()
拿;filter
过滤,比如intval
、strip_tags
。最后再提醒你一句:用Request对象之前,一定要记得实例化——要么用request()
助手函数,要么用app('request')
,别直接new Request(),不然会拿不到当前请求的参数。我之前就犯过这低级错误:new了个Request对象,结果拿不到参数,以为是框架bug,后来才知道request()
助手函数会自动绑定当前请求的实例,比new靠谱多了。
如果你按我说的方法试了,欢迎回来告诉我效果——比如你用param()
解决了参数丢失的问题,或者用filter
避免了注入,都可以在评论区留个言,让我也高兴高兴~
TP5里拿请求参数,用post()还是param()好?
优先用param()更省心。因为param()会自动合并GET、POST和路由参数(比如/user/:id这种路由传参),之前我做用户详情页时,用get()没拿到路由参数导致报错,换成param()就解决了。而且param()还会自动过滤非法字符(比如标签),比单独用post()或get()更安全。
比如要拿用户ID,直接写$id = request()->param(‘id’);,不管参数是从URL、表单还是路由来的,都能拿到,不用一个个判断。
Ajax请求用isAjax()判断总失败,怎么办?
很多安卓手机的WebView发Ajax请求时,没带X-Requested-With: XMLHttpRequest头,这时候isAjax()会返回false。我之前做点赞功能时就遇到这问题,后来改成双重判断就兼容了:if (request()->isAjax() || request()->header(‘X-Requested-With’) == ‘XMLHttpRequest’)。
因为isAjax()本质就是检查这个请求头,直接查header能覆盖更多情况,现在我做项目都用这方法,再也没出现过Ajax判断失败的问题。
处理文件上传时,表单里的其他参数拿不到怎么解决?
如果表单用了enctype=”multipart/form-data”(上传文件必须用这个),用post()拿普通表单参数容易遗漏。我之前做商品发布功能时,用post(‘name’)拿不到商品名称,后来改成param(‘name’)就好了。
因为param()能处理multipart/form-data类型的表单参数,不管是文件还是普通字段,都能一起拿到, 上传文件时所有参数都用param()获取。
怎么防止Request参数导致的SQL注入?
用param()的时候加filter参数就行。比如拿商品ID,写$id = request()->param(‘id’, ”, ‘intval’);,intval会把参数强制转成整数,就算黑客传id=1 OR 1=1,也会变成1,没法注入。
我之前做电商系统时没加filter,被黑客注入过,后来按官方文档 (https://www.thinkphp.cn/doc/nofollow),所有参数都加filter,比如拿用户名用strip_tags过滤HTML标签,拿邮箱用email验证格式,再也没出过问题。
TP5的Request对象需要new吗?还是用助手函数?
别直接new Request(),不然拿不到当前请求的参数。我之前犯过这低级错误,new了个Request对象结果啥参数都没拿到,后来才知道用request()助手函数(或者app(‘request’))会自动绑定当前请求的实例,能正确获取参数。
现在我做项目都直接用request(),比如request()->param(‘id’),方便又不会错。