Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

Zend Framework: Zend_Acl dynamic loading Component Proposal

Proposed Component Name Zend_Acl dynamic loading
Developer Notes http://framework.zend.com/wiki/display/ZFDEV/Zend_Acl dynamic loading
Proposers Aldemar Bernal
Zend Liaison Ralph Schindler
Revision 1.0 - 17 November 2007: Proporsal created.
1.1 - 21 January 2008: UCs Created. (wiki revision: 36)

Table of Contents

1. Overview

Zend_Acl dynamic loading isn't meant to be a replacement of the current good implementation of Zend_Acl, it is just an update proporsal based on get better performance in the component in medium/large ACL implementations as well as a base to allow the load of persistenced ACLs (from a database or a file or ..).

2. References

3. Component Requirements, Constraints, and Acceptance Criteria

  • This update will boost performance in medium/large Acl Implementations.
  • This update will allow the component to load only the needed Roles/Resources.
  • This update will allow the component to load data from datasources.

4. Dependencies on Other Framework Components

  • Zend_Acl
  • Zend_Acl_Role
  • Zend_Acl_Resource
  • Zend_Acl_Exception

5. Theory of Operation

This update doesn't make any change of current Zend_Acl implementations, it includes only a new method called registerLoader in the Zend_Acl component and a new abstract class called Zend_Acl_Loader_Abstract. The main goal of this new feature is to be able to load dynamically Roles and Resources using an instance of the abstract class. Here an example is given to make clearer the new functionality and its use:

My/AclLoader.php:

At bootstrap:

So, as you could see in the example above, the Loader class will allow to avoid the problem of loading all ACL at once in bootstrap, and will help to only load the data needed, the results are better response times and less memory usage.

6. Milestones / Tasks

  • Milestone 1: [DONE] Create ZF Wiki info.
  • Milestone 2: [DONE] Working prototype and some examples. UCs implemented click here to download.
  • Milestone 3: Working prototype checked into the incubator supporting use cases.
  • Milestone 4: Unit tests exist, work, and are checked into SVN.
  • Milestone 5: Initial documentation exists.

7. Class Index

  • Zend_Acl
  • Zend_Acl_Loader_Abstract

8. Use Cases

I recommend you to download this file where you can find all UCs implemented for better comprehension of the component use.

9. Class Skeletons

]]></ac:plain-text-body></ac:macro>

]]></ac:plain-text-body></ac:macro>

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Feb 14, 2008

    <p>Hello Aldemar,</p>

    <p>First and foremost, a big thanks for your work in this proposal. Most people wont realize this but ACL/MVC integration and dynamic loading is keeping the Zend Framework away (w/o custom implementations) from big sites.</p>

    <p>Before "converting" into the Zend Framework I developed an ACL method for loading the entire user permission system on login, and then use it for AC and menu building (with TREE assistance).</p>

    <p>So, my question is, have you contemplated any kind of storage (like Zend_Auth) for your proposals?</p>

    <p>The idea in my mind for a complete ACL system is:<br />
    1. User logs in.<br />
    2. User entire MVC ACL is fetched (from db) and loaded using your loader.<br />
    3. Object is stored in SESSION and freely used through out the application.<br />
    4. Changes to the user ACL could be made on the fly as needed using your loader.</p>

    <p>The advantages are obvious: only one database call, possibility for automatic MVC ACL checks and stored acl ready to be used for other options like menu building or backoffice changes.</p>

    1. Feb 17, 2008

      <p>Thanks Nuno for your comments,</p>

      <p>well, Zend_Auth would only require one table, an ACL storage would require one or multiple tables, that depends on how is your ACL structure. Maybe if there is some kind of standard way of doing it, we could implement it. But, you could also use UC-4 in order to work with a database.</p>

      <p>Aldemar</p>

      1. Feb 18, 2008

        <p>I think Michael Ziegler <a href="http://www.phpclasses.org/browse/package/4100.html">MyACL</a> class is a good starting point. UC-4 does allow database usage but without any king of storage you will be calling the database every time you load a new page and/or check for a new permission. Lots of users, lots of resources and a database intensive site, it's likely to stall the server with the current Zend_ACL (database) usage.</p>

        1. Feb 18, 2008

          <p>Nuno - once you register this loader into your Acl object, you must store this object (Acl object that also contains the loader) into session, so you are not registering and doing queries every time a page is loaded, that's only done when it is needed (when something is not found in the session Acl object).</p>

          <p>Aldemar</p>

    2. Feb 18, 2008

      <p>Nuno - I don't really understand why the current implementation would discourage 'big sites'. Can you provide a little more information around the way your ACL is structured so that it opens up some reasons why ZF's ACL is/isn't suitable?</p>

      <p>I've found some issues with Zend_Acl that have been resolved with a little ingenuity from the community (dynamic resources for one!) We may need to 'fatten' up with Zend_Acl section with some further documentation to show how ACLs can be expanded upon - integration with Zend_Auth, MVC and database backends are subjects that crop up quite a bit.</p>

      <p>Aldemar, had you considered opening up the scope of 'registerLoader' so that you could selectively apply modules to different parts of the site? E.g. registerLoader(new myAclLoaderOrders(), 'orders') could be mapped to an orders module, whilst another registerLoader(new myAclLoaderReports(), 'reports') applies to a completely separate MVC module. It then opens up the possibilities of selective loading based on module name, so in effect you could register 5+ modules, some of which may apply to 1 or more modules.</p>

      1. Feb 18, 2008

        <p>Please see the explanation i gave to Aldemar. You mention yourself that it was ingenuity (custom implementations) that allowed Zend_ACL to be usable with the expectations of the "real world" (database, MVC and Zend_Auth). Let's see if i can explain what i had in mind...</p>

        <p>I had my ACL like this: Module/Page based on user level.<br />
        A table would then contain<br />
        Module - Page - Level</p>

        <p>According to the user access level a tree would be built and stored in a SESSION. This would be the user actual ACL and could be used to dynamically build the app menu. Something like:</p>

        <p>SESSION<br />
        -<ac:link><ri:page ri:content-title="0" /></ac:link><br />
        --<ac:link><ri:page ri:content-title="module_name" /></ac:link><br />
        --<ac:link><ri:page ri:content-title="module_link" /></ac:link><br />
        ---<ac:link><ri:page ri:content-title="0" /></ac:link><br />
        ----<ac:link><ri:page ri:content-title="module_page_name" /></ac:link><br />
        ----<ac:link><ri:page ri:content-title="module_page_link" /></ac:link><br />
        ---<ac:link><ri:page ri:content-title="1" /></ac:link><br />
        ----<ac:link><ri:page ri:content-title="module_page_name" /></ac:link><br />
        ----<ac:link><ri:page ri:content-title="module_page_link" /></ac:link><br />
        -<ac:link><ri:page ri:content-title="1" /></ac:link><br />
        --<ac:link><ri:page ri:content-title="module_name" /></ac:link><br />
        --<ac:link><ri:page ri:content-title="module_link" /></ac:link><br />
        (etc)</p>

        <p>It didn't matter how many tables i was using or the level of fine tuning involved (i had groups, overrides and even another unrelated acl check). One database call, one session with the entire acl for that user then I would auto-check in bootstrap and no more worries about it.</p>

        <p>In theory, i could use the MyACL class with dynamic loading and just store the object myself. But IMHO the current object is still a little bloated and contains insecure information (like database access). So, that was more or less the (high) expectation i was looking for.</p>

        <p>Anyway, further documentation on the MVC and database integration is still welcome.</p>

      2. Feb 18, 2008

        <p>Simon - Jurrien Stutterheim already suggested me (at #zftalk) that feature (to register more than one loader and select one), I'll do that update in the following days.</p>

        <p>Aldemar</p>

  2. Jul 02, 2008

    <ac:macro ac:name="note"><ac:parameter ac:name="title">Zend Official Comment</ac:parameter><ac:rich-text-body>

    <p>This proposal is accepted to the <strong>Labratory</strong>.</p>

    <p>Currently, this proposal does not fully demonstrate the problem that is being solved by this proposed component.</p>

    <p>We suggest that this proposal is developed in the labratory so that both the problem and solution can become clearer, and that this proposal might become more detailed.</p>
    </ac:rich-text-body></ac:macro>

  3. Jul 18, 2008

    <p>I thought a little bit about how something like this could be implemented using structures similar to those already used by other components and for me the way Zend_Cache uses backends (Zend_Cache_Backend_*) to save data fit best.</p>

    <p>The existing Zend_Acl methods could be modified and the class itself could be extended by some methods to implement this.</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[class Zend_Acl
    {
    const BACKEND = 'backend';

    protected $_backend = null;

    [...]

    public function __construct($config = array());
    public function getBackend();
    public function setBackend(Zend_Acl_Backend_Interface $backend);

    public function addRole(Zend_Acl_Role_Interface $role, $parents = null, $useBackend = true)

    Unknown macro: { if (($useBackend === true) && ($this->_backend !== null)) $this->_backend->addRole($role, $parents); $this->_getRoleRegistry()->add($role, $parents); return $this; }

    [...]
    }]]></ac:plain-text-body></ac:macro>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[interface Zend_Acl_Backend_Interface
    {
    public function setAcl(Zend_Acl $acl);
    public function getAcl();

    public function addResource(Zend_Acl_Resource_Interface $resource, $parent);
    public function loadResource($resource);
    public function loadResources($resources);
    public function removeResource($resource);
    public function removeAllResources();

    public function addRole(Zend_Acl_Role_Interface $role, $parents);
    public function loadRole($role);
    public function loadRoles($roles);
    public function removeRole($role);
    public function removeAllRoles();

    public function setRule($operation, $type, $roles = null, $resources = null, $privileges = null, Zend_Acl_Assert_Interface $assert = null);
    }]]></ac:plain-text-body></ac:macro>

    1. Jul 19, 2008

      <p>Hmmm Felix, I don't get your point. Is this an idea about storing the Zend_Acl object? if it is, then this proposal is about something else, it's about dynamic loading roles/resources/permissions. If I'm wrong about it please make me know.</p>

      <p>Aldemar</p>

      1. Jul 19, 2008

        <p>Basically I combined your idea of dynamically loading ACL data with complete storage of ACL data. I thought of defining an interface for backends which could be used to save and load ACL data from other sources (e.g. databases: Zend_Acl_Backend_Database <ac:emoticon ac:name="question" />) and presented just another way of implementing such a behaviour with structures similar to those already used by other components.</p>

  4. Sep 08, 2009

    <p>Is there a status update on this code?</p>

    <p>Also see:
    <a class="external-link" href="http://framework.zend.com/issues/browse/ZF-2124">http://framework.zend.com/issues/browse/ZF-2124</a></p>

    1. Sep 08, 2009

      <p>Hi Ralph, I haven't updated it since I was waiting feedback from the community, but I had already write the code and it's been working well in a couple of projects. Do you think we should now put this again in <span style="text-decoration: line-through;">Ready for review</span> state?</p>