Issues

ZF-11219: zend_loader_autoloader confuses chained namespaces

Description

scenario

i have chained namespaces in the following way:

Level1_
Level1_Level2_
Level1_Level2_Level3_
...

all the namespaces are correctily registered at {{Zend_Loader_Autoloader}} with their respective paths.

problem

when i ask for the class {{Level1_Level2_Level3_Some}} the autoloader activates the namespace {{Level1_}} instead of {{Level1_Level2_Level3_}}

possible solution

the following sollution worked for me:

  1. in file {{Zend/Loader/Autoloader.php}} replace the lines 338-340 with:
if (false === $namespace
    || (strlen($ns) > strlen($namespace))
) {
    $namespace   = $ns;
    $autoloaders = $this->getNamespaceAutoloaders($ns);
}
  1. in file {{Zend/Loader/Autoloader/Resource.php}} replace the line 148 with:
$namespace = array();
$topLevelSegments = count(explode('_', $namespaceTopLevel));
for ($i = 0; $i < $topLevelSegments; $i++) {
    $namespace[] = array_shift($segments);
}
$namespace = implode('_', $namespace);

Comments

I don't get this, could you clarify why you'd need to add a namespace for Level1_ and Level1_Level2_?

Zend_Loader_Autoloader does not have path mapping to namespaces, only the resource loader does this!

As for the resource loader, that will work fine for such a situation (look at the models/mappers for Model_Mapper in the module resource loader)

{quote} I don't get this, could you clarify why you'd need to add a namespace for Level1_ and Level1_Level2_? {quote}

i've implemented chained modules support on my application. for that, the submodules' identificator is a chain of their hierarchy. for example, the module HR (Human Resources) - Curricula - Admin has the key {{hr_curricula_admin}}.

why does submodules is needed? 'cause inside human resources i have financial control, horary control, salary control. as each one has it's own permission control and controllers and views, it seems to me more likely a submodule than a parameter to a more-general-purpose module.

{quote} Zend_Loader_Autoloader does not have path mapping to namespaces, only the resource loader does this! {quote}

yep, but it do deals with namespaces -- even the mapping namespaces-paths residing at resource loaders -- and in a way wich does not support more than one level.

{quote} As for the resource loader, that will work fine for such a situation (look at the models/mappers for Model_Mapper in the module resource loader) {quote}

the fact is that {{Model_Mappers}} is not treated as a chained namespace, but as a component and resource type inside {{Zend_Loader_Autoloader_Resource}}.

for default, Zend allows me to map {{Hr_Model_Mapper}} because {{Hr}} is the namespace and {{Model_Mapper}} a resource autoloader's component, such as {{Model_DbTable}}, {{Form}}, {{Model}}, {{Plugin}} and so on. if i need {{Hr_Curricula_Model_Mapper}} where {{Model_Mapper}} is still a component and {{Hr_Curricula}} the namespace, autoloader fails.

To fully understand this, I had to write unit tests - which is what was missing from your report. As such, I was able to understand the issues, which were:

  • The autoloader stops searching at the first namespace that matches a class, even if a more specific autoloader exists
  • The resource autoloader assumes only a single segment namespace -- which means it will fail if the resource namespace is multi-segment.

I've added tests and patched the library files in trunk and the 1.11 release branch at this time.