我有两个模型,我不想在其URL前面加前缀。例如。用户和帖子
如果我有一个网址https://example.com/title-of-the-post和https://example.com/username
我将在web.php
路由文件中执行以下操作:
// User
Route::get('{slug}', function ($slug) {
$user = User::whereSlug($slug)->get();
return view('users.show', $user);
});
// Post
Route::get('{slug}', function ($slug) {
$post = Post::whereSlug($slug)->get();
return view('posts.show', $user);
});
现在,我面临的问题是,即使没有模型带有匹配的塞子,也要输入第一个路径,并且永远不会到达第二个路径。
如果找不到$user
,如何退出下一条路线(邮政)?
注意:我尝试了许多不同的退出策略,但似乎都没有用。
return;
return false;
return null;
// and return nothing
谢谢!
更新:
另一个问题是,如果我有其他resource
条路由,它们也会被第一条路由阻塞。
例如如果我有Route::resource('cars', 'CarController')
,它将生成一个/cars
路径,该路径与{slug}相匹配,并且也被第一条用户路由阻止。
答案 0 :(得分:3)
我认为您已经知道了,但是我在我的应用程序中具有类似的设置,在我的特殊情况下,我还需要能够捕获多段路线。
这就是我的做法。例如,我的web.php
中的最后一条路线如下。
Route::get('{catchall}', 'SlugRoutesController@route')->where('catchall', '.*');
where类->where('catchall', '.*');
确保我们也能够捕获具有多个段的子弹。
例如,以下路线将全部匹配:
/blog/this-is-an-article
/user/mozammil/articles
然后,在我的SlugRoutesController
中,我可以注入其他Controller依赖项。
<?php
namespace App\Http\Controllers;
use App\Post;
use App\User;
use PostController;
use UserController;
use Illuminate\Http\Request;
class HomeController extends Controller
{
private $postController;
private $userController;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct(UserController $userController, PostController $postController)
{
$this->userController = $userController;
$this->postController = $postController;
}
public function route(Request $request, string $slug)
{
$post = Post::where('slug', $slug)->first();
if(post) {
return $this->postController->index($request);
}
$user = User::where('slug', $slug)->first();
if($user) {
return $this->userController->index($request);
}
abort(404);
}
}
我的实际控制器要比这复杂一些,但是您明白了。
答案 1 :(得分:2)
您应该在一条路线中同时检查它们:
Route::get('{slug}', function ($slug)
{
$user = User::whereSlug($slug)->first();
if ($user)
{
return view('users.show', $user);
}
else
{
$post = Post::whereSlug($slug)->first();
if ($post)
{
return view('posts.show', $post);
}
else
{
abort(404);
}
}
});
但是,它可以更清洁。但是概念在那里。
答案 2 :(得分:0)
不确定这是否是最佳做法,但这是为了完成我所需要的工作。
在Post模型上创建了一个函数,用于检查子弹是否正在调用帖子。它同时使用正则表达式和数据库查找。
public static function isRequestedPathAPost() {
return !preg_match('/[^\w\d\-\_]+/', \Request::path()) &&
Post::->whereSlug(\Request::path())->exists();
}
然后,将路由包裹在if
语句中,
if (\App\Models\Post::isRequestedPathAPost()) {
Route::get('{slug}', 'PostController@show');
}
现在仅在实际存在的情况下使用该路由。您可以将其放在路由文件的底部,以减少对数据库的不必要查找。