Laravel 文档阅读: HTTP 请求
获得请求实例
在控制器方法里,可以通过依赖注入的方式自动获得咱们的请求实例,也就是 Illuminate\Http\Request
类实例,这是用服务容器注入的。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UsersController extends Controller
{
/**
* Store a new user.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$name = $request->input('name');
//
}
}
依赖注入 & 路由参数
如果控制器方法还要接收路由参数,你应该把接收路由参数的参数位置放在所有依赖注入参数之后。比如,有这么一个路由:
Route::put('users/{id}', 'UsersController@update');
在控制器方法里,你还要依赖注入请求实例,还要呢,接收路由参数 id
。那你就要这么做:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UsersController extends Controller
{
/**
* Update the specified user.
*
* @param Request $request
* @param string $id
* @return Response
*/
public function update(Request $request, $id)
{
//
}
}
在路由的闭包里获得请求实例
在基于闭包的路由中,可以依赖注入请求实例:
use Illuminate\Http\Request;
Route::get('/', function (Request $request) {
//
});
请求路径 & 请求方法
Illuminate\Http\Request
实例对象提供了许多丰富的、检查应用程序中的 HTTP 请求信息的方法,并且 Illuminate\Http\Request
类自身继承了 Symfony\Component\HttpFoundation\Request
。在这里,我们仅讨论几个重要的方法。
获得请求路径
path
方法返回请求路径信息。如果请求路径是 http://domain.com/foo/bar
,那么用 path
方法得到的值是 foo/bar
:
$uri = $request->path();
path
方法验证当前的请求路径是否匹配给定的模式。你还可以使用通配符 *
:
if ($request->is('admin/*')) {
//
}
获得请求 URL
获得请求的完整路径请使用 url
和 fullUrl
方法。url
方法会返回不包含请求字符串的 URL,而 fullUrl
方法会返回包含请求字符串的 URL。
// Without Query String...
$url = $request->url();
// With Query String...
$url = $request->fullUrl();
获得请求方法
method
方法返回 HTTP 请求动词。而 isMethod
方法可以判断为指定的 HTTP 请求动词。
$method = $request->method();
if ($request->isMethod('post')) {
//
}
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 zendframework/zend-diactoros
依赖包安装完毕后,就可以在路由闭包或者控制器方法里依赖注入 PSR-7 请求实例对象了:
use Psr\Http\Message\ServerRequestInterface;
Route::get('/', function (ServerRequestInterface $request) {
//
});
需要注意的是,如果你从路由或者控制器里返回一个 PSR-7 响应实例,它会被自动转换为 Laravel 响应实例,便于框架处理。
TrimStrings
和 ConvertEmptyStringsToNull
中间件
在 App\Http\Kernel
类的 $middleware
属性里,包含两个中间件,TrimStrings
和 ConvertEmptyStringsToNull
,它们会在应用程序的每次请求中使用。TrimStrings
中间件用来修剪字符串(比如去掉字符串两端的空格);ConvertEmptyStringsToNull
中间件将空字符串转换为 null
,这就省去了我们一些琐碎的工作,得到规范化的字符串了。
如果要禁用这两个中间件,只要从 $middleware
属性中移除掉就可以了。
获得输入数据
获得输入数据的过程,就是操作 Illuminate\Http\Request
实例方法的过程。
获得所有的输入数据
使用 all
方法。该方法会得到一个数组,数组里就是输入数据。
$input = $request->all();
获得一条输入数据值
使用 input
方法,不论 HTTP 的请求类型如何,input
方法都能获得请求里的数据。
$name = $request->input('name');
还可以为 input
方法传递第二个参数,作为字段缺省值。当请求字段不在输入数据中,就会使用这个值。
$name = $request->input('name', 'Sally');
当操作数组形式的输入数据时,使用点(.
)符号:
$name = $request->input('products.0.name');
$names = $request->input('products.*.name');
获得查询字符串
input
方法是从整个请求中搜罗输入数据的,包括表单数据、查询字符串和路由参数等。但如果只是要从查询字符串获得输入数据的话,就使用 query
方法:
$name = $request->query('name');
同样,如果查询字段没有出现在查询字符串中,还可以为它指定缺省值:
$name = $request->query('name', 'Helen');
直接使用 query()
方法得到是一个包含所有查询字符串数据的关联数组:
$query = $request->query();
通过动态属性获得数据数据
可以在 Illuminate\Http\Request
实例上直接使用动态属获得输入数据。例如,如果传递过来的表单数据里包含一个 name
字段,可以这样获得它的值:
$name = $request->name;
使用动态属性时,Laravel 会从请求中尽可能得搜罗输入数据值,如果没找到,再去找路由参数。
获得 JSON 格式中的数据值
当项目接收的是 JSON 请求,也就是请求的 Content-Type
标头值为 application/json
的时候,使用点(.
)符号获得 JSON 字段值:
$name = $request->input('user.name');
获得局部输入数据
有时只需要获得输入数据的一个子集,这时要用到 only
和 except
方法。这两个方法接收一个数组或者参数列表:
$input = $request->only(['username', 'password']);
$input = $request->only('username', 'password');
$input = $request->except(['credit_card']);
$input = $request->except('credit_card');
需要注意的是,only
方法中列举的字段如果没有出现在请求字段里,那么最终返回的结果中将不会包含这个字段数据。
判断输入数据是否存在
使用 has
方法,该方法返回一个布尔值。如果请求数据里包含此字段,就会返回 true
,否则返回 false
:
if ($request->has('name')) {
//
}
has
方法还可以接收一个数组,返回的结果值表示是否数组里的所有字段都出现在了输入数据中:
if ($request->has(['name', 'email'])) {
//
}
如果要 判断出现在输入数据中的字段值是否为空,使用 filled
方法:
if ($request->filled('name')) {
//
}
旧输入数据
Laravel 能够将本次请求的数据保留到下一次,这个特性能实现表单验证失败后,再次返回表单填写页的时候,旧输入数据仍然填充在表单里。如果使用了 Laravel 的本身的验证特性,更是不需要你手动使用下面要说的这些方法了,因为内置的验证功能会自动调用这些方法。
闪存数据到 Session
Illuminate\Http\Request
类的 flash
方法会将当前输入数据闪存到 Session 中,使得在下一次的请求中还能获得这些数据。
$request->flash();
或者使用 flashOnly
/flashExcept
方法闪存一部分数据到 Session。这两个方法能让一些诸如密码的敏感信息不保存在 Session 中。
$request->flashOnly(['username', 'email']);
$request->flashExcept('password');
闪存数据后重定向
通常我们会在闪存完数据后,重定向到之前的页面。可以在 redirect
方法屁股后头跟上 withInput
方法实现这个功能:
return redirect('form')->withInput();
return redirect('form')->withInput(
$request->except('password')
);
获得旧数据
获得之前的请求闪存到 Session 里的数据,使用 Request
实例的 old
方法。old
方法会拉出闪存到 Session 中的对应数据:
$username = $request->old('username');
Laravel 还提供了一个全局的 old
辅助函数。在 Blade 模板里面使用这个方法显示数据会更加方便。如果 Session 中闪存的数据里不包含该条,就直接返回 null
:
<input type="text" name="username" value="{{ old('username') }}">
Cookies
从请求中获得 Cookie
Laravel 中生成的 Cookie 都会经过加密,并且使用认证码进行签名,所以客户端上的 Cookie 修改都被视为无效。获得请求里的 Cookie 值,使用 Illuminate\Http\Request
实例的 cookie
方法:
$value = $request->cookie('name');
为响应附加 Cookie
Illuminate\Http\Response
实例中也有一个 cookie
方法,让你可以为响应附加 Cookie,这个方法接收的 3 个参数分别是名称、值和有效时间。
return response('Hello World')->cookie(
'name', 'value', $minutes
);
cookie
方法还可以接受更多的参数,列举如下:
return response('Hello World')->cookie(
'name', 'value', $minutes, $path, $domain, $secure, $httpOnly
);
通常,这些参数与 PHP 原生 setcookie
方法的参数具有相同的目的和意义。
生成 Cookie 实例
你也可以选择先生成一个 Symfony\Component\HttpFoundation\Cookie
实例,在稍晚些将此 Cookie 实例附加到响应上。生成 Cookie 实例使用全局 cookie
辅助函数。只有当 Cookie 实例附加到响应实例上后,才会被发送回客户端:
$cookie = cookie('name', 'value', $minutes);
return response('Hello World')->cookie($cookie);
文件
获得上传文件
使用 Illuminate\Http\Request
实例的 file
方法或者动态属性获得上传文件。file
方法返回 Illuminate\Http\UploadedFile
实例,UploadedFile
这个类继承了 PHP 的 SplFileInfo
类,提供了丰富地操作文件的方法。
$file = $request->file('photo');
$file = $request->photo;
还可以使用 hasFile
方法判断请求里是否包含指定的上传文件:
if ($request->hasFile('photo')) {
//
}
上传文件是否有效
上传文件获得后,还可以使用 isValid
方法检查文件是否没有问题、是有效的:
if ($request->file('photo')->isValid()) {
//
}
上传文件路径 & 扩展名
UploadedFile
类还包括查询文件完整路径和扩展名的方法。extension
方法会基于文件内容猜测文件扩展名,得到的这个文件扩展名或许与在客户端提供的扩展名不一样:
$path = $request->photo->path();
$extension = $request->photo->extension();
其他文件方法
在 UploadedFile
实例上还有大量其他可以使用的方法。查阅 API 文档 获得更多信息。
保存上传文件
保存上传文件,需要先配置 config/filesystems.php
文件。UploadedFile
类有一个 store
方法用来移动上传文件到你的一个「硬盘」里,可能是本地文件系统,也可能是像 Amazon S3 这样的远程云存储服务。
store
方法接收的路径是相对路径,是相对于文件系统根目录的。该路径不应该包含文件名,因为会自动生成一个唯一 ID 作为文件名。
store
方法接收的第二个可选参数是保存文件使用的硬盘。store
方法返回的是相对于硬盘根目录的路径:
$path = $request->photo->store('images');
$path = $request->photo->store('images', 's3');
如果不使用自动生成的文件名,而是使用自己指定的文件名(包含扩展名),那么就要用 storeAs
方法,它接收路径、文件名和硬盘名作为参数:
$path = $request->photo->storeAs('images', 'filename.jpg');
$path = $request->photo->storeAs('images', 'filename.jpg', 's3');
配置可信代理
当你的应用程序运行在终止 TLS / SSL 证书的负载平衡器后面,你可能会看到你的应用程序有时候不生成 HTTPS 链接。通常这是因为您的应用程序正在 80 端口上从你的负载平衡器上转发流量,而且不知道应该生成安全链接。
为了解决这个问题,需要在你的应用程序中使用 App\Http\Middleware\TrustProxies
中间件。这个中间件允许你快速自定义受应用程序信任的负载平衡器或者代理。你的信任代理应该列举在该中间件的 $proxies
属性内。除了配置可信代理之外,您还可以配置代理发送的标头,其中包含有关原始请求的信息:
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Fideloper\Proxy\TrustProxies as Middleware;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array
*/
protected $proxies = [
'192.168.1.1',
'192.168.1.2',
];
/**
* The current proxy header mappings.
*
* @var array
*/
protected $headers = [
Request::HEADER_FORWARDED => 'FORWARDED',
Request::HEADER_X_FORWARDED_FOR => 'X_FORWARDED_FOR',
Request::HEADER_X_FORWARDED_HOST => 'X_FORWARDED_HOST',
Request::HEADER_X_FORWARDED_PORT => 'X_FORWARDED_PORT',
Request::HEADER_X_FORWARDED_PROTO => 'X_FORWARDED_PROTO',
];
}
信任所有代理
如果你正在使用 Amazon AWS 或其他「云」负载平衡器提供商,可能不知道实际平衡器的 IP 地址。 在这种情况下,您可以使用 **
来信任所有代理:
/**
* The trusted proxies for this application.
*
* @var array
*/
protected $proxies = '**';
本作品采用《CC 协议》,转载必须注明作者和本文链接