【Laravel】 基本的なルーティングを行おう

LaravelのルーティングでHTTPメソッドの指定、コントローラの指定、名前の付与、ルートパラメータといった基本的な設定を見ていきましょう。

基本的なルーティングの設定

ルーティング関連の一覧は、app/routes/ディレクトリ内に入っています。基本的にはweb.phpを触ることになると思います。

特定のパスにアクセスが来たら特定のコントローラのメソッドを起動する、といった処理は、次のように書きます。

app/routes/web.php
// /hello-world にgetメソッドでアクセスされたら、HelloControllerのindex()を実行する
Route::get('/hello-world', [App\Http\Controllers\HelloController::class, 'index']);

useするとクラス名を短縮できます。

use App\Http\Controllers\HelloController;

Route::get('/hello-world', [HelloController::class, 'index']);

コントローラを使わない場合

静的ページなどでは、コントローラを使用せずに直接ビューを返すことでコード量を減らせます。 (それが良い設計かはともかくとして)

Route::get('/', function () {
    // app/resources/views/welcome.blade.php を返す
    return view('welcome');
});

リダイレクト

特定のパスから別のパスにリダイレクトしたい場合、Route::redirect('元ページ', 'リダイレクト先');のように書きます。第3引数にはステータスコードを入れることができます。

また、ページを移転したなど、永続的なリダイレクトを示したい場合はRoute::permanentRedirect('元ページ', 'リダイレクト先');のように書きます。

// デフォルトのステータスコードは302
Route::redirect('/hello-world', '/home');

// ステータスコードを指定する場合 (301を入れた場合とpermanentRedirectは同じ)
Route::redirect('/hello-world', '/home', 301);

// ステータスコードは301
Route::permanentRedirect('/hello-world', '/home');

HTTPメソッド

Laravelのルーティングでは、6種類のHTTPメソッドを利用できます。

Route::get('/hello-world', [HelloController::class, 'index']);
Route::post('/hello-world', [HelloController::class, 'index']);
Route::put('/hello-world', [HelloController::class, 'index']);
Route::patch('/hello-world', [HelloController::class, 'index']);
Route::delete('/hello-world', [HelloController::class, 'index']);
Route::options('/hello-world', [HelloController::class, 'index']);

anyとmatch

HTTPメソッドの部分には、anymatchも指定できます。

anyは全てのHTTPメソッドにマッチさせたい場合に、matchは指定したHTTPメソッドにマッチさせたい場合に使用します。

ここで、anyは他の同じパスの別メソッドより後に宣言する必要があります。

// 同じパスなら、anyを後に宣言
Route::get('/hello-world', [HelloController::class, 'index']);
// 先に宣言したget以外にマッチする
Route::any('/hello-world', [HelloController::class, 'index']);

// POSTとPUTにマッチさせる
Route::match(['get', 'post'], '/hello-world2', [HelloController::class, 'index']);

ルートパラメータ (パスパラメータ)

例えば、https://.../user/120/friendsのように、URLの途中にリソースを表す値が入る場合があります。このURLでは、IDが120であるユーザを示していますね。

このような値を設定して取得したい場合、user/{id}のように{}を使用して設定します。これらのパラメータはコントローラの引数に設定し、複数のパラメータがある場合はその順番どおりに格納されます。

もしリクエストボディのようなリクエストがある場合は、それが1番目の引数で、ルートパラメータは2つ目以降に入ります。

router
Route::get('/notes/{id}', [HelloController::class, 'getNote']);
Route::get('/user/{id}/files/{fileId}', [HelloController::class, 'getFile']);
controller
public function getNote($id)
{
    return Note::find($id);
}

// リクエストがある場合は、第1引数にRequest、第2引数以降にルートパラメータの箱を設定する
public function getNote2(Request $request, $id)
{
    Log::debug($request->all());
    return Note::find($id);
}

// ルートパラメータが複数ある場合は順番通りに並べる
public function getFile($id, $fileId)
{
    Log::debug($id);
    Log::debug($fileId);

    return /*...*/;
}

もし入るかどうかがわからないパラメータがある場合、/user/{id?}のように?を付与します。

ルートパラメータに制約をつける

正規表現を使用して、ルートパラメータの規則を指定できます。その規則から外れた値が入ってきた場合、404を返します。

設定するには、Route::get('user/{id}')->where(['id' => '[0-9]+')のようにwhereをつなぎ、引数には連想配列を入れます。

// idを0~9の数値のみかつ1桁以上に制限
Route::get('/notes/{id}', [HelloController::class, 'getNote'])
    ->where(['id' => '[0-9]+']);

Route::get('/user/{id}/files/{fileId}', [HelloController::class, 'getFile'])
    ->where(['id' => '[0-9]+', 'fileId' => '[0-9a-zA-Z]{16}']);

ルートパラメータが1つだけの場合、->where('id', '[0-9]+')のように、配列ではなく実引数2つでも設定できます。

また、->where('id', '[0-9]+')->where('fileId', '[0-9a-zA-Z]{16}');のようにメソッドチェーンでつなぐこともできます。

名前がついている制約を使う

一部のしばしば利用するような制約は、whereの代わりにwhereNumberといったメソッドを用いると楽です。

引数は1つで、ルートパラメータ名を入れます。複数のルートパラメータがある場合はメソッドチェーンでつなぎます。

Route::get('/notes/{id}', [HelloController::class, 'getNote'])
    ->whereNumber('id');
Route::get('/user/{id}/files/{fileId}', [HelloController::class, 'getFile'])
    ->whereNumber('id')
    ->whereAlphaNumeric('fileId');

// 同じ制約が複数ある場合は配列で並べられる
Route::get('hoge/{id}/{foo}/{bar}', [HelloController::class, 'hogehoge'])
    ->whereNumber(['id', 'foo', 'bar']);

利用できる制約は4種類あります。

制約名役割
whereNumber任意の桁数の数値
whereAlpha任意の文字数の大文字小文字
whereAlphaNumeric任意の桁数の英数字
whereUuidUUID

グローバル制約

URLでルートパラメータを設定する際に、例えばユーザ名などが何度も出現する場合があります。しかし、出現する度に制約を1つ1つ書いていては大変なことになります。

そこで、app/Providers/RouteServiceProvider.phpbootメソッド内に、Route::pattern('id', '[0-9]+')のような形式で定義できます。定義したら、同名のルートパラメータ全てに反映されます。

app/Providers/RouteServiceProvider.php
public function boot()
{
    Route::pattern('userId', '[0-9]+');
}
// userIdに対し、自動的に [0-9]+ の制約が適用される
Route::get('/user/{userId}', [HelloController::class, 'user']);

ルートに名前をつける

ルートに名前をつけることで、URLではなく名前を利用してURLを生成できるようになります。URLは様々な理由によって変化する可能性があり、かつ内容によっては変更するタイミングを選ぶ必要がありますが、名前はそれに縛られません。

名前は、Route::get(...)->name('名前')のように定義します。

Route::get('/hello-world', [HelloController::class, 'index'])->name('home');
Route::get('/notes/{id}', [HelloController::class, 'getNote'])->name('getNote');

定義した名前は、route('home')route('getNote', ['id' => 10])のようにするとURLを取得できます。

$url = route('home'); // http://localhost/hello-world

route関数はビュー側でも利用できます。

@for ($i = 1; $i <= 4; $i++)
    <!-- ルートパラメータを設定する場合は、routeの第2引数に連想配列で入れる -->
    <a href="{{ route('getNote', ['id' => $i]) }}">note {{ $i }}</a>
@endfor

まとめ

ルーティングでは単にパスを書くだけでなく、ルートパラメータを定義したり、名前をつけて管理できるようにしたりといったことが可能です。

他にもグルーピングしたりと言った操作も可能なので、続きの記事も見ていきましょう。

laravel routing basic thumb

役に立ったらシェアしよう!