HTTP 请求
介绍
Laravel 的 Illuminate\Http\Request
类提供了一种面向对象的方式来与当前由应用程序处理的 HTTP 请求进行交互,并检索提交请求的输入内容、Cookie 和文件。
与请求交互
访问请求
要通过依赖注入获取当前的 HTTP 请求实例,您应该在路由闭包或控制器方法中导入 Illuminate\Http\Request
类。传入的请求实例将由 Laravel 服务容器 自动注入:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* 存储新用户。
*/
public function store(Request $request): RedirectResponse
{
$name = $request->input('name');
// 存储用户……
return redirect('/users');
}
}
如上所述,您也可以在路由闭包上导入 Illuminate\Http\Request
类。服务容器将在执行时自动将传入请求注入闭包中:
use Illuminate\Http\Request;
Route::get('/', function (Request $request) {
// ...
});
依赖注入和路由参数
如果您的控制器方法还需要从路由参数中获取输入,则应该在其他依赖项之后列出路由参数。例如,如果您的路由定义如下:
use App\Http\Controllers\UserController;
Route::put('/user/{id}', [UserController::class, 'update']);
您仍然可以在控制器方法中使用类型提示的 Illuminate\Http\Request
并通过以下方式访问您的 id
路由参数来定义您的控制器方法:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* Update the specified user.
*/
public function update(Request $request, string $id): RedirectResponse
{
// 更新用户...
return redirect('/users');
}
}
请求路径、主机和方法
Illuminate\Http\Request
实例提供各种方法来检查传入的 HTTP 请求,并扩展了 Symfony\Component\HttpFoundation\Request
类。下面我们将讨论一些最重要的方法。
获取请求路径
path
方法返回请求的路径信息。因此,如果传入的请求针对 http://example.com/foo/bar
,则 path
方法将返回 foo/bar
:
$uri = $request->path();
检查请求路径/路由信息
is
方法允许您验证传入请求路径是否与给定的模式匹配。当使用此方法时,您可以使用 *
字符作为通配符:
if ($request->is('admin/*')) {
// ...
}
使用 routeIs
方法,您可以确定传入的请求是否与 命名路由 匹配:
if ($request->routeIs('admin.*')) {
// ...
}
获取请求 URL
要获取传入请求的完整 URL,您可以使用 url
或 fullUrl
方法。url
方法将返回不带查询字符串的 URL,而fullUrl
方法将包括查询字符串:
$url = $request->url();
$urlWithQueryString = $request->fullUrl();
如果您想将查询字符串数据附加到当前 URL,请调用 fullUrlWithQuery
方法。此方法将给定的查询字符串变量数组与当前查询字符串合并:
$request->fullUrlWithQuery(['type' => 'phone']);
获取请求 Host
您可以通过 host
、httpHost
和 schemeAndHttpHost
方法获取传入请求的 「host」:
$request->host();
$request->httpHost();
$request->schemeAndHttpHost();
获取请求方法
method
方法将返回请求的 HTTP 动词。您可以使用 isMethod
方法来验证 HTTP 动词是否与给定的字符串匹配:
$method = $request->method();
if ($request->isMethod('post')) {
// ...
}
请求头
您可以使用header
方法从 Illuminate\Http\Request
实例中检索请求标头。如果请求中没有该标头,则返回 null
。但是,header
方法接受两个可选参数,如果该标头在请求中不存在,则返回第二个参数:
$value = $request->header('X-Header-Name');
$value = $request->header('X-Header-Name', 'default');
hasHeader
方法可用于确定请求是否包含给定的标头:
if ($request->hasHeader('X-Header-Name')) {
// ...
}
为了方便起见,bearerToken
方法可用于从 Authorization
标头检索授权标记。如果不存在此类标头,将返回一个空字符串:
$token = $request->bearerToken();
请求 IP 地址
ip
方法可用于检索向您的应用程序发出请求的客户端的 IP 地址:
$ipAddress = $request->ip();
内容协商
Laravel 提供了几种方法,通过 Accept
标头检查传入请求的请求内容类型。首先,getAcceptableContentTypes
方法将返回包含请求接受的所有内容类型的数组:
$contentTypes = $request->getAcceptableContentTypes();
accepts
方法接受一个内容类型数组,并在请求接受任何内容类型时返回 true
。否则,将返回 false
:
if ($request->accepts(['text/html', 'application/json'])) {
// ...
}
您可以使用 prefers
方法确定给定内容类型数组中的哪种内容类型由请求最具优势。如果请求未接受任何提供的内容类型,则返回 null
:
$preferred = $request->prefers(['text/html', 'application/json']);
由于许多应用程序仅提供 HTML 或 JSON,因此您可以使用 expectsJson
方法快速确定传入请求是否期望获得 JSON 响应:
if ($request->expectsJson()) {
// ...
}
PSR-7 请求
PSR-7 标准 指定了 HTTP 消息的接口,包括请求和响应。如果您想要获取 PSR-7 请求的实例而不是 Laravel 请求,您首先需要安装一些库。Laravel 使用 Symfony HTTP Message Bridge 组件将典型的 Laravel 请求和响应转换为 PSR-7 兼容的实现:
composer require symfony/psr-http-message-bridge
composer require nyholm/psr7
安装这些库之后,您可以通过在路由闭包或控制器方法上的请求接口进行类型提示来获取 PSR-7 请求:
use Psr\Http\Message\ServerRequestInterface;
Route::get('/', function (ServerRequestInterface $request) {
// ...
});
如果您从路由或控制器返回 PSR-7 响应实例,它将自动转换回 Laravel 响应实例,并由框架显示。
输入
检索输入
检索所有输入数据
您可以使用 all
方法将所有传入请求的输入数据作为 array
检索。无论传入请求是否来自 HTML 表单或 XHR 请求,都可以使用此方法:
$input = $request->all();
使用 collect
方法,您可以将所有传入请求的输入数据作为 集合 检索:
$input = $request->collect();
collect
方法还允许您将传入请求的子集作为集合检索:
$request->collect('users')->each(function (string $user) {
// ...
});
检索输入值
使用几个简单的方法,无论请求使用了哪种 HTTP 动词,都可以从您的 Illuminate\Http\Request
实例访问所有用户输入。input
方法可用于检索用户输入:
$name = $request->input('name');
您可以将默认值作为 第二个参数传递给 input
方法。如果请求中不存在所请求的输入值,则返回此值:
$name = $request->input('name', 'Sally');
处理包含数组输入的表单时,请使用「.」符号访问数组:
$name = $request->input('products.0.name');
$names = $request->input('products.*.name');
您可以调用不带任何参数的 input
方法,以将所有输入值作为关联数组检索出来:
$input = $request->input();
从查询字符串检索输入
虽然 input
方法从整个请求消息载荷(包括查询字符串)检索值,但 query
方法仅从查询字符串检索值:
$name = $request->query('name');
如果请求的查询字符串值数据不存在,则将返回此方法的第二个参数:
$name = $request->query('name', 'Helen');
您可以调用不带任何参数的 query
方法,以将所有查询字符串值作为关联数组检索出来:
$query = $request->query();
检索 JSON 输入值
当向您的应用程序发送 JSON 请求时,只要请求的 Content-Type
标头正确设置为 application/json
,您就可以通过 input
方法访问 JSON 数据。您甚至可以使用「.」语法来检索嵌套在 JSON 数组/对象中的值:
$name = $request->input('user.name');
检索可字符串化的输入值
您可以使用 string
方法将请求的输入数据检索为 Illuminate\Support\Stringable
的实例,而不是将其作为基本 string
检索:
$name = $request->string('name')->trim();
检索布尔值输入
处理类似复选框的 HTML 元素时,您的应用程序可能会接收到实际上是字符串的「true」。例如,「true」或「on」。为了方便起见,您可以使用 boolean
方法将这些值作为布尔值检索。boolean
方法对于 1,「1」,true,「true」,「on」和「yes」,返回 true
。所有其他值将返回 false
:
$archived = $request->boolean('archived');
检索日期输入值
为了方便起见,包含日期 / 时间的输入值可以使用 date
方法检索为 Carbon 实例。如果请求中不包含给定名称的输入值,则返回 null
:
$birthday = $request->date('birthday');
date
方法可接受的第二个和第三个参数可用于分别指定日期的格式和时区:
$elapsed = $request->date('elapsed', '!H:i', 'Europe/Madrid');
如果输入值存在但格式无效,则会抛出一个 InvalidArgumentException
异常;因此,在调用 date
方法之前建议对输入进行验证。
检索枚举输入值
还可以从请求中检索对应于 PHP 枚举 的输入值。如果请求中不包含给定名称的输入值或枚举没有与输入值匹配的备份值,则返回 null
。enum
方法接受输入值的名称和枚举类作为其第一个和第二个参数:
use App\Enums\Status;
$status = $request->enum('status', Status::class);
通过动态属性检索输入
您也可以使用 Illuminate\Http\Request
实例上的动态属性访问用户输入。例如,如果您的应用程序的表单之一包含一个 name
字段,则可以像这样访问该字段的值:
$name = $request->name;
使用动态属性时,Laravel 首先会在请求负载中查找参数的值,如果不存在,则会在匹配路由的参数中搜索该字段。
检索输入数据的一部分
如果您需要检索输入数据的子集,则可以使用 only
和 except
方法。这两个方法都接受一个单一的 array
或动态参数列表:
$input = $request->only(['username', 'password']);
$input = $request->only('username', 'password');
$input = $request->except(['credit_card']);
$input = $request->except('credit_card');
only
方法返回您请求的所有键 / 值对;但是,它不会返回请求中不存在的键 / 值对。
判断输入是否存在
您可以使用 has
方法来确定请求中是否存在某个值。如果请求中存在该值则 has
方法返回 true
:
if ($request->has('name')) {
// ...
}
当给定一个数组时,has
方法将确定所有指定的值是否都存在:
if ($request->has(['name', 'email'])) {
// ...
}
whenHas
方法将在请求中存在一个值时执行给定的闭包:
$request->whenHas('name', function (string $input) {
// ...
});
可以通过向 whenHas
方法传递第二个闭包来执行,在请求中没有指定值的情况下:
$request->whenHas('name', function (string $input) {
// "name" 值存在...
}, function () {
// "name" 值不存在...
});
hasAny
方法返回 true
,如果任一指定的值存在,则它返回 true
:
if ($request->hasAny(['name', 'email'])) {
// ...
}
如果您想要确定请求中是否存在一个值且不是一个空字符串,则可以使用 filled
方法:
if ($request->filled('name')) {
// ...
}
whenFilled
方法将在请求中存在一个值且不是空字符串时执行给定的闭包:
$request->whenFilled('name', function (string $input) {
// ...
});
可以通过向 whenFilled
方法传递第二个闭包来执行,在请求中没有指定值的情况下:
$request->whenFilled('name', function (string $input) {
// "name" 值已填写...
}, function () {
// "name" 值未填写...
});
要确定给定的键是否不存在于请求中,可以使用 missing
和 whenMissing
方法:
if ($request->missing('name')) {
// ...
}
$request->whenMissing('name', function (array $input) {
// "name" 值缺失...
}, function () {
// "name" 值存在...
});
合并其他输入
有时,您可能需要手动将其他输入合并到请求的现有输入数据中。为此,可以使用 merge
方法。如果给定的输入键已经存在于请求中,它将被提供给 merge
方法的数据所覆盖:
$request->merge(['votes' => 0]);
如果请求的输入数据中不存在相应的键,则可以使用 mergeIfMissing
方法将输入合并到请求中:
$request->mergeIfMissing(['votes' => 0]);
旧输入
Laravel 允许你在两次请求之间保留数据。这个特性在检测到验证错误后重新填充表单时特别有用。但是,如果您使用 Laravel 的包含的 表单验证,不需要自己手动调用这些方法,因为 Laravel 的一些内置验证功能将自动调用它们。
闪存输入到 Session
在 Illuminate\Http\Request
类上的 flash
方法将当前输入闪存到 session,以便在下一次用户请求应用程序时使用:
$request->flash();
您还可以使用 flashOnly
和 flashExcept
方法闪存一部分请求数据到 Session。这些方法对于将敏感信息(如密码)排除在 Session 外的情况下非常有用:
$request->flashOnly(['username', 'email']);
$request->flashExcept('password');
闪存输入后重定向
由于您通常希望闪存输入到 Session,然后重定向到以前的页面,因此您可以使用 withInput
方法轻松地将输入闪存到重定向中:
return redirect('form')->withInput();
return redirect()->route('user.create')->withInput();
return redirect('form')->withInput(
$request->except('password')
);
检索旧输入值
若要获取上一次请求所保存的旧输入数据,可以在 Illuminate\Http\Request
的实例上调用 old
方法。old
方法会从 session 中检索先前闪存的输入数据:
$username = $request->old('username');
此外,Laravel 还提供了一个全局辅助函数 old
。如果您在 Blade 模板 中显示旧的输入,则更方便使用 old
辅助函数重新填充表单。如果给定字段没有旧输入,则会返回 null
:
<input type="text" name="username" value="{{ old('username') }}">
Cookies
检索请求中的 Cookies
Laravel 框架创建的所有 cookies 都经过加密并签名,这意味着如果客户端更改了 cookie 值,则这些 cookie 将被视为无效。要从请求中检索 cookie 值,请在 Illuminate\Http\Request
实例上使用 cookie
方法:
$value = $request->cookie('name');