当前位置: 首页 > news >正文

ThinkPHP8学习篇(四):请求和响应

在请求流程中,请求与响应构成了应用与客户端交互的核心纽带 —— 请求负责捕获并解析客户端传递的各类数据(如参数、头信息、请求方式等),响应则承担着将处理结果以合适形式(如页面、JSON、文件等)返回给客户端的重任,是完成一次完整交互的关键闭环。本篇文章将记录 ThinkPHP 请求与响应的学习过程。


一、请求

1、请求对象

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

在项目里面应该使用 app\Request 对象,该对象继承了系统的 think\Request 对象,但可以增加自定义方法或者覆盖已有方法。

继承 app\BaseController 基础控制器类可以直接使用 request 属性调用 think\Request 对象实例。

当然,继承基础控制器类并不是必须的,接下来说明不继承基础控制器类如何使用请求对象。

1.1、构造方法注入

只需要在构造方法的参数中声明 Request 对象参数就可以在构造方法中使用 Request 对象了。例如:

<?php
namespace app\controller;use think\Request;class Index 
{// 在类中声明 Request 实例protected $request;/*** 构造方法,通过向构造方法中传入 Request 对象完成注入* @param Request $request*/public function __construct(Request $request){// 将注入的 Request 对象赋值给当前类中的 $request$this->request = $request;}public function index(){return $this->request->param('name');}
}

1.2、操作方法注入

Request 对象可以通过构造方法注入,同样的,也可以通过普通方法进行注入。注入的方式是一样的,只需要在需要注入 Request 对象的方法上声明该参数就可以了。例如:

<?php
namespace app\controller;use think\Request;class Index
{public function index(Request $request){return $request->param('name');}
}

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

1.3、静态调用

除了使用依赖注入的方式使用 Request,也可以通过 Facade 机制来静态调用请求对象的方法(注意 use 引入的类库区别)。

示例

<?php
namespace app\controller;use think\facade\Request;class Index
{public function index(){return Request::param('name');}
}

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

1.4、助手函数

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

示例

<?php
namespace app\controller;class Index
{public function index(){return request()->param('name');}
}

1.5、自定义请求对象

可以在项目里面自定义 Request 对象,修改已有的方法或者增加新的方法,默认已经在项目里准备了 app\Request 类,只需要直接修改该类就可以为你的项目单独自定义请求对象。

2、请求信息

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);

2.1、获取当前控制器/操作

可以通过请求对象获取当前请求的控制器/操作名。

方法

含义

controller

当前请求的控制器名

action

当前请求的操作名

示例

// 获取当前控制器,返回的是控制器的驼峰形式(首字母大写),和控制器类名保持一致(不含后缀)。
Request::controller();
// 获取当前操作,返回的是当前操作方法的实际名称。
Request::action();

3、输入变量

可以通过 Request 对象完成全局输入变量的检测、获取和安全过滤,包括 $_GET$_POST$_REQUEST$_SERVER$_SESSION$_COOKIE$_ENV 等系统变量,以及文件上传信息。

3.1、检测变量是否设置

has(变量名, 请求类型) 方法来检测一个变量参数是否设置。设置返回 true,未设置返回 false

Request::has('id','get'); // GET 请求中是否设置 id 变量
Request::has('name','post'); // POST 请求中是否设置 name 变量

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

3.2、变量获取

变量获取使用 \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 类型变量是框架提供的用于自动识别当前请求的一种变量获取方式,是系统推荐的获取请求参数的方法,用法如下:

// 获取当前请求的 name 变量
Request::param('name');
// 获取当前请求的所有变量(经过过滤)
Request::param();
// 获取当前请求未经过滤的所有变量
Request::param(false);
// 获取部分变量
Request::param(['name', 'email']);

param 方法会把当前请求类型的参数和 GET 请求合并。

其它的输入变量获取方法和 param 方法用法基本一致。

3.3、变量修饰符

支持对变量使用修饰符功能,可以一定程度上简单过滤变量。

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

支持的变量修饰符有:

修饰符

作用

s

强制转换为字符串类型

d

强制转换为整型类型

b

强制转换为布尔类型

a

强制转换为数组类型

f

强制转换为浮点类型

示例

Request::get('id/d'); // 变量 id 为整型
Request::post('name/s'); // 变量 name 为字符串
Request::post('ids/a'); // 变量 ids 为数组

4、请求类型

4.1、获取请求类型

在有些情况下,我们需要判断当前操作的请求类型是GET、POST、PUT、DELETE或者HEAD,一方面可以针对请求类型作出不同的逻辑处理,另外一方面有些情况下面需要验证安全性,过滤不安全的请求。

请求对象 Request 类提供了下列方法来获取或判断当前请求类型:

用途

方法

获取当前请求类型

method

判断是否GET请求

isGet

判断是否POST请求

isPost

判断是否PUT请求

isPut

判断是否DELETE请求

isDelete

判断是否AJAX请求

isAjax

判断是否PJAX请求

isPjax

判断是否JSON请求

isJson

判断是否手机访问

isMobile

判断是否HEAD请求

isHead

判断是否PATCH请求

isPatch

判断是否OPTIONS请求

isOptions

判断是否为CLI执行

isCli

判断是否为CGI模式

isCgi

method 方法返回的请求类型始终是大写,这些方法都不需要传入任何参数。

4.2、请求类型伪装

ThinkPHP 支持请求类型伪装,可以在POST表单里面提交 _method 变量,传入需要伪装的请求类型,例如:

<form method="post" action=""><input type="text" name="name" value="Hello"><input type="hidden" name="_method" value="PUT" ><input type="submit" value="提交">
</form>

提交后的请求类型会被系统识别为 PUT 请求。

可以设置为任何合法的请求类型,包括GET、POST、PUT和DELETE等,但伪装变量 _method 只能通过 POST 请求进行提交。

5、HTTP头信息

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

示例

// 获取的信息为数组,通过信息头名称获取值
$info = Request::header();
echo $info['accept'];
echo $info['accept-encoding'];
echo $info['user-agent'];// 也可以直接获取某个请求头信息
$agent = Request::header('user-agent');

HTTP 请求头信息的名称不区分大小写,并且 _ 会自动转换为 -

6、参数绑定

参数绑定是把当前请求的变量作为操作方法的参数直接传入,参数绑定并不区分请求类型。

参数绑定方式默认是按照变量名进行绑定。例如,我们给 Blog 控制器定义了 read 方法,read 方法需要指定年份(year)和月份(month)两个参数,那么我们可以这样定义:

<?php
namespace app\controller;class Blog
{public function read($year, $month='01'){return 'year=' . $year . '&month=' . $month;}
}

URL的访问地址是:

http://serverName/blog/read/year/2025/month/12
或者
http://serverName/blog/read?year=2021&month=02

按照变量名进行参数绑定的参数必须和URL中传入的变量名称一致,但是参数顺序不需要。

二、响应

ThinkPHP的 Response 响应对象由 think\Response 类或者子类完成,ThinkPHP的响应输出是自动的,最终会调用 Response 对象的 send 方法完成输出。

1、响应输出

大多数情况下,我们不需要关注 Response 对象本身,只需要在控制器的操作方法中返回数据即可。最简单的响应输出是直接在控制器操作方法中返回一个字符串,例如:

<?php
namespace app\controller;class Index
{public function hello($name='thinkphp'){return 'Hello,' . $name . '!';}
}

默认是输出 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

2、响应参数

Response 对象提供了一系列方法用于设置响应参数,包括设置输出内容、状态码及 header 信息等,并且支持链式调用以及多次调用。

2.1、设置数据

Response 基类提供的 data 方法用于设置响应数据。

示例

response()->data($data);
json()->data($data);

需要注意的是 data 方法设置的只是原始数据,并不一定是最终的输出数据,最终的响应输出数据是会根据当前的 Response 响应类型做自动转换。例如:

json()->data($data);

最终的输出数据就是 json_encode($data) 转换后的数据。

2.2、设置状态码

Response 基类提供的 code 方法用于设置响应的状态码,但一般情况下,都是在调用助手函数的时候直接传入状态码。

示例

json($data, 201);
view($data, 401);// 或者在后面链式调用code方法:
json($data)->code(201);

除了 redirect 函数的默认返回状态码是302之外,其它方法没有指定状态码都是返回200状态码。

2.3、设置头信息

Response 基类提供的 header 方法用于设置响应的头信息。

示例

json($data)->code(201)->header(['Cache-control' => 'no-cache,must-revalidate'
]);

3、重定向

使用 redirect(URL) 助手函数进行重定向。

示例

<?php
namespace app\controller;class Index
{public function hello(){return redirect('http://www.baidu.com');}
}

还可以支持使用 with 方法附加 Session 闪存数据重定向。

<?php
namespace app\controller;class Index
{public function index(){return redirect('/hello')->with('name','thinkphp');}public function hello(){$name = session('name');return 'hello,'.$name.'!';}    
}

需要说明的是,Session 闪存的数据仅在下一次请求有效,再次访问重定向地址的时候无效。

4、文件下载

支持文件下载功能,可以更简单的读取文件进行下载操作,支持直接下载输出内容。

助手函数 download(要下载的文件, 显示的文件名, 是否为内容, 有效期(秒)) 用于文件下载。

示例

public function download($year, $month='01')
{return download('image.jpg', 'my.jpg');
}

访问 download 操作就会下载命名为 my.jpg 的图像文件。

下载文件的路径是服务器路径而不是URL路径,如果要下载的文件不存在,系统会抛出异常。

支持设置是否强制下载,例如需要打开图像文件而不是浏览器下载的话,可以使用 force 方法:

public function download()
{// force()方法:是否强制下载return download('image.jpg', 'my.jpg')->force(false);
}

除了 force 方法外,还支持下面的方法:

方法

描述

name

命名下载文件

expire

下载有效期

isContent

是否为内容下载

mimeType

设置文件的mimeType类型

force

是否强制下载

http://www.dtcms.com/a/347972.html

相关文章:

  • 基于FPGA的情绪感知系统设计方案:心理健康监测应用(一)
  • centos搭建gitlab服务器
  • 【R语言】R语言中 rbind() 与 merge() 的区别详解
  • 【企业标准开发框架 01】全局异常处理+自定义异常类
  • JAVA限流方法
  • System.IO.Pipelines 与“零拷贝”:在 .NET 打造高吞吐二进制 RPC
  • 【SpringBoot集成篇】SpringBoot 深度集成 Elasticsearch 搜索引擎指南
  • rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(十五)网格布局
  • rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(十三)菜单、右键菜单
  • 【JavaEE】了解synchronized
  • 大数据毕业设计选题推荐-基于大数据的丙型肝炎患者数据可视化分析系统-Hadoop-Spark-数据可视化-BigData
  • 【数据结构】从基础到实战:全面解析归并排序与计数排序
  • 基于stm32汽车雨刮器控制系统设计
  • Java基础第3天总结(面向对象)
  • Shell Case 条件语句详解
  • EP01:【DA】数据分析的概述
  • 01Shell脚本入门:基础命令与变量解析
  • JVM之【类加载系统】
  • 【Qt开发】常用控件(六)
  • Golang云端编程深度指南:架构本质与高阶实践
  • Flink Slot 不足导致任务Pending修复方案
  • 互联网大厂Java面试实录:从Spring到微服务的全面考察
  • 【软件安全】ARM64、x86、32 位与 64 位架构的区别、定义、应用背景
  • 个人搭建小网站教程(云服务器Ubuntu版本)
  • 【数据结构】二叉树的顺序存储、堆的实现及其应用:堆排序与Top-K问题
  • 以国产IoTDB为代表的主流时序数据库架构与性能深度选型评测
  • kanass V1.1.4版本发布,支持Mysql数据库、ubuntu安装与Mantis数据导入
  • Thonny+MicroPython搭建ESP32芯片开发环境
  • 代码性能测试——benchmark库
  • Elasticsearch Ruby 客户端故障排查实战指南