Загрузка...

Как работает Route Model Binding в Laravel

laravel cover

В Laravel есть удобный механизм, который позволяет автоматически подставлять модели в маршруты и контроллеры — Route Model Binding. Благодаря ему можно избежать лишнего кода для поиска модели в базе и сразу работать с готовым экземпляром.


Зачем нужен Route Model Binding?

Обычно, если мы хотим получить запись из базы по id, приходится писать что-то вроде:

Route::get('/users/{id}', function ($id) {
    $user = User::findOrFail($id);
    return $user;
});

С Route Model Binding это сокращается до:

Route::get('/users/{user}', function (User $user) {
    return $user;
});

Laravel автоматически поймёт, что {user} в маршруте нужно заменить на модель User, и выполнит запрос в БД.


Виды Route Model Binding

1. Неявное (Implicit Binding)

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

Поиск происходит по id (или по ключу из getRouteKeyName). Если модель не найдена — вернётся 404.


2. Явное (Explicit Binding)

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

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

Здесь мы сами определяем, как именно искать модель.


3. Кастомизация ключа поиска (getRouteKeyName)

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

Теперь {post} будет искаться по slug, а не по id.


Scoped Route Model Binding (scopeBindings)

Иногда нужно подгружать вложенные ресурсы, и тогда простого биндинга недостаточно. Например, у пользователя (User) есть посты (Post), и важно, чтобы загруженный post действительно принадлежал указанному user.

Без scopeBindings

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

/users/1/posts/10 сработает даже если пост id=10 не принадлежит пользователю id=1.


С включением scopeBindings

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

Теперь /users/1/posts/10 вернёт 404, если пост не принадлежит пользователю.


Route Model Binding в контроллерах

Route::get('/posts/{post}', [PostController::class, 'show']);
class PostController extends Controller
{
    public function show(Post $post)
    {
        return view('posts.show', compact('post'));
    }
}

Laravel автоматически загрузит модель и передаст её в метод контроллера.


Дополнительные возможности

🔹 Optional Binding

Route::get('/posts/{post?}', function (?Post $post) {
    return $post ?? 'Нет поста';
});

Сравнительная таблица способов Route Model Binding

Способ Где применяется Как работает Пример
Implicit (неявный) Везде (по умолчанию) Поиск по id или getRouteKeyName() Route::get('/posts/{post}', fn(Post $post) => $post);
Explicit (явный) RouteServiceProvider / Route::bind Полный контроль над логикой поиска Route::bind('post', fn($v) => Post::where('slug', $v)->firstOrFail());
getRouteKeyName В модели Позволяет указать поле для поиска (например, slug) В модели: public function getRouteKeyName() { return 'slug'; }
scopeBindings Вложенные маршруты Проверяет, принадлежит ли дочерняя модель родителю Route::get('/users/{user}/posts/{post}')->scopeBindings();
Optional Binding В маршрутах Параметр может быть пустым (null) Route::get('/posts/{post?}', fn(?Post $post) => $post ?? 'Нет поста');

Преимущества Route Model Binding

  • Меньше кода — не нужно вручную писать findOrFail().
  • Единообразие — маршруты становятся чище и понятнее.
  • Гибкость — легко переопределить ключ поиска или добавить кастомную логику.
  • Безопасность — при отсутствии модели возвращается 404.
  • scopeBindings — защищает вложенные маршруты от доступа к чужим данным.

Итог

Route Model Binding — это мощный инструмент Laravel, который позволяет работать с моделями напрямую в маршрутах и контроллерах.

  • Если нужен поиск по id — используем неявный биндинг.
  • Если по другому ключу — getRouteKeyName или явный биндинг.
  • Для вложенных ресурсов — scopeBindings().
  • Для опциональных параметров — Optional Binding.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *