PHP Profi

Неявная привязка модели при роутинге в Laravel 5.2 Перевод Серия 

Этот функционал нельзя назвать новым, и route model binding уже давно есть в Laravel, но в Laravel 5.2 он стал ещё проще.

Основы привязки модели к роуту

Давайте предположим, что у нас есть некий стандартный роут привязанный к URL-у и выглядит это как-то так:

Route::get('shoes/{id}', function ($id) {
    $shoe = Shoe::findOrFail($id);
    // некий ваш код
});

Это тот самый кейс, который встречается очень часто. Было бы неплохо, если бы вам не приходилось бы каждый раз писать строчку с findOrFail, а просто как-то рассказать роутеру Laravel-а, что этот роут предоставляет Shoe? И это возможно. В вашем сервис—провайдере роутинга вы можете просто указать, что $router->model('shoe', 'App\Shoe');. Это означает, что "каждый раз, когда у роута есть параметр с именем shoe, это ID, представляющий экземпляр App\Shoe". Это позволяет вам избавиться от строки с findOrFail и переписать вышеприведенный код примерно так:

Route::get('shoes/{shoe}', function ($shoe) {
    // некий ваш код
});

Неявная привязка модели к роуту

В Laravel 5.2 это стало ещё проще. Просто пропишите тип передаваемого параметра в вышеприведённом Closure (или в вашем методе контроллера) и назовите параметр также как параметр роута. Вот и всё, это будет автоматически восприниматься как привязка модели:

Route::get('shoes/{shoe}', function (App\Shoe $shoe) {
    // Do stuff
});

И, как вы понимаете, теперь вы можете применять такую привязку без надобности прописывать что-либо в сервис-провайдере роутинга. Easy!

Вот и весь фольклор по поводу неявной привязки модели к роуту.

Малоизвестные особенности привязки

Эти функции не являются новыми в 5.2, и поэтому не относятся к неявной привязке модели, но, кажется, они не особо известны, поэтому хотелось бы о них рассказать.

Собственная логика привязки модели

Если при привязке модели к роуту вы хотите настроить свою логику по поиску и возврату экземпляра вашей модели, вы можете передать анонимную функцию (Closure) в качестве второго параметра в метод явной привязки вместо передачи имени класса:

$router->bind('shoe', function ($value) {
    return App\Shoe::where('slug', $value)->where('status', 'public')->first();
});

Свои исключения при привязке модели

Также вы можете настроить исключения, которые выбрасываются при привязке моделей к роуту (если не удалось найти экземпляр модели), передав анонимную функцию в качестве третьего параметра:

$router->model('user', 'App\User', function () {
    throw new NotFoundHttpException;
});

Настройка "ключа роута" для Eloquent-модели

По умолчанию Laravel предполагает, что Eloquent-модель соотносится с сегментом URL по столбцу id. (Прим. переводчика: точнее используется указанный первичный ключ). Но что если вы хотите, чтобы она всегда соотносилась по «читаемому» адресу, как в примере выше с изменённой логикой привязки shoe?

Eloquent реализует интерфейс Illuminate\Contracts\Routing\UrlRoutable, что означает, что каждый объект Eloquent имеет метод getRouteKeyName(), который указывает какой столбец следует использовать при поиске экземпляра по сегменту URL-а. По умолчанию это id, но вы можете переопределить его для любой Eloquent-модели:

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

Теперь вы можете использовать явную или неявную привязку модели к роуту, и она будет искать тот shoe, в котором поле slug совпадает с сегментом URL. Красота!

2016-08-22 оригинал

Последние посты

Комментарии

авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий
scif (7 лет назад)

Угу, хорошо конечно и приятно. Но вот Model $model=null как бы логично иногда, но вместо этого он берёт и хинтит новый инстанс модели :( Можно дальше проверять isNew() и прочими костыликами. Ну и при этом перестаёт работать выброс 404-ых исключений (лара не различает пустой слаг или неверный). Короче используйте только если модель является обязательным параметром.