Laravel5.5 LTS 日本語ドキュメント

このリポジトリはPHP Webアプリフレームワークである、LaravelのLTSバージョンである5.5の公式英文ドキュメントを日本語へ翻訳しています。

This project is maintained by okinaka

ルーティング

基本的なルーティング

一番基本のLaravelルートはシンプルにURIと「クロージャ」により定義され、単純で記述しやすいルートの定義方法を提供しています。

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

デフォルトルート定義ファイル

Laravelの全ルートは、routesディレクトリ下に設置されている、ルートファイルで定義されます。これらのファイルはフレームワークにより、自動的に読み込まれます。routes/web.phpファイルで、Webインターフェイスのルートを定義します。定義されたルートはwebミドルウェアグループにアサインされ、セッション状態やCSRF保護などの機能が提供されます。routes/api.php中のルートはステートレスで、apiミドルウェアグループにアサインされます。

ほとんどのアプリケーションでは、routes/web.phpファイルからルート定義を始めます。routes/web.php中で定義されたルートは、ブラウザで定義したルートのURLを入力することでアクセスします。たとえば、次のルートはブラウザからhttp://your-app.dev/userでアクセスします。

Route::get('/user', 'UserController@index');

routes/api.phpファイル中で定義したルートはRouteServiceProviderにより、ルートグループの中にネストされます。このグループには、/apiのURIが自動的にプレフィックスされ、それによりこのファイル中の全ルートにわざわざ指定する必要はありません。プレフィックスや他のルートグループオプションに変更する場合は、RouteServiceProviderを変更してください。

使用可能なルート定義メソッド

ルータはHTTP動詞に対応してルートを定義できるようにしています。

Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);

複数のHTTP動詞に対応したルートを登録する必要が起きることもあります。matchメソッドが利用できます。もしくは全HTTP動詞に対応するanyメソッドを使い、ルート登録することもできます。

Route::match(['get', 'post'], '/', function () {
    //
});

Route::any('foo', function () {
    //
});

CSRF保護

webルートファイル中で定義され、POSTPUTDELETEルートへ送信されるHTMLフォームはすべて、CSRFトークンフィールドを含んでいる必要があります。含めていないと、そのリクエストは拒否されます。CSRF保護についての詳細は、CSRFのドキュメントをご覧ください。

<form method="POST" action="/profile">
    
    ...
</form>

リダイレクトルート

他のURIへリダイレクトするルートを定義する場合は、Route::redirectメソッドを使用します。このメソッドは便利な短縮形を提供しているので、単純なリダイレクトを実行するために、完全なルートやコントローラを定義する必要はありません。

Route::redirect('/here', '/there', 301);

ビュールート

ルートからビューを返すだけの場合は、Route::viewメソッドを使用します。redirectメソッドと同様に、このメソッドはシンプルな短縮形を提供しており、完全なルートやコントローラを定義する必要はありません。viewメソッドは、最初の引数にURIを取り、ビュー名は第2引数です。更に、オプションの第3引数として、ビューへ渡すデータの配列を指定することもできます。

Route::view('/welcome', 'welcome');

Route::view('/welcome', 'welcome', ['name' => 'Taylor']);

ルートパラメーター

必須パラメータ

もちろん、ルートの中のURIセグメントを取り出す必要が起きることもあります。たとえば、URLからユーザーIDを取り出したい場合です。ルートパラメーターを定義してください。

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

ルートで必要なだけのルートパラメーターを定義することができます。

Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) {
    //
});

ルートパラメータは、いつも{}括弧で囲み、アルファベット文字で構成してください。ルートパラメータには、ハイフン(-)を使えません。下線(_)を代わりに使用してください。ルートパラメータは、ルートコールバック/コントローラへ順番通りに注入されます。コールバック/コントローラ引数の名前は考慮されません。

任意パラメータ

ルートパラメータを指定してもらう必要があるが、指定は任意にしたいこともよく起こります。パラメータ名の後に?を付けると、任意指定のパラメータになります。対応するルートの引数に、デフォルト値を必ず付けてください。

Route::get('user/{name?}', function ($name = null) {
    return $name;
});

Route::get('user/{name?}', function ($name = 'John') {
    return $name;
});

正規表現制約

ルートインスタンスのwhereメソッドを使用し、ルートパラメータのフォーマットを制約できます。whereメソッドはパラメータ名と、そのパラメータがどのように制約を受けるのかを定義する正規表現を引数に取ります。

Route::get('user/{name}', function ($name) {
    //
})->where('name', '[A-Za-z]+');

Route::get('user/{id}', function ($id) {
    //
})->where('id', '[0-9]+');

Route::get('user/{id}/{name}', function ($id, $name) {
    //
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);

グローバル制約

指定した正規表現でいつもルートパラメータを制約したい場合は、patternメソッドを使ってください。RouteServiceProviderbootメソッドの中で、このようなパターンを定義します。

/**
 * ルートモデル結合、パターンフィルタなどの定義
 *
 * @return void
 */
public function boot()
{
    Route::pattern('id', '[0-9]+');

    parent::boot();
}

パターンを定義すると、パラメータ名を使用している全ルートで、自動的に提供されます。

Route::get('user/{id}', function ($id) {
    // {id}が数値の場合のみ実行される
});

名前付きルート

名前付きルートは特定のルートへのURLを生成したり、リダイレクトしたりする場合に便利です。ルート定義にnameメソッドをチェーンすることで、そのルートに名前がつけられます。

Route::get('user/profile', function () {
    //
})->name('profile');

コントローラアクションに対しても名前を付けることができます。

Route::get('user/profile', 'UserController@showProfile')->name('profile');

名前付きルートへのURLを生成する

ルートに一度名前を付ければ、その名前をグローバルなroute関数で使用することで、URLを生成したり、リダイレクトしたりできます。

// URLの生成
$url = route('profile');

// リダイレクトの生成
return redirect()->route('profile');

そのルートでパラメーターを定義してある場合は、route関数の第2引数としてパラメーターを渡してください。指定されたパラメーターは自動的にURLの正しい場所へ埋め込まれます。

Route::get('user/{id}/profile', function ($id) {
    //
})->name('profile');

$url = route('profile', ['id' => 1]);

現在ルートの検査

現在のリクエストが指定した名前付きルートのものであるかを判定したい場合は、Routeインスタンスのnamedメソッドを使います。たとえば、ルートミドルウェアから、現在のルート名を判定できます。

/**
 * 送信されたリクエストの処理
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Closure  $next
 * @return mixed
 */
public function handle($request, Closure $next)
{
    if ($request->route()->named('profile')) {
        //
    }

    return $next($request);
}

ルートグループ

ルートグループは多くのルートで共通なミドルウェアや名前空間のようなルート属性をルートごとに定義するのではなく、一括して適用するための手法です。Route::groupメソッドの最初の引数には、共通の属性を配列で指定します。

ミドルウェア

グループ中の全ルートにミドルウェアを指定するには、そのグループを定義する前にmiddlewareメソッドを使用します。ミドルウェアは、配列に定義された順番で実行されます。

Route::middleware(['first', 'second'])->group(function () {
    Route::get('/', function () {
        // firstとsecondミドルウェアを使用
    });

    Route::get('user/profile', function () {
        // firstとsecondミドルウェアを使用
    });
});

名前空間

ルートグループのもう一つのよくあるユースケースで、グループ内のコントローラに同じPHP名前空間を指定する場合は、namespaceメソッドを使用します。

Route::namespace('Admin')->group(function () {
    // "App\Http\Controllers\Admin"名前空間下のコントローラ
});

App\Http\Controllers名前空間をコントローラルート登録時に毎回指定しなくても済むように、デフォルトでRouteServiceProviderが名前空間グループの中でroutes.phpファイルを読み込み、指定していることを覚えておいてください。これにより、先頭のApp\Http\Controllers名前空間を省略でき、続きの部分を指定するだけで済みます。

サブドメインルーティング

ルートグループはワイルドカードサブドメインをルート定義するためにも使えます。サブドメインの部分を取り出しルートやコントローラで使用するために、ルートURIにおけるルートパラメーターのように指定できます。サブドメインはグループを定義する前に、domainメソッドを呼び出し指定します。

Route::domain('{account}.myapp.com')->group(function () {
    Route::get('user/{id}', function ($account, $id) {
        //
    });
});

ルートプレフィックス

prefixメソッドはグループ内の各ルートに対して、指定されたURIのプレフィックスを指定するために使用します。たとえばグループ内の全ルートのURIにadminを付けたければ、次のように指定します。

Route::prefix('admin')->group(function () {
    Route::get('users', function () {
        // Matches The "/admin/users" URL
    });
});

モデル結合ルート

ルートかコントローラアクションへモデルIDが指定される場合、IDに対応するそのモデルを取得するため、大抵の場合クエリします。Laravelのモデル結合はルートへ直接、そのモデルインスタンスを自動的に注入する便利な手法を提供しています。つまり、ユーザーのIDが渡される代わりに、指定されたIDに一致するUserモデルインスタンスが渡されます。

暗黙の結合

Laravelはタイプヒントされた変数名とルートセグメント名が一致する場合、Laravelはルートかコントローラアクション中にEloquentモデルが定義されていると、自動的に依存解決します。

Route::get('api/users/{user}', function (App\User $user) {
    return $user->email;
});

$user変数がApp\User Eloquentモデルとしてタイプヒントされており、変数名が{user} URIセグメントと一致しているため、Laravelは、リクエストされたURIの対応する値に一致するIDを持つ、モデルインスタンスを自動的に注入します。一致するモデルインスタンスがデータベースへ存在しない場合、404 HTTPレスポンスが自動的に生成されます。

キー名のカスタマイズ

指定されたモデルクラス取得時に、id以外のデータベースカラムをモデル結合で使用したい場合、EloquentモデルのgetRouteKeyNameメソッドをオーバーライドしてください。

/**
 * モデルのルートキーの取得
 *
 * @return string
 */
public function getRouteKeyName()
{
    return 'slug';
}

明示的な結合

明示的に結合を登録するには、ルータのmodelメソッドで、渡されるパラメータに対するクラスを指定します。RouteServiceProviderクラスのbootメソッドの中で明示的なモデル結合を定義してください。

public function boot()
{
    parent::boot();

    Route::model('user', App\User::class);
}

次に{user}パラメーターを含むルートを定義します。

Route::get('profile/{user}', function (App\User $user) {
    //
});

{user}パラメーターをApp\Userモデルへ結合しているため、Userインスタンスはルートへ注入されます。ですからたとえば、profile/1のリクエストでは、IDが1Userインスタンスが注入されます。

一致するモデルインスタンスがデータベース上に見つからない場合、404 HTTPレスポンスが自動的に生成されます。

依存解決ロジックのカスタマイズ

独自の依存解決ロジックを使いたい場合は、Route::bindメソッドを使います。bindメソッドに渡す「クロージャ」は、URIセグメントの値を受け取るので、ルートへ注入したいクラスのインスタンスを返してください。

public function boot()
{
    parent::boot();

    Route::bind('user', function ($value) {
        return App\User::where('name', $value)->first() ?? abort(404);
    });
}

擬似フォームメソッド

HTLMフォームはPUTPATCHDELETEアクションをサポートしていません。ですから、HTMLフォームから呼ばれるPUTPATCHDELETEルートを定義する時、フォームに_method隠しフィールドを追加する必要があります。_methodフィールドとして送られた値は、HTTPリクエストメソッドとして使用されます。

<form action="/foo/bar" method="POST">
    <input type="hidden" name="_method" value="PUT">
    <input type="hidden" name="_token" value="">
</form>

_method入力フィールドを生成するために、method_fieldヘルパ関数を使用することもできます。

現在のルートへのアクセス

送信されたリクエストを処理しているルートに関する情報へアクセスするには、RouteファサードへcurrentcurrentRouteNamecurrentRouteActionメソッドを使用します。

$route = Route::current();

$name = Route::currentRouteName();

$action = Route::currentRouteAction();

組み込まれている全メソッドを確認するには、Routeファサードの裏で動作しているクラスと、Routeインスタンスの2つについてのAPIドキュメントを参照してください。