Php Laravel 5.6-路由模型与默认控制器绑定

Php Laravel 5.6-路由模型与默认控制器绑定,php,laravel,binding,controller,routes,Php,Laravel,Binding,Controller,Routes,我正在使用Laravel构建一个购物应用程序,其中每个产品的URL必须保持简洁 而不是使用以下permalink结构:(这是常见的,但不合适) www.example.com/products/{product slug} 我想使用这个permalink结构: www.example.com/{product slug} 为了实现这一点,我在路由文件中使用隐式路由模型绑定: Route::get( '{product}', function ( App\Product $product ) {

我正在使用Laravel构建一个购物应用程序,其中每个产品的URL必须保持简洁

而不是使用以下permalink结构:(这是常见的,但不合适)

www.example.com/products/{product slug}

我想使用这个permalink结构:

www.example.com/{product slug}


为了实现这一点,我在路由文件中使用隐式路由模型绑定:

Route::get( '{product}', function ( App\Product $product ) {

   return view( 'product' ); // this works, but is not what I want

});
我正在覆盖我的
产品
模型中的查找行为:

class Product extends Model
{

   public function getRouteKeyName()
   {
      return 'slug'; // use the 'product.slug' column for look ups within the database
   }

}
现在,根据Laravel的文件:

Laravel自动解析路由或控制器操作中定义的雄辩模型,其类型提示变量名称与路由段名称匹配。

因此,我知道Laravel将把
{product}
变量与存储在我的数据库中的产品相匹配,如果找不到,则返回404响应

这一切对我来说都很有意义


然而

每个产品页都是唯一的,因此在路由与
{product}
匹配后,
{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'));
}

指向控制器功能的路由

这将是您的路线(我将控制器命名为
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'));
}

为了回答我自己的问题,我认为我找到了一个结合了我最初的方法和回应的伟大解决方案:

这一想法值得称赞

事实证明,您还可以通过将雄辩的模型作为依赖项传递,在控制器内执行隐式模型绑定:

/* 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自动解析routes或中定义的雄辩模型 控制器操作其类型提示变量名称与路由匹配 段名称。

我第一次读的时候一定是漏掉了那些词


现在,为了设置
{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文件中,我们仍然将参数命名为
{product}
(而不是
{product slug}
),因为参数的名称必须与雄辩模型的名称匹配


使用此配置,在以下位置发出请求:

www.example.com/{product slug}

如果提供的
{product slug}
与数据库中存储的页面匹配,则将返回产品页面。如果未找到产品,将返回404 not found响应

但是,由于我们将此路由绑定到基本路径
/
,这意味着客户端请求的每个URL都将通过此配置传递


要避免此问题,请确保路由定义在路由文件中的顺序正确(从最高优先级到最低优先级),并在发生冲突时使用验证

为了回答我自己的问题,我想我已经找到了一个结合我最初的方法和回应的很好的解决方案:

这一想法值得称赞

事实证明,您还可以通过将雄辩的模型作为依赖项传递,在控制器内执行隐式模型绑定:

/* 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自动解析routes或中定义的雄辩模型 控制器操作其类型提示变量名称与路由匹配 段名称。

我第一次读的时候一定是漏掉了那些词


现在,为了设置
{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文件中,我们仍然将参数命名为
{product}
(而不是
{product slug}
),因为参数的名称必须与雄辩模型的名称匹配


使用此配置,在以下位置发出请求:

www.example.com/{product slug}

如果提供的
{product slug}
与数据库中存储的页面匹配,则将返回产品页面。如果未找到产品,将返回404 not found响应

但是,由于我们将此路由绑定到基本路径
/
,这意味着客户端请求的每个URL都将通过此配置传递


要避免此问题,请确保路由定义在路由文件中的顺序正确(从最高优先级到最低优先级),并在发生冲突时使用验证

应用程序中的其他页面如何?
www.example.com/login
页面也会意外匹配并传递到此cont