响应输出
大多数情况,我们不需要关注Response对象本身,只需要在控制器的操作方法中返回数据即可。
最简单的响应输出是直接在路由闭包或者控制器操作方法中返回一个字符串,例如:
Route::get('hello/:name', function ($name) {return 'Hello,' . $name . '!';});
<?phpnamespace app\controller;class Index{public function hello($name='thinkphp'){return 'Hello,' . $name . '!';}}
由于默认是输出Html输出,所以直接以html页面方式输出响应内容。如果你发起一个JSON请求的话,输出就会自动使用JSON格式响应输出。
为了规范和清晰起见,最佳的方式是在控制器最后明确输出类型(毕竟一个确定的请求是有明确的响应输出类型),默认支持的输出类型包括:
| 输出类型 | 快捷方法 | 对应Response类 | | —- | —- | —- |
| HTML输出 | response | \think\Response |
| 渲染模板输出 | view | \think\response\View |
| JSON输出 | json | \think\response\Json |
| JSONP输出 | jsonp | \think\response\Jsonp |
| XML输出 | xml | \think\response\Xml |
| 页面重定向 | redirect | \think\response\Redirect |
| 附件下载 | download | \think\response\File |
每一种输出类型其实对应了一个不同的Response子类(response()函数对应的是Response基类),也可以在应用中自定义Response子类满足特殊需求的输出。
例如我们需要输出一个JSON数据给客户端(或者AJAX请求),可以使用:
<?phpnamespace app\controller;class Index{public function hello(){$data = ['name' => 'thinkphp', 'status' => '1'];return json($data);}}
如果你只需要输出一个html格式的内容,可以直接使用
<?phpnamespace app\controller;class Index{public function hello(){$data = 'Hello,ThinkPHP!';return response($data);}}
或者使用return直接返回输出的字符串。
<?phpnamespace app\controller;class Index{public function hello(){return 'Hello,ThinkPHP!';}}
响应参数
Response对象提供了一系列方法用于设置响应参数,包括设置输出内容、状态码及header信息等,并且支持链式调用以及多次调用。
设置数据
Response基类提供了data方法用于设置响应数据。
response()->data($data);json()->data($data);
不过需要注意的是data方法设置的只是原始数据,并不一定是最终的输出数据,最终的响应输出数据是会根据当前的Response响应类型做自动转换的,例如:
json()->data($data);
最终的输出数据就是json_encode($data)转换后的数据。
如果要获取当前响应对象实例的实际输出数据可以使用
getContent方法。
设置状态码
Response基类提供了code方法用于设置响应数据,但大部分情况一般我们是直接在调用助手函数的时候直接传入状态码,例如:
json($data,201);view($data,401);
或者在后面链式调用code方法是等效的:
json($data)->code(201);
除了redirect函数的默认返回状态码是302之外,其它方法没有指定状态码都是返回200状态码。
如果要获取当前响应对象实例的状态码的值,可以使用
getCode方法。
设置头信息
可以使用Response类的header设置响应的头信息
json($data)->code(201)->header(['Cache-control' => 'no-cache,must-revalidate']);
除了header方法之外,Response基类还提供了常用头信息的快捷设置方法:
| 方法名 | 作用 | | —- | —- |
|
lastModified
| 设置Last-Modified头信息
|
|
expires
| 设置Expires头信息
|
|
eTag
| 设置ETag头信息
|
|
cacheControl
| 设置Cache-control头信息
|
|
contentType
| 设置Content-Type头信息
|
除非你要清楚自己在做什么,否则不要随便更改这些头信息,每个Response子类都有默认的contentType信息,一般无需设置。
你可以使用getHeader方法获取当前响应对象实例的头信息。
写入Cookie
response()->cookie('name', 'value', 600);
设置额外参数
有些时候,响应输出需要设置一些额外的参数,例如:
在进行json输出的时候需要设置json_encode方法的额外参数,jsonp输出的时候需要设置jsonp_handler等参数,这些都可以使用options方法来进行处理,例如:
jsonp($data)->options(['var_jsonp_handler' => 'callback','default_jsonp_handler' => 'jsonpReturn','json_encode_param' => JSON_PRETTY_PRINT,]);
关闭当前的请求缓存
支持使用allowCache方法动态控制是否需要使用请求缓存。
// 关闭当前页面的请求缓存json($data)->code(201)->allowCache(false);
自定义响应(未理解)
如果需要特别的自定义响应输出,可以自定义一个Response子类,并且在控制器的操作方法中直接返回。又或者通过设置响应参数的方式进行响应设置输出。
重定向
可以使用redirect助手函数进行重定向
<?phpnamespace app\controller;class Index{public function hello(){return redirect('http://www.thinkphp.cn');}}
重定向传参
如果是站内重定向的话,可以支持URL组装,有两种方式组装URL,第一种是直接使用完整地址(/打头)
redirect('/index/hello/name/thinkphp');
如果你需要自动生成URL地址,应该在调用之前调用url函数先生成最终的URL地址。
redirect((string) url('hello',['name' => 'think']));
还可以支持使用with方法附加Session闪存数据重定向。
<?phpnamespace app\controller;class Index{public function index(){return redirect('/hello')->with('name','thinkphp');}public function hello(){$name = session('name');return 'hello,'.$name.'!';}}
从示例可以看到重定向隐式传值使用的是Session闪存数据隐式传值,并且仅在下一次请求有效,再次访问重定向地址的时候无效。
记住请求地址(需要测试研究)
在很多时候,我们重定向的时候需要记住当前请求地址(为了便于跳转回来),我们可以使用remember方法记住重定向之前的请求地址。
下面是一个示例,我们第一次访问index操作的时候会重定向到hello操作并记住当前请求地址,然后操作完成后到restore方法,restore方法则会自动重定向到之前记住的请求地址,完成一次重定向的回归,回到原点!(再次刷新页面又可以继续执行)
<?phpnamespace app\controller;class Index{public function index(){// 判断session完成标记是否存在if (session('?complete')) {// 删除sessionsession('complete', null);return '重定向完成,回到原点!';} else {// 记住当前地址并重定向return redirect('hello')->with('name', 'thinkphp')->remember();}}public function hello(){$name = session('name');return 'hello,' . $name . '! <br/><a href="/index/index/restore">点击回到来源地址</a>';}public function restore(){// 设置session标记完成session('complete', true);// 跳回之前的来源地址return redirect()->restore();}}
文件下载
持文件下载功能,可以更简单的读取文件进行下载操作,支持直接下载输出内容。
你可以在控制器的操作方法中添加如下代码:
public function download(){// download是系统封装的一个助手函数return download('image.jpg', 'my.jpg');}
访问download操作就会下载命名为my.jpg的图像文件。
下载文件的路径是服务器路径而不是URL路径,如果要下载的文件不存在,系统会抛出异常。
下载文件名可以省略后缀,会自动判断(后面的代码都以助手函数为例)
public function download(){// 和上面的下载文件名是一样的效果return download('image.jpg', 'my');}
如果需要设置文件下载的有效期,可以使用
public function download(){// 设置300秒有效期return download('image.jpg', 'my')->expire(300);}
除了expire方法外,还支持下面的方法:
| 方法 | 描述 | | —- | —- |
|
name
| 命名下载文件
|
|
expire
| 下载有效期
|
|
isContent
| 是否为内容下载
|
|
mimeType
| 设置文件的mimeType类型
|
|
force
| 是否强制下载(V6.0.3+),主要针对图片,不然图片可能浏览而不是下载
|
助手函数提供了内容下载的参数,如果需要直接下载内容,可以在第三个参数传入true:
public function download(){$data = '这是一个测试文件';return download($data, 'test.txt', true);}
V6.0.3+版本开始,支持设置是否强制下载,例如需要打开图像文件而不是浏览器下载的话,可以使用:
public function download(){return download('image.jpg', 'my.jpg')->force(false);}
中断
不要在控制器中使用包括die、exit在内的中断代码。如果你需要调试并中止执行,可以使用系统提供的halt助手函数。
halt('输出测试');
