Php – Best Practices PHP mvc routing

mvcPHP

I have a custom MVC framework that is in a constant state of evolution. There's a long standing debate with a co-worker how the routing should work. Considering the following directory structure:

/core/Router.php
/mvc/Controllers/{Public controllers}
/mvc/Controllers/Private/{Controllers requiring valid user}
/mvc/Controllers/CMS/{Controllers requiring valid user and specific roles}

The question is:
"Where should the current User's authentication be established: in the Router, when choosing which controller/directory to load, or in each Controller?"

My argument is that when authenticating in the Router, an Error Controller is created instead of the requested Controller, informing you of your mishap; And the directory structure clearly indicates the authentication required.

His argument is that a router should do routing and only routing. Leave it to the Controller to handle it on a case by case basis. This is more modular and allows more flexibility should changes need to be made by the router.

https://codereview.stackexchange.com/questions/26345/php-mvc-custom-routing-mechanism alluded to it, but the topic was of a different nature.

Alternative suggestions would be welcomed as well.

Best Answer

I'd have another component in between that determines the access rights. This component can have a set of mappings of user roles to resources, where controllers and/or actions are the resources. The execution would then go like this:

Router -> Authorization -> Controller

Router: determines which controller and action to execute

Auth: find out which user role is logged in and check
if the user has access to the controller/action,
if not, throw an exception that will get caught by the error handler,
or redirect to login page for guests, or whatever

Controller: if the authorization component didn't complain, do work as usual

If you want to get fancy, you can use php doc comments and reflection to annotate your methods and controllers on the spot instead of having a big list of allowed resources for user roles. Something like:

class Controller {
    /**
     * @allow({'admin','user'})
     * @prevent({'guest'})
     */
    public function someAction(){}
}

The auth component can then read the annotations to determine access rights, instead of having a big list of role->resource mappings