Я создаю приложение для шоппинга с использованием Laravel, где URL каждого продукта должен быть кратким.
Вместо использования следующей структуры постоянных ссылок: (что является распространенным, но неблагоприятным)
www.example.com/products/{product-slug}
Я хочу использовать эту структуру постоянных ссылок:
www.example.com/{product-slug}
Для этого я использую неявную привязку модели маршрута в моем файле маршрутов:
Route::get( '{product}', function ( App\Product $product ) {
return view( 'product' ); // this works, but is not what I want
});
И я переопределяю поведение поиска в моем Product
модель:
class Product extends Model
{
public function getRouteKeyName()
{
return 'slug'; // use the 'product.slug' column for look ups within the database
}
}
Теперь, согласно документации Laravel:
Laravel автоматически разрешает модели Eloquent, определенные в маршрутах или действиях контроллера, чьи имена переменных с подсказками типов соответствуют имени сегмента маршрута.
(Просмотреть исходный код)
Так что я знаю, что Laravel будет соответствовать {product}
переменная для продукта, хранящегося в моей базе данных, или возврат 404 ответа, если он не найден.
И все это имеет смысл для меня …
Тем не мение…
Каждая страница продукта уникальна, поэтому после того, как маршрут соответствует {product}
, тот {product}
объект необходимо передать контроллеру для дальнейшей обработки.
Итак, как мне передать этот маршрут контроллеру, если я хочу сохранить неявную привязку модели?
Укажите маршрут к функции контроллера.
Это будет ваш маршрут (я назвал контроллер ProductController
и указал на это show
функция, но вы можете переименовать оба по своему вкусу):
Route::get( '{product}', 'ProductController@show');
И это будет в вашем ProductController:
public function show(Request $request, \App\Product $product)
{
// Do stuff with $product
// Return view and pass it the $product variable
return view('product', compact('product'));
}
Чтобы ответить на мой собственный вопрос, я думаю, что нашел отличное решение, которое сочетает в себе мой первоначальный подход и devk-х ответ:
Кредиты для Блог Арджуна для идеи.
Как оказалось, вы также можете выполнить неявное связывание модели в контроллере, передав модель Eloquent в качестве зависимости:
/* App/Http/Controllers/ProductController.php */
/**
* Get the Product object.
*
* @param App\Models\Product
*/
public function show( Product $product )
{
return view( 'product', compact( 'product' ) );
}
Несмотря на то, что мы сейчас ссылаемся на модель с помощью контроллера, Laravel все равно автоматически разрешит модель. На самом деле, это поведение четко определено в документации:
Laravel автоматически разрешает модели Eloquent, определенные в маршрутах или же
действия контроллера чьи имена переменных с подсказкой типа соответствуют маршруту
имя сегмента.
(Просмотреть исходный код)
Должно быть, я пропустил эти слова, когда я прочитал это в первый раз …
Теперь, чтобы настроить {product-slug}
маршрут (так, как я хотел), вы должны настроить свою модель и определения маршрута следующим образом:
/* App/Models/Product.php */
class Product extends Model
{
/**
* Get the route key for the model.
*
* @return string
*/
public function getRouteKeyName()
{
return 'slug';
}
}
Как упоминалось ранее, переопределение getRouteKeyName()
метод заставит Laravel искать продукт, используя его slug
столбец в базе данных вместо его id
столбец (который по умолчанию).
/* routes/web.php */
Route::get( '{product}', 'ProductController@show' );
В нашем файле маршрутов мы все еще называем наш параметр {product}
(вместо {product-slug}
) потому что имя параметра должно совпадать с именем модели Eloquent.
Используя эту конфигурацию, запросы делаются на:
www.example.com/{product-slug}
вернет страницу товара, если {product-slug}
соответствует одному, хранящемуся в базе данных. Если продукт не найден, вместо него будет возвращен ответ 404 Not Found.
Однако, поскольку мы связываем этот маршрут с базовым путем /
это означает, что каждый URL, запрошенный клиентом, будет проходить через эту конфигурацию.
Чтобы избежать этой проблемы, убедитесь, что определения вашего маршрута находятся в правильном порядке в вашем файле маршрутов (от наибольшего до наименьшего приоритета), и используйте проверку при возникновении конфликтов.