【Laravelメモ】URLルーティングにImplicit Bindingを使おう

# LaravelのImplicit BindingとRequestクラスでのモデルIDの取得方法

## はじめに

LaravelのImplicit Binding（暗黙的バインディング）は、ルートパラメータに対応するEloquentモデルを自動的に解決し、コントローラのメソッドに注入する便利な機能です。本記事では、Implicit Bindingの基本的な使い方と、Requestクラス内でバインドされたモデルのIDを取得する方法について解説します。

## Implicit Bindingとは？

Implicit Bindingは、ルートパラメータに指定された値をEloquentモデルとして自動的に解決する機能です。通常、以下のようにルート定義を行います。

```php
Route::get('/projects/{project}/tickets/{ticket}', 'TicketController@show');
```

このルートを使用すると、URLの`{project}`および`{ticket}`の部分には、それぞれ`Project`モデルと`Ticket`モデルの`id`カラムの値が入ります。Laravelはそれをもとにデータベースから対応するレコードを取得し、自動的にEloquentモデルのインスタンスへ変換します。

## コントローラでのImplicit Bindingの使用

Implicit Bindingを利用すると、コントローラのメソッドにバインドされたモデルのインスタンスを直接受け取ることができます。

```php
use App\Models\Project;
use App\Models\Ticket;
use Illuminate\Http\Request;

class TicketController extends Controller
{
    public function show(Request $request, Project $project, Ticket $ticket)
    {
        return response()->json([
            'project' => $project,
            'ticket' => $ticket,
        ]);
    }
}
```

## Requestクラス内でImplicit BindingされたモデルのIDを取得する方法

カスタムリクエストクラス（`FormRequest`を継承したクラス）内で、ルートパラメータからバインドされたモデルのIDのみを取得したい場合は、以下のように実装できます。

### 1. Requestクラスの作成

まず、`StoreRequest`というカスタムリクエストクラスを作成します。

```bash
php artisan make:request StoreRequest
```

### 2. StoreRequestクラスのrulesメソッドでモデルのIDを取得

`rules`メソッド内で、ルートパラメータとしてバインドされた`Project`や`Ticket`モデルのIDを取得するには、次のように記述します。

```php
use Illuminate\Foundation\Http\FormRequest;

class StoreRequest extends FormRequest
{
    public function rules()
    {
        $project = $this->route('project'); // Projectモデルのインスタンス
        $ticket = $this->route('ticket');   // Ticketモデルのインスタンス

        $projectId = $project->id; // ProjectのIDを取得
        $ticketId = $ticket->id;   // TicketのIDを取得

        return [
            'title' => 'required|string|max:255',
            'description' => 'required|string',
            'project_id' => 'exists:projects,id,' . $projectId, // Projectの存在チェック
            'ticket_id' => 'exists:tickets,id,' . $ticketId, // Ticketの存在チェック
        ];
    }
}
```

### 3. コントローラでStoreRequestを利用

作成した`StoreRequest`をコントローラのメソッドの引数として渡します。

```php
use App\Http\Requests\StoreRequest;
use App\Models\Project;
use App\Models\Ticket;

class TicketController extends Controller
{
    public function store(StoreRequest $request, Project $project, Ticket $ticket)
    {
        // バリデーション済みのデータを取得
        $validatedData = $request->validated();

        return response()->json([
            'message' => 'Validation passed!',
            'data' => $validatedData,
        ]);
    }
}
```

## 実際のリクエストURLと取得データ

例えば、以下のリクエストを実行した場合：

```
GET /projects/1/tickets/5
```

コントローラ内で取得されるデータは次のようになります。

```json
{
    "project": {
        "id": 1,
        "name": "Project A",
        "created_at": "2024-02-27T10:00:00.000000Z",
        "updated_at": "2024-02-27T10:00:00.000000Z"
    },
    "ticket": {
        "id": 5,
        "title": "Bug Fix Request",
        "description": "Fix issue in API endpoint.",
        "project_id": 1,
        "created_at": "2024-02-27T11:00:00.000000Z",
        "updated_at": "2024-02-27T11:00:00.000000Z"
    }
}
```

## まとめ

本記事では、LaravelのImplicit Bindingの基本的な使い方と、Requestクラス内でバインドされたモデルのIDを取得する方法について解説しました。

- **Implicit Binding** を使用すると、ルートパラメータの値に基づいて自動的にEloquentモデルのインスタンスを取得できます。
- **Requestクラスの****`rules`****メソッド内** で `$this->route('modelName')` を使用すると、バインドされたモデルのインスタンスを取得できます。
- **モデルのIDを取得するには** `$this->route('modelName')->id` を使用します。

この方法を活用することで、ルートパラメータを使ったバリデーションやモデルの操作をより簡潔に記述できます。