目录

Laravel 11.x 请求


原文


介绍

Laravel 的 Illuminate\Http\Request 类提供了一种面向对象的方式来与当前应用程序处理的 HTTP 请求进行交互,同时可以检索请求中提交的输入、Cookies 和文件。

请求交互

访问请求

通过依赖注入进行获取当前HTTP请求的实例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
 
class UserController extends Controller
{
    /**
     * Store a new user.
     */
    public function store(Request $request): RedirectResponse
    {
        $name = $request->input('name');
 
        // Store the user...
 
        return redirect('/users');
    }
}

同样的也可以在闭包中使用:

1
2
3
4
5
use Illuminate\Http\Request;
 
Route::get('/', function (Request $request) {
    // ...
});

依赖注入和路由参数

如果控制器方法也需要来自路由参数的输入,则应该在其他依赖项之后列出路由参数。

例如,路由定义如下:

1
2
3
use App\Http\Controllers\UserController;
 
Route::put('/user/{id}', [UserController::class, 'update']);

那么控制器就应该按照以下方式进行定义:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?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
    {
        // Update the user...
 
        return redirect('/users');
    }
}

请求路由、主机和方法

检索请求路径

path方法返回请求的路径信息。

1
$uri = $request->path();

检查请求路径/路由

is方法允许验证传入请求路径是否与给定模式匹配。

可以将*字符用作通配符

1
2
3
if ($request->is('admin/*')) {
    // ...
}

routeIs方法,可以确定出入请求是否与命名路由匹配:

1
2
3
if ($request->routeIs('admin.*')) {
    // ...
}

检索请求URL

urlfullUrl方法可以检索传入请求的完整URL。

url方法将返回不带查询字符串的URL

fullUrl方法返回的URL包含查询字符串

1
2
3
$url = $request->url();
 
$urlWithQueryString = $request->fullUrl();

fullUrlWithQuery方法,可以将查询字符串数据追加到当前URL。

此方法将给定的查询字符串变量数组与当前查询字符串合并

1
$request->fullUrlWithQuery(['type' => 'phone']);

fullUrlWithoutQuery方法在没有给定查询字符串参数的情况下获取当前URL

1
$request->fullUrlWithoutQuery(['type']);

检索请求主机

hosthttpHostschemeAndHttpHost方法可以检索传入请求的主机

1
2
3
$request->host();
$request->httpHost();
$request->schemeAndHttpHost();

检索请求方法

method方法将返回请求的方式

isMethod方法用来验证HTTP请求方式是否与给定字符串匹配

1
2
3
4
5
$method = $request->method();
 
if ($request->isMethod('post')) {
    // ...
}

请求标头

header方法从Illuminate\Http\Request实例中检索请求标头。

如果不存在,则返回nullheader方法接受可选的第二个参数,如果不存在,则使用此参数

1
2
3
$value = $request->header('X-Header-Name');
 
$value = $request->header('X-Header-Name', 'default');

hasHeader方法用于确定请求是否包含给定的标头

1
2
3
if ($request->hasHeader('X-Header-Name')) {
    // ...
}

bearerToken方法可用于从Authorization标头中检索持有者令牌。

如果不存在,则返回空字符串

1
$token = $request->bearerToken();

请求IP地址

ip方法用于检索发出请求的IP地址

1
$ipAddress = $request->ip();

ips方法可以检索IP地址数组,包括代理转发的所有客户端IP地址

原始客户端IP地址将位于数组的末尾

1
$ipAddresses = $request->ips();

内容协商

Laravel 提供了几种方法,用于通过 Accept 标头检查传入请求的请求内容类型。

getAcceptableContentTypes方法返回一个数组,其中包含请求接受的所有内容类型。

1
$contentTypes = $request->getAcceptableContentTypes();

accepts方法接受内容类型的数组,

如果请求接受任何内容类型,则返回true,否则false

1
2
3
if ($request->accepts(['text/html', 'application/json'])) {
    // ...
}

prefers方法用来确定请求在给定的一组内容类型中最喜欢哪种内容类型。

如果请求不接受所提供的任何内容类型,则会返回null

1
$preferred = $request->prefers(['text/html', 'application/json']);

expectsJson方法用于快速确定传入请求是否需要JSON响应

1
2
3
if ($request->expectsJson()) {
    // ...
}

PRS-7 请求

PSR-7 标准指定了 HTTP 消息的接口,包括请求和响应。如果要获取 PSR-7 请求的实例而不是 Laravel 请求,则首先需要安装一些库。Laravel 使用 Symfony HTTP 消息桥接组件将典型的 Laravel 请求和响应转换为兼容 PSR-7 的实现:

1
2
composer require symfony/psr-http-message-bridge
composer require nyholm/psr7

安装后,就可以通过在路由闭包或控制器方法上键入提示请求接口来获取PSR-7请求:

1
2
3
4
5
use Psr\Http\Message\ServerRequestInterface;
 
Route::get('/', function (ServerRequestInterface $request) {
    // ...
});

输入

检索输入

检索所有输入数据

all方法检索array所有传入入请求的输入数据。

无论请求来组HTML表单还是XHR请求,都适用。

1
$input = $request->all();

collect方法可以将传入请求的所有输入数据作为集合检索

1
$input = $request->collect();

collect方法还允许将传入的输入的子集作为集合检索

1
2
3
$request->collect('users')->each(function (string $user) {
    // ...
});

检索输入值

input方法用于检索用户输入

无参数调用,将所有输入值作为关联数组检索

1
2
3
4
5
6
$name = $request->input('name');

$input = $request->input();

// 如果请求的输入值不存在,则可以设置默认值:
$name = $request->input('name', 'Sally');

使用.表示法访问数组

1
2
3
$name = $request->input('products.0.name');
 
$names = $request->input('products.*.name');

从查询字符串中检索输入

query方法将仅从查询字符串中检索值

无参数调用,将所有查询字符串值检索为关联数组

1
2
3
4
5
6
$name = $request->query('name');

$name = $request->query('name', 'Helen');

// 不存在则使用给定的默认值
$name = $request->query('name', 'Helen');

检索JSON输入值

发送JSON请求时,只要请求Content-Type=application/json就可以通过input方法访问JSON数据。

也可以使用.语法来检索嵌套在JSON数组/对象中的值

1
$name = $request->input('user.name');

检索字符串输入值

string方法可以将请求数据作为Illuminate\Support\Stringable实例进行检索

1
$name = $request->string('name')->trim();

检索布尔值输入值

boolean方法将请求数据检索为布尔值

1
$archived = $request->boolean('archived');

检索日期输入值

date方法将包含日期/时间的输入值作为Carbon实例进行检索。

如果不存在,则返回null

1
$birthday = $request->date('birthday');

date方法接受的第二三参数可以分别用于指定日期的格式和时区

如果格式无效,则会抛出InvalidArgumentException异常

1
$elapsed = $request->date('elapsed', '!H:i', 'Europe/Madrid');

检索枚举输入值

enum方法可以从请求中检索与PHP枚举相对应的输入值。

如果请求不包括具有给定名称的输入值,或者枚举没有输入值匹配的支持值,则返回null

enum方法接受输入值的名称和枚举类作为其第一二参数

1
2
3
use App\Enums\Status;
 
$status = $request->enum('status', Status::class);

通过动态属性检索输入

可以使用Illuminate\Http\Request实例上的动态属性访问用户输入

1
$name = $request->name;

检索部分输入数据

onlyexcept方法可以检索输入数据的子集

两个方法都接受单个array或动态参数列表

only方法不会返回请求中不存在的键值对

1
2
3
4
5
6
7
$input = $request->only(['username', 'password']);
 
$input = $request->only('username', 'password');
 
$input = $request->except(['credit_card']);
 
$input = $request->except('credit_card');

输入状态

has方法可以确定请求中是否存在值。存在返回true

1
2
3
if ($request->has('name')) {
    // ...
}

has还可以接收一个数组,那么将确定是否存在所有指定的值

1
2
3
if ($request->has(['name', 'email'])) {
    // ...
}

hasAny如果存在任意指定值,则返回true

1
2
3
if ($request->hasAny(['name', 'email'])) {
    // ...
}

whenHas方法如果请求上存在值则将执行给定的闭包

1
2
3
$request->whenHas('name', function (string $input) {
    // ...
});

whenHas方法,如果请求中不存在指定的值,则可以将第二个闭包传递给将要执行的方法中

1
2
3
4
5
$request->whenHas('name', function (string $input) {
    // The "name" value is present...
}, function () {
    // The "name" value is not present...
});

filled方法用来确定请求中是否存在值并且不是空字符串

1
2
3
if ($request->filled('name')) {
    // ...
}

anyFilled方法如果任意一个指定的值不是空字符串,则返回true

1
2
3
if ($request->anyFilled(['name', 'email'])) {
    // ...
}

whenFilled如果请求上存在值并且不是空字符串,将执行给定的闭包

1
2
3
$request->whenFilled('name', function (string $input) {
    // ...
});

whenFilled如果不存在,则可以传递第二个闭包进行处理

1
2
3
4
5
$request->whenFilled('name', function (string $input) {
    // The "name" value is filled...
}, function () {
    // The "name" value is not filled...
});

missingwhenMissing方法用于确定请求中是否缺少给定的key

1
2
3
4
5
6
7
8
9
if ($request->missing('name')) {
    // ...
}
 
$request->whenMissing('name', function () {
    // The "name" value is missing...
}, function () {
    // The "name" value is present...
});

合并其他输入

merge方法,用于手动将其他输入合并到请求的现有输入数据中。

如果请求中已存在给定的输入key,则将会被覆盖掉

1
$request->merge(['votes' => 0]);

如果请求的输入数据中尚不存在响应的key,则mergeIfMissing方法可用于将输入合并到请求中

1
$request->mergeIfMissing(['votes' => 0]);

刷新会话输入

flash方法将刷新会话的当前输入。

以便在用户对应用程序的下一个请求期间可用

1
$request->flash();

flashOnlyflashExcept 方法用于将敏感信息排除在会话之外

1
2
3
$request->flashOnly(['username', 'email']);
 
$request->flashExcept('password');

刷新输入并重定向

withInput方法可以刷新输入并进行重定向

1
2
3
4
5
6
7
return redirect('form')->withInput();
 
return redirect()->route('user.create')->withInput();
 
return redirect('form')->withInput(
    $request->except('password')
);

检索旧输入

old方法将从会话中提取先前刷新的输入数据

1
$username = $request->old('username');

Cookies

从请求中检索Cookie

cookie方法将从请求中进行检索Cookie值

1
$value = $request->cookie('name');

输入修整和归一化

默认情况下,Laravel将Illuminate\Foundation\Http\Middleware\TrimStrings and Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull中间件包含在应用程序的全局中间件中了。这些中间件将自动修剪请求上的所有输入字符串字段,并将任何空字符串转换为null

禁用输入归一化

如果要对所有请求禁用此行为,可以通过调用应用程序 bootstrap/app.php 文件中 $middleware->remove 的方法从应用程序的中间件中删除两个中间件:

1
2
3
4
5
6
7
8
9
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
use Illuminate\Foundation\Http\Middleware\TrimStrings;
 
->withMiddleware(function (Middleware $middleware) {
    $middleware->remove([
        ConvertEmptyStringsToNull::class,
        TrimStrings::class,
    ]);
})

如果想要在应用程序中禁用对一部分请求的字符串修剪和空字符串转换,可以在应用程序的 bootstrap/app.php 文件中使用 trimStringsconvertEmptyStringsToNull 中间件方法。这两个方法都接受一个闭包数组,闭包应返回 true 或 false,以指示是否应跳过输入的规范化处理:

1
2
3
4
5
6
7
8
9
->withMiddleware(function (Middleware $middleware) {
    $middleware->convertEmptyStringsToNull(except: [
        fn (Request $request) => $request->is('admin/*'),
    ]);
 
    $middleware->trimStrings(except: [
        fn (Request $request) => $request->is('admin/*'),
    ]);
})

文件

检索上传的文件

file/Illuminate\Http\Request动态属性用于检索上传的文件

file方法返回Illuminate\Http\UploadedFile类实例,

1
2
3
$file = $request->file('photo');
 
$file = $request->photo;

hasFile方法确定请求中是否存在文件

1
2
3
if ($request->hasFile('photo')) {
    // ...
}

验证成功上传

isValid方法用于验证上传文件是否成功

1
2
3
if ($request->file('photo')->isValid()) {
    // ...
}

文件路径和扩展名

UploadedFile 类还包含用于访问文件的完全限定路径及其扩展名的方法。

extension 方法将尝试根据文件的内容猜测文件的扩展名。

此扩展可能与客户端提供的扩展不同

1
2
3
$path = $request->photo->path();
 
$extension = $request->photo->extension();

存储上传的文件

UploadedFile类的store方法将上传的文件移动到磁盘中,该磁盘可以是本地文件系统某一位置,也可以是 Amazon S3等云存储位置

store方法接受存储文件的路径,此路径不包含文件名,自动生成唯一ID作为文件名

1
2
3
$path = $request->photo->store('images');
 
$path = $request->photo->store('images', 's3');

如果不想自动生成文件名,则可以使用路径、文件名和磁盘名称作为其参数storeAs的方法

1
2
3
$path = $request->photo->storeAs('images', 'filename.jpg');
 
$path = $request->photo->storeAs('images', 'filename.jpg', 's3');

配置受信任的代理

启用Laravel应用程序中包含的Illuminate\Http\Middleware\TrustProxies中间件,可以快速自定义应用程序应信任的负载均衡或代理。

使用bootstrap/app.php文件中的trustProxies中间件方法指定受信任的代理:

1
2
3
4
5
6
->withMiddleware(function (Middleware $middleware) {
    $middleware->trustProxies(at: [
        '192.168.1.1',
        '192.168.1.2',
    ]);
})

也可以配置应受信任的代理标头:

1
2
3
4
5
6
7
8
->withMiddleware(function (Middleware $middleware) {
    $middleware->trustProxies(headers: Request::HEADER_X_FORWARDED_FOR |
        Request::HEADER_X_FORWARDED_HOST |
        Request::HEADER_X_FORWARDED_PORT |
        Request::HEADER_X_FORWARDED_PROTO |
        Request::HEADER_X_FORWARDED_AWS_ELB
    );
})

信任所有代理

1
2
3
->withMiddleware(function (Middleware $middleware) {
    $middleware->trustProxies(at: '*');
})

配置受信任的主机

启动Illuminate\Http\Middleware\TrustHosts 中间件来实现配置受信任的主机。

bootstrap/app.php 文件中调用 trustHosts 中间件方法。使用此方法的 at 参数,可以指定应用程序应响应的主机名。带有其他 Host 标头的传入请求将被拒绝:

1
2
3
->withMiddleware(function (Middleware $middleware) {
    $middleware->trustHosts(at: ['laravel.test']);
})

默认情况下,来自应用程序 URL 的子域的请求也会自动受信任。如果要禁用此行为,可以使用以下 subdomains 参数:

1
2
3
->withMiddleware(function (Middleware $middleware) {
    $middleware->trustHosts(at: ['laravel.test'], subdomains: false);
})