Laravelでポートフォリオ作り vol.3【ルーティング編】

前回に引き続き、ポートフォリオ作りを進めていきます。
今回はルーティングの定義をしていきます。
もちろん、この初期段階ですべてのルーティングを定義することはできませんが、最初にルーティング設定の基本的な部分を確認していこうと思います。

前回の記事

Laravelの画面表示までの流れを確認

モックアップの作成ではありますが、HTMLファイルを作成するのではなくBladeを作成します。
また、Laravelプロジェクト上に作成していくので、改めて画面表示までの流れを確認しましょう。

WebアプリではURLという形でリクエストを受け取って、サーバ側の処理の結果をレスポンスとして返却します。
今回は画面遷移を作成していくため、受け取ったリクエストに対応する画面(HTML)を返却するように実装を行います。

ざっくりの処理の流れとしては

  1. URLに対応する処理をルーティングファイル(routes/web.php)で決定する
  2. bladeファイルを通してHTMLを作成して返却する

となります。
ルーティングファイルから直接bladeを返却することも可能ではありますが、基本的にはControllerで処理を行った結果としてbladeファイルを返却します。
そのため今回も「web.php→controller→blade」と作成していきます。

ルーティングの修正

現在のルーティングファイルの確認

現時点のルーティングファイルをチェックしてみましょう。

Route::get('/', function () {
    return view('welcome');
});

Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');

Route::middleware('auth')->group(function () {
    Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
    Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
    Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});

require __DIR__.'/auth.php';

Laravelの認証機能をインストールしたため、認証機能に関するルーティングがすでに実装されています。
ルーティングに2つのミドルウェアが使用されています。これは

  • auth:ユーザーがログインしているかどうかをチェックし、ログインしていなければ、ログインページにリダイレクトする
  • verified:メールアドレスを認証しているかどうかをチェックし、認証していなければ、メール認証を促すページにリダイレクトする

といった機能を提供しています。
「dashboard」は「verified」ミドルウェアを使用しているのに、メールアドレス認証をしていないユーザーで表示できてしまっています。
この原因は認証で使用されるUserモデルを確認すると分かります。

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable

このように、「use Illuminate\Contracts\Auth\MustVerifyEmail;」がコメントアウトされています。
Userモデルが「MustVerifyEmail」を読み込んでいることがメールアドレス認証チェックの対象となる条件になっているため、現在はメールアドレス認証が行われていません。

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;  // コメントアウト解除
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable implements MustVerifyEmail  // implementsの追加

このように修正することでメールアドレス認証ミドルウェアを有効化することができます。
しかし、今回はメール送信機能をサーバに用意していないため、この修正は行わずに進めていきます。

ルーティングファイルの編集

Topページアクセスの修正

それでは実装に向けてルーティングファイルの実装をしていきたいと思います。
まずwelcomeページは使用しないので、welcomeのルーティングをコメントアウトします

//Route::get('/', function () {
//    return view('welcome');
//});

Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');

Route::middleware('auth')->group(function () {
    Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
    Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
    Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});

require __DIR__.'/auth.php';

「/」に対する設定をコメントアウトしてしまったため、「/」にアクセスすると「404:Not Found」とエラーになってしまいます。

そのため、「/」にアクセスした際にはログイン画面に自動的に遷移するように書き換えていきます。
先ほどコメントアウトしたルーティング設定を以下のように書き換えます。

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

これにより、「/」にアクセスした際にログイン画面が表示されます。
また、ログイン中にログイン画面にアクセスすると、自動的にdashboardに遷移します。
そのため、この書き換えを行うことによって、トップページ(/)にアクセスすると

  • 未ログイン:ログイン画面を表示する
  • ログイン済み:dashboardを表示する

という動きが可能になります。

ルーティンググループの作成

今後実装していく機能は、dashboardと同様に「auth」「verified」のミドルウェアを通して動作させます。
※先述の通り、「verified」ミドルウェアを設定しても、メールアドレス認証済みチェックは行われません

ルーティンググループという表現が正しいかわかりませんが、2つのミドルウェアを経由して動作するようにグループを作成します。

修正前

Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');

修正後

Route::middleware(['auth', 'verified'])->group(function () {
    Route::get('/dashboard', function () {
        return view('dashboard');
    })->name('dashboard');
    
    // 以降のルーティングはこの下に書いていく
    
});

グループを作成して、そのグループ内にルーティングを記載することで、ルーティングごとにミドルウェアの設定を行うことは不要となります。
個別にミドルウェアの設定が必要な場合は、個別にミドルウェアを指定しましょう。

Controllerの作成

続いてControllerを作成していきます。
ルーティングの設定を行いたいところですが、ルーティング設定で呼び出す先であるController処理が今は未実装のため、ルーティングの定義がおこなえません。そのため、ルーティングの定義の前にControllerを作成していきます。

Controllerファイルはコマンドで作成することが可能です。
StudentControllerの部分は、自分で作成したいController名を設定してください。

php artisan make:controller StudentController

app\Http\Controllers\StudentController.phpが作成されます。

Controllerのメソッド定義

続いてメソッドを定義していきます。
今回のStudentControllerは名前の通り、生徒に関する機能を持つControllerになる予定です。
そのため「生徒一覧」「生徒詳細」「生徒登録」「生徒編集」のそれぞれの画面への遷移を作成していきます。

  • index:一覧画面
  • detail:詳細画面
  • create:登録画面
  • edit:編集画面

といったような形でメソッドを作成します。

class StudentController extends Controller
{
    /**
     * 一覧画面
     */
    public function index()
    {
        return view('student.index');
    }

    /**
     * 詳細画面
     */
    public function detail()
    {
        return view('student.detail');
    }

    /**
     * 登録画面
     */
    public function create()
    {
        return view('student.create');
    }

    /**
     * 編集画面
     */
    public function edit()
    {
        return view('student.edit');
    }
}

bladeはまだ作成していませんが、同じように名前を付けて作成する予定なので、それを見越して記述しています。

bladeの作成

続いて、先ほど作成したControllerから呼び出すbladeの作成を行っていきます。

StudentControllerから呼び出すbladeは全て「’student.***’」の形式になっています。
これは、bladeが格納される「resources/views」内の「student」ディレクトリ内のbladeを指定することになるので、studentフォルダを作成して、その中にbladeファイルを作成していきます。

続いてbladeファイルの中身を作成していきます。
今回はLaravelの認証機能をインストールして作成されたdashboardのレイアウトを活かしていきたいと思います。
dashboard.blade.phpを確認すると、このようになっています。

<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            {{ __('Dashboard') }}
        </h2>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 text-gray-900">
                    {{ __("You're logged in!") }}
                </div>
            </div>
        </div>
    </div>
</x-app-layout>

dashboard用のコード部分を生徒一覧用に書き換えたものを、index.blade.phpに記述していきます。
<x-app-layout>や<x-slot>というタグを用いることで、dashboardと同じレイアウトテンプレートを使用することができます。

<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            生徒一覧
        </h2>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 text-gray-900">
                    生徒一覧コンテンツ
                </div>
            </div>
        </div>
    </div>
</x-app-layout>

「生徒一覧コンテンツ」の部分は、後の開発で書き換えていきますが、今はどの画面のbladeであるかが分かればよいので、ここまでの修正とします。

ルーティングの設定を行う

続いてルーティングの記述をしていきます。
先ほど作成したルーティンググループ内に記述します。

Route::middleware(['auth', 'verified'])->group(function () {
    Route::get('/dashboard', function () {
        return view('dashboard');
    })->name('dashboard');

    // 以降のルーティングはこの下に書いていく
    Route::get('/student', [StudentController::class, 'index'])->name('student.index'); // 生徒一覧
});

Route::get(‘/student’, [StudentController::class, ‘index’])->name(‘student.index’);の構文はざっくり説明すると

  • get:getメソッドによるアクセス
  • StudentController::class, ‘index’:StudentControllerのindexメソッドの呼び出し
  • name(‘student.index’):ルート定義に「student.index」という名前をつける

となっています。ルート定義は適宜、目的に合わせて定義していきましょう。

ヘッダメニューにリンクを追加

続いてヘッダーメニューにリンクを追加していきます。
認証機能によって作成されたテンプレートにはヘッダーメニューが備わっています。
最初は「Dashboard」のリンクしかりませんが、ここに「生徒一覧」のリンクを作成していきます。
このヘッダーメニューは「resources/views/layouts/navigation.blade.php」のソースによって作成されているので、このファイルを確認します。
Navigation Linksというコメントが記述されている部分がリンクのソースになるので、Dashboardリンクのソースを元に生徒一覧のリンクを作成します。

<!-- Navigation Links -->
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
    <x-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')">
        {{ __('Dashboard') }}
    </x-nav-link>
</div>

{{-- 生徒一覧のリンク --}}
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
    <x-nav-link :href="route('student.index')" :active="request()->routeIs('student.index')">
        生徒一覧
    </x-nav-link>
</div>

:href=”route(‘student.index’)” には遷移先のURLを指定します。
ルート定義に名前をつけているので、routeメソッドを利用して名前でURLを設定することが可能です。
:active=”request()->routeIs(‘student.index’)” にはメニューを強調表示するための条件を記載します。今回の設定では開いている画面のURLが「route(‘student.index’)」と一致する場合に強調表示されます。

動作確認

それでは動作確認を行っていきます。
Dashboardを開くと、メニューに「生徒一覧」が追加されていると思います。
生徒一覧を押下することでページが切り替わり、メニューの強調表示も生徒一覧に代わっていると思います。

今回はここまで!
画面表示までの流れと、必要な実装をしっかりと理解しておきましょう。

Tips

便利な書き方、機能を紹介。
本編では触れていないものもありますが、便利機能なので知っておいてもらいたい機能です。

名前付きルートについて

基本的に私は名前付きルートの使用を推奨しています。
もちろん名前での指定ではなく、直接URLを記述することもありますが、名前付きルートの方が良い点として

  • 途中でURLが変更となった場合もルーティングファイルの修正のみで済む
    • 呼び出し部分は名前で指定しているため、名前を変更しない限りは修正の必要が無い
  • 存在しない名前を指定した場合、即座にエラーとなる
    • URLの指定の場合、リンクを踏んだ際に404エラーとなるが、リンクを踏むまでは分からない
    • 名前付きルートの場合はURL生成時点でエラーとなるため、画面表示時点でエラー表示される
      • これにより、開発時点でURL指定のミスに気づくことが出来る

といった点が挙げられます。他にも優位性があると思いますが、これだけでも採用するのに十分な理由だと思います。

__(‘Dashboard’)

このソース、「__(名称)」という立派なメソッドの呼び出しになっています。
Laravelでは「__」によって用意されているメソッドで「翻訳文字列の取得」を行うメソッドです。
翻訳ファイルを作成して、翻訳ファイルのキーを指定することでキーに対応する文字列を返却してくれます。
多言語に対応したシステムを作る際には非常に有用で、多言語対応をしていないとしても、表記ゆれなどを防げるので私も現場の開発ではよく使用しています。参考