响应对象, 代表着 发送给最终用户的应用程序的响应, 由 header, cookie, content 和一些其他的在用户浏览器渲染页面时要用到的指令组成.

Laravel 的 Illuminate\Http\Response 类拓展自 Symfony 的 Symfony\Component\HttpFoundation\Response 类.

在控制器中使用和创建响应对象

  1. Route::get('route', function(){
  2. return new Illuminate\Http\Response('hello');
  3. });
  4. // same
  5. Route::get('route', function(){
  6. return response('hello');
  7. });

以上, 仅仅创建响应, 给它一些数据, 然后返回给最终用户,我们还可以做更多的事.

Route::get('route', function(){
    return response('Error', 400)
        ->header('X-Header-Name', 'header-value')
        ->cookie('cookie-name', 'cookie-value');
});

特殊的响应类型

有一些特殊的响应类型, 例如:视图, 下载, 文件, JSON. 这些每一个都是预定义的宏, 可以重复应用于特定的 header 或 content 结构中.

视图响应

// 返回视图并设置 header
Route::get('/', function(XmlGetterService $xml){
    $data = $xml->get();
    return response()
        ->view('xml-structure', $data)
        ->header('Content-Type', 'text/xml');
});

下载视图

有时你需要你的用户下载一个文件. download() 响应使这变得很简单.

public function export(){
    /**
     * 参数1 你希望用户下载的 文件路径, 如果是 生成的文件 你要临时存储一下 ( 必传 )
     * 参数2 下载后的 保存的名字 , 如果不传, 将随机生成
     * 参数3  header 的 array 
     */
    return response()
        ->download('download/file.csv', 'export.csv',['header'=>'value']);
}

public function otherExport(){
    return response()->download('file.pdf');
}

//  下载之后 删除原始文件
public function exportThenDel(){
    return response()
        ->download('file.csv', 'newfile.csv')
        ->deleteFileAfterSend();
}

文件响应

文件响应, 类似于下载响应, 不同之处在于 文件响应是让浏览器直接显示文件, 而不是下载, 最常见的是图片和pdf.

public function invoice(){
    /**
     * 参数1 文件路径
     * 参数2 header 的数组
     */
    return response()->file("./invoice/{$id}.pdf", ['header'=>'value']);
}

JSON 响应

JSON 响应很普遍, 尽管它实现并不复杂, 它也是一个自定义响应.

JSON 响应就是把数据转换成 JSON 格式(使用 json_encode()), 并且设置 Content-Typeapplication/json. 你也可以使用 setCallback() 方法,创建 JSONP 来代替 JSON.

// JSON 
public function contacts()
{
    return response()->json(Contact::all());
}

// JSONP
public function jsonpContacts(Request $request)
{
    return response()
        ->json(Contact::all())
        ->setCallback($request->input('callback'));
}

// 不使用模型
public function nonEloquentContacts()
{
    return response()->json(['Tom', 'Jerry']);
}

重定向响应

重定向 别调用的时, 没有用到 response() 方法. 它和以上我们谈到的响应有点不同, 但它也属于响应的一种. 重定义, 返回一个 Laravel 路由给用户, 告诉用户是重定向(通常 301 状态)到上个页面或者其他页面.

技术上来讲, 你可以在 response() 上调用一个 redirect, 作为返回, 就像这样 return response()->redirectTo('/') , 但是更多时候我们使用 redirect 的一些特别定制的全局函数.

  • redirect() 全局函数 可以创建一个 重定向响应, 等价于 redirect()->to()
  • back() 全局函数 是 redirect()->back() 的缩写 返回上一页的意思, 在验证用户输入时候很有用.
return redirect('account/payment');
return redirect()->to('account/payment'); // 字符串
return redirect()->route('account.payment'); // 路由名
return redirect()->action('AccountController@showPayment'); 

// If redirecting to an external domain
return redirect()->away('https://tighten.co'); // 外部链接

// If named route or controller needs parameters 传参数
return redirect()->route('contacts.edit', ['id' => 15]);
return redirect()->action('ContactsController@edit', ['id' => 15]);

back() 用于校验

public function store()
{
    // If validation fails...
    return back()->withInput();
}

重定向携带闪存数据, 常用于 成功或失败的提示

Route::post('contacts', function () {
    // Store the contact
    return redirect('dashboard')->with('message', 'Contact created!');
});

Route::get('dashboard', function () {
    // Get the flashed data from session--usually handled in Blade template
    echo session('message');
});

自定义响应宏

你可以使用响应宏创造你自己的自定义响应, 宏 允许你对响应和响应内容做一系列修改.

例子: 创建 json 响应宏 (仅用于理解)

...

/**
 * 这是 创建宏
 * 
 * 你应该创建一个自定义的服务提供者,绑定这些
 * 这里 仅用 AppServiceProvider 
 */
class AppServiceProvider
{
    public function boot()
    {
        Response::macro('myJson', function ($content) {
            return response(json_encode($content))
                ->withHeaders(['Content-Type' => 'application/json']);
        });
    }

    ...
}

// 使用 宏
return response()->myJson(['name' => 'Sangeetha']);

The Responsable interface

如果你想自定义返回的响应的方式, 而宏没有提供足够的空, 或者您希望您的任何对象都能够以自己的显示方式逻辑作为“响应”返回,那么 Responsable 接口( 在Laravel 5.5中引入)非常适合您。

要实现 Illuminate\Contracts\Support\Responsable 接口, 必须实现 toResponse() 方法, 它需要返回一个 Illuminate Response object.

最简单的例子

...
use Illuminate\Contracts\Support\Responsable;

class MyJson implements Responsable
{
    public function __construct($content)
    {
        $this->content = $content;
    }

    public function toResponse()
    {
        return response(json_encode($this->content))
            ->withHeaders(['Content-Type' => 'application/json']);
    }
// 使用 就像使用 宏
return new MyJson(['name' => 'Sangeetha']);

这里可能和宏没什么区别, 也没啥优势. Responsable interface 真正闪光的地方在于, 被用于更加复杂的控制器操作. 一个常见的例子就是, 用于创建 view models (or view objects).

例: Using Responsable to create a view object

...
use Illuminate\Contracts\Support\Responsable;

class GroupDonationDashboard implements Responsable
{
    public function __construct($group)
    {
        $this->group = $group;
    }

    public function budgetThisYear()
    {
        // ...
    }

    public function giftsThisYear()
    {
        // ...
    }

    public function toResponse()
    {
        return view('groups.dashboard')
            ->with('annual_budget', $this->budgetThisYear())
            ->with('annual_gifts_received', $this->giftsThisYear());
    }

这下开始变得有点意思了—将复杂的视图准备工作移到 专用的可测试 的对象中,保持控制器的整洁.

这是控制器代码:

...
class GroupController
{
    public function index(Group $group)
    {
        return new GroupDonationsDashboard($group);
    }