Laravel 文件閱讀: HTTP 響應

zhangbao發表於2017-09-20

翻譯、衍生自:https://learnku.com/docs/laravel/5.5/responses

建立響應

字串 & 陣列

使用者的每個請求無一例外得都要給予一個響應。Laravel 提供了幾種不同的響應方式。最簡單的響應是從路由或控制器中返回一個字串。Laravel 會將這個字串自動轉換為完整的 HTTP 響應。

Route::get('/', function () {
    return 'Hello World';
});

除了返回字串,還可以返回一個陣列。Laravel 會將這個陣列自動轉換為 JSON 響應。

Route::get('/', function () {
    return [1, 2, 3];
});

小提示:從路由或控制器中返回的 Eloquent 集合也會被自動轉換為 JSON 響應哦~

響應物件

我們一般不會只返回一個字串或者陣列。相反,我們經常返回完整的 Illuminate\Http\Response 例項或者檢視。

返回一個 Response 例項的話,允許我們自定義 HTTP 響應碼和標頭。Response 例項繼承了 Symfony\Component\HttpFoundation\Response 類,提供了大量構建 HTTP 響應的方法:

Route::get('home', function () {
    return response('hello world', 200)
            ->header('Content-Type', 'text/plain');
});

為響應附加標頭

記住,Response 例項的大多數方法都是可以鏈式呼叫的。例如,你可以連續使用幾次 header 方法,在最終響應給瀏覽器之前,指定一系列的標頭資訊。

return response($content)
        ->header('Content-Type', $type)
        ->header('X-Header-One', 'Header Value')
        ->header('X-Header-Two', 'Header Value');

或者使用 withHeaders 方法指定一個陣列引數,一次性指定所有標頭資訊。

return response($content)
        ->withHeaders([
            'Content-Type' => $type,
            'X-Header-One' => 'Header Value',
            'X-Header-Two' => 'Header Value',
        ]);

為響應附加 Cookie

使用 cookie 方法為響應附加 Cookie,向下面這樣:

return response($content)
        ->header('Content-Type', $type)
        ->cookie('name', 'value', $minutes);

cookie 方法還接收一些引數,不過不常用。如果要使用,只要記住,cookie 方法的簽名和原生 PHP 方法 setcookie 是一樣的:

->cookie($name, $value, $minutes, $path, $domain, $secure, $httpOnly)

Cookie & 加密

預設,Laravel 生成的所有 Cookie 都會經過加密和簽名處理,不能被客戶端修改和讀取。如果需要列出一個「白名單」,不用對名單裡的 Cookie 加密的話,就要用到 App\Http\Middleware\EncryptCookies 中介軟體的 $except 屬性,位於 app/Http/Middleware 目錄下:

/**
 * The names of the cookies that should not be encrypted.
 *
 * @var array
 */
protected $except = [
    'cookie_name',
];

重定向

重定向響應是 Illuminate\Http\RedirectResponse 例項,並且包含重定向所需的正確標頭資訊。有幾種生成 RedirectResponse 例項的方式。最簡單的是使用全域性 redirect 輔助函式:

Route::get('dashboard', function () {
    return redirect('home/dashboard');
});

有時需要重定向到之前地址,比如當提交表單無效時。這時可以使用 back 輔助函式。因為這個函式使用了 Session,所以要保證呼叫 call 函式的路由使用了 web 中介軟體組或者是應用了所有的 Session 相關中介軟體:

Route::post('user/profile', function () {
    // Validate the request...

    return back()->withInput();
});

重定向到命名路由

直接呼叫 redirect() 方法會返回一個 Illuminate\Routing\Redirector 例項,你就可以使用這個例項上的方法了。例如,你可以使用 route 方法產生一個到命名路由的 RedirectResponse 例項:

return redirect()->route('login');

如果路由包含引數,給 route 方法傳遞第二個引數指定:

// For a route with the following URI: profile/{id}

return redirect()->route('profile', ['id' => 1]);

使用 Eloquent Model 填充路由引數

如果你重定向的那個路由包含一個叫 id 的路由引數,那麼可以向 route 方法直接傳遞 Eloquent Model 例項。ID 值會被自動解析:

// For a route with the following URI: profile/{id}

return redirect()->route('profile', [$user]);

如果路由引數使用的不是 id,而是其他欄位名(比如 email),那這個時候就需要在 Eloquent Model 設定 getRouteKey 方法了,告訴 Laravel 從 Eloquent Model 中解析 email 這個欄位值給路由引數:

/**
 * Get the value of the model's route key.
 *
 * @return mixed
 */
public function getRouteKey()
{
    return $this->email;
}

重定向到控制器 Action

action 方法傳遞控制器和 action 名就可以重定向到某個控制器 action。記住,你無需指定包含完整名稱空間的控制器類名,只需指定 App\Http\Controllers 後面那部分的內容,這是在 Laravel 的 RouteServiceProvider 中設定的:

return redirect()->action('HomeController@index');

如果路由包含引數,給 action 方法傳遞第二個引數指定:

return redirect()->route(
    'UserController@profile', ['id' => 1]
);

重定向時攜帶 Session 快閃記憶體資料

重定向到一個新 URL,並且快閃記憶體資料到 Session 經常同時進行。比如,我們在成功操作某一個動作後,返回一條提示操作成功的訊息。為了方便,你可以在 RedirectResponse例項上直接使用 with 方法將訊息快閃記憶體到 Session 中,一行程式碼搞定!

Route::post('user/profile', function () {
    // Update the user's profile...

    return redirect('dashboard')->with('status', 'Profile updated!');
});

重定向後,就可以從 Session 中獲得快閃記憶體訊息了。下面以 Blade 模板檔案為例,展示訊息內容:

@if (session('status'))
    <div class="alert alert-success">
        {{ session('status') }}
    </div>
@endif

其他響應型別

response 輔助函式可以產生其他型別的響應例項。當以無參的形式呼叫 response 函式的時候,也就是 response()——它會返回一個實現了 Illuminate\Contracts\Routing\ResponseFactory 契約的例項。在這個契約裡提供了一些有用的產生響應的方法。

檢視響應

如果需要指定響應的狀態碼、標頭,而且還要返回一個檢視,可以使用 view 方法:

return response()
        ->view('hello', $data, 200)
        ->header('Content-Type', $type);

當然,如果不用自定義響應狀態碼或者標頭,直接返回檢視,那麼用全域性 view 輔助函式完全 OK。

JSON 響應

json 方法會自動設定 Content-Type 標頭為 application/json,並且使用 PHP json_encode 函式將陣列轉換為 JSON 資料:

return response()->json([
    'name' => 'Abigail',
    'state' => 'CA'
]);

如果需要建立一個 JSONP 響應,可以讓 json 方法結合 withCallback 方法使用:

return response()
        ->json(['name' => 'Abigail', 'state' => 'CA'])
        ->withCallback($request->input('callback'));

檔案下載

download 方法強制瀏覽器下載指定路徑下的檔案。該方法接收第二個引數作為檔名(終端使用者看到的檔名)。最後,你可以傳遞第三個包含標頭資訊的陣列引數:

return response()->download($pathToFile);

return response()->download($pathToFile, $name, $headers);

return response()->download($pathToFile)->deleteFileAfterSend(true);

注意!管理檔案下載的 Symfony HttpFoundation 需要下載的檔案具有 ASCII 檔名。

檔案響應

file 方法用來強制顯示檔案,比如圖片和 PDF 檔案(而不是下載)。該方法的第一個引數是檔案路徑,第二個引數是包含標頭資訊的陣列:

return response()->file($pathToFile);

return response()->file($pathToFile, $headers);

響應巨集

可以使用 Response 門面的 macro 方法,自定義可以在各種路由和控制器中重複使用的響應,這就是「響應巨集」。例如,在服務提供者的 boot 方法裡設定我們們的響應巨集:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Response;

class ResponseMacroServiceProvider extends ServiceProvider
{
    /**
     * Register the application's response macros.
     *
     * @return void
     */
    public function boot()
    {
        Response::macro('caps', function ($value) {
            return Response::make(strtoupper($value));
        });
    }
}

macro 函式的第一個引數是巨集的名字,第二個引數是閉包。巨集的閉包會在呼叫 response 輔助函式時候被執行,或者是從 ResponseFactory 的實現呼叫巨集的時候被執行。

return response()->caps('foo');
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章