今回は、ルーティングに含まれるルートパラメータのid がコントローラアクションで定義したEloquentモデル とリンクする理由をご紹介します!
開発環境
- aws Cloud9
- PHP 8.2.15 (cli)
- laravel/framework v10.45.1 The Laravel Framework
- javascript
- mariadb105-server-10.5.23-1.amzn2023.0.1.x86_64
- cloudinary-labs/cloudinary-laravel 2.0.3 A Laravel Cloudinary Package
前提
- 今回、私はルーティングにルートパラメータで
/profile/{user}と記述していました。そして、~/profile/1というリンクにアクセスした際、コントローラ側でモデルを特定し、その特定のモデルから情報を取得していました。 - しかし、なぜコントローラアクションでインスタンス化するモデルが特定できるのかが分かりませんでした。(
~/profile/1の"1"はuser_id を表しています。)
課題
ルーティングの記述
Route::middleware('auth')->group(function () {
# /{user}の部分
Route::get('/profile/{user}', [ProfileController::class, 'profileShow'])->name('profile.show');
});
コントローラの記述
# (User $user)の部分
public function profileShow(User $user)
{
return view('profile.show')->with(['user' => $user ]);
}
説明
理由は単純で、暗黙の結合が発生していたからです。
以下は、川瀬さんの個人運営による日本語ドキュメントです。目次に暗黙の結合とあるので簡単にそこへ飛べます。
- 続いて、暗黙の結合について説明します。
暗黙の結合(Implicit Binding)は、Laravelの機能の1つで、ルートやコントローラのアクションでモデルを定義することで、自動的に対応するリクエストのURIセグメントに基づいてモデルを取得する仕組みです。
具体的には、ルートやコントローラのアクションで、型宣言された変数名がURIセグメントの名前と一致し、その型宣言された変数がEloquentモデルである場合、Laravelは自動的に対応するURIセグメントの値を使用して、データベースからモデルインスタンスを取得します。
例えば、以下のようなルートがあるとします。
use App\Models\User;
Route::get('/users/{user}', function (User $user) {
return $user->email;
});
この場合、$user 変数は App\Models\User クラスのインスタンスとしてタイプヒントされています。そして、URIの {user} セグメントの値に基づいて、Laravelはデータベースから対応するユーザーレコードを取得し、そのユーザーのメールアドレスを返します。
同様に、コントローラのアクションでも同じ機能が利用できます。
use App\Http\Controllers\UserController;
use App\Models\User;
Route::get('/users/{user}', [UserController::class, 'show']);
namespace App\Http\Controllers;
use App\Models\User;
class UserController extends Controller
{
public function show(User $user)
{
return view('user.profile', ['user' => $user]);
}
}
ここでは、$user 変数が User モデルでタイプヒントされており、URIの {user} セグメントに基づいて自動的にユーザーレコードが取得され、ビューに渡されます。
暗黙の結合を使用することで、コードがより簡潔で読みやすくなり、データベースからのデータの取得が効率化されます。
- また、
{user}には自動的にuserモデルの主キーが挿入されます。
結論
- 暗黙の結合はlaravelの便利機能で、これを利用することで、より簡潔にデータベースからのデータ取得が実現します!🙌
*何か間違えなどがございましたらコメント欄にてご連絡いただけると幸いです。