Урок 08

Route Model Binding

Route Model Binding — это механизм, при котором Laravel автоматически подставляет модель вместо ID из URL. Не нужно писать Post::findOrFail($id) — фреймворк делает это сам.

Неявный binding

Если в аргументе метода указан тип модели с именем, совпадающим с параметром роута:

Route::get('/posts/{post}', function (App\Models\Post $post) {
    return $post->title;
});

Laravel:

  1. Видит параметр {post}
  2. Видит тип Post в аргументе
  3. Ищет Post::findOrFail($id)
  4. Передаёт модель в функцию

Если запись не найдена — 404.

В контроллере

public function show(Post $post)
{
    return view('posts.show', compact('post'));
}

Binding по slug

По умолчанию ищется по id. Если нужен другой столбец — переопредели getRouteKeyName:

class Post extends Model
{
    public function getRouteKeyName(): string
    {
        return 'slug';
    }
}

Теперь /posts/hello-world найдёт пост с slug = hello-world.

Явное указание ключа в роуте

Route::get('/posts/{post:slug}', function (Post $post) {
    return $post;
});

Не требует менять модель.

Составные ключи

Если нужно искать по двум полям:

public function resolveRouteBinding($value, $field = null)
{
    return $this->where('slug', $value)
        ->where('published', true)
        ->firstOrFail();
}

Кастомизация

Можно задать свою логику:

Route::bind('post', function ($value) {
    return Post::where('slug', $value)->firstOrFail();
});

Вложенный binding

Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
    // Laravel найдёт и user, и post
});

Если нужно, чтобы пост принадлежал пользователю — используй scoped bindings:

Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
    //
})->scopeBindings();

Теперь post ищется среди постов пользователя.