简体   繁体   English

检查模型是否存在,如果在 Laravel 中没有找到则继续路由

[英]Check if model exist and continue routing if not found in Laravel

I have two models that I don't want to have a prefix in front of its URLs.我有两个模型,我不想在其 URL 前面有前缀。 Eg Users and Posts例如用户和帖子

If I have a URL https://example.com/title-of-the-post and https://example.com/username如果我有一个 URL https://example.com/title-of-the-posthttps://example.com/username

I will do something like this in the web.php routes file:我将在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);
});

Now the issue I am facing is that the first route is entered and will never reach the second even if there is no model with a matching slug.现在我面临的问题是,即使没有具有匹配 slug 的模型,输入的第一条路线也永远不会到达第二条路线。

How can I exit to the next route (Post) if $user is not found?如果找不到$user如何退出到下一条路线(Post)?

Note: I have tried many different exit strategies but none seem to work.注意:我尝试了许多不同的退出策略,但似乎都没有奏效。

return;
return false;
return null;
// and return nothing

Thanks in advance!提前致谢!

UPDATE :更新

Another issue is that if I have other resource routes they too get blocked by the first route.另一个问题是,如果我有其他resource路由,它们也会被第一条路由阻塞。

Eg If I have Route::resource('cars', 'CarController') it generates a /cars path which matches the {slug} and is also being blocked by first User route.例如,如果我有Route::resource('cars', 'CarController')它会生成一个/cars路径,该路径与 {slug} 匹配并且也被第一个用户路由阻止。

I think you already got the idea but I ,kind of, have a similar setup in my application and in my particular case, I also needed to be able to catch multi-segments routes.我想你已经明白了,但我在我的应用程序中有类似的设置,在我的特殊情况下,我还需要能够捕获多段路由。

So here's how I did it.所以这就是我如何做到的。 For example, the last route in my web.php is the following.例如,我的web.php的最后一个路由如下。

Route::get('{catchall}', 'SlugRoutesController@route')->where('catchall', '.*');

The where class ->where('catchall', '.*'); where 类->where('catchall', '.*'); ensures that we are also able to catch slugs that have multiple segments.确保我们还能够捕获具有多个段的 slug。

For example, the following routes will all be matched:比如下面的路由都会匹配:

/blog/this-is-an-article
/user/mozammil/articles

Then, in my SlugRoutesController , I am able to inject my other Controller dependencies.然后,在我的SlugRoutesController ,我可以注入我的其他控制器依赖项。

<?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);
    }
}

My actual controller is a bit more complex than that, but you get the idea.我的实际控制器比这更复杂一点,但你明白了。

You should check both of them in one route :您应该在一条路线中检查它们:

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);
        }
    }
});

However, it can be more cleaner.但是,它可以更清洁。 But the concept is there.但是这个概念是存在的。

Not sure if this is best practice but here is what was done to accomplish what I needed.不确定这是否是最佳实践,但这里是完成我需要的工作。

Created a function on the Post model that checks if the slug is calling a post.在 Post 模型上创建了一个函数,用于检查 slug 是否正在调用 post。 It uses both a regex and database lookup.它同时使用正则表达式和数据库查找。

public static function isRequestedPathAPost() {
    return !preg_match('/[^\w\d\-\_]+/', \Request::path()) &&
        Post::whereSlug(\Request::path())->exists();
}

Then I wrap the Route in a if statement like this.然后我将 Route 包装在这样的if语句中。

if (\App\Models\Post::isRequestedPathAPost()) {
    Route::get('{slug}', 'PostController@show');
}

Now the route is only used if it actually exist.现在,该路线仅在实际存在时才使用。 You can put this at the bottom of the route file to reduce unnecessary lookups to the database.您可以将其放在路由文件的底部,以减少对数据库的不必要查找。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM