Skip to content

HTTPレスポンス

レスポンスの作成

文字列と配列

すべてのルートとコントローラは、ユーザーのブラウザに送り返されるレスポンスを返す必要があります。Laravelは、レスポンスを返すためのいくつかの異なる方法を提供しています。最も基本的なレスポンスは、ルートまたはコントローラから文字列を返すことです。フレームワークは自動的に文字列を完全なHTTPレスポンスに変換します:

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

ルートやコントローラから文字列を返すだけでなく、配列を返すこともできます。フレームワークは自動的に配列をJSONレスポンスに変換します:

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

Note

ルートやコントローラから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');
});

Eloquentモデルとコレクション

ルートやコントローラから直接Eloquent ORMモデルとコレクションを返すこともできます。そうすると、Laravelは自動的にモデルとコレクションをJSONレスポンスに変換し、モデルの非表示属性を尊重します:

use App\Models\User;

Route::get('/user/{user}', function (User $user) {
    return $user;
});

レスポンスにヘッダーを添付する

ほとんどのレスポンスメソッドはチェーン可能であり、レスポンスインスタンスを流暢に構築できます。たとえば、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',
            ]);

キャッシュコントロールミドルウェア

Laravelにはcache.headersミドルウェアが含まれており、これを使用してルートのグループに対してCache-Controlヘッダーをすばやく設定できます。ディレクティブは、対応するキャッシュコントロールディレクティブの「スネークケース」相当で提供され、セミコロンで区切る必要があります。ディレクティブのリストにetagが指定されている場合、レスポンス内容のMD5ハッシュが自動的にETag識別子として設定されます:

Route::middleware('cache.headers:public;max_age=2628000;etag')->group(function () {
    Route::get('/privacy', function () {
        // ...
    });

    Route::get('/terms', function () {
        // ...
    });
});

レスポンスにクッキーを添付する

送信されるIlluminate\Http\Responseインスタンスにクッキーを添付するには、cookieメソッドを使用します。このメソッドには、名前、値、およびクッキーが有効とみなされる分数を渡す必要があります:

return response('Hello World')->cookie(
    'name', 'value', $minutes
);

cookieメソッドは、より頻繁に使用されないいくつかの引数も受け入れます。一般に、これらの引数はPHPのネイティブsetcookieメソッドに与えられる引数と同じ目的と意味を持っています:

return response('Hello World')->cookie(
    'name', 'value', $minutes, $path, $domain, $secure, $httpOnly
);

送信されるレスポンスにクッキーを添付することを確認したいが、まだそのレスポンスのインスタンスがない場合は、Cookieファサードを使用してクッキーを「キュー」に入れることができます。queueメソッドは、クッキーインスタンスを作成するために必要な引数を受け入れます。これらのクッキーは、ブラウザに送信される前に送信レスポンスに添付されます:

use Illuminate\Support\Facades\Cookie;

Cookie::queue('name', 'value', $minutes);

クッキーインスタンスの生成

後でレスポンスインスタンスに添付できるSymfony\Component\HttpFoundation\Cookieインスタンスを生成したい場合は、グローバルなcookieヘルパーを使用できます。このクッキーは、レスポンスインスタンスに添付されない限り、クライアントに送り返されません:

$cookie = cookie('name', 'value', $minutes);

return response('Hello World')->cookie($cookie);

クッキーの早期期限切れ

送信レスポンスのwithoutCookieメソッドを介してクッキーを期限切れにすることで、クッキーを削除できます:

return response('Hello World')->withoutCookie('name');

送信レスポンスのインスタンスがまだない場合は、Cookieファサードのexpireメソッドを使用してクッキーを期限切れにすることができます:

Cookie::expire('name');

クッキーと暗号化

デフォルトでは、Laravelによって生成されるすべてのクッキーは、Illuminate\Cookie\Middleware\EncryptCookiesミドルウェアのおかげで暗号化され、署名されているため、クライアントによって変更または読み取られることはありません。アプリケーションによって生成されるクッキーのサブセットの暗号化を無効にしたい場合は、アプリケーションのbootstrap/app.phpファイルでencryptCookiesメソッドを使用できます:

->withMiddleware(function (Middleware $middleware) {
    $middleware->encryptCookies(except: [
        'cookie_name',
    ]);
})

リダイレクト

リダイレクトレスポンスはIlluminate\Http\RedirectResponseクラスのインスタンスであり、ユーザーを別のURLにリダイレクトするために必要な適切なヘッダーを含んでいます。RedirectResponseインスタンスを生成する方法はいくつかあります。最も簡単な方法は、グローバルなredirectヘルパーを使用することです:

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

ユーザーを以前の場所にリダイレクトしたい場合があります。たとえば、送信されたフォームが無効な場合などです。グローバルなbackヘルパー関数を使用してこれを行うことができます。この機能はセッションを利用しているため、back関数を呼び出すルートがwebミドルウェアグループを使用していることを確認してください:

Route::post('/user/profile', function () {
    // リクエストの検証...

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

名前付きルートへのリダイレクト

パラメータを指定せずにredirectヘルパーを呼び出すと、Illuminate\Routing\Redirectorのインスタンスが返され、Redirectorインスタンスの任意のメソッドを呼び出すことができます。たとえば、名前付きルートへのRedirectResponseを生成するには、routeメソッドを使用できます:

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

ルートにパラメータがある場合は、それらをrouteメソッドの2番目の引数として渡すことができます:

// 次のようなURIのルートの場合: /profile/{id}

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

Eloquentモデルによるパラメータの設定

Eloquentモデルから「ID」パラメータを設定するルートにリダイレクトする場合は、モデル自体を渡すことができます。IDは自動的に抽出されます:

// 次のようなURIのルートの場合: /profile/{id}

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

ルートパラメータに配置される値をカスタマイズしたい場合は、ルートパラメータ定義(/profile/{id:slug})で列を指定するか、EloquentモデルでgetRouteKeyメソッドをオーバーライドできます:

/**
 * モデルのルートキーの値を取得します。
 */
public function getRouteKey(): mixed
{
    return $this->slug;
}

コントローラアクションへのリダイレクト

コントローラアクションへのリダイレクトを生成することもできます。そのためには、コントローラとアクションの名前をactionメソッドに渡します:

use App\Http\Controllers\UserController;

return redirect()->action([UserController::class, 'index']);

もしコントローラーのルートがパラメータを必要とする場合、それらをactionメソッドの第二引数として渡すことができます。

return redirect()->action(
    [UserController::class, 'profile'], ['id' => 1]
);

外部ドメインへのリダイレクト

アプリケーション外のドメインにリダイレクトする必要がある場合があります。その場合、awayメソッドを呼び出すことで、追加のURLエンコーディング、検証、または検証なしでRedirectResponseを作成できます。

return redirect()->away('https://www.google.com');

セッションデータをフラッシュしてリダイレクト

新しいURLにリダイレクトし、セッションにデータをフラッシュすることは、通常同時に行われます。これは通常、アクションが正常に実行された後に成功メッセージをセッションにフラッシュする場合に行われます。便宜上、RedirectResponseインスタンスを作成し、セッションにデータをフラッシュすることができます。

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

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

ユーザーがリダイレクトされた後、セッションからフラッシュされたメッセージを表示できます。例えば、Blade構文を使用して:

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

入力を伴うリダイレクト

RedirectResponseインスタンスが提供するwithInputメソッドを使用して、ユーザーを新しい場所にリダイレクトする前に現在のリクエストの入力データをセッションにフラッシュすることができます。これは通常、ユーザーがバリデーションエラーに遭遇した場合に行われます。入力がセッションにフラッシュされると、次のリクエスト中に簡単に取得してフォームを再入力することができます。

return back()->withInput();

その他のレスポンスタイプ

responseヘルパーは、他のタイプのレスポンスインスタンスを生成するために使用できます。responseヘルパーが引数なしで呼び出されると、Illuminate\Contracts\Routing\ResponseFactory契約の実装が返されます。この契約は、レスポンスを生成するためのいくつかの便利なメソッドを提供します。

ビューレスポンス

レスポンスのステータスとヘッダーを制御する必要があるが、レスポンスの内容としてビューも返す必要がある場合は、viewメソッドを使用する必要があります。

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

もちろん、カスタムHTTPステータスコードやカスタムヘッダーを渡す必要がない場合は、グローバルなviewヘルパー関数を使用できます。

JSONレスポンス

jsonメソッドは、Content-Typeヘッダーを自動的にapplication/jsonに設定し、与えられた配列をjson_encode PHP関数を使用してJSONに変換します。

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

JSONPレスポンスを作成する場合は、jsonメソッドとwithCallbackメソッドを組み合わせて使用できます。

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

ファイルダウンロード

downloadメソッドは、指定されたパスのファイルをユーザーのブラウザにダウンロードさせるレスポンスを生成するために使用できます。downloadメソッドは、メソッドの第二引数としてファイル名を受け取り、ユーザーがファイルをダウンロードする際に表示されるファイル名を決定します。最後に、メソッドの第三引数としてHTTPヘッダーの配列を渡すことができます。

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

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

Warning

Symfony HttpFoundation(ファイルダウンロードを管理する)は、ダウンロードされるファイルがASCIIファイル名を持つ必要があります。

ファイルレスポンス

fileメソッドは、画像やPDFなどのファイルをダウンロードを開始する代わりにユーザーのブラウザに直接表示するために使用できます。このメソッドは、ファイルへの絶対パスを第一引数として受け取り、ヘッダーの配列を第二引数として受け取ります。

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

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

ストリーミングレスポンス

データを生成されると同時にクライアントにストリーミングすることで、特に非常に大きなレスポンスの場合にメモリ使用量を大幅に削減し、パフォーマンスを向上させることができます。ストリーミングレスポンスにより、サーバーがデータの送信を完了する前にクライアントがデータの処理を開始できます。

function streamedContent(): Generator {
    yield 'Hello, ';
    yield 'World!';
}

Route::get('/stream', function () {
    return response()->stream(function (): void {
        foreach (streamedContent() as $chunk) {
            echo $chunk;
            ob_flush();
            flush();
            sleep(2); // チャンク間の遅延をシミュレート...
        }
    }, 200, ['X-Accel-Buffering' => 'no']);
});

Note

内部的には、LaravelはPHPの出力バッファリング機能を利用しています。上記の例でわかるように、バッファリングされたコンテンツをクライアントにプッシュするためにob_flushflush関数を使用する必要があります。

ストリーミングJSONレスポンス

JSONデータをインクリメンタルにストリーミングする必要がある場合は、streamJsonメソッドを利用できます。このメソッドは、特にJavaScriptで簡単に解析できる形式でブラウザに徐々に送信する必要がある大規模なデータセットに特に便利です。

use App\Models\User;

Route::get('/users.json', function () {
    return response()->streamJson([
        'users' => User::cursor(),
    ]);
});

ストリーミングダウンロード

特定の操作の文字列レスポンスをディスクに書き込むことなくダウンロード可能なレスポンスに変換したい場合があります。このような場合には、streamDownloadメソッドを使用できます。このメソッドは、コールバック、ファイル名、およびオプションのヘッダー配列を引数として受け取ります。

use App\Services\GitHub;

return response()->streamDownload(function () {
    echo GitHub::api('repo')
                ->contents()
                ->readme('laravel', 'laravel')['contents'];
}, 'laravel-readme.md');

レスポンスマクロ

さまざまなルートやコントローラーで再利用できるカスタムレスポンスを定義したい場合は、Responseファサードのmacroメソッドを使用できます。通常、このメソッドは、App\Providers\AppServiceProviderサービスプロバイダーなど、アプリケーションのサービスプロバイダーbootメソッドから呼び出す必要があります。

<?php

namespace App\Providers;

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

class AppServiceProvider extends ServiceProvider
{
    /**
     * アプリケーションサービスの初期化処理
     */
    public function boot(): void
    {
        Response::macro('caps', function (string $value) {
            return Response::make(strtoupper($value));
        });
    }
}

macro関数は、名前を第一引数として受け取り、クロージャを第二引数として受け取ります。マクロのクロージャは、ResponseFactory実装またはresponseヘルパーからマクロ名を呼び出すと実行されます。

return response()->caps('foo');

ユーザーノート