Issues

ZF-8225: Wrong class gets instantiated in Zend_Application_Bootstrap_BootstrapAbstract::getPluginResource()

Description

Using ZF 1.9.5 with Doctrine 1.1.5 and Dwoo 1.1.0

In my application.ini I have the following:


...
autoloaderNamespaces.Zoul = "Zoul"
pluginPaths.Zoul_Application_Resource = "Zoul/Application/Resource"
...
resources.doctrine.connections.cx1.dsn = "mysql://user:pass@host/cx1"
...

There is a resource plugin class named Zoul_Application_Resource_Doctrine in the Zoul/Application/Resource folder. My application is running fine with this plugin, except when I include the main file Doctrine.php from the Doctrine library before I bootstrap the application. Then I get the following error: {color:red} Fatal error: Uncaught exception 'Doctrine_Exception' with message 'Doctrine is static class. No instances can be created.' {color}

I've traced it back to line 354 of Zend_Application_Bootstrap_BootstrapAbstract:


public function getPluginResource($resource)
{

...

if (class_exists($plugin)) {
    $spec = (array) $spec;
    $spec['bootstrap'] = $this;
    $instance = new $plugin($spec);
    $pluginName = $this->_resolvePluginResourceName($instance);
    unset($this->_pluginResources[$plugin]);
    $this->_pluginResources[$pluginName] = $instance;

    if (0 === strcasecmp($resource, $pluginName)) {
        return $instance;
    }
}

...

}

So what happens is that the main Doctrine class is included and this piece of code tries to instantiate it ($plugin has value 'doctrine'), instead of trying to instantiate the resource plugin! Not including the main Doctrine class is a solution for now, but I came across this problem while testing my application and putting more than one test in a testcase. I re-bootstrap the app before every testcase and on the second bootstrap the main Doctrine class automatically exists in the php environment. As I'm not completely aware of what the above piece of code should do I haven't found a solution yet.

Comments

Upgraded Doctrine to 1.2 branch. They moved class Doctrine to Doctrine_Core which solves the problem for the Doctrine part.

Now I'm getting the error because the main Dwoo class gets instantitiated instead of Zoul_Application_Resource_Dwoo. I could (and I propably will) ask the guys from Dwoo to move to something like Dwoo_Core but those changes could take a while.

However, looking at the related issues that wouldn't solve the problems of others. Although they propably could rename their main class quite easily.

Are there any thoughts on how to solve this problem?

My work-around was to use a different name for the resource class, for example Site_Application_Resource_Doctrinelibrary. I attempted Site_Application_Resource_DoctrineLibrary and other combinations to no avail, any idea about the formatting necessities for Resource class names to achieve camel casing?

I got the same problem. I solved it by this code. Check the $plugin is a resource or not.


Index: BootstrapAbstract.php
===================================================================
--- BootstrapAbstract.php   (revision 19975)
+++ BootstrapAbstract.php   (working copy)
@@ -351,7 +351,8 @@
                 }
             }
 
-            if (class_exists($plugin)) { //@SEE ZF-7550
+            if (class_exists($plugin) //{ //@SEE ZF-7550
+                && is_subclass_of($plugin, 'Zend_Application_Resource_Resource')) { //@see ZF-8225
                 $spec = (array) $spec;
                 $spec['bootstrap'] = $this;
                 $instance = new $plugin($spec);

Based on the patch submitted by Tomoaki Kosugi, using instanceof operator rather than is_subclass_of() function to avoid autoloading.

Patched in r24393. Patch modified not to use instanceof since that creates a silent FALSE evaluation in plugin checks.