Zend_Acl and MVC Integration Part I (Basic Use)
By Aldemar Bernal
So, what is wrong with Zend_Acl and the current MVC implementation in the Zend Framework? there is nothing wrong, it is just that it gets not too obvious for developers how to achieve an optimal integration between these two important parts of the framework.
First at all, this article is based on the following Zend Framework Proporsal (link), by this moment this proposal is in Pending Recommendation state.
Well, how it works? There are two key components in this proposal:- A Front Controller Plugin: This component resolves if the current user has access to the page which is being opened.
- An Action Helper: This component allows you to check whether the current user has access inside a controller.
Based on these two components, let's try them with an example. Let's talk about a website like DevZone, we would need a controller that work with the user management and another one which will deal with article management, as well we need 3 types of users (roles), one for guests, one for writers and another one which will approve the articles; resuming, we have:
Resources:- user controller.
- article controller.
- Guest.
- Writer.
- Admin.
Setting up the Zend_Acl component
After defined what we want to do, the next step will create a Zend_Acl instance which will reflect our model.
/** Creating the ACL object */
require_once 'Zend/Acl.php';
$myAcl = new Zend_Acl();
Creating the roles
Now we create the roles in our Zend_Acl instance.
/** Creating Roles */
require_once 'Zend/Acl/Role.php';
$myAcl->addRole(new Zend_Acl_Role('guest'))
->addRole(new Zend_Acl_Role('writer'), 'guest')
->addRole(new Zend_Acl_Role('admin'), 'writer');
Creating the resources
And then we create the resources needed (one per controller) and their relationship with the roles we created.
/** Creating resources */
require_once 'Zend/Acl/Resource.php';
$myAcl->add(new Zend_Acl_Resource('user'))
->add(new Zend_Acl_Resource('article'));
Creating the permissions
Now that we added the roles and resources to our Zend_Acl instance, it's time to explain what actions must be available to which roles.
- Guest won't have access to edit, add or approve an article.
- Writer won't have access to approve an article.
- Admin will have complete access.
/** Creating permissions */
$myAcl->allow('guest', 'user')
->deny('guest', 'article')
->allow('guest', 'article', 'view')
->allow('writer', 'article', array('add', 'edit'))
->allow('admin', 'article', 'approve');
Creating the access denied view file
We will need to create a view and an action which will address all those denied users, in order to do it, first we create a new action in our error controller:
class ErrorController extends Zend_Controller_Action
{
....
public function deniedAction()
{
}
....
}
And then we create our view file (/application/views/scripts/error/denied.phtml) with some warning message:
<h1>Error</h1>
<h2>Access denied</h2>
<p>You are trying to access an area which you have not allowed.</p>
Finishing the configuration
Okay, we have setup our Zend_Acl configuration, so far, it doesn't look like something new, but the next step is register the controller plugin, this important part takes the Zend_Acl instance we created and then validates it against the current page being accessed by an user.
/** Setting up the front controller */
require_once 'Zend/Controller/Front.php';
$front = Zend_Controller_Front::getInstance();
$front->setControllerDirectory('path/to/controllers');
/** Registering the Plugin object */
require_once 'Zend/Controller/Plugin/Acl.php';
$aclPlugin = new Zend_Controller_Plugin_Acl($myAcl);
$aclPlugin->setRoleName($currentUserRole);
$front->registerPlugin(new Zend_Controller_Plugin_Acl($acl, 'guest'));
/** Dispatching the front controller */
$front->dispatch();
After this configuration is done, once an user enters in our application, depending the role he/she has the page will be displayed or an access denied page will be displayed.
For more information about this you can go to:
Zend_Acl & MVC Integration
and here is a small implementation source code of this:
Source Code

Comments
Nice writeup, Aldemar! ACLs are often seen as an arcane subject in ZF, and they’re actually dirt simple, as you clearly illustrate. I also like the idea of the deniedAction() in your error controller.
The problem with Zend_Acl is that nobody wants to hardcode roles, resources and permissions in some file (at least not me). I have database tables for user, roles, resources and permissions, so an admin can easily modify and extend them as needed.
A db-query for the current user and the requested resource (action) is enough to determine rights and let the MVC act accordingly. There is simply no reason to use Zend_Acl as that would just double the db structure and the queries. - Know what I mean?
Sometimes it's not necessary to take Acl from a database, for example in a website as the one shown in the article (devzone), there is no moment where an Admin would like Guests to approve articles =P, so, it can be hardcoded. I'm writing right now another article about other proposal I have, that talks about those cases where you need to change Acl in the fly, so, not hardcoded but using anything you'd like (a DB, a config file, etc), stay tuned =D
I think you may not have read or understood the ACL documentation because it sounds like you're trying to use a framework as to not re-invent the wheel yet you rolled your own ALC that reinvented the wheel.
The Zend ACL can be created once, all the resources, roles and perms set up, then serialzed and stored in something like memcached a flat file or DB for increased performance. The backend store can be a database if you wish, you just extend the ACL class and load up your roles, resources and perms from the DB, then loop and add the rights.
This allows you to store the data in the database, use the Zend_Acl, and Save trips to the DB.
But if I use Doctrine, is it wise to use nested set for roles?
About storing acl into a DB, I will talk later about how to integrate datasources into Acl with another proposal I wrote, so stay tuned!.
Aldemar
About storing acl into a DB, I will talk later about how to integrate datasources into Acl with another proposal I wrote, so stay tuned!.
Aldemar
$front->registerPlugin(new Zend_Controller_Plugin_Acl($aclPlugin, 'guest'));
?
$front->registerPlugin(new Zend_Controller_Plugin_Acl($aclPlugin, 'guest'));
?
but in fact , we can't do like this in real project.
For advance usage of Zend_Acl , we may combin other components like Zend_Config,Zend_Cache , etc..
http://devzone.zend.com/article/3510-Zend_Acl-and-MVC-Integration-Part-II-Advanced-Use
I created Dir Struct as
Controller/
Models/
Views/
index/
index.phtml
test.phtml
I am able to get the output of index.phtml but when i type
http://localhost/zf/public/test
i am not getting the test file output it shows me error
"Object not found!..."
plz help me to resolve this problem.
Thanx,
with kind regards,
Amit
Is there a simpeler way to load all relevant data from the db into the acl in a lazy manner?