【问题标题】:Disabling the calling of the two routes禁用两条路由的调用
【发布时间】:2021-04-24 14:03:13
【问题描述】:

对于我的项目,我需要动态路由,因为 URL 中的 {slug} 可以指向多个资源。

/shoes - poinst to category
/black-slippers - points to product

除了通配符路由之外,我还有一些 (50) 个静态路由(全部在 routes/web.php 中的通配符路由之前定义) 但是现在,当被称为静态路由时,也执行通配符路由,例如:

Route::get('/profile', [\App\Http\Controllers\Frontend\UserProfileController::class, 'show'])->name('profile.show');
Route::get('{address}', [\App\Http\Controllers\Core\WebaddressController::class, 'resolveAddress'])->where('address', '.*');

在浏览器中显示配置文件页面(正确),但在 SQL 查询中我看到,在 WebaddressController@resolveAddress 中调用的查询也被执行。

如果我注释通配符 Route,查询就会消失。

如何不执行通配符路由?谢谢

请不要建议更改路线样式,我不能,这是要求的形式。

【问题讨论】:

    标签: laravel routes


    【解决方案1】:

    您可以在where 语句中使用正则表达式从通配符路由中排除一些关键字:

    Route::get(
        '{address}', 
        [\App\Http\Controllers\Core\WebaddressController::class, 'resolveAddress']
    )
        ->where('address', '^(?!profile|other-static-route)$');
    

    关键字列表不必进行硬编码。您可以自己创建一个列表,或者从您定义的路由中解析关键字,如下所示:

    use Illuminate\Support\Str;
    
    $keywords = collect(Route::getRoutes())
        ->map(function ($route) {
            return Str::afterLast($route->uri(), '/');
        })
        ->filter(function ($keyword) {
            return !Str::endsWith($keyword, '}');
        })
        ->implode('|');
    

    像这样将它们添加到 where 语句中:

    ->where('address', '^(?!' . $keywords . ')$');
    

    【讨论】:

    • 是的,我在文档中看到了这一点。我希望会有一些更优雅的解决方案。有 50 条静态路由,正则表达式会很疯狂:D
    • @Autista_z 该列表不必进行硬编码;)。查看更新的答案以获取建议。
    【解决方案2】:

    我不确定这是否是最佳做法,但您可以为以下各项制作自定义中间件:

    Route::get('{address}', [\App\Http\Controllers\Core\WebaddressController::class, 'resolveAddress'])->where('address', '.*')
    

    ->中间件('is_slug_route');

    在新创建的中间件的处理方法中,您可以检查是否提供了一个实际的 slug。

    public function handle($request, Closure $next) {
        $possibleSlug = $request->getPathInfo();
        if (Address::where('slug',$possibleSlug)->exists()) {
            return $next($request);
        }
    }
    

    类似的东西

    【讨论】:

    • 实际上,您可以创建静态路由列表并与它们进行比较,而无需查询 slug。
    • 我现在正在尝试这样做。但看起来它不起作用:(
    • 您在 Kernel.php 中注册了您的中间件吗? project>app>http>kernel.php 在 $routeMiddleware 数组的末尾,如 $routeMiddleware = [ ..., ..., 'is_slug_route'=>\App\Http\Middleware\YourMiddleware ]
    • 是的。我解决了。通过中间件是中间件顺序的问题。但它也应该起作用。
    • 对你有好处:)
    猜你喜欢
    • 2023-01-13
    • 2017-11-07
    • 1970-01-01
    • 1970-01-01
    • 2021-05-07
    • 1970-01-01
    • 1970-01-01
    • 2012-12-15
    • 1970-01-01
    相关资源
    最近更新 更多