如何使用三个级别的用户访问来路由多级用户列表和创建操作。

Here is the requirements. I will have three levels of access to a dashboard that is restricted from the public (System Admin, Manager, Employee).

System admin, to simply put is essentially super admin. They have the ability to index,show,create,update,delete all companies and users.

Managers are created by system admin and assigned to a company, they have the ability to index,show,create,update,delete employees only for the company they belong to.

Employees have a read only access to their companies information and files.

Here is my current routes for the users. (using Slim Framework)

System Admin only access protected by middleware: These actions are for the system admin to manage all users.

/*** USERS ***/

// View to List Users
$this->get('/users', 'App\Controller\User\UserController:index')->setName('user.index');

// View containing user registration form
$this->get('/users/new', 'App\Controller\User\UserController:create')->setName('user.create');

// Creates new user from registration form
$this->post('/users' , 'App\Controller\User\UserController:store');

// Show single user view
$this->get('/users/{id}', 'App\Controller\User\UserController:show')->setName('user.show');

// View containing edit user form
$this->get('/users/{id}/edit', 'App\Controller\User\UserController:edit')->setName('user.edit');

// Updates new user from edit user form
$this->put('/users/{id}', 'App\Controller\User\UserController:update');

// Deletes new user from edit user form
$this->delete('/users/{id}', 'App\Controller\User\UserController:delete');

System Admin & Manager only access protected by middleware: These interactions are for the manager to manage employees

/*** COMPANIES Employees ***/

// View to List Companies employees
$this->get('/companies/{id}/users', 'App\Controller\Company\CompanyUsersController:index')->setName('company.user.index');

// View containing new employee registration form
$this->get('/companies/{id}/users/new', 'App\Controller\Company\CompanyUsersController:create')->setName('company.user.create');

// Creates new employee from registration form
$this->post('/companies/{id}/users' , 'App\Controller\Company\CompanyUsersController:store');

// Show single user
$this->get('/companies/{id}/users/{id}', 'App\Controller\Company\CompanyUsersController:show')->setName('company.user.show');

// View containing edit company employee form
$this->get('/companies/{id}/users/{id}/edit', 'App\Controller\Company\CompanyUsersController:edit')->setName('company.user.edit');

// Updates user from edit user form
$this->put('/companies/{id}/users/{id}', 'App\Controller\Company\CompanyUsersController:update');

// Deletes new user from edit user form
$this->delete('/companies/{id}/users/{id}', 'App\Controller\Company\CompanyUsersController:delete');

You will notice that for system admin, company id is not required. However, for store manager it is. So these interactions will have separate queries. My question is more about best practice. This solution seems a little redundent to me but it effectively separates concerns as well as simplifies the methods on each controller as well as the middlewares needed for access control. Am I going about this completely wrong?

I would have the same routes for all roles as the URL represents the canonical way to view that information.

e.g.

$this->get('/companies/{id}/users', 'App\Controller\Company\CompanyUsersController:index')->setName('company.user.index');

is the correct URL for the list of users for a given company.

I understand that the store manager can only access users for her own company, but that doesn't mean that the URL has to be different. It means that even though she can access /companies/123/users, she cannot access /companies/456/users. This should be done either in group middleware or in each controller. Personally, I suspect that I'd use group middleware like this:

$app->group(/companies/{id}, function () {
    $this->get('/users', 'App\Controller\Company\CompanyUsersController:index')->setName('company.user.index');
})->add(CheckUserCompanyMiddlerware::class);

and either display an error page or redirect back to the correct URL for the store manager if they go to the "wrong" company.