HTTP 请求

获取请求

要通过依赖注入的方式获取 HTTP 请求的实例,就必须在控制器的构造器或方法中,使用 Illuminate\Http\Request 类型提示。当前的请求实例便会自动由 服务容器 注入:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;

class UserController extends Controller
{
    /**
     * 保存新的用户。
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        $name = $request->input('name');

        //
    }
}

如果控制器方法也有输入数据是从路由参数传入的,只需将路由参数置于其它依赖之后。举例来说,如果你的路由是这样定义的:

Route::put('user/{id}', 'UserController@update');

只要像下方一样定义控制器方法,就可以使用 Illuminate\Http\Request 类型提示,同时获取到你的路由参数 id

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;

class UserController extends Controller
{
    /**
     * 更新指定的用户。
     *
     * @param  Request  $request
     * @param  int  $id
     * @return Response
     */
    public function update(Request $request, $id)
    {
        //
    }
}

基本请求信息

Illuminate\Http\Request 的实例提供了多种方法来用于检查应用程序的 HTTP 请求。Larevel 的 Illuminate\Http\Request 继承了 Symfony\Component\HttpFoundation\Request 类。下方是该类的几个有用的方法:

获取请求的 URI

path 方法会返回请求的 URI。所以,如果接收到的请求目标是 http://domain.com/foo/bar,那么 path 方法就会返回 foo/bar

$uri = $request->path();

is 方法可以验证接收到的请求 URI 与指定的规则是否相匹配。使用此方法时你可以将 * 符号作为通配符:

if ($request->is('admin/*')) {
    //
}

使用 url 方法,可以获取完整的网址,fullUrl 方法可以获取到带 get 请求参数的完整网址:

// 不包含请求字串
$url = $request->url();

// 包含请求字串(请求字串如:`?id=2`)
$url = $request->fullUrl();

你可以获取整个 URL ,然后在后面再增加请求字串,如: http://domain.com/foo 执行以下代码后会产生 http://domain.com/foo?bar=baz

$url = $request->fullUrlWithQuery(['bar' => 'baz']);

获取请求的方法

method 方法会返回此次请求的 HTTP 动作。也可以通过 isMethod 方法来验证 HTTP 动作和指定的字符串是否相匹配:

$method = $request->method();

if ($request->isMethod('post')) {
    //
}

PSR-7 请求

PSR-7 标准制定的 HTTP 消息接口包含了请求及响应。如果你想获得一个 PSR-7 的请求实例,你就必须先安装几个函数库。Laravel 使用 Symfony 的 HTTP 消息桥接组件,将原 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 的响应实例并显示。

获取输入数据

获取特定输入值

你可以通过 Illuminate\Http\Request 的实例,借助几个简洁的方法获取所有的用户输入数据。而不需要去担心发出请求时使用的 HTTP 动作,因为它们获取输入数据的方式都是相同的。

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

此外,可以使用 Illuminate\Http\Request 的属性访问用户输入。例如,如果你应用程序的表单含有一个 name 字段,你可以从传递的字段访问它的值,像这样:

$name = $request->name;

你可以在 input 方法的第二个参数中传入一个默认值。当请求的输入数据不存在于此次请求时,就会返回默认值:

$name = $request->input('name', 'Sally');

如果是「数组」形式的输入数据,则可以使用「点」语法来获取数组:

$name = $request->input('products.0.name');

$names = $request->input('products.*.name');

获取 JSON 输入信息

当你发送 JSON 数据到应用的时候,只要请求表头设置了 Content-Typeapplication/json,你就可以直接从 input 方法中读取到内容,你甚至可以使用 语法来读取 JSON 数组:

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

确认是否有输入值

要判断数据是否存在于此次请求,可以使用 has 方法。当该数据存在 并且 字符串不为空时,has 方法就会传回 true

if ($request->has('name')) {
    //
}

获取所有输入数据

你也可以使用 all 方法以 数组 形式获取到所有输入数据:

$input = $request->all();

获取部分输入数据

如果你想获取输入数据的子集,则可以使用 onlyexcept 方法。这两个方法都接受单个数组或是动态列表作为参数:

$input = $request->only(['username', 'password']);

$input = $request->only('username', 'password');

$input = $request->except(['credit_card']);

$input = $request->except('credit_card');

动态属性

此外,你也可以通过使用 Illuminate\Http\Request 实例上的动态属性来访问用户输入。例如,如果你的应用表单包含 name 字段,那么可以像这样访问提交的值:

$name = $request->name;

Laravel 在处理动态属性的优先级是,从请求的数据中查找,没有的话再到路由参数中找。

旧输入数据

Laravel 可以让你将本次的输入数据保留到下一次请求发送前。对于在表单验证失败后重新填入表单值相当有用。当然,如果你使用 Laravel 的 验证服务,你就不需要再手动使用这些方法,因为 Laravel 的一些内置验证功能会自动调用它们。

将输入数据闪存至 Session

Illuminate\Http\Request 实例的 flash 方法会将当前的输入数据存进 Session 中,所以下次用户发出请求至应用程序时就可以使用它们:

$request->flash();

你也可以使用 flashOnlyflashExcept 方法将请求数据的子集保存至 Session:

$request->flashOnly('username', 'email');

$request->flashExcept('password');

闪存输入数据至 Session 后重定向

你可能需要将输入数据闪存并重定向至前一页,这时只要在重定向方法后加上 withInput 即可:

return redirect('form')->withInput();

return redirect('form')->withInput($request->except('password'));

获取旧输入数据

若要获取上一次请求后所闪存的输入数据,则可以使用 Request 实例中的 old 方法。old 方法提供一个简便的方式从 Session 取出被闪存的输入数据:

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

Laravel 也提供了全局辅助函数 old。如果你要在 Blade 模板 中显示旧输入数据,可以使用更加方便的 old 辅助函数:

<input type="text" name="username" value="{{ old('username') }}">

Cookies

从请求取出 Cookie 值

Laravel 框架创建的每个 cookie 都会被加密并且加上认证标识,这代表着用户擅自更改的 cookie 都会失效。若要从此次请求获取 cookie 值,你可以使用 Illuminate\Http\Request 实例中的 cookie 方法:

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

将新的 Cookie 附加到响应

Laravel 提供了全局辅助函数 cookie,可通过简易的工厂生成新的 Symfony\Component\HttpFoundation\Cookie 实例。可以在 Illuminate\Http\Response 实例之后加上 withCookie 方法来把 cookie 附加至响应:

$response = new Illuminate\Http\Response('Hello World');

$response->withCookie(cookie('name', 'value', $minutes));

return $response;

如果要创建一个可长期存在,为期五年的 cookie,可以先调用 cookie 辅助函数且不带入任何参数,再使用 cookie 工厂的 forever 方法,接着将 forever 方法拼接在返回的 cookie 工厂之后:

$response->withCookie(cookie()->forever('name', 'value'));

译者注: 关于 Cookie,需要注意一点,默认 Laravel 创建的所有 Cookie 都是加密过的,创建未加密的 Cookie 的方法请见 【小技巧分享】在 Laravel 中设置没有加密的 cookie

上传文件

获取上传文件

你可以使用 Illuminate\Http\Request 实例中的 file 方法获取上传的文件。file 方法返回的对象是 Symfony\Component\HttpFoundation\File\UploadedFile 类的实例,该类继承了 PHP 的 SplFileInfo 类,并提供了许多和文件交互的方法:

$file = $request->file('photo');

确认文件是否有上传

你可以使用请求的 hasFile 方法确认上传的文件是否存在:

if ($request->hasFile('photo')) {
    //
}

确认上传的文件是否有效

除了检查上传的文件是否存在外,你也可以通过 isValid 方法验证上传的文件是否有效:

if ($request->file('photo')->isValid()) {
    //
}

移动上传的文件

若要移动上传的文件至新位置,则必须使用 move 方法。该方法会将文件从缓存位置(由你的 PHP 配置决定)移动至你指定的永久保存位置:

$request->file('photo')->move($destinationPath);

$request->file('photo')->move($destinationPath, $fileName);

其它上传文件的方法

UploadedFile 的实例还有许多可用的方法,可以到 该对象的 API 文档 了解这些方法的详细信息。


{note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。

转载请注明:本文档由 Laravel China 社区 [laravel-china.org] 组织翻译。

文档永久地址: http://d.laravel-china.org