强大的 Illuminate Request 对象

Laravel

当我第一次使用 Symfony 框架时, 它的 http-foundation 组件让我大吃一惊。 在我看来, 它是支持现代 PHP web 应用最重要的包之一。 HTTP foundation 为请求和响应提供了面向对象的接口,同时也填补了 PHP 在这方面特性的空白。

在 Laravel 框架中, Illuminate 的请求和响应对象继承自 HTTP foundation 组件, 并在核心类之上提供了一个优秀的 API, 使用起来非常优雅。

在这篇文章中, 让我们来探讨一下 Laravel 通过 Illuminate Request 对象提供的一些语法糖和有用的方法!

Illuminate\Http\Request 这个类将功能组织在以下三个 traits 中:

  • InteractsWithContentTypes
  • InteractsWithInput
  • InteractsWithFlashData

在这里我希望在我没有给你介绍具体的新内容时,你可以自己发现一两个有用的方法。 我希望对 Laravel 框架不熟悉的开发者能深入研究这些重要类的源码, 并体会到 Illuminate Request 对象带来的便利性。

Interacting with Content Types

在请求/响应的生命周期中,你有时需要通过 HTTP 的标头 Content-Type 来确定请求的类型。围绕着这个头,InteractsWithContentTypes 给我们提供了大量的语法糖来处理重复的事情。

具体来说,我们可以使用以下的方法来判断用户是否要求返回 JSON,这些方法都会返回给我们一个boolean 值。

$request->wantsJson();
$request->expectsJson();
$request->isJson();
$request->acceptsJson();

首先,isJson()方法显式检查Content-Type头中的/json+jsonisJson() 方法可用于确定客户端是否发送JSON。

细化了isJson()wantsJson()之间的区别:wantsJson()在形成适当的标题时会被Accept标头赋予对请求的响应,而isJson()用于确定当前请求的格式。

类似地,expectsJson()方法确定用户在以下情况下是否合理地期望JSON响应:

  • true如果请求是AJAX请求而不是PJAX请求,并且接受任何内容类型(*/*)
  • 要么
  • 如果上述情况不正确,则推迟到wantsJson()

最后,acceptsJson() 方法可用于确定application/json是否在可接受的响应类型内。 acceptsJson() 方法在称为 accepts() 的相同特征中使用更通用的方法,该方法采用字符串或内容类型数组:

$request->accepts(['application/xml', 'text/xml']);

我要在此特征中提及的最后一种方法是format()方法,您可以使用该方法来确定预期响应中的格式(具有可选的默认值):

// 根据请求确定格式
// 如果找不到格式,则返回`json`
// 在可接受的内容类型内
$request->format('json');

您还可以通过浏览 InteractsWithContentTypes.php trait.

与输入交互

我为使用HTTP输入提供的便利是扩展的Illuminate Request对象最喜欢的部分。它在Laravel应用程序中为您可能会重复编写的样板代码提供了极大的便利和实用性。

InteractsWithInput特征的主力是** input()**方法。该方法很简单,因此在深入了解如何使用之前,我将在此处向您展示:

/**
 * 从请求中检索输入项目.
 *
 * @param  string|null  $key
 * @param  mixed  $default
 * @return mixed
 */
public function input($key = null, $default = null)
{
    return data_get(
        $this->getInputSource()->all() + $this->query->all(), $key, $default
    );
}

如果您不了解,data_get()帮助程序与此方法结合使用,可提供一站式服务,可从各种来源获取输入:

  • 输入 ParameterBag
  • 请求查询

通常,您可以使用此方法获取POST|PUT|PATCH参数,甚至可以使用它来访问查询字符串中的输入:

$email = $request->input('email');

主要的Request类还利用InteractsWithInput特征的all()方法来提供输入的快捷方式:

// 内部调用 $request->all() 并尝试
// 从请求中获取输入
$request->email

我的另一个喜欢的是关于此特征的only()方法。通常,除了要尝试访问并可能存储的数据外,我想消除所有内容:

// 通过 func_get_args() 获取可变参数
$request->only('email', 'password');

// 或通过数组
$request->only(['email', 'password']);

我更喜欢only()将请求中的内容列入白名单,并避免意外的数据从客户端数据泄漏到应用程序中。

另一个有用的方法是将输入检索为 boolean,这对于确定输入是true还是false非常有用:

// 检查 opt_in 的布尔值, 默认为true
// 当输入为:
// "1", "true", "on", 和 "yes"
$request->boolean('opt_in', true);

此特征具有使用HTTP标头的有用方法:

// 从授权标头中获取令牌
// 删除 "Bearer" 前缀(如果存在)。
// 即, `Authorization: Bearer 1234`, 将返回 1234.
$request->bearerToken();

$request->hasHeader('X-Custom-Header');

$request->header('X-Custom-Header');

这些标头方法可以方便地避免从基础 Symfony 请求访问标头:

// 相当于 $request->header('X-Custom-Header');
$request->headers->get('X-Custom-Header');

// 相当于 $request->hasHeader('X-Custom-Header')
!is_null($request->headers->get('X-Custom-Header'));

使用输入时,其他一些有用的辅助方法包括:

// 除密码外的所有输入
$request->except('password');

// 查看请求是否包含密钥
$request->has('age');

// 查看请求是否具有以下任何键
$request->hasAny('age', 'height', 'weight');

// 获取输入和文件的所有键
$request->keys();

// 查看请求是否缺少输入
$request->missing('age');

// 查看输入是否为非空值
$request->filled('age');

// 查看是否填充了以下任何输入
$request->anyFilled('age', 'height', 'weight');

// Get ?id=12345
$request->query('id');

// 获取请求中所有文件的数组
$request->allFiles();

// 查看上传的数据是否包含给定密钥的文件
$request->hasFile('avatar');

// 从请求中获取文件
$request->file('avatar');

与 Flash 数据进行交互

服务器端应用程序中的一个常见需求是,当发生诸如验证错误之类的事件时,将请求数据存储在会话中。将数据刷新到会话可确保用户可以更正任何无效的表单输入,并存储请求中的所有相关数据以用于next 请求和响应。

您可能熟悉Blade文件中的 old() 帮助器,该帮助器使用来自上一个请求的刷新的会话数据填充输入值:

<input type="email" value="{{ old("email") }}" required />

实际上,old() 帮助器在此特征上确实遵循相同的 old() 方法:

function old($key = null, $default = null)
{
    return app('request')->old($key, $default);
}

但是我们如何首先在会话中获取数据?

如果您不熟悉Laravel,刷新会话数据可能看起来很神奇,因为Validation会自动执行此操作。发生验证错误时,框架会引发ValidationException,最终会通过响应通过异常处理程序在会话中存储闪存数据:

/**
 * 将验证异常转换为响应。
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Illuminate\Validation\ValidationException  $exception
 * @return \Illuminate\Http\Response
 */
protected function invalid($request, ValidationException $exception)
{
    return redirect($exception->redirectTo ?? url()->previous())
                ->withInput(Arr::except($request->input(), $this->dontFlash))
                ->withErrors($exception->errors(), $exception->errorBag);
}

请注意,$this->dontFlash重要地确保密码password_confirmation输入不存储在会话中。

大多数时候,验证器会负责将数据刷新到会话,但是您可以通过请求对象手动将输入刷新到会话:

// 将 $request->input() 数据存入 session
$request->flash();

要再次强调,请直接使用此方法时要小心,以确保您不会将敏感数据闪烁到用户的会话中。更保守地说,您可以使用请求对象的flashOnly()方法:

$request->flashOnly('email', 'first_name', 'last_name');

或者反过来:

$request->flashExcept('password', 'secret_input');

宏和更多

请记住,由于Listar请求对象继承 HTTP-foundation 请求,您拥有基础组件必须在您的指尖提供的所有内容。如果您想深入了解,我将链接到下面的组件文档。

除此之外,您还可以通过宏在应用程序中扩展Request对象。 Laravel使用Request::validate()方法做到这一点:

Request::macro('validate', function (array $rules, ...$params) {
    return validator()->validate($this->all(), $rules, ...$params);
});

学习更多

我希望这篇文章对那些希望发现Laravel应用程序核心HTTP层之上的有用工具的Laravel框架新手有所帮助。对于那些更熟悉Laravel的人,我希望本文在illustration Request对象中引入了一些新方法,或者启发您深入研究这些类。

我建议您查看以下资源,以了解有关Laravel中的请求和响应对象的更多信息:

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://laravel-news.com/the-mighty-illu...

译文地址:https://learnku.com/laravel/t/47353

本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!