Laravel Route 模型绑定(slug)仅适用于 show 方法?

Posted

技术标签:

【中文标题】Laravel Route 模型绑定(slug)仅适用于 show 方法?【英文标题】:Laravel Route model binding (slug) only works for show method? 【发布时间】:2016-10-25 19:26:17 【问题描述】:

我在数据库中有 Article 模型和 articles 表。每篇文章都可以使用 Laravel 的标准 URI 结构显示:www.example.com/articles/5(其中5 是文章id)。每篇文章都有一个 slug 字段(文章表中的slug 列),因此对于 Route Model Binding,我使用 slug 而不是 @987654327 @:

RouteServiceProvider.php:

public function boot(Router $router)

    parent::boot($router);

    \Route::bind('articles', function($slug) 
        return \App\Article::where('slug', $slug)->firstOrFail();
    );

在 routes.php 我有:

Route::resource('articles', 'ArticleController');

现在可以通过以下 URL 访问文章:www.example.com/some_slug

但是现在,当我想编辑一些文章时,我收到以下错误:

没有模型 [App\Article] 的查询结果。

例如,当我尝试打开以下内容时:www.example.com/some_slug/edit - 我收到该错误。

所以,方法 ArticleController@show(Article $article) 工作正常,但 ArticleController@edit(Article $article) 不起作用。

这是我的路线列表:

这里是来自 ArticleController 的 show 和编辑方法:

public function show(Article $article)  // THIS WORKS FINE

    $tags = $article->tags()->get();
    return view('articles.show', compact('article', 'tags'));


public function edit(Article $article) // DOESN'T WORK -> When I open article/slug/edit I get error: No query results for model [App\Article].

    $tags = Tag::lists('name', 'id');
    $categories = Category::orderBy('lft', 'asc')->get()->lists('padded_name', 'id');
    return view('articles.edit', compact('article', 'tags', 'categories'));

【问题讨论】:

您在edit 参数末尾缺少s。应该是 edit(Article $articles) 而不是 edit(Article $article) 以匹配 /articles/articles 【参考方案1】:

如果有人想同时使用idslug 进行路由模型绑定,则可以像这样显式绑定:

// App\Providers\RouteServiceProvider::boot

Route::bind('product', function($value) 
   return \App\Product::where('id', $value)->orWhere('slug', $value)->first();
);

【讨论】:

这很棒。只需补充一点,如果最后将first() 更改为firstOrFail(),它将避免非对象错误并引发404。 经过 2 个多小时打破我的头......谢谢@swadhwa 完美!【参考方案2】:

我有另一种方法供您使用,而无需触及 RouteServiceProvider.php。我希望它有所帮助。 您需要在 ArticleController 中使用 App\Article;使用 App\Tag;ArticleController

public function show($slug)
    
        $article = Article::where('slug', $slug)->first();

        $tags = Tag::lists('name', 'id');

        return view('articles.edit', compact('article', 'tags'));
    

public function edit($slug)
     
        $article = Article::where('slug', $slug)->first();

        $tags = Tag::lists('name', 'id');

        return view('articles.edit', compact('article', 'tags'));
    

【讨论】:

【参考方案3】:

相信5.2,可以直接在模型中使用getRouteKeyName方法自定义键名:

public function getRouteKeyName()

    return 'slug';

docs

【讨论】:

我猜是最好和最简洁的答案。每个开发人员似乎都懒惰(和我一样)不阅读整个文档。

以上是关于Laravel Route 模型绑定(slug)仅适用于 show 方法?的主要内容,如果未能解决你的问题,请参考以下文章

Laravel Route 模型与关系绑定

在升级laravel 5.2到5.3之后,无法在Route :: model中绑定模型

Laravel 5.2路径模型使用方法和控制器进行绑定

为啥模型除了 id 不通过 slug 返回数据?

从 Laravel 中的 url 获取最新的 slug

Blade 视图组件的 Laravel 路由模型绑定