我如何才能同时在Laravel中仅对子类别,帖子和页面使用子弹

时间:2019-10-28 16:33:32

标签: laravel

我正在尝试使用laravel编写CMS。我想同时将Slug用于类别,页面和帖子。

帖子:www.domain.com/slug

类别:www.domain.com/slug

页数:www.domain.com/slug

Controller页面:

public function categories($slug)
{
  $settings = Settings::find(1);
  $categories = Categories::where('slug', '=', $slug)->first();
  $posts = Posts::where('category', '=', $categories->id)->get();
  return view('web.'.$settings->template.'.category',compact('posts','categories'));
}

public function posts($slug)
{
  $categories = Categories::all();
  $settings = Settings::find(1);
  $posts = Posts::where('slug', '=', $slug)->first();
  return view('web.'.$settings->template.'.single',compact('posts','similars','categories'));
}

Web.php

Route::get('/{slug}','HomeController@categories')->name('show.category');
Route::get('/{slug}','HomeController@pages')->name('show.page');
Route::get('/{slug}','HomeController@posts')->name('show.post');

有了这些代码,我得到了这个错误-> https://prnt.sc/pp9196

如果我删除类似帖子的代码,则会收到此错误。 -> https://prnt.sc/pp91u1

那么我该如何使用那些页面的唯一标签? 谢谢...

3 个答案:

答案 0 :(得分:0)

您不能有3条具有相同网址的路由。您需要以某种方式区分它们。最简单的方法是在{slug}之前的标识符:

Route::get('/categories/{slug}','HomeController@categories')->name('show.category');
Route::get('/pages/{slug}','HomeController@pages')->name('show.page');
Route::get('/posts/{slug}','HomeController@posts')->name('show.post');

答案 1 :(得分:0)

只需在控制器上创建一个新方法:

public function show($slug) {
    return $this->posts($slug) || $this->categories($slug) || $this->pages($slug) || abort(404)
}

您可以在此处更改呼叫顺序以赋予不同的优先级(仅在您的子弹不是唯一的情况下才有意义)

然后修改您的posts()pages()categories()方法以返回null(如果找不到):

public function categories($slug)
{
  $categories = Categories::where('slug', '=', $slug)->first();
  // Moved top because makes no sense load settings if the category doesn't exists.

  if (!$categories) {
    return null
  }

  $settings = Settings::find(1);
  $posts = Posts::where('category', '=', $categories->id)->get();
  return view('web.'.$settings->template.'.category',compact('posts','categories'));
}

public function posts($slug)
{
  $posts = Posts::where('slug', '=', $slug)->first();

  if (!$posts) {
    return null
  }

  $categories = Categories::all();
  $settings = Settings::find(1);
  return view('web.'.$settings->template.'.single',compact('posts','similars','categories'));
}

最后将您的路线缩减为一条路线:

Route::get('/{slug}','HomeController@show')->name('show');

请注意,此路由必须是您的路由文件中的最后一条路由,因为它将捕获任何内容。将其设置为最后一条将为其他路线提供更具体的机会。

答案 2 :(得分:0)

根据Laravel documentation,您可以执行以下操作:

Route::bind('user', function ($value) {
    return App\User::where('name', $value)->first() ?? abort(404);
});

在RouteServiceProvider引导上