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_Loader_Autoloader_Resource Component Proposal

Proposed Component Name Zend_Loader_Autoloader_Resource
Developer Notes
Proposers Matthew Weier O'Phinney
Zend Liaison Ralph Schindler
Revision 1.0 - 1 January 2008: Initial Draft. (wiki revision: 6)

Table of Contents

1. Overview

Zend_Loader_Autoloader_Resource is intended to simplify loading resources that do not have 1:1 class prefix/filesystem mappings. The primary use case is for use with modular applications, to allow autoloading of module-specific classes.

2. References

3. Component Requirements, Constraints, and Acceptance Criteria

  • This component will implement Zend_Loader_Autoloader_Interface.
  • This component will require specification of both a prefix and base directory
  • This component will provide default component/subdirectory mappings
    • Users will be able to register custom component/subdirectory mappings
    • This component will allow autoloading arbitrarily nested classes under existing component maps
  • This component should also act as an object factory and registry for the given resource namespace

4. Dependencies on Other Framework Components

5. Theory of Operation

Typically, this component will be instantiated in a module's bootstrap. It's purpose is to provide the ability to autoload components in that subdirectory, assuming a standard directory layout.

For instance, the bootstrap might do the following:

This would then allow your module code to use autoloading to arbitrary resources. For instance, the following directory structure would establish the associated classes:

When the resource autoloader is in play, you can simply instantiate these classes, without worrying where they are:

6. Milestones / Tasks

  • Milestone 1: [DONE] Proposal created
  • Milestone 2: [DONE] Working prototype checked into public repository
  • Milestone 3: Community review of proposal
  • Milestone 4: Proposal acceptance
  • Milestone 5: Passing unit tests and initial documentation committed to incubator
  • Milestone 6: Review for inclusion in trunk

7. Class Index

  • Zend_Loader_Autoloader_Resource

8. Use Cases


Basic usage:


Using as an object factory and registry:


Registering custom resource paths:

9. Class Skeletons



Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Dec 17, 2008

    <p>Great idea – any chance to share code yet?</p>

    1. Dec 17, 2008

      <p>Yes – see the link to the "Pastebin resource loader implementation" in the References section.</p>

  2. Dec 18, 2008

    <p>Nice thing. Even the service location issue is solved that way. When this component is settled, we can start doing proposals for automatic dependency injection. Thanks Matthew!</p>

  3. Jan 01, 2009


    <p>I noticed in your Pastebin application that you are using the conventional and modular directory structure, however, the conventional doesn't have a models directory. So, the million euros question is: What happens if you don't have a modular directory structure? How do you load resources?</p>

    <p>I see this working fine in modular applications, but what if I'm building small applications like these ones:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[


    <p>Also, the way you are instantiating your class:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $foo = new Spindle_Model_Foo();

    <p>Doesn't it go against the naming convention the framework uses? Shouldn't it be Spindle_Models_Foo?</p>

    1. Jan 08, 2009

      <p>Federico, the naming convention the framework uses applies to "library" code, not "application" code. So, that said, I think that naming suggested works well.</p>

      <p>I will try and do a writeup on the distinction between library and application code, as its been something that has come up alot recently.</p>

  4. Jan 13, 2009

    <p>Firstly I think this is a brilliant idea and much needed. A couple of things just to clear up what you've written and may be obvious but aren't upon first glance! (to me anyway!!).</p>

    <p>In the very first example under Theory of Operation you setup a basic loader you then call a form:<br />
    $form = new Spindle_Form_Bug(); <br />
    But your module directory structure has forms in the forms directory, from the auto loading I would assume forms should be in a Form directory?</p>

    <p>If this is the case are we saying that setting up a simple autoloader as in the first example allows for the use of any resource as long as it's named correctly? Much like the autoloader now for framework components.</p>

    <p>What does it do about upper and lower case naming? Should models be located at:<br />
    module/model/ or module/Model? What would the default be (I assume it's as your directory structure is above).</p>

    <p>With regards to this it would also be nice if the prefix was automatically set to the module name, this would save our own logic and I'm 99% sure most people would want it to generally autoload from the module.</p>

    <p>Finally is the resourceloader->addResourceType() first attribute necessary?</p>

    <p>$resourceLoader->addResourceType('validator', 'validators', 'Validate');</p>

    <p>I haven't looked how it works internally yet but do you need to specify the type of resource it is? Wouldn't it be simpler with notation much like the helper paths?</p>

    1. Jan 13, 2009

      <p>Thanks for reviewing the proposal! To answer some of your questions:</p>

      <p>"But your module directory structure has forms in the forms directory, from the auto loading I would assume forms should be in a Form directory?"</p>

      <p>No – look at the implementation. A resource loader requires a namespace (mapped to a base directory), and then one or more resource types. Each resource type is mapped to a particular directory. In the case of a 'form' type, it maps to the 'forms' subdirectory – so class Spindle_Form_Bug is found in 'spindle/forms/Bug.php'. So, to answer your followup question, it <em>does</em> allow loading any resource as long as it is named correctly – i.e., if the namespace, resource prefix, and class name resolve to a file, then it will load that class from that file.</p>

      <p>In the default implementation I provided, the following mappings occur:</p>
      <li>module name => resource namespace (e.g., 'spindle' => 'Spindle')</li>
      <li>'Model' maps to subdirectory 'models' (e.g., 'Spindle_Model_' => spindle/models/')</li>
      <li>'Form' maps to subdirectory 'forms' (e.g., 'Spindle_Form_' => spindle/forms/')</li>
      <li>'Plugin' maps to subdirectory 'plugins' (e.g., 'Spindle_Plugin_' => 'spindle/plugins/')</li>
      <li>'Helper' maps to subdirectory 'controllers/helpers/' (e.g., 'Spindle_Helper_' => 'spindle/controllers/helpers/')</li>

      <p>The first argument of addResourceType() is used with the load() method and with overloading: $loader->loadValidator('Foo') would load 'Spindle_Validate_Foo'. It's also used to allow fetching the resource type for modifications or removal.</p>

      1. Jan 15, 2009

        <p>Ok I see, I was basing the implementation off the Theory of Operation example where there is no mapping (or as far as I can see anyway!).</p>

        <p>$autoloader = new Zend_Loader_Autoloader_Resource(array( <br />
        'prefix' => 'Spindle', <br />
        'basePath' => realpath(dirname(<em>FILE</em>)), <br />

        <p>Thus my question was meant to be do you then have to add resourceTypes to make it work? Or does the autoloader use a bit of magic and as long as there's a base prefix and path try and resolve paths based on the name?</p>

        <p>If I have classes Module_Model_Test, by just setting the basic setting above would it try and autoload Module/Model/Test.php or do I have to specify the resource as addResourceType('model', 'Model', 'Model')?</p>

        <p>What about my question about automatically setting he prefix to the current module? To be clear would you set every resource up in the bootstrap for all your modules or would you set them up on a per module basis? This depends on how the above question turns out.</p>

        1. Jan 15, 2009

          <p>There are default mappings provided in the implementation – this is why the Theory of Operation sample does not show using any mappings. So, for the default use case, if you follow the project structure recommendations that were approved in another proposal, you don't need to create any mappings. If you have additional resource types, or your directory structure is not consistent with the ZF recommendations, then you would define your own mappings.</p>

          <p>In your example of Module_Model_Test, it would attempt to load it from module/models/Test.php by default.</p>

          <p>As for automatically setting the prefix to the current module, there is another proposal at play. Zend_Application provides for both application-wide and module-level bootstrapping. Currently, our plan is that each module's bootstrap would register a resource loader for that module by default. This allows for each module to have it's own structure, if desired.</p>

          1. Feb 24, 2009

            <p>Hi Matthew,</p>

            <p>personaly i'am not a big fan of the module-level bootstraping. What solution do i have to use if i need a model from another module? If there is only a ressource loader for every module, what happens in the following case:</p>

            <ul class="alternate">
            <li>Assuming current module is 'Spindle'.</li>

            <p>$model = new Forum_Model_Thread()</p>

            <p>Isn't it a better solution to create automatically a full Autoloader for every module in bootstrap? Doing this will give you access to all module ressources.</p>

            <p>A second advantage is you can provide a simple caching functionality. Thus saves the "per Request" building of the Ressource Loader.</p>

            <p>What do you mean?</p>

            <p>Of course i can't wait to see the final component in the next release. <ac:emoticon ac:name="wink" /></p>

            1. Feb 24, 2009

              <p>The way we are approaching it currently is that every module's bootstrap is loaded on each request (assuming the module has a bootstrap). This way all autoloaders are setup, and any routing or other tasks that may be necessary are accomplished. This immediately solves the issue of needing to use models and other resources from another module.</p>

              <p>You will also have the flexibility to define your entire autoloading solution up front in your application bootstrap.</p>

              <p>I do hope to add caching ability to the resource loader prior to the final 1.8 release, and it will likely work similarly to how the PluginLoader's caching works.</p>

  5. Jan 14, 2009

    <p>Good proposal, I have spent a lot of time finding ways to load resources, this would be a great addition.</p>

  6. Jan 16, 2009


    <p>The prefix option is mandatory and always maps to a module, but what happens if you don't have a modular directory structure? I guess you can group the MVC into a module in order to use this component. So, is it right to say that users who want to use this component have to create a modular directory structure? And therefore Zend_Application and this proposal will make the standard directory structure obsolete?</p>

    1. Jan 16, 2009

      <p>In the examples shown here, it maps to a module – but it doesn't have to. It does, however, assume that all items which it can autoload share a common class prefix and are grouped in a common tree. If you pass an empty string as a prefix, than the prefix is omitted, and only the resource type prefix will be used (e.g, Form_Login might map to forms/Login.php within the base directory registered for the loader). </p>

      <p>Thus, it does not make the standard directory structure obsolete by any means. However, it does encourage you to choose a class prefix for your application resources – which will simplify refactoring later should you choose to utilize a modular directory structure.</p>

  7. Jan 20, 2009


    <p>I have been trying out the code from the spindle app and it works very well indeed, I did have a bit of trouble getting it off the git hub though, seems if you browse backwards from the link you gave it seems to go to a different fork??</p>

    <p>While testing I wanted to have my ZDB row classes autoloaded, however Zend_Db_Table uses Zend_Loader::loadClass() which does not touch the autoload mechanism. I was thinking maybe we could have a way of either injecting the resourceLoader or a switch to tell the ZDB classes not to use Zend_Loader? Unless there is a way to hook loadClass into the autoloader implementation? </p>

    <p>I think the need to be able to load rows/rowsets etc would be a fairly common use-case.</p>

  8. Jan 23, 2009

    <p>Hi Matthew,</p>

    <p>I have noticed there are two issues tracking my problem with Zend_Loader usage in Zend_Db_Table.</p>

    <p><a class="external-link" href=""></a> </p>

    <p>It would be cool if you could put some weight behind these issues or link them to this proposal so that all the work can be completed at together.</p>



    1. Jan 23, 2009

      <p>Yes, one of the factors pushing this solution and the general Autoloader proposal is to fix some issues found elsewhere in the framework. Besides the issues you link above, there are some that are related to autoloading that we simply cannot overcome with a Zend_Loader based solution (but where moving to a separate autoloader class, we can), and there are other places where using Zend_Loader could be minimized or eliminated if we can fall back to an Autoloader (which would make class_exists() calls return true).</p>

      1. Jan 23, 2009

        <p>Thats great <ac:emoticon ac:name="smile" /></p>

        <p>I have another suggestion from using your spindle implementation, when using load it would be good if you could pass in extra args that would be passed to the construct.</p>

        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        // from action helper
        $this->_helper->resourceLoader->getForm('myForm', array('config_array'));

        //in resource loader
        $resourceLoader->load('myForm', 'Form', array('config'), $otherArgs, $etc);

        <p>Though as I write this I realize that the instances are not instantiated on every call. Anyway might be something to think about.</p>

        <p>Other than some little things like that it has been working very well, if this can be made uniform across the framework like you suggest I think it will make a very good addition.</p>

  9. Jan 27, 2009

    <p>Just stopped by to say that this is a great proposal.</p>

    <p>Any thoughts on when we might see it in ZF?</p>

    1. Jan 27, 2009

      <p>I'll be posting it to the incubator this week, and it will likely be in trunk within the month.</p>

  10. Feb 18, 2009

    <p>Good extension. Would be a nice feature.</p>

    <p>Testing it...</p>

  11. Feb 18, 2009


    <p>I can see some variations in the way I'm using the getModel() method. A model can be anything, a db model, cache model, array model, etc, and at the moment I'm treating the resource type and the classes differently. For example, in my controller I can get an instance of a model using the getModel() method like this:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $user = $this->getModel('User'); // returns an instance of <class UserModel extends My_Model>
    $user = $this->getModel('UserInput'); // <class UserInputModel extends My_Model_Input>
    $user = $this->getModel('UserDb'); // <class UserDbModel extends My_Model_Db>
    $user = $this->getModel('UserDbTable'); // <class UserTableModel extends My_Model_Db_Table>

    <p>This way I have more control over what I'm loading. If I load UserDbModel, an instance of Zend_Db gets injected into UserDbModel. If I load UserInputModel, specific filters and validators get injected, etc.</p>

    <p>So, my question is, what problem is this component trying to solve? Autoloading a class? That's not really a problem. The reason I'm asking is because, although some users keep asking "how do I load a model?", I don't think they are asking "how do I include a class?". What I think they are really asking is: "Hold on, there's no model in the ZF. The M is missing! Cake has it, Symfony has it, and hell, even Rails has it. So, how do I load a model?"</p>

    <p>I honestly think people are struggling to understand this. Matthew's "Model infrastructure" post targets this problem, and I think it should be added to the manual, otherwise not a lot of people are going to find it.</p>

    <p>Anyway, that's just my opinion.</p>

    1. Feb 18, 2009

      <p>This component is primarily targetted at autoloading of classes that fall under a different filesystem layout than that outlined in the Coding Standards – its original purpose was to serve as a mechanism to autoload resources (classes) falling under modules.</p>

      <p>A secondary requirement is to act as an object factory and registry for the given set of resources. This allows for a couple of things: first, the ability to re-use objects within the application lifetime, and second, the potential to provide dependency injection during object instantiation. This latter is not directly treated, in part because we're not addressing what objects may need to be injected into the various resources. However, you can easily extend the resource loader to do this, and it is an intended part of the design.</p>

      1. Feb 18, 2009


        <p>Great. "Provide dependency injection during object instantiation", I like the sound of that. I'm glad we finally have a resource loader!</p>

  12. Mar 02, 2009

    <p>I've just implemented the autoloader in my test application and I like it a lot! (And it works well so far).</p>

    <p>One question, if I have sub directories do I need to specify each one as a prefix / directory?</p>

    <p>i.e.<br />
    Model - models/<br />
    Model_Rowset - models/rowset/<br />
    Model_Row - models/rows/</p>

    <p>$autoloader->addResourceType('model', 'models', 'Model_');<br />
    $autoloader->addResourceType('modelRowset', 'models/rowsets', 'Model_Rowset_');<br />
    $autoloader->addResourceType('modelRow', 'models/rows', 'Model_Row_');</p>

    <p>Would each of the above need a mapping or is there a way to make Model pick up it's sub directories. It doesn't appear to by default so I'm assuming the answer is to set each one (which is probably correct as they are individual resources).</p>

    <p>Also in other elements of the framework that require paths if an additional (or un-required) / is added to the path passed to the element it is removed (or more correctly a new one is not added). For the sake of continuity should the autoloader not do the same?</p>

    <p>i.e. at the moment the following seems to occur:<br />
    $autoloader->addResourceType('model', 'models', 'Model_');<br />
    path: base_path/models/</p>

    <p>$autoloader->addResourceType('model', 'models/', 'Model_');<br />
    path: base_path/models//</p>

    <p>This is just an observation, I don't know how much of an effect the check has on speed.</p>


    1. Mar 03, 2009

      <p>First off, as you create your resource maps, the third "namespace" or "component" argument does not need a trailing '<em>' – it in fact will get stripped off. As for the trailing slash, I _think</em> we trim it off already; if not, I'll add a check for that.</p>

      <p>Second, if you do your directory structure the way you suggest, yes, you'll need to create a mapping per resource type. But there's an easier way. <ac:emoticon ac:name="smile" /></p>

      <p>If you have:</p>
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[

      <p>then you can simply say "new Namespace_Model_Row_User()", and it will happily do its business. The key to allowing the resource loader to find items in subdirectories is to simply name the subresource segments following ZF coding standards.</p>

      1. Mar 03, 2009

        <p>Stupidly that's how I had it originally before I started using the autoloader! Changing it back works perfectly thanks.</p>

        <p>As mentioned in my first comment the directory path trailing / is added but is not stripped if one is used, the additional prefix underscore is added.</p>

  13. Mar 03, 2009

    <p>How do I go about using multiple autoloaders, if I can?</p>

    <p>I have my defaults for the module the user is currently in using Application_Module_Autoloader but I also want to invoke the account module during the controller plugin process to authenticate the user. This has the prefix Account_Model_User and is invoked from a different plugin to the one the autoloader is run in.</p>

    <p>How do I allow this to work? The obvious way is to call the file directly via include, this may or may not be faster anyway?</p>

    1. Mar 03, 2009

      <p>Each autoloader has its own instance; you simply instantiate multiple autoloaders.</p>

      <p>Zend_Application will have a 'modules' or 'module' resource which, as part of its work, instantiate a Zend_Application_Module_Autoloader for each registered module and attach it to the module bootstrap as well as the main autoloader instance.</p>

      <p>In the meantime, simply loop through the results of getControllerDirectory(), and instantiate them:</p>
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      $loaders = array();
      foreach ($front->getControllerDirectory() as $module => $directory) {
      $loaders[$module] = new Zend_Application_Module_Autoloader(array(
      'namespace' => ucfirst($module),
      'basePath' => dirname($directory),

  14. Mar 06, 2009


    <p>I am using by not more than one week resource autoloader. Which makes working with modules and their resources very good.</p>

    <p>But, i have also one problem. I am working over an application with multiple modules. Things started to mess up when i added for two modules (or even for one module) models, plugins, forms with same name as: Users, Acl, Auth, aso.</p>

    <p>Due to this similarity of names is a terrible mess into my Eclipse now... Always when i saw opened an Acl.php file i need to check before:</p>
    <ul class="alternate">
    <li>what module is related ?</li>
    <li>what's the purpose: is model, plugin, aso ?</li>

    <p>If it's not the file needed i am start looking over project tree, and of course, i need to look very carefully to pick the right file.</p>

    <p>I am wondering if is not maybe an ideea to add a facility to allow file names as:<br />
    Admin_Plugin_Acl.php instead of Acl.php. This way i think would be much easier to "locate" files into opened files list.</p>

    <p>That's just an ideea... Resources autoloading is great otherwise...</p>

    1. Mar 06, 2009

      <p>In our naming conventions, '_' indicates either a directory separator, a component separator – putting it into the filename breaks many assumptions and introduces unnecessary complexity into how classes are loaded.</p>

      <p>The class name should tell you what it is, and the directory structure should as well, to a certain degree. Again, looking at the recommended directory structure for modules:</p>
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      <p>Yes, there are three "User.php" files – but the directory structure clearly indicates their purpose. Additionally, the classes they contain will be different: Foo_Form_User, Foo_Model_User, and Foo_Api_User.</p>

      <p>Different IDEs and editors deal with open files differently. Vim, for instance, allows you to see the entire path to the file, and for each open file, which allows you to determine at a glance which file you need to work with. (Additionally, the status bar tells you the filename and path.) Code folding in editors makes it easy to trivially jump around and determine the class name if you forget.</p>

      <p>While I understand your pain, explore your IDE carefully, as you can likely get it to help you in situations like these.</p>

  15. Mar 24, 2009

    <p>Unless I'm missing something, there is a <strong>performance problem</strong> with the current code that is trivial to fix.</p>

    <p>The performance could be O(1), but currently it's O( n ). The loop in the main My_Loader_Autoloader class is unnecessary. It could be removed if the array of My_Loader_Autoloader_Resource classes were stored as an associative array keyed by prefix. So, instead of parsing the class to be autoloaded within each My_Loader_Autoloader_Resource class and checking for the prefix, simply do that in the main My_Loader_Autoloader class. Simplified example:</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        // ...

    Unknown macro: {        $autoloader = $this->_autoloaders[$prefix];        $autoloader->autoload($class);    }

        // ...

    1. Mar 24, 2009

      <p>I have three comments.</p>

      <p>First, the code here is out of date with the current implementation. Please look at the code in the incubator, which is much different from what is presented here in order to make your commentary. I'll try and update the code samples here, but this is lower priority than documenting the code at this point.</p>

      <p>Second, it does not make sense to associate a prefix or multiple prefixes with each and every autoloader; some autoloaders may not be prefix based (PEAR is a good example, as there is not a common prefix across all classes).</p>

      <p>Third, it's entirely possible that more than one autoloader will target the same prefix. In such a case, doing a key-based lookup could result in a false negative as another, later registered autoloader would be capable of loading the class.</p>

      1. Mar 24, 2009

        <p>Thanks for the clarification Matthew.</p>

        <p>The Zend_Loader_Autoloader is now more complex, but performance is better now since only  Zend_Loader_Autoloader_Resource objects that were instantiated with the proper namespace (prefix) will be attempted.</p>

        <p>Still, considering Zend_Loader_Autoloader_Resource objects are allowed only one namespace (prefix) and assuming no two Zend_Loader_Autoloader_Resource objects will share the same namespace, perhaps it's better to register a new, simpler autoloader. After all, loading resources was the intent of this proposal.</p>

        <p>Something unrelated that I noticed was that namespaces are stripped of an underscore in Zend_Loader_Autoloader_Resource. So, for example, the loading of My_Class MyClass may be attempted by the same Zend_Loader_Autoloader_Resource object?<br class="atl-forced-newline" /></p>

        1. Mar 24, 2009

          <p>You're making some rather broad assumptions that may or may not be true. First, the primary Autoloader class is not registering <em>only</em> resource autoloaders; it is meant to manage arbitrary autoloaders, which may be resource autoloaders or userland autoloader implementations. As such, there may be overlap at times – a general purpose autoloader and a resource autoloader may both be intercepting the same namespace.</p>

          <p>The reason the underscore is stripped inside of the resource autoloader is that the classes served by Zend_Loader_Autoloader_Resource are expected to follow ZF naming conventions – not arbitrary conventions. As such, we strip it off, as the comparison will always be with the segment of the class preceding the first underscore. For Zend_Loader_Autoloader, namespaces can be arbitrary, and may or may not load classes following ZF naming conventions.</p>

          <p>Now, all of this said... there is one piece of development left with Zend_Loader_Autoloader, and it has to do with what you're touching on: having Zend_Loader_Autoloader::autoload() do some optimistic matching of namespaces to determine which autoloaders to try. It's still marked as a todo in development, and you'll likely see this feature before the 1.8 release.</p>

        2. Mar 24, 2009

          <p>Also, one more thing, can we move this discussion to the mailing lists instead of the proposal page?</p>