请求对象
当前的请求对象由think\Request类负责,该类不需要单独实例化调用,通常使用依赖注入即可。在其它场合则可以使用think\facade\Request静态类操作。
项目里面应该使用app\Request对象,该对象继承了系统的think\Request对象,但可以增加自定义方法或者覆盖已有方法。项目里面已经在provider.php中进行了定义,所以你仍然可以和之前一样直接使用容器和静态代理操作请求对象。
构造方法注入
一般适用于没有继承系统的控制器类的情况。
<?php
namespace app\index\controller;
use think\Request;
class Index
{
/**
* @var \think\Request Request实例
*/
protected $request;
/**
* 构造方法
* @param Request $request Request对象
* @access public
*/
public function __construct(Request $request)
{
$this->request = $request;
}
public function index()
{
return $this->request->param('name');
}
}
操作方法注入
另外一种选择是在每个方法中使用依赖注入。
<?php
namespace app\index\controller;
use think\Request;
class Index
{
public function index(Request $request)
{
return $request->param('name');
}
}
无论是否继承系统的控制器基类,都可以使用操作方法注入。
静态调用
在没有使用依赖注入的场合,可以通过Facade机制来静态调用请求对象的方法(注意use引入的类库区别)。
<?php
namespace app\index\controller;
use think\facade\Request;
class Index
{
public function index()
{
return Request::param('name');
}
}
该方法也同样适用于依赖注入无法使用的场合。
助手函数
为了简化调用,系统还提供了request助手函数,可以在任何需要的时候直接调用当前请求对象。
<?php
namespace app\index\controller;
class Index
{
public function index()
{
return request()->param('name');
}
}
自定义请求对象
你可以在项目里面自定义Request对象,修改已有的方法或者增加新的方法,默认已经在项目里面为你准备了app\Request类,你只需要直接修改该类就可以为你的项目单独自定义请求对象。
自定义请求对象不支持为多应用的某个应用自定义,只能是全局自定义,如果你需要为某个应用定义不同的请求对象,可以在入口文件里面修改。例如:
// 执行HTTP应用并响应
$request = new app\common\Request();
$http = (new App())->http;
$response = $http->run($request);
$response->send();
$http->end($response);
请求信息
1. Request对象支持全局变量的检测、获取和安全过滤,支持$_GET、$_POST...等;
2. 为了方便演示,这里一律使用Facade的静态调用模式;
3. 使用has()方法,可以检测全局变量是否已经设置:
Request::has('id', 'get');
Request::has('username', 'post');
它是以get的方式不存在,还是以post方式不存在呢?


然后显示以get方式不存在。
如果改成name了呢


就变成了true
4. Request支持的所有变量类型方法,如下表:

5. param()变量方法是自动识别GET、POST等的当前请求,推荐使用;
//获取请求为name的值,过滤
Request::param('name');
//获取所有请求的变量,以数组形式,过滤
Request::param();
//获取所有请求的变量(原始变量),不包含上传变量,不过滤
Request::param(false);
//获取部分变量
Request::param(['name','age']);

怎么取出name的值呢,如下

如果param()不输入指定的值,就是获取所有值。


获取部分值:


6.默认情况下,并没有配置字符过滤器,可在app\Request.php配置;
protected $filter = ['htmlspecialchars'];

设置字符过滤(转义),第二个为什么不转移呢,是由于上面所说的
//获取所有请求的变量(原始变量),不包含上传变量,不过滤
Request::param(false);
7.如果没有设置字符过滤器,或者局部用别的字符过滤器,可以通过第三参数;
Request::param('name','','htmlspecialchars');
Request::param('name','','strip_tags,strtolower');

如果设置了全局过滤器,那么这个局部过滤器就会把全局过滤器给替换掉。
如果两个都想要的话,就加个逗号。

8.如果设置了全局字符过滤器,但又不想某个局部使用,可以只用null参数;
Request::param('name','',null)
9.如果获取不到值,支持请求的变量设置一个默认值;
Request::param('name','默认值');
10.如果采用的是路由URL,也可以获取到变量,但param::get()不支持路由变量;
Request::param('id');
Request::route('id');
Request::get('id'); //路由参数,get获取不到
使用Request::get("id"),获取不到。


使用Route呢?


就可以获取。
那Request::get("id")可以获取什么呢?只能获取''?''后面的值

(一个就是获取路由的id,一个是获取网址的id)不管哪种id都可以通过param获取。
11.使用only()方法,可以获取指定的变量,也可以设置默认值;
Request::only(['id','name']);
Request::only(['id'=>1,'name'=>'默认值']);
12.使用only()方法,默认是param变量,可以在第二参数设置GET、POST等;
Request::only(['id','name'],'post');
13.相反的except()方法,就是排除指定的变量;
Request::except('id,name');
Request::except(['id','name']);
Request::except(['id'=>1,'name'=>'默认值']);
Request::except(['id','name'],'post');
14.使用变量修饰符,可以将参数强制转换成指定的类型;
15./s(字符串)、/d(整型)、/b(布尔)、/a(数组)、/f(浮点);
Request::param('id/d');
14.15传入的age目前只是字符串。


加个/d的话就是强制类型整型。

把网址改成abc之后就会变成0

助手函数
1.为了简化操作,Request对象提供了助手函数;
input('?get.id'); //判断get下的id是否存在
input('?post.name'); //判断post下的name是否存在
input('param.name'); //获取param下的name值
input('param.name', '默认值'); //默认值
input('param.name', '', 'htmlspecialchars'); //过滤器
input('param.id/d'); //设置强制转换

===================================================================
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参数,表示获取带域名的完整地址,例如:
use think\facade\Request;
// 获取完整URL地址 不带域名
Request::url();
// 获取完整URL地址 包含域名
Request::url(true);
// 获取当前URL(不含QUERY_STRING) 不带域名
Request::baseFile();
// 获取当前URL(不含QUERY_STRING) 包含域名
Request::baseFile(true);
// 获取URL访问根地址 不带域名
Request::root();
// 获取URL访问根地址 包含域名
Request::root(true);
注意domain方法的值本身就包含协议和域名
获取当前控制器/操作
可以通过请求对象获取当前请求的控制器/操作名。
| 方法 | 含义 |
|---|---|
controller | 当前请求的控制器名 |
action | 当前请求的操作名 |
获取当前控制器
Request::controller();
返回的是控制器的驼峰形式(首字母大写),和控制器类名保持一致(不含后缀)。
如果需要返回小写可以使用
Request::controller(true);
如果要返回小写+下划线的方式,可以使用
parse_name(Request::controller());
获取当前操作
Request::action();
返回的是当前操作方法的实际名称,如果需要返回小写可以使用
Request::action(true);
如果要返回小写+下划线的方式,可以使用
parse_name(Request::action());
如果使用了多应用模式,可以通过下面的方法来获取当前应用
app('http')->getName();
输入变量
可以通过Request对象完成全局输入变量的检测、获取和安全过滤,支持包括$_GET、$_POST、$_REQUEST、$_SERVER、$_SESSION、$_COOKIE、$_ENV等系统变量,以及文件上传信息。
为了方便说明,本篇内容的所有示例代码均使用Facade方式,因此需要首先引入
use think\facade\Request;
检测变量是否设置
可以使用has方法来检测一个变量参数是否设置,如下:
Request::has('id','get');
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 V6.0.8+ | 获取包括 $_FILES 变量在内的请求变量,相当于param+file |
获取PARAM变量
PARAM类型变量是框架提供的用于自动识别当前请求的一种变量获取方式,是系统推荐的获取请求参数的方法,用法如下:
// 获取当前请求的name变量
Request::param('name');
// 获取当前请求的所有变量(经过过滤)
Request::param();
// 获取当前请求未经过滤的所有变量
Request::param(false);
// 获取部分变量
Request::param(['name', 'email']);
param方法会把当前请求类型的参数和路由变量以及GET请求合并,并且路由变量是优先的。
其它的输入变量获取方法和param方法用法基本一致。
你无法使用get方法获取路由变量,例如当访问地址是
http://localhost/index.php/index/index/hello/name/thinkphp
下面的用法是错误的
echo Request::get('name'); // 输出为空
正确的用法是
echo Request::param('name'); // 输出thinkphp
除了server和env方法的变量名不区分大小写(会自动转为大写后获取),其它变量名区分大小写。
默认值
获取输入变量的时候,可以支持默认值,例如当URL中不包含$_GET['name']的时候,使用下面的方式输出的结果比较。
Request::get('name'); // 返回值为null
Request::get('name',''); // 返回值为空字符串
Request::get('name','default'); // 返回值为default
前面提到的方法都支持在第二个参数中传入默认值的方式。
变量过滤
框架默认没有设置任何全局过滤规则,你可以在
app\Request对象中设置filter全局过滤属性:
namespace app;
class Request extends \think\Request
{
protected $filter = ['htmlspecialchars'];
}
也支持使用Request对象进行全局变量的获取过滤,过滤方式包括函数、方法过滤,以及PHP内置的Types of filters,我们可以设置全局变量过滤方法,支持设置多个过滤方法,例如:
Request::filter(['strip_tags','htmlspecialchars']),
也可以在获取变量的时候添加过滤方法,例如:
Request::get('name','','htmlspecialchars'); // 获取get变量 并用htmlspecialchars函数过滤
Request::param('username','','strip_tags'); // 获取param变量 并用strip_tags函数过滤
Request::post('name','','org\Filter::safeHtml'); // 获取post变量 并用org\Filter类的safeHtml方法过滤
如果当前不需要进行任何过滤的话,可以使用
// 获取get变量 并且不进行任何过滤 即使设置了全局过滤
Request::get('name', '', null);
对于body中提交的json对象,你无需使用php://input去获取,可以直接当做表单提交的数据使用,因为系统已经自动处理过了
获取部分变量
如果你只需要获取当前请求的部分参数,可以使用:
// 只获取当前请求的id和name变量
Request::only(['id','name']);
采用only方法能够安全的获取你需要的变量,避免额外变量影响数据处理和写入
only方法可以支持批量设置默认值,如下:
// 设置默认值
Request::only(['id'=>0,'name'=>'']);
表示id的默认值为0,name的默认值为空字符串。
默认获取的是当前请求参数(PARAM类型变量),如果需要获取其它类型的参数,可以在第二个参数传入,例如:
// 只获取GET请求的id和name变量
Request::only(['id','name'], 'get');
// 等效于
Request::get(['id', 'name']);
// 只获取POST请求的id和name变量
Request::only(['id','name'], 'post');
// 等效于
Request::post(['id', 'name']);
也支持排除某些变量后获取,例如
// 排除id和name变量
Request::except(['id','name']);
同样支持指定变量类型获取:
// 排除GET请求的id和name变量
Request::except(['id','name'], 'get');
// 排除POST请求的id和name变量
Request::except(['id','name'], 'post');
变量修饰符
支持对变量使用修饰符功能,可以一定程度上简单过滤变量,更为严格的过滤请使用前面提过的变量过滤功能。
用法如下:
Request::变量类型('变量名/修饰符');
支持的变量修饰符,包括:
| 修饰符 | 作用 |
|---|---|
| s | 强制转换为字符串类型 |
| d | 强制转换为整型类型 |
| b | 强制转换为布尔类型 |
| a | 强制转换为数组类型 |
| f | 强制转换为浮点类型 |
下面是一些例子:
Request::get('id/d');
Request::post('name/s');
Request::post('ids/a');
中间件变量
可以在中间件里面设置和获取请求变量的值,这个值的改变不会影响PARAM变量的获取。
<?php
namespace app\http\middleware;
class Check
{
public function handle($request, \Closure $next)
{
if ('think' == $request->name) {
$request->name = 'ThinkPHP';
}
return $next($request);
}
}
助手函数
为了简化使用,还可以使用系统提供的input助手函数完成上述大部分功能。
判断变量是否定义
input('?get.id');
input('?post.name');
获取PARAM参数
input('param.name'); // 获取单个参数
input('param.'); // 获取全部参数
// 下面是等效的
input('name');
input('');
获取GET参数
// 获取单个变量
input('get.id');
// 使用过滤方法获取 默认为空字符串
input('get.name');
// 获取全部变量
input('get.');
使用过滤方法
input('get.name','','htmlspecialchars'); // 获取get变量 并用htmlspecialchars函数过滤
input('username','','strip_tags'); // 获取param变量 并用strip_tags函数过滤
input('post.name','','org\Filter::safeHtml'); // 获取post变量 并用org\Filter类的safeHtml方法过滤
使用变量修饰符
input('get.id/d');
input('post.name/s');
input('post.ids/a');
请求类型
1. 有时,我们需要判断Request的请求类型,比如GET、POST等等;
2. 可以使用method()方法来判断当前的请求类型,当然,还有很多专用的请求判断;

判断GET请求:


判断是否为POST请求:


3. 使用普通表单提交,通过method()方法获取类型;
<form action="http://localhost/tp6/public/rely/get" method="post">
<input type="text" name="name" value="Lee">
<input type="submit" value="提交">
</form>
return Request::method();
根据这个来POST请求:


使用method方法获取get还是post请求。
return Request::method();



上面这个图片虽然,method='put',但是识别的还是POST。
4. 在表单提交时,我们也可以设置请求类型伪装,设置隐藏字段_method;


根据上面的操作才能变成PUT
5. 而在判断请求,使用method(true)可以获取原始请求,否则获取伪装请求;
<input type="hidden" name="_method" value="PUT">
Request::method(true);
6. 如果想更改请求伪装变量类型的名称,可以在app/Request.php中更改;
protected $varMethod = '_m';
7. AJAX/PJAX 伪装,使用?_ajax=1和?_pjax=1,并使用isAjax()和isPjax();
.../rely?_ajax=1
Request::isAjax();
8. 这里需要用isAjax()和isPjax()来判断,用method无法判断是否为a(p)jax;


9. 在app.php也可以更改ajax和pjax的名称;
protected $varAjax = '_a';
protected $varPjax = '_p';
HTTP头信息
1. 使用header()方法可以输出HTTP头信息,返回是数组类型,也可单信息获取;
Request::header();
Request::header('host');

伪静态
1. 可以通过route.php修改伪静态的后缀,比如修改成shtml、xml等;
'url_html_suffix'=> 'html',
2. 如果地址栏用后缀访问成功后,可以使用Request::ext()方法得到当前伪静态;
return Request::ext();
3. 配置文件伪静态后缀,可以支持多个,用竖线隔开;
'url_html_suffix'=> 'shtml|xml|pdf',
4. 直接将伪静态配置文件设置为false,则关闭伪静态功能;
'url_html_suffix'=> false,
=====================================================================
URL伪静态通常是为了满足更好的SEO效果,ThinkPHP支持伪静态URL设置,可以通过设置url_html_suffix参数随意在URL的最后增加你想要的静态后缀,而不会影响当前操作的正常执行。例如,我们在route.php中设置
'url_html_suffix' => 'shtml'
的话,我们可以把下面的URL
http://serverName/blog/read/id/1
变成
http://serverName/blog/read/id/1.shtml
后者更具有静态页面的URL特征,但是具有和前面的URL相同的执行效果,并且不会影响原来参数的使用。
默认情况下,伪静态的设置为html,如果我们设置伪静态后缀为空字符串,
'url_html_suffix'=>''
则支持所有的静态后缀访问,如果要获取当前的伪静态后缀,可以使用Request对象的ext方法。
例如:
http://serverName/blog/3.html
http://serverName/blog/3.shtml
http://serverName/blog/3.xml
http://serverName/blog/3.pdf
都可以正常访问。
我们可以在控制器的操作方法中获取当前访问的伪静态后缀,例如:
$ext = Request::ext();
如果希望支持多个伪静态后缀,可以直接设置如下:
// 多个伪静态后缀设置 用|分割
'url_html_suffix' => 'html|shtml|xml'
那么,当访问 http://serverName/blog/3.pdf 的时候会报系统错误。
如果要关闭伪静态访问,可以设置
// 关闭伪静态后缀访问
'url_html_suffix' => false,
关闭伪静态访问后,不再支持伪静态方式的URL访问,并且伪静态后缀将会被解析为最后一个参数的值,例如:
http://serverName/blog/read/id/3.html
最终的id参数的值将会变成 3.html。
参数绑定
1. 参数绑定功能:即URL地址栏的数据传参,我们一直在使用的功能;
public function get($id)
{
return 'get:'.$id;
}
2. 操作方法URL:/get,而带上id参数后,则为:/get/id/5;
3. 如果缺少了/5或者缺少了/id/5,则都会报错方法参数错误:id;
4. 那么解决方案,就是给$id = 0一个默认值,防止URL参数错误;
5. 如果设置了两个参数,那么参数传递的执行顺序可以设置,比如;
public function get($id, $name)
{
return 'get:'.$id.','.$name;
}
6. 不管是:/id/5/name/lee,还是:/name/lee/id/5,都不会产生错误;
==================================================================
参数绑定是把当前请求的变量作为操作方法(也包括架构方法)的参数直接传入,参数绑定并不区分请求类型。
参数绑定传入的值会经过全局过滤,如果你有额外的过滤需求可以在操作方法中单独处理。
参数绑定方式默认是按照变量名进行绑定,例如,我们给Blog控制器定义了两个操作方法read和archive方法,由于read操作需要指定一个id参数,archive方法需要指定年份(year)和月份(month)两个参数,那么我们可以如下定义:
<?php
namespace app\controller;
class Blog
{
public function read($id)
{
return 'id=' . $id;
}
public function archive($year, $month='01')
{
return 'year=' . $year . '&month=' . $month;
}
}
注意这里的操作方法并没有具体的业务逻辑,只是简单的示范。
URL的访问地址分别是:
http://serverName/index.php/blog/read/id/5
http://serverName/index.php/blog/archive/year/2016/month/06
两个URL地址中的id参数和year和month参数会自动和read操作方法以及archive操作方法的同名参数绑定。
变量名绑定不一定由访问URL决定,路由地址也能起到相同的作用
输出的结果依次是:
id=5
year=2016&month=06
按照变量名进行参数绑定的参数必须和URL中传入的变量名称一致,但是参数顺序不需要一致。也就是说
http://serverName/index.php/blog/archive/month/06/year/2016
和上面的访问结果是一致的,URL中的参数顺序和操作方法中的参数顺序都可以随意调整,关键是确保参数名称一致即可。
如果用户访问的URL地址是:
http://serverName/index.php/blog/read
那么会抛出下面的异常提示: 参数错误:id
报错的原因很简单,因为在执行read操作方法的时候,id参数是必须传入参数的,但是方法无法从URL地址中获取正确的id参数信息。由于我们不能相信用户的任何输入,因此建议你给read方法的id参数添加默认值,例如:
public function read($id = 0)
{
return 'id=' . $id;
}
这样,当我们访问 http://serverName/index.php/blog/read/ 的时候 就会输出
id=0
始终给操作方法的参数定义默认值是一个避免报错的好办法(依赖注入参数除外)
为了更好的配合前端规范,支持自动识别小写+下划线的请求变量使用驼峰注入,例如:
http://serverName/index.php/blog/read/blog_id/5
可以使用下面的方式接收blog_id变量,所以请确保在方法的参数使用驼峰(首字母小写)规范。
public function read($blogId = 0)
{
return 'id=' . $blogId;
}
请求缓存
1. 请求缓存仅对GET请求有效,可以在全局和局部设置缓存;
2. 如果要设置全局请求缓存,在中间件文件middleware.php中设置;
'think\middleware\CheckRequestCache',
3. 然后在route.php中设置缓存的声明周期即可; 'request_cache_expire' => 3600,
4. 当第二次访问时,会自动获取请求缓存的数据响应输出,并发送304状态码;
5. 如果要对路由设置一条缓存,直接使用cache(3600)方法;
Route::get('get/:id', 'Rely/get')->cache(3600)
================================================================
支持请求缓存功能,支持对GET请求设置缓存访问,并设置有效期。
请求缓存仅对GET请求有效
有两种方式可以设置请求缓存:
路由设置
可以在路由规则里面调用cache方法设置当前路由规则的请求缓存,例如:
// 定义GET请求路由规则 并设置3600秒的缓存
Route::get('new/:id','News/read')->cache(3600);
第二次访问相同的路由地址的时候,会自动获取请求缓存的数据响应输出,并发送304状态码。
默认请求缓存的标识为当前访问的pathinfo地址,可以定义请求缓存的标识,如下:
// 定义GET请求路由规则 并设置3600秒的缓存
Route::get('new/:id','News/read')->cache(
[ 'new/:id/:page', 3600]
);
:id、:page表示使用当前请求的param参数进行动态标识替换,也就是根据id和page变量进行3600秒的请求缓存。
如果cache参数传入false,则表示关闭当前路由的请求缓存(即使开启全局请求缓存)。
// 定义GET请求路由规则 并关闭请求缓存(即使开启了全局请求缓存)
Route::get('new/:id','News/read')->cache(false);
支持给一组路由设置缓存标签
// 定义GET请求路由规则 并设置3600秒的缓存
Route::get('new/:id','News/read')->cache(
[ 'new/:id/:page', 3600, 'page']
);
这样可以在需要的时候统一清理缓存标签为page的请求缓存。
全局请求缓存
如果需要开启全局请求缓存,只需要在全局(或者应用)的中间件定义文件middleware.php中增加
'think\middleware\CheckRequestCache',
然后只需要在route.php配置文件中设置全局缓存的有效时间(秒):
'request_cache_expire' => 3600,
就会自动根据当前请求URL地址(只针对GET请求类型)进行请求缓存,全局缓存有效期为3600秒。
如果需要对全局缓存设置缓存规则,可以直接设置request_cache_key参数,例如:
'request_cache_key' => '__URL__',
'request_cache_expire' => 3600,
缓存标识支持下面的特殊定义
| 标识 | 含义 |
|---|---|
__CONTROLLER__ | 当前控制器名 |
__ACTION__ | 当前操作名 |
__URL__ | 当前完整URL地址(包含域名) |
全局请求缓存支持设置排除规则,使用方法如下:
'request_cache_key' => true,
'request_cache_expire' => 3600,
'request_cache_except' => [
'/blog/index',
'/user/member',
],
排除规则为不使用请求缓存的地址(不支持变量)开头部分(不区分大小写)。
路由中设置的请求缓存依然有效并且优先,如果需要设置特殊的请求缓存有效期就可以直接在路由中设置。
1368

被折叠的 条评论
为什么被折叠?



