ZF-7550: Bootstrap fails after checking out r17414

Description

Due to commit r17414 my bootstrap fails because zend_app "can't" find a custom resource plugin. The only decent fix I can think of is reverting r17414 ( http://framework.zend.com/code/changelog/… ).

The exception I get is: {quote}Zend_Application_Bootstrap_Exception: Resource matching "freak_application_resource_acl" not found in /home/dolf/Projects/Kandelaaronline/website/application/library/Zend/Application/Bootstrap/BootstrapAbstract.php on line 685{quote}

Comments

Need a reproduce case, please. All current tests pass, so I need a test that fails to debug against. :)

It's real easy (if you think otherwise I will set up a reproduce-project), it's just that I depend on autoloading for finding the resource plugins, which was effectively disabled by r17414.

As discussed on IRC, a bare minimum of reproducible code (I can't get it any smaller though).

I'm not sure that there is an issue here at all. I suspect that loading a custom resource by passing the class name as a string was perhaps an unintended side effect of the previous use of class_exists(). Matthew would have to comment on that.

In any case, the manual states "As long as you register the prefix path for this resource plugin, you can then use it in your application."

Can't you just set your plugin path first instead of relying on autoloading?

pluginpaths.Freak_Application_Resource  = "Freak/Application/Resource"
resources.Acl = "array()"

No, that does not fix it. Besides; it was working functionality; not something you'd expect to be changed in a mini-release.

Actually, Dolf, Graham's example DOES work, assuming (a) the class has been loaded previously or (b) the class may be autoloaded.

In fact, I have serious doubts if that commit is the one that caused your problems. The exception line mentioned in your report is in the _executeResource() method, and indicates that the bootstrap was unable to find either a class or plugin resource matching the name provided. The class_exists() call is within getPluginResource, which is called on line 673, and by proxy on line 671 when hasPluginResource is called.

I have personally tested the following situations:

  • adding a pluginPaths. entry, and using the resource's short name
  • adding a pluginPaths. entry, and using the resource's full class name
  • using only the resource's full class name, and manually require'ing the classfile

In all of the above cases, it works perfectly -- the resource is loaded without error. I only get the error message you describe if the class does not exist or is not loadable via the plugin path specified -- which is exactly how it should work.

I think you misidentified the source of the error -- that class_exists() call is actually now more lenient than it was previously in that it now allows a lookup by the autoloader. The previous situation did not do autoloading -- and the only way this would cause a conflict is if your class name could match the path of another class on the include_path. In that particular case, the issue is on your end.

I'm closing this issue; please re-open if you can provide a reproduce case.

Actually, Dolf, Graham's example DOES work

Apologies; before I said that it didn't work I /did/ try it, but I guess I must have done something wrong there cause testing it again works perfectly, my bad.

using only the resource's full class name, and manually require'ing the classfile

And that's exactly where my problem is. Until r17414 it was not necessary to manually require resource plugins whereas it is necessary now all of a sudden (changed during a mini release)

I forgot one more important use case:

  • using only the resource's full class name, and class is on include_path

This fails both with and without the change suggested. In looking at the code, it could never have worked; _executeResource() explicitly casts the resource name to lowercase, which obviates a match.

I feel it should work, however, as getResourcePlugin() actually allows for having the resource name be the class name, and am currently working on a fix.

Please, next time have a reproduce case in hand so I don't have to hunt it down. I've wasted literally hours trying to find this based on your descriptions, and it was literally as simple as:

  • create a resource plugin class in library/My/Resource/Foo.php with an init() method that echoes "I'm Here"
  • Add "My_" to the autoloaderNamespaces
  • add an entry: resources.My_Resource_Foo.foo = "bar"
  • Bootstrap the application

I did add a reproduce case (which took me in turn 3 hours to get zend_tool up and running which didn't work on php5.3 (ralph has more details)) through zend_tool a few days ago as discussed on IRC. The reproduce project has been attached to this issue. The project resembles the situation perfectly. If I undo what was done in r17414 everything works at once. Applying r17414 breaks everything immediately.

My bad -- missed the attachment.

However, the code you provided does not work for me on current trunk either with or without the second flag passed to class_exists(). Frankly, I'm not sure why it was working for you before.

I've got a fix in place currently, but getting a test case that works inside the test suite is proving to be problematic. Regardless, a fix will be in 1.9.2.

Fixed in trunk and 1.9 release branch with the caveat that resources must be autoloadable for this to work.

Thank you! I'm loving ZF :D

There is still an issue in ZF 1.10.1 related to that plugin bootstrapper:

I am loading standard db resource, but it in my case class named 'db' is already defined by my legacy code. So this class is being called as a recource class even if it is not a resource at all.

As I found out instead of "if (class_exists($plugin))" should be "if (class_exists($plugin) && $plugin instanceof Zend_Application_Resource_ResourceAbstract)" - to be sure that it's a resource class.

And it's still an issue in ZF 1.10.3 at least.

I agree with Jonas that line 354 of Zend_Application_Bootstrap_BootstrapAbstract needs to have the additional guard condition added to make sure you only instantiate a resource subclass.

Actually, I think a better solution would be to just use the pluginLoader to test for the existence of the class...since it's already configured to look in paths where resource classes exist...