首页 » PHP » 正文

thinkphp5学习笔记(3)

请求和响应

1、请求对象

ThinkPHP5 的 Request 对象由 think\Request 类完成。

Request 对象的一个主要职责是统一和更安全地获取当前的请求信息,你需要避免直接操作 $_GET 、$_POST 、$_REQUEST 、 $_SESSION 、 $_COOKIE ,甚至 $_FILES 等全局变量,而是统一使用Request 对象提供的方法来获取请求变量。

下面来举一个最简单的例子(获取当前访问的url地址)来说明在不同的情况下如何调用 Request 对象。

(1)传统方式调用

该用法主要是用来告诉大家 Request 对象是如何实例化的,因为实际开发中很少选择这种方式调用。

<?php
namespace app\index\controller;
use think\Request;
class Index
{
public function hello($name = 'World')
{
$request = Request::instance();
// 获取当前URL地址 不含域名
echo 'url: ' . $request->url() . '<br/>';
return 'Hello,' . $name . '!';
}
}

访问下面的URL地址:
http://192.168.0.102/index/index/hello?name=thinkphp
输出:
url: /index/index/hello?name=thinkphp
Hello,World!

(2)继承think\Controller

如果控制器类继承了 think\Controller 的话,可以做如下简化调用:

<?php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{
public function hello($name = 'World')
{
// 获取当前URL地址 不含域名
echo 'url: ' . $this->request->url() . '<br/>';
return 'Hello,' . $name . '!';
}
}

(3)自动注入请求对象

如果没有继承 think\Controller ,则可以使用 Request 对象注入的方式来简化调用:

<?php
namespace app\index\controller;
use think\Request;
class Index
{
public function hello(Request $request, $name = 'World')
{
// 获取当前URL地址 不含域名
echo 'url: ' . $request->url() . '<br/>';
return 'Hello,' . $name . '!';
}
}
注意:hello方法的request参数是系统自动注入的,而不需要通过URL请求传入。

(4)动态绑定属性

可以给Request请求对象绑定属性,方便全局调用,例如我们可以在公共控制器中绑定当前登录的用户模型到
请求对象:

<?php
namespace app\index\controller;
use app\index\model\User;
use think\Controller;
use think\Request;
use think\Session;
class Base extends Controller
{
public function _initialize()
{
$user = User::get(Session::get('user_id'));
Request::instance()->bind('user',$user);
}
}

然后,在其它的控制器中就可以直接使用

<?php
namespace app\index\controller;
use app\index\controller\Base;
use think\Request;
class Index extends Base
{
public function index(Request $request)
{
echo $request->user->id;
echo $request->user->name;
}
}

(5)使用助手函数

如果既没有继承 think\Controller 也不想给操作方法添加额外的 Request 对象参数,那么也可以使用
系统提供的助手,例如:

<?php
namespace app\index\controller;
class Index
{
public function hello($name = 'World')
{
// 获取当前URL地址 不含域名
echo 'url: ' . request()->url() . '<br/>';
return 'Hello,' . $name . '!';
}
}

上面任意一种方式都可以调用当前请求的 Request 对象实例,然后通过请求对象实例的方法来完成不同的
信息获取或者设置。

在后面的示例中,如果没有特别说明,我们均以第三种方式,自动注入请求对象的方式来讲解,请注意根据自己的调用方式灵活运用。

——————————————————–

2、请求信息

(1)获取请求变量

系统推荐使用 param 方法统一获取当前请求变量,该方法最大的优势是让你不需要区分当前请求类型而使用
不同的全局变量或者方法,并且可以满足大部分的参数需求,下面举一个例子。

<?php
namespace app\index\controller;
use think\Request;
class Index
{
public function hello(Request $request)
{
echo '请求参数:';
dump($request->param());
echo 'name:'.$request->param('name');
}
}

访问下面的URL地址:

http://192.168.0.102/index/index/hello.html?name=thinkphp&home=house

输出结果:

请求参数:
array(2) {
  ["name"] => string(8) "thinkphp"
  ["home"] => string(5) "house"
}
name:thinkphp

系统提供了一个input助手函数来简化 Request 对象的param方法,用法如下:

<?php
namespace app\index\controller;
class Index
{
public function hello()
{
echo '请求参数:';
dump(input());
echo 'name:'.input('name');
}
}

param 方法获取的参数会自动判断当前的请求,以 POST 请求为例的话,参数的优先级别为:路由变量 > 当前请求变量($_POST变量) > $_GET变量

注意:这里的路由变量指的是路由规则里面定义的变量或者 PATH_INFO 地址中的变量。路由变量无法使用
get 方法或者 $_GET 变量获取。

param 方法支持变量的过滤和默认值,例如:

<?php
namespace app\index\controller;
use think\Request;
class Index
{
public function hello(Request $request)
{
echo 'name:'.$request->param('name','World','strtolower');
echo '<br/>test:'.$request->param('test','thinkphp','strtoupper');
}
}

访问:http://192.168.0.102/index/index/hello.html?name=thinkphp&test=house
输出:
name:thinkphp
test:HOUSE

可以设置全局的过滤方法,如下:

// 设置默认的全局过滤规则 多个用数组或者逗号分隔
'default_filter' => 'htmlspecialchars ',

除了 Param 方法之外, Request 对象也可以用于获取其它的输入参数,例如:

<?php
namespace app\index\controller;
use think\Request;
class Index
{
public function hello(Request $request)
{
echo 'GET参数:';
dump($request->get());
echo 'GET参数:name';
dump($request->get('name'));
echo 'POST参数:name';
dump($request->post('name'));
echo 'cookie参数:name';
dump($request->cookie('name'));
echo '上传文件信息:image';
dump($request->file('image'));
}
}

qq%e5%9b%be%e7%89%8720161207104106

(2)获取请求参数

把 Hello 方法改为如下:

<?php
namespace app\index\controller;
use think\Request;
class Index
{
public function hello(Request $request)
{
echo '请求方法:' . $request->method() . '<br/>';
echo '资源类型:' . $request->type() . '<br/>';
echo '访问IP:' . $request->ip() . '<br/>';
echo '是否AJax请求:' . var_export($request->isAjax(), true) . '<br/>';
echo '请求参数:';
dump($request->param());
echo '请求参数:仅包含name';
dump($request->only(['name']));
echo '请求参数:排除name';
dump($request->except(['name']));
}
}

访问:http://192.168.0.102/index/index/hello.html?name=thinkphp&test=house

输出:

请求方法:GET
资源类型:xml
访问IP:192.168.0.102
是否AJax请求:false
请求参数:
array(2) {
  ["name"] => string(8) "thinkphp"
  ["test"] => string(5) "house"
}
请求参数:仅包含name
array(1) {
  ["name"] => string(8) "thinkphp"
}
请求参数:排除name
array(1) {
  ["test"] => string(5) "house"
}

(3)获取URL信息

<?php
namespace app\index\controller;
use think\Request;
class Index
{
public function hello(Request $request,$name = 'World')
{
// 获取当前域名
echo 'domain: ' . $request->domain() . '<br/>';
// 获取当前入口文件
echo 'file: ' . $request->baseFile() . '<br/>';
// 获取当前URL地址 不含域名
echo 'url: ' . $request->url() . '<br/>';
// 获取包含域名的完整URL地址
echo 'url with domain: ' . $request->url(true) . '<br/>';
// 获取当前URL地址 不含QUERY_STRING
echo 'url without query: ' . $request->baseUrl() . '<br/>';
// 获取URL访问的ROOT地址
echo 'root:' . $request->root() . '<br/>';
// 获取URL访问的ROOT地址
echo 'root with domain: ' . $request->root(true) . '<br/>';
// 获取URL地址中的PATH_INFO信息
echo 'pathinfo: ' . $request->pathinfo() . '<br/>';
// 获取URL地址中的PATH_INFO信息 不含后缀
echo 'pathinfo: ' . $request->path() . '<br/>';
// 获取URL地址中的后缀信息
echo 'ext: ' . $request->ext() . '<br/>';
return 'Hello,' . $name . '!';
}
}

访问下面的URL地址:http://192.168.0.102/index/index/hello.html?name=thinkphp

输出:

domain: http://192.168.0.102
file: /index.php
url: /index/index/hello.html?name=thinkphp
url with domain: http://192.168.0.102/index/index/hello.html?name=thinkphp
url without query: /index/index/hello.html
root:
root with domain: http://192.168.0.102
pathinfo: index/index/hello.html
pathinfo: index/index/hello
ext: html
Hello,thinkphp!

qq%e5%9b%be%e7%89%8720161207104106

(4)获取当前模块/控制器/操作信息

hello方法修改如下:

public function hello(Request $request, $name = 'World')
{
echo '模块:'.$request->module();
echo '<br/>控制器:'.$request->controller();
echo '<br/>操作:'.$request->action();
}

访问:http://192.168.0.102/index/index/hello.html?name=thinkphp
输出:

模块:index
控制器:Index
操作:hello
controller方法获取的是驼峰命名的实际的控制器名,其它都是小写返回。

(5)获取路由和调度信息

hello方法修改如下:

<?php
namespace app\index\controller;
use think\Request;
class Index
{
public function hello(Request $request, $name = 'World')
{
echo '路由信息:';
dump($request->routeInfo());
echo '调度信息:';
dump($request->dispatch());
return 'Hello,' . $name . '!';
}
}

然后在配置文件中添加路由定义为:

return [
'hello/:name' =>['index/hello',[],['name'=>'\w+']],
];

访问下面的URL地址:http://192.168.0.102/hello/thinkphp
输出:

路由信息:
array(4) {
  ["rule"] => array(2) {
    [0] => string(5) "hello"
    [1] => string(5) ":name"
  }
  ["route"] => string(11) "index/hello"
  ["option"] => array(0) {
  }
  ["var"] => array(1) {
    ["name"] => string(8) "thinkphp"
  }
}
调度信息:
array(3) {
  ["type"] => string(6) "module"
  ["module"] => array(3) {
    [0] => NULL
    [1] => string(5) "index"
    [2] => string(5) "hello"
  }
  ["convert"] => bool(false)
}
Hello,thinkphp!

(6)响应对象

Response 对象用于动态响应客户端请示,控制发送给用户的信息,并将动态生成响应。通常用于输出数据给客户端或者浏览器。
ThinkPHP5 的 Response 响应对象由 think\Response 类或者子类完成,下面介绍下基本的用法。

自动输出

大多数情况,我们不需要关注 Response 对象本身,只需要在控制器的操作方法中返回数据即可,系统会根
据 default_return_type 和 default_ajax_return 配置决定响应输出的类型。
默认的自动响应输出会自动判断是否 AJAX 请求,如果是的话会自动输出 default_ajax_return 配置的
输出类型。

<?php
namespace app\index\controller;
class Index
{
public function hello()
{
$data = ['name' => 'thinkphp', 'status' => '1'];
return $data;
}
}

由于默认是输出 Html 输出,所以访问页面输出结果为:variable type error: array

修改配置文件,添加:
// 默认输出类型
‘default_return_type’ => ‘json’,
再次访问的输出结果为:
{“name”:”thinkphp”,”status”:”1″}

修改输出类型为xml:
// 默认输出类型
‘default_return_type’ => ‘xml’,
则输出结果变成:

<think>
<name>thinkphp</name>
<status>1</status>
</think>

手动输出

在必要的时候,可以手动控制输出类型和参数,这种方式较为灵活。如果需要指定输出类型,可以通过下面
的方式:

<?php
namespace app\index\controller;
class Index
{
public function hello()
{
$data = ['name' => 'thinkphp', 'status' => '1'];
return json($data);
}
}

无论配置参数如何设置,页面输出的结果为:
{“name”:”thinkphp”,”status”:”1″}
默认的情况下发送的http状态码是 200 ,如果需要返回其它的状态码,可以使用:

<?php
namespace app\index\controller;
class Index
{
public function hello()
{
$data = ['name' => 'thinkphp', 'status' => '1'];
return json($data, 201);
}
}

或者发送更多的响应头信息:

<?php
namespace app\index\controller;
class Index
{
public function hello()
{
$data = ['name' => 'thinkphp', 'status' => '1'];
return json($data, 201, ['Cache-control' => 'no-cache,must-revalidate']);
}
}

也支持使用下面的方式:

<?php
namespace app\index\controller;
class Index
{
public function hello()
{
$data = ['name' => 'thinkphp', 'status' => '1'];
return json($data)->code(201)->header(['Cache-control' => 'no-cache,must-revali
date']);
}
}

qq%e5%9b%be%e7%89%8720161207104106

所以,同样的可以使用 xml 方法输出 XML 数据类型:

<?php
namespace app\index\controller;
class Index
{
public function hello()
{
$data = ['name' => 'thinkphp', 'status' => '1'];
return xml($data, 201);
}
}

页面跳转

如果需要进行一些简单的页面操作提示或者重定向,可以引入 traits\controller\Jump ,就可以使用
相关页面跳转和重定向方法,下面举一个简单的例子,当页面传入name参数为thinkphp的时候,跳转到欢迎
页面,其它情况则跳转到一个guest页面。

namespace app\index\controller;
class Index
{
use \traits\controller\Jump;
public function index($name='')
{
if ('thinkphp' == $name) {
$this->success('欢迎使用ThinkPHP
5.0','hello');
} else {
$this->error('错误的name','guest');
}
}
public function hello()
{
return 'Hello,ThinkPHP!';
}
public function guest()
{
return 'Hello,Guest!';
}
}
这里我们使用
use \traits\controller\Jump;
引入了一个 Jump trait,这是 PHP5.4 版本的新特性,如果你的控制器类是继承的
\think\Controller 的话,系统已经自动为你引入了 \traits\controller\Jump ,无需再次引
入。

页面重定向

如果要进行页面重定向跳转,可以使用:

namespace app\index\controller;
class Index
{
use \traits\controller\Jump;
public function index($name='')
{
if ('thinkphp' == $name) {
$this->redirect('http://thinkphp.cn');
} else {
$this->success('欢迎使用ThinkPHP','hello');
}
}
public function hello()
{
return 'Hello,ThinkPHP!';
}
}
redirect 方法默认使用 302 跳转,如不需要可以使用第二个参数进行301跳转。
$this->redirect('http://thinkphp.cn',301);

在任何时候(即使没有引入Jump trait的话),我们可以使用系统提供的助手函数redirect函数进行重定向。

namespace app\index\controller;
class Index
{
public function index($name='')
{
if ('thinkphp' == $name) {
return redirect('http://thinkphp.cn');
} else {
return 'Hello,ThinkPHP!';
}
}
}
博主的文章或程序如果给您带来了价值,感谢您打赏一二
微信扫码支付 支付宝扫码支付

发表评论