Issues

ZF-6525: does not work at all - Mac OS X, custom LAMP build

Description

I cannot get Zend_Tool to work at all. This is all I get:-

paul-courts-mac-pro:XAMP_Build paul$ zf show version PHP 5.2.9 (cli) (built: May 4 2009 22:25:46) Copyright (c) 1997-2009 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies .:/Volumes/WORK/XAMP/lib/php/ An Error Has Occurred
Action 'show' is not a valid action.

Zend FrameworkPHP Fatal error: Class 'Zend_Version' not found in /Volumes/WORK/XAMP/lib/Zend1.8/Tool/Framework/Client/Console/HelpSystem.php on line 159

Fatal error: Class 'Zend_Version' not found in /Volumes/WORK/XAMP/lib/Zend1.8/Tool/Framework/Client/Console/HelpSystem.php on line 159

paul-courts-mac-pro:XAMP_Build paul$ php /Volumes/WORK/sites/test 1.8.0

paul-courts-mac-pro:XAMP_Build paul$ cat /Volumes/WORK/sites/test <?php require_once 'Zend/Loader/Autoloader.php'; $loader = Zend_Loader_Autoloader::getInstance(); echo Zend_Version::VERSION . "\n"; paul-courts-mac-pro:XAMP_Build paul$

I added the commands to show the php version and the include path to zf.sh just to make sure, and my very short test script works fine. Any ideas?

Comments

Are you sure ZF is in your include path?

Just found the problem. It does not like the "Zend" entry in my include path being a symlink!

I did a little debugging, as well, as I get the same errors on "release-1.8.3", using a symlink to Zend in my "include_path". I added the following in Zend/Tool/Framework/Client/Console/HelpSystem.php on line 164 to test a few things:

[code] var_dump(array( 'Is Zend_Loader_Autoloader available?' => class_exists('Zend_Loader_Autoloader', false), 'Is autoloading enabled?' => ( spl_autoload_functions() !== false ), 'Is Zend_Loader_Autoloader::autoload() registered?' => ( in_array(array('Zend_Loader_Autoloader', 'autoload'), (array) spl_autoload_functions()) ), )); [code]

Then executing "zf.sh" with no arguments, the expected output should be:

[code] array(3) { ["Is Zend_Loader_Autoloader available?"]=> bool(true) ["Is autoloading enabled?"]=> bool(true) ["Is Zend_Loader_Autoloader::autoload() registered?"]=> bool(true) } [code]

Actual:

[code] array(3) { ["Is Zend_Loader_Autoloader available?"]=> bool(false) ["Is autoloading enabled?"]=> bool(false) ["Is Zend_Loader_Autoloader::autoload() registered?"]=> bool(false) } [code]

I was able to remedy the problem by performing either of the following in Zend/Tool/Framework/Client/HelpSystem.php @ 164:

[code] require_once 'Zend/Loader/Autoloader.php'; Zend_Loader_Autoloader::getInstance(); // Register the autoloader... require_once 'Zend/Version.php'; // Or just include the unloaded class before it's used... [code]

The bug actually appears to be in Zend_Tool_Framework_Client_Console::_preInit() @ 111, where the autoloader class is registered:

[code] // support setting the loader from the environment if (isset($_ENV['ZEND_TOOL_FRAMEWORK_LOADER_CLASS'])) { if (class_exists($_ENV['ZEND_TOOL_FRAMEWORK_LOADER_CLASS']) || Zend_Loader::loadClass($_ENV['ZEND_TOOL_FRAMEWORK_LOADER_CLASS']) ) { $this->_registry->setLoader(new $_ENV['ZEND_TOOL_FRAMEWORK_LOADER_CLASS']); } } [code]

Note that there's no "else" clause there if the $_ENV variable isn't set, so Zend_Loader_Autoloader doesn't get registered by default. Thus, if "ZEND_TOOL_FRAMEWORK_LOADER_CLASS" isn't set in our local environments, the autoloader stack is empty. Boo. I'll attach a patch.

This patch should be applied to the base project directory and affect Zend_Tool_Framework_Client_Console, adding default autoloader support via Zend_Loader_Autoloader::autoload() if no other class is specified via the ENV variable ZEND_TOOL_FRAMEWORK_LOADER_CLASS. It contains the following lines, applied to library/Zend/Tool/Framework/Client/Console.php @ 119:


        // otherwise register the default autoloader: Zend_Loader_Autoloader
        else {
            require_once 'Zend/Loader/Autoloader.php';
            $this->_registry->setLoader(Zend_Loader_Autoloader::getInstance());
        } // END if-else

The problem from this ticket can also be resolved by patching Zend_Tool_Framework_Client_Console_HelpSystem by adding the following line to library/Zend/Tool/Framework/Client/Console/HelpSystem.php @ 164:


        require_once 'Zend/Version.php';

However, the included patch is a more elegant solution, IMO, since it addresses a yet undetected issue with Zend_Tool, as explained above. Please feel free to apply either. I'm using the former for now. Thanks,

David @ OrlandoPHP.org

If an admin would also please edit my earlier comment to correct my use of "[code]" instead of "```" for readability. Thanks.

Actually, scratch that. I neglected to test before I uploaded that patch. The simpler, more specific one does the job, although having an autoloader registered would be handy, too... However, my earlier patch doesn't actually do that. Sorry.

So this does get Zend_Tool executable for me, but the list of providers is still empty, and {{zf.sh}} does not recognize any commands...

To test out Paul's solution, I renamed my symlink and copied over the contents of the "Zend" directory into my {{include_path}}, instead. {{zf.sh ?}} now returns a list of colorized providers, but this problem still bugs me...

So my workaround for the moment is to set the ENV variable {{ZEND_TOOL_INCLUDE_PATH_PREPEND}} to {{/usr/local/share/php/Zend_Framework/library/}}, and I've found the following in {{library/Zend/Tool/Framework/Loader/IncludePathLoader.php}} @ 98:


                // no links allowed here for now
                if ($item->isLink()) {
                    continue;
                }

Apparently there's not a good solution for what to do with symlinks at this point, yet the Quickstart Documentation recommends a symlink to the library... Obviously after you get {{zf.sh}} running, though.

Perhaps the problem here is that the IncludePathLoader is scanning the entire tree defined by the {{include_path}} for files named "Manifest.php" or "Provider.php", which seems rather wasteful... Couldn't this operate more like the Plugin patterns, such that a number of known, assumed valid paths / namespaces are added to a stack for scanning...? That would bypass the symlink problem, at least.

Is there a use-case for walking the entire tree like that?

I think this issue could be resolved by ZF-7036. It seems to be more simply.

I think it would be too complex to use Zend_Loader_Autoloader.