【问题标题】:Laravel 5.5 use of env string in route name screws Route::has()Laravel 5.5 在路由名称螺丝 Route::has() 中使用 env 字符串
【发布时间】:2018-07-13 18:06:36
【问题描述】:

出于绝对测试目的(这可能不是我将在我的代码上保留的一致行为)我尝试使用带有 .env 文件的自定义管理面板路由设置(因为它似乎与保护整个事情有关,但不是所以确定了)。

因为我希望访问该站点的人可以在访客模式下看到管理面板,所以我认为设置一个重新路由中间件会很酷,该中间件只需在 .env 设置管理路由之后放置一个访客。尝试访问 /admin/jobs 的访客将在 /admin/guest/jobs 以降低的权限控制器结束。

下面的代码在没有 .env 的情况下可以正常工作。

在\Route\web.php中是这样设置的

Route::namespace('Admin')->middleware('auth')->group(function () {
    $adminRoute = config('app.admin-route');
    $adminRoute = (preg_match('/[\/].*/', $adminRoute)) ? $adminRoute : '/' . $adminRoute;

    Route::middleware('isadmin')->group(function () use ($adminRoute) {
        Route::get($adminRoute, 'AdminController@index')->name('adminPanel');
        Route::get($adminRoute . '/test', function () {
            echo 'test';
        });
    });
    Route::get($adminRoute . '/guest/{where?}', 'AdminController@guest')->where('where', '.*')->name('adminAsGuest');
});

以及对应的isAdmin中间件:

public function handle($request, Closure $next)
{
    $adminRoute = config('app.admin-route');
    $adminRoute = (preg_match('/\/.*/', $adminRoute)) ? $adminRoute : '/' . $adminRoute;
    // check if authentified
    if (Auth::check())
    {
        // check if admin
        if (Auth::user()->role == 1) {
            return $next($request);
        }
        else
        {
            $route = "/".$request->route()->uri;
            // check if route exists
            if (Route::has($route)) {
                // trim the route after admin and puts a guest inside
                $redirect = preg_replace("/\\".$adminRoute."/", "", $route);
                return redirect($adminRoute . '\/guest/' . $redirect);
            }
            else {
                // if it doesn't, let it go to the laravel error
                return $next($request);
            }
        }

    }

    // if auth middleware was used on same route, won't go there anyways
    // if not, redirect to root route
    return redirect('/');
}

只要我使用 env("APP_ADMIN_ROUTE") 作为管理路由的根目录,Route::has($route) 就无法正确触发,因此我正处于挣扎之中。

这是我在if (Route::has($route)) 之前的调试输出

Auth::check()
    true
Auth::user()->role
    0
$route
    "/admin/test"
Route::has($route);
    false


vagrant@ubuntu-xenial:/var/www/html$ wphp artisan route:list
+--------+----------+------------------------+------------------+------------------------------------------------------------------------+------------------+
| Domain | Method   | URI                    | Name             | Action                                                                 | Middleware       |
+--------+----------+------------------------+------------------+------------------------------------------------------------------------+------------------+
|        | GET|HEAD | /                      |                  | App\Http\Controllers\WelcomeController@index                           | web              |
|        | GET|HEAD | admin                  | adminPanel       | App\Http\Controllers\Admin\AdminController@index                       | web,auth,isadmin |
|        | GET|HEAD | admin/guest/{where?}   | adminAsGuest     | App\Http\Controllers\Admin\AdminController@guest                       | web,auth         |
|        | GET|HEAD | admin/test             |                  | Closure                                                                | web,auth,isadmin |

我知道使用管理员控制器肯定会更加一致,在这些控制器中,我不断跟踪所连接用户的角色,并授予或不授予修改内容的权利。但我真的很想知道是否有任何可能的方法来像我在这里尝试过的那样工作。

我见过Zizaco/entrust,它肯定会在更简单的方法上工作得很好,如果我当前的问题没有积极的答案,这是我的下一步:)

这是我关于 StackOverflow 的第一个问题。我对那个精确的东西进行了很好的搜索,但没有成功。如果我在某处遗漏了明显的答案,我深表歉意。

编辑:根据 Joel Hinz 的评论更新了代码。

// \Config\app.php
'admin-route' => env('APP_ADMIN_ROUTE', 'admin'),

【问题讨论】:

  • 哦,我现在很困惑。昨天在没有 env 的情况下工作,所以我把它反转了,我无法让它再次工作。 Route::has() 似乎适用于路由名称而不是 URI。我会以这种方式进行调查并与laracasts.com/discuss/channels/general-discussion/…核对

标签: php laravel routes middleware


【解决方案1】:

通常最好让配置文件读取 .env 变量,然后从配置文件中加载您实际需要的设置。这样一来,它们就可以被缓存,并且您几乎总是知道它们已经被正确读取,而不必怀疑它们会在哪里工作以及在哪里不会工作。

在你的情况下,这样的事情就足够了:

// in .env
APP_ADMIN_ROUTE=something

// in e.g. config/app.php
'admin-route' => env('APP_ADMIN_ROUTE');

// in the middleware
$adminRoute = config('app.admin-route');

我不能 100% 确定这实际上是您的问题,但值得一试 - 即使它不起作用,它仍然是最佳实践。 :)

【讨论】:

  • 感谢乔尔的提示。我相应地进行了更改,并将从现在开始使用它。不幸的是,它没有解决问题。
  • 很遗憾听到这个消息。希望其他人有正确的答案!
【解决方案2】:

好的,第一个问题,第一个答案,看来我没有探索所有的可能性。

问题不是在路由 URI 定义中使用变量,而是 Route::has() 的不当使用。这仅适用于路由名称,不适用于路由 URI。根据https://laracasts.com/discuss/channels/general-discussion/check-if-route-exists,检查路由是否存在的正确方法是使用Route::checkRoutes->match($testValue) 和Illuminate\Http\Request 的$testValue 成员。

Route::checkRoutes->match($testValue) 将返回一个带有第一个匹配项的 Illuminate\Routing\Route 实例,如果没有匹配项则返回一个空值。

在中间件 handle() 上下文中,它可以这样表达:

$route = "/" . $request->route()->uri;
// Shape your test route URI in a request
$testValue = $request->create($route);
// check if route exists
if (Route::getRoutes()->match($testValue)) {
    // statements here
}

那么,正确的中间件完整代码是:

public function handle($request, Closure $next)
{
    $adminRoute = config('app.admin-route');
    $adminRoute = (preg_match('/\/.*/', $adminRoute)) ? $adminRoute : '/' . $adminRoute;
    // check if authentified
    if (Auth::check())
    {
        // check if admin
        if (Auth::user()->role == 1) {
            return $next($request);
        }
        else
        {
            $route = "/" . $request->route()->uri;
            $nreq = $request->create($route);
            // check if route exists
            if (Route::getRoutes()->match($nreq)) {
                // trim the route after admin and puts a guest inside
                $redirect = preg_replace("/\\".$adminRoute."/", "", $route);
                return redirect($adminRoute.'/guest' . $redirect);
            }
            else {
                // if it doesn't, let it go to the laravel error
                return $next($request);
            }
        }

    }

    // if auth middleware was used on same route, won't go there anyways
    // if not, redirect to root route
    return redirect('/');
}

是什么让我认为这只是无用的代码块,因为中间件只会在现有的 /admin/something 路由 URI 上触发,并且测试路由是否存在毫无意义。

好吧,无论如何,感谢所有花时间阅读的人,再见。

【讨论】:

    猜你喜欢
    • 2018-07-05
    • 1970-01-01
    • 2018-03-21
    • 2018-04-30
    • 2018-03-19
    • 2018-09-12
    • 2018-11-08
    • 2018-08-05
    • 1970-01-01
    相关资源
    最近更新 更多