两次声明相同的路由,但根据中间件期望不同的行为
Declare same route twice but expect different behaviour according to a middleware
我开始使用 lumen 框架创建 REST API,并想为我的 GET /user
路由设置特定的行为。行为如下:
- 如果请求来自经过身份验证的用户(使用
auth
中间件),则会调用 UserController
中的方法 getAllFields
并且 return 来自 user
- 如果不是这种情况,将调用
UserController
中的方法 get
并且 return 来自 user
的一些数据
在我的 web.php
中使用一个简单的中间件来编写它似乎合乎逻辑:
<?php
$router->group(['middleware' => 'auth'], function () use ($router) {
$router->get('/user/{id}', [
'uses' => 'UserController@getAllFields'
]);
});
$router->get('/user/{id}', [
'uses' => 'UserController@get'
]);
但是由于某些原因,即使中间件是正确的,我总是得到第二个路由声明(即调用get()
)的响应。我明确指出,如果我删除第二个路由声明,中间件中的那个将按预期工作。
有人知道我如何才能实现类似的效果吗?
这种模式违背了Laravel的路由理念。每个路由应该定义一次。
您可以在不启用 auth
中间件的情况下定义您的路由,然后在控制器中定义您的逻辑。
路由器将检查您的请求是否与任何声明的路由相匹配。中间件将 运行 在该匹配之后,因此您不能只是 return 到路由器并尝试找到另一个匹配。
休闲 Laravel 和路由模式 - 你应该有一个指向控制器内部方法的路由。然后在其中您可以检查用户是否已登录并从该控制器执行 getAllFields() 。重写并不多,因为无论如何您目前都在两条路线中使用 UserController。
web.php
$router->get('/user/{id}', 'UserController@get');
UserController.php
public function get()
{
return auth()->check() ? YourMethodForLogged() : YourMethodForNotLogged();
}
或者如果没有太多逻辑你可以把它放在一个方法中。
另外,使用 Laravels REST 标准也是个好主意(所以使用 show 而不是 get,"users" 而不是 "user" 等等 - 阅读更多 https://laravel.com/docs/7.x/controllers)
web.php
$router->get('/users/{user}', 'UserController@show');
UserController.php
public function show(User $user)
{
if (auth()->check()) {
//
} else {
//
}
}
总而言之 - 根据您的需要,在控制器内部使用 Auth 而不是中间件。
检查用户是否登录您可以使用 Facade Auth::check() 或 helper auth()->check(),或者相反 Auth::guest() 或 auth()->guest()。
如果你实际上使用的是 Lumen 而不是完整的 Laravel 那么默认情况下没有 auth helper(你可以自己制作或使用像 lumen-helpers 这样的包)或者只是保持简单而只使用 Facades (如果您随后在 Lumen 中启用了)。
阅读更多https://laravel.com/docs/7.x/authentication and https://lumen.laravel.com/docs/7.x/authentication
我开始使用 lumen 框架创建 REST API,并想为我的 GET /user
路由设置特定的行为。行为如下:
- 如果请求来自经过身份验证的用户(使用
auth
中间件),则会调用UserController
中的方法getAllFields
并且 return 来自user
- 如果不是这种情况,将调用
UserController
中的方法get
并且 return 来自user
的一些数据
在我的 web.php
中使用一个简单的中间件来编写它似乎合乎逻辑:
<?php
$router->group(['middleware' => 'auth'], function () use ($router) {
$router->get('/user/{id}', [
'uses' => 'UserController@getAllFields'
]);
});
$router->get('/user/{id}', [
'uses' => 'UserController@get'
]);
但是由于某些原因,即使中间件是正确的,我总是得到第二个路由声明(即调用get()
)的响应。我明确指出,如果我删除第二个路由声明,中间件中的那个将按预期工作。
有人知道我如何才能实现类似的效果吗?
这种模式违背了Laravel的路由理念。每个路由应该定义一次。
您可以在不启用 auth
中间件的情况下定义您的路由,然后在控制器中定义您的逻辑。
路由器将检查您的请求是否与任何声明的路由相匹配。中间件将 运行 在该匹配之后,因此您不能只是 return 到路由器并尝试找到另一个匹配。
休闲 Laravel 和路由模式 - 你应该有一个指向控制器内部方法的路由。然后在其中您可以检查用户是否已登录并从该控制器执行 getAllFields() 。重写并不多,因为无论如何您目前都在两条路线中使用 UserController。
web.php
$router->get('/user/{id}', 'UserController@get');
UserController.php
public function get()
{
return auth()->check() ? YourMethodForLogged() : YourMethodForNotLogged();
}
或者如果没有太多逻辑你可以把它放在一个方法中。
另外,使用 Laravels REST 标准也是个好主意(所以使用 show 而不是 get,"users" 而不是 "user" 等等 - 阅读更多 https://laravel.com/docs/7.x/controllers)
web.php
$router->get('/users/{user}', 'UserController@show');
UserController.php
public function show(User $user)
{
if (auth()->check()) {
//
} else {
//
}
}
总而言之 - 根据您的需要,在控制器内部使用 Auth 而不是中间件。 检查用户是否登录您可以使用 Facade Auth::check() 或 helper auth()->check(),或者相反 Auth::guest() 或 auth()->guest()。
如果你实际上使用的是 Lumen 而不是完整的 Laravel 那么默认情况下没有 auth helper(你可以自己制作或使用像 lumen-helpers 这样的包)或者只是保持简单而只使用 Facades (如果您随后在 Lumen 中启用了)。
阅读更多https://laravel.com/docs/7.x/authentication and https://lumen.laravel.com/docs/7.x/authentication