当前的请求对象由think\Request类负责,该类不需要单独实例化调用,通常使用依赖注入即可。在其它场合则可以使用think\facade\Request静态类操作。

使用

项目里面应该使用app\Request对象,该对象继承了系统的think\Request对象,但可以增加自定义方法或者覆盖已有方法。项目里面已经在provider.php中进行了定义,所以你仍然可以和之前一样直接使用容器和静态代理操作请求对象。

构造方法注入

一般适用于没有继承系统的控制器类的情况。

  1. <?php
  2. namespace app\index\controller;
  3. use think\Request;
  4. class Index
  5. {
  6. /**
  7. * @var \think\Request Request实例
  8. */
  9. protected $request;
  10. /**
  11. * 构造方法
  12. * @param Request $request Request对象
  13. * @access public
  14. */
  15. public function __construct(Request $request)
  16. {
  17. $this->request = $request;
  18. }
  19. public function index()
  20. {
  21. return $this->request->param('name');
  22. }
  23. }

操作方法注入

另外一种选择是在每个方法中使用依赖注入。

  1. <?php
  2. namespace app\index\controller;
  3. use think\Request;
  4. class Index
  5. {
  6. public function index(Request $request)
  7. {
  8. return $request->param('name');
  9. }
  10. }

无论是否继承系统的控制器基类,都可以使用操作方法注入。

更多关于依赖注入的内容,请参考依赖注入章节。

静态调用

在没有使用依赖注入的场合,可以通过Facade机制来静态调用请求对象的方法(注意use引入的类库区别)。

  1. <?php
  2. namespace app\index\controller;
  3. use think\facade\Request;
  4. class Index
  5. {
  6. public function index()
  7. {
  8. return Request::param('name');
  9. }
  10. }

该方法也同样适用于依赖注入无法使用的场合。

助手函数

为了简化调用,系统还提供了request助手函数,可以在任何需要的时候直接调用当前请求对象。

  1. <?php
  2. namespace app\index\controller;
  3. class Index
  4. {
  5. public function index()
  6. {
  7. return request()->param('name');
  8. }
  9. }

自定义请求对象

你可以在项目里面自定义Request对象,修改已有的方法或者增加新的方法,默认已经在项目里面为你准备了app\Request类,你只需要直接修改该类就可以为你的项目单独自定义请求对象。
自定义请求对象不支持为多应用的某个应用自定义,只能是全局自定义,如果你需要为某个应用定义不同的请求对象,可以在入口文件里面修改。例如:

  1. // 执行HTTP应用并响应
  2. $request = new app\common\Request();
  3. $http = (new App())->http;
  4. $response = $http->run($request);
  5. $response->send();
  6. $http->end($response);

请求变量

可以通过Request对象完成全局输入变量的检测、获取和安全过滤,支持包括$_GET$_POST$_REQUEST$_SERVER$_SESSION$_COOKIE$_ENV等系统变量,以及文件上传信息。
为了方便说明,本篇内容的所有示例代码均使用Facade方式,因此需要首先引入

  1. use think\facade\Request;

如果你使用的是依赖注入,请自行调整代码为动态调用即可。

检测变量是否设置

可以使用has方法来检测一个变量参数是否设置,如下:

  1. Request::has('id','get');
  2. Request::has('name','post');

变量检测可以支持所有支持的系统变量,包括get/post/put/request/cookie/server/session/env/file

变量获取

变量获取使用\think\Request类的如下方法及参数:

变量类型方法(‘变量名/变量修饰符’,’默认值’,’过滤方法’)

变量类型方法包括:

| 方法 | 描述 | | —- | —- |

| param | 获取当前请求的变量 |

| get | 获取$_GET变量 |

| post | 获取$_POST变量 |

| put | 获取PUT变量 |

| delete | 获取DELETE变量 |

| session | 获取SESSION变量 |

| cookie | 获取$_COOKIE变量 |

| request | 获取$_REQUEST变量 |

| server | 获取$_SERVER变量 |

| env | 获取$_ENV变量 |

| route | 获取 路由(包括PATHINFO) 变量 |

| middleware | 获取 中间件赋值/传递的变量 |

| file | 获取$_FILES变量 |

| all | 获取包括$_FILES变量在内的请求变量,相当于param+file |

获取PARAM变量

param方法会把当前请求类型的参数和路由变量以及GET请求合并,并且路由变量是优先的。

PARAM类型变量是框架提供的用于自动识别当前请求的一种变量获取方式,是系统推荐的获取请求参数的方法,用法如下:

  1. // 获取当前请求的name变量
  2. Request::param('name');
  3. // 获取当前请求的所有变量(经过过滤)
  4. Request::param();
  5. // 获取当前请求未经过滤的所有变量
  6. Request::param(false);
  7. // 获取部分变量
  8. Request::param(['name', 'email']);

其它的输入变量获取方法和param方法用法基本一致。
你无法使用get方法获取路由变量,例如当访问地址是
你无法使用get方法获取路由变量,例如当访问地址是

  1. http://localhost/index.php/index/index/hello/name/thinkphp

下面的用法是错误的

  1. echo Request::get('name'); // 输出为空

正确的用法是

  1. echo Request::param('name'); // 输出thinkphp

除了serverenv方法的变量名不区分大小写(会自动转为大写后获取),其它变量名区分大小写。

默认值

获取输入变量的时候,可以支持默认值,例如当URL中不包含$_GET[‘name’]的时候,使用下面的方式输出的结果比较。

  1. Request::get('name'); // 返回值为null
  2. Request::get('name',''); // 返回值为空字符串
  3. Request::get('name','default'); // 返回值为default

前面提到的方法都支持在第二个参数中传入默认值的方式。

变量过滤

框架默认没有设置任何全局过滤规则,你可以在app\Request对象中设置filter全局过滤属性:

  1. namespace app;
  2. class Request extends \think\Request
  3. {
  4. protected $filter = ['htmlspecialchars'];
  5. }

也支持使用Request对象进行全局变量的获取过滤,过滤方式包括函数、方法过滤,以及PHP内置的Types of filters,我们可以设置全局变量过滤方法,支持设置多个过滤方法,例如:

  1. Request::filter(['strip_tags','htmlspecialchars']);

也可以在获取变量的时候添加过滤方法,例如:

  1. Request::get('name','','htmlspecialchars'); // 获取get变量 并用htmlspecialchars函数过滤
  2. Request::param('username','','strip_tags'); // 获取param变量 并用strip_tags函数过滤
  3. Request::post('name','','org\Filter::safeHtml'); // 获取post变量 并用org\Filter类的safeHtml方法过滤

可以支持传入多个过滤规则,例如:

  1. Request::param('username','','strip_tags,strtolower'); // 获取param变量 并依次调用strip_tags、strtolower函数过滤

如果当前不需要进行任何过滤的话,可以使用

  1. // 获取get变量 并且不进行任何过滤 即使设置了全局过滤
  2. Request::get('name', '', null);

对于body中提交的json对象,你无需使用php://input去获取,可以直接当做表单提交的数据使用,因为系统已经自动处理过了。

获取部分变量

如果你只需要获取当前请求的部分参数,可以使用:

  1. // 只获取当前请求的id和name变量
  2. Request::only(['id','name']);

采用only方法能够安全的获取你需要的变量,避免额外变量影响数据处理和写入。

only方法可以支持批量设置默认值,如下:

  1. // 设置默认值
  2. Request::only(['id'=>0,'name'=>'']);

表示id的默认值为0,name的默认值为空字符串。
默认获取的是当前请求参数(PARAM类型变量),如果需要获取其它类型的参数,可以在第二个参数传入,例如:

  1. // 只获取GET请求的id和name变量
  2. Request::only(['id','name'], 'get');
  3. // 等效于
  4. Request::get(['id', 'name']);
  5. // 只获取POST请求的id和name变量
  6. Request::only(['id','name'], 'post');
  7. // 等效于
  8. Request::post(['id', 'name']);

也支持排除某些变量后获取,例如

  1. // 排除id和name变量
  2. Request::except(['id','name']);
  3. 同样支持指定变量类型获取:
  4. // 排除GET请求的id和name变量
  5. Request::except(['id','name'], 'get');
  6. // 排除POST请求的id和name变量
  7. Request::except(['id','name'], 'post');

变量修饰符

支持对变量使用修饰符功能,可以一定程度上简单过滤变量,更为严格的过滤请使用前面提过的变量过滤功能。
用法如下:

Request::变量类型(‘变量名/修饰符’);

支持的变量修饰符,包括:

| 修饰符 | 作用 | | —- | —- |

| s | 强制转换为字符串类型 |

| d | 强制转换为整型类型 |

| b | 强制转换为布尔类型 |

| a | 强制转换为数组类型 |

| f | 强制转换为浮点类型 |

下面是一些例子:

  1. Request::get('id/d');
  2. Request::post('name/s');
  3. Request::post('ids/a');

中间件变量

可以在中间件里面设置和获取请求变量的值,这个值的改变不会影响PARAM变量的获取。

  1. <?php
  2. namespace app\http\middleware;
  3. class Check
  4. {
  5. public function handle($request, \Closure $next)
  6. {
  7. if ('think' == $request->name) {
  8. $request->name = 'ThinkPHP';
  9. }
  10. return $next($request);
  11. }
  12. }

助手函数input

为了简化使用,还可以使用系统提供的input助手函数完成上述大部分功能。

判断变量是否定义

  1. input('?get.id');
  2. input('?post.name');

获取PARAM参数

  1. input('param.name'); // 获取单个参数
  2. input('param.'); // 获取全部参数
  3. // 下面是等效的
  4. input('name');
  5. input('');

获取GET参数

  1. // 获取单个变量
  2. input('get.id');
  3. // 使用过滤方法获取 默认为空字符串
  4. input('get.name');
  5. // 获取全部变量
  6. input('get.');

使用过滤方法

  1. input('get.name','','htmlspecialchars'); // 获取get变量 并用htmlspecialchars函数过滤
  2. input('username','','strip_tags'); // 获取param变量 并用strip_tags函数过滤
  3. input('post.name','','org\Filter::safeHtml'); // 获取post变量 并用org\Filter类的safeHtml方法过滤

使用变量修饰符

  1. input('get.id/d');
  2. input('post.name/s');
  3. input('post.ids/a');

获取请求类型

在很多情况下面,我们需要判断当前操作的请求类型是GETPOSTPUTDELETE或者HEAD,一方面可以针对请求类型作出不同的逻辑处理,另外一方面有些情况下面需要验证安全性,过滤不安全的请求。
请求对象Request类提供了下列方法来获取或判断当前请求类型:

| 方法 | 用途 | | —- | —- |

| method | 获取当前请求类型 |

| isGet | 判断是否GET请求 |

| isPost | 判断是否POST请求 |

| isPut | 判断是否PUT请求 |

| isDelete | 判断是否DELETE请求 |

| isAjax | 判断是否AJAX请求 |

| isPjax | 判断是否PJAX请求 |

| isJson | 判断是否JSON请求 |

| isMobile | 判断是否手机访问 |

| isHead | 判断是否HEAD请求 |

| isPatch | 判断是否PATCH请求 |

| isOptions | 判断是否OPTIONS请求 |

| isCli | 判断是否CLI请求 |

| isCgi | 判断是否CGI请求 |

method方法返回的请求类型始终是大写,这些方法都不需要传入任何参数。
没有必要在控制器中判断请求类型再来执行不同的逻辑,完全可以在路由中进行设置。

请求类型伪装

method 伪装

你可以设置为任何合法的请求类型,包括GETPOSTPUTDELETE等,但伪装变量_method只能通过POST请求进行提交。
支持请求类型伪装,可以在POST表单里面提交_method变量,传入需要伪装的请求类型,例如:

  1. <form method="post" action="">
  2. <input type="text" name="name" value="Hello">
  3. <input type="hidden" name="_method" value="PUT" >
  4. <input type="submit" value="提交">
  5. </form>

提交后的请求类型会被系统识别为PUT请求。
如果要获取原始的请求类型,可以使用

  1. Request::method(true);

在命令行下面执行的话,请求类型返回的始终是GET
如果你需要改变伪装请求的变量名,可以修改自定义Request类的varMethod属性。

AJAX/PJAX伪装

可以对请求进行AJAX请求伪装,如下:

  1. http://localhost/index?_ajax=1

或者PJAX请求伪装

  1. http://localhost/index?_pjax=1

如果你需要改变伪装请求的变量名,可以修改自定义Request类的varAjaxvarPjax属性:

_ajax_pjax可以通过GET/POST/PUT等请求变量伪装。

其他请求信息

基本方法

Request对象支持获取当前的请求信息,包括:

| 方法 | 含义 | | —- | —- |

| host | 当前访问域名或者IP |

| scheme | 当前访问协议 |

| port | 当前访问的端口 |

| remotePort | 当前请求的REMOTE_PORT |

| protocol | 当前请求的SERVER_PROTOCOL |

| contentType | 当前请求的CONTENT_TYPE |

| domain | 当前包含协议的域名 |

| subDomain | 当前访问的子域名 |

| panDomain | 当前访问的泛域名 |

| rootDomain | 当前访问的根域名 |

| url | 当前完整URL |

| baseUrl | 当前URL(不含QUERY_STRING) |

| query | 当前请求的QUERY_STRING参数 |

| baseFile | 当前执行的文件 |

| root | URL访问根地址 |

| rootUrl | URL访问根目录 |

| pathinfo | 当前请求URL的pathinfo信息(含URL后缀) |

| ext | 当前URL的访问后缀 |

| time | 获取当前请求的时间 |

| type | 当前请求的资源类型 |

| method | 当前请求类型 |

| rule | 当前请求的路由对象实例 |

对于上面的这些请求方法,一般调用无需任何参数,但某些方法可以传入true参数,表示获取带域名的完整地址,例如:

  1. use think\facade\Request;
  2. // 获取完整URL地址 不带域名
  3. Request::url();
  4. // 获取完整URL地址 包含域名
  5. Request::url(true);
  6. // 获取当前URL(不含QUERY_STRING) 不带域名
  7. Request::baseFile();
  8. // 获取当前URL(不含QUERY_STRING) 包含域名
  9. Request::baseFile(true);
  10. // 获取URL访问根地址 不带域名
  11. Request::root();
  12. // 获取URL访问根地址 包含域名
  13. Request::root(true);

获取当前控制器/操作

| 方法 | 含义 | | —- | —- |

| controller | 当前请求的控制器名,默认返回首字母大写,参数true,返回小写 |

| action | 当前请求的操作名,默认返回首字母大写,参数true,返回小写 |

获取当前控制器

  1. Request::controller();

返回的是控制器的驼峰形式(首字母大写),和控制器类名保持一致(不含后缀)。
如果需要返回小写可以使用

  1. Request::controller(true);

如果要返回小写+下划线的方式,可以使用

  1. parse_name(Request::controller());

获取当前操作

  1. Request::action();

返回的是当前操作方法的实际名称,如果需要返回小写可以使用

  1. Request::action(true);

如果要返回小写+下划线的方式,可以使用

  1. parse_name(Request::action());

如果使用了多应用模式,可以通过下面的方法来获取当前应用

  1. app('http')->getName();

HTTP头信息

可以使用Request对象的header方法获取当前请求的HTTP请求头信息,例如:

  1. $info = Request::header();
  2. echo $info['accept'];
  3. echo $info['accept-encoding'];
  4. echo $info['user-agent'];

也可以直接获取某个请求头信息,例如:

  1. $agent = Request::header('user-agent');

HTTP请求头信息的名称不区分大小写,并且_会自动转换为-,所以下面的写法都是等效的:

  1. $agent = Request::header('user-agent');
  2. $agent = Request::header('USER_AGENT');

```