多个控制器的单个 Laravel 路由

Posted

技术标签:

【中文标题】多个控制器的单个 Laravel 路由【英文标题】:Single Laravel Route for multiple controllers 【发布时间】:2015-09-30 20:03:36 【问题描述】:

我正在创建一个具有多种用户类型的项目,例如。超级管理员、管理员、管理员等。一旦用户通过身份验证,系统就会检查用户类型并将其发送到相应的控制器。中间件工作正常。

因此,当经理转到 http://example.com/dashboard 时,他将看到经理仪表板,而当管理员转到同一链接时,他可以看到管理员仪表板。

以下路线组单独工作正常,但放在一起时只有最后一个工作。

/*****  Routes.php  ****/
 // SuperAdmin Routes
    Route::group(['middleware' => 'App\Http\Middleware\SuperAdminMiddleware'], function () 
        Route::get('dashboard', 'SuperAdmin\dashboard@index'); // SuperAdmin Dashboard
        Route::get('users', 'SuperAdmin\manageUsers@index'); // SuperAdmin Users
    );

 // Admin Routes
    Route::group(['middleware' => 'App\Http\Middleware\AdminMiddleware'], function () 
        Route::get('dashboard', 'Admin\dashboard@index'); // Admin Dashboard
        Route::get('users', 'Admin\manageUsers@index'); // Admin Users
    );

我知道我们可以重命名路由,例如 superadmin/dashboard 和 admin/dashboard,但我想知道是否有其他方法可以实现干净的路由。有谁知道任何解决方法?

顺便说一句,我使用的是 LARAVEL 5.1

任何帮助表示赞赏:)

【问题讨论】:

当你把它们放在一起时,你只是用第二个覆盖第一个...... 没有。这行不通。 【参考方案1】:

您可以使用 Before Middleware 覆盖路由操作的 namespaceusescontroller 属性:

use Closure;
use Illuminate\Http\Request;
use Illuminate\Contracts\Container\Container;
use App\Http\Middleware\AdminMiddleware;
use App\Http\Middleware\SuperAdminMiddleware;

class AdminRoutingMiddleware

    /**
     * @var Container
     */
    private $container;

    public function __construct(Container $container)
    
        $this->container = $container;
    

    private static $ROLES = [
        'admin' => [
            'namespace' => 'Admin',
            'middleware' => AdminMiddleware::class,
        ],
        'super' => [
            'namespace' => 'SuperAdmin',
            'middleware' => SuperAdminMiddleware::class,
        ]
    ];

    public function handle(Request $request, Closure $next)
    
        $action = $request->route()->getAction();
        $role = static::$ROLES[$request->user()->role];

        $namespace = $action['namespace'] . '\\' . $role['namespace'];

        $action['uses'] = str_replace($action['namespace'], $namespace, $action['uses']);
        $action['controller'] = str_replace($action['namespace'], $namespace, $action['controller']);
        $action['namespace'] = $namespace;

        $request->route()->setAction($action);

        return $this->container->make($role['middleware'])->handle($request, $next);
    

这样你只需要注册每个路由一次,没有最终的命名空间前缀:

Route::group(['middleware' => 'App\Http\Middleware\AdminRoutingMiddleware'], function () 
    Route::get('dashboard', 'dashboard@index');
    Route::get('users', 'manageUsers@index');
);

中间件将根据当前用户的role 属性将'dashboard@index' 转换为'Admin\dashboard@index''SuperAdmin\dashboard@index',并应用角色特定的中间件。

【讨论】:

AdminMiddleware 是做什么的?为什么我需要为每个角色使用另一个中间件? @rostamiani 这是 OP 的问题。【参考方案2】:

我能想到的最佳解决方案是创建一个控制器来管理用户的所有页面。

routes.php 文件中的示例:

Route::get('dashboard', 'PagesController@dashboard');
Route::get('users', 'PagesController@manageUsers');

您的 PagesController.php 文件:

protected $user;

public function __construct()

    $this->user = Auth::user();


public function dashboard()
    //you have to define 'isSuperAdmin' and 'isAdmin' functions inside your user model or somewhere else
    if($this->user->isSuperAdmin())
        $controller = app()->make('SuperAdminController');
        return $controller->callAction('dashboard');    
    
    if($this->user->isAdmin())
        $controller = app()->make('AdminController');
        return $controller->callAction('dashboard');    
    

public function manageUsers()
    if($this->user->isSuperAdmin())
        $controller = app()->make('SuperAdminController');
        return $controller->callAction('manageUsers');  
    
    if($this->user->isAdmin())
        $controller = app()->make('AdminController');
        return $controller->callAction('manageUsers');  
    

【讨论】:

谢谢你的回复,我试过了。但由于某种原因 app()->make('SuperAdminController');给出了 SuperAdminController 不存在的错误。虽然它确实存在,但我也使用该命令转储自动加载。它很奇怪,但我认为这可能是因为我使用的是最新版本,它可能不理解 make 命令。 尝试$app = app(); 然后$app->make() 谢谢,我设法让它以这种方式工作 app()->make('App\Http\Controllers\SuperAdmin\SuperAdminController')->dashboard();一切都按我的意愿工作。我只是担心这是否是从另一个控制器调用方法的好方法? 一般来说,从 HTTP 请求以外的任何地方调用控制器方法不是一个好习惯。在这种情况下,从技术上讲,HTTP 请求仍会调用控制器操作。您可能会发现此对话很有用:laracasts.com/discuss/channels/general-discussion/…

以上是关于多个控制器的单个 Laravel 路由的主要内容,如果未能解决你的问题,请参考以下文章

Laravel:如何在路由中传递单个 ID

如何从单个控制器将数据插入到 laravel 中的多个表中?

Laravel中的路由问题,带有多个控制器和具有相同名称的不同路由[关闭]

多个路由到同一个 Laravel 资源控制器操作

laravel 控制器多个方法共用一个路由

Laravel - 控制器中路由的中间件