This is what I do too.
The simplicity of the code for checking authenticaton in the construct is more favorable to me (the construct is not too fat either).
I check the minimal permission required in the construct and individual permissions in the individual methods.
If all the method of the controller require same and only minimal permissions, i just put them in the construct.
One other form of the implementation is separating the controller for Authenticated users.
The backend controllers would extend 'Admin_Controller' which checks authentication in its construct, thereby restricting any operations it the user is not authenticated.
This makes the code more reusable and reliable.
As there is no right or wrong in this question, I could give an example about how I like to use Dependency Injection in PHP.
I'm using the Dependency Injection Component from Symfony with the LosoDiAnnotationsBundle and extracted everything from the Bundle to use it as standalone as the Dependency Injection Component. I'm not using the rest of the Symfony Framework.
There are two functions in my system which use the Dependency Injection Container. The main function and the dispatcher. The main function (application entry point) retrieves the configured Dispatcher like this:
$dispatcher = $service_container->get('Dispatcher');
$response = $dispatcher->route( $request );
The service called "Dispatcher" is either defined in the global dependency config or annotated in the class itself like this:
/*
* @Service
*/
class Dispatcher {
/**
* @Inject({"@service_container"})
*/
public function __construct($serviceContainer) {
$this->serviceContainer = $serviceContainer;
}
}
The Dispatcher needs this service locator because thats how my routing works. If you use some extra mapping between routes and called methods, you could avoid this.
To inject something into other services I use the @inject
annotation:
/** @Inject({"@SomeLogic", "@SomeGateway"}) */
public function setDependencies(SomeLogic $someLogic, SomeGateway $someGateway) {
$this->someLogic = $someLogic;
$this->someGateway = $someGateway;
}
I like this approach because the configuration of a Service Class is done in the class itself and not in a separate file. Refactoring doesn't involve messing around with lengthy XML or YAML files.
To not harm the performance I run a script everytime I change some annotations and at build time (or in general on every vagrant up). It uses Symfony's ContainerBuilder and PHP Dumper to generate a PHP Lookup file which extends the Base ServiceContainer Class.
The lookup for the example dispatcher would look like this:
protected function getDispatcherService()
{
return $this->services['dispatcher'] = new \Some\Dispatcher($this);
}
This looks like a lot of work upfront, but it clearly separates concerns later on, especially in bigger projects. Classes do what they are supposed to do and need little to no non-domain-logic code at all.
And I try to keep factories to an absolutely minimum. The DI Container itself is one big factory and repository but it is not manually maintained.
EDIT:
My Routing Function looks like this, request_uri is something like Controller/action/...
$path = explode( self::ACTION_SEPARATOR, $request_uri );
if( empty( $path[1] ))
throw new RoutingException( 'Invalid Action' );
$method = ucfirst( $path[1] );
$className = $path[0].'Controller';
$qualifiedClassName = 'Some\\Namespace\\'.$className;
if( !class_exists( $qualifiedClassName ))
throw new RoutingException(sprintf('Invalid controller "%s" for route "%s"', $qualifiedClassName, $route));
if( !is_callable( array( $qualifiedClassName, $method ) ))
throw new RoutingException(sprintf('Invalid Action "%s"', $method));
$controller = $this->serviceContainer->get( $className );
call_user_func( array( $controller, $method ), $message );
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:
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:
The auth component can then read the annotations to determine access rights, instead of having a big list of role->resource mappings