5

in a 'native' Zend Framework application I would enable the use of ezComponents by adding the autoloader of ezComponents to Zends autoloader:

$autoLoader = Zend_Loader_Autoloader::getInstance();
require_once('../library/EZComponents/Base/src/base.php');
$autoLoader->pushAutoloader(array('ezcBase', 'autoload'), 'ezc'); 

Now, I'm wondering how I could do the same with Magento. Is there a way to extend Varien_Autoload (magentos autoloader) to enable easy integration of ezComponents? OR: Is there a way to use Zends autoloader beside the one from Magento without interfering each other?

edit:

Well, I implemented a workaround, by adding the following to function autoload() in Varien_Autoload:

if(substr($class, 0, 3) == 'ezc'){
        require_once('EZComponents/Base/src/base.php');
        return ezcBase::autoload($class);

    }

I consider this as a very bad hack though, because it will be overwritten, when upgrading Magento. Does anyone has a better idea?

Gordon
  • 312,688
  • 75
  • 539
  • 559
volka
  • 51
  • 1
  • 3
  • Well, I implemented a workaround, by adding the following to function autoload() in Varien_Autoload: [code] if(substr($class, 0, 3) == 'ezc'){ require_once('EZComponents/Base/src/base.php'); return ezcBase::autoload($class); } [/code] I consider this as a very bad hack though, because it will be overwritten, when upgrading Magento. Does anyone has a better idea? – volka Nov 03 '10 at 13:29

3 Answers3

17

My basic approach here would be to create a custom module with an observer for the

controller_front_init_before

event. In the event observer, you'd be able to setup your autoloader however you want. There's a Magento Wiki article on Setting up Event Observers. The controller_front_init_before event is one of the first non-generic events to fire in Magento. That's why we're using it.

The big problem we need to solve is this: Magento's autoloader is on the stack first, and if it doesn't find a file (which will be the case with the EZComponent classes), its include will raise a error that will halt execution.

So, what we need to do in our event observer above is to

  1. Remove the Varien_Autoloader from the spl_autoload stack

  2. Register our own autoloader (we'll use Zend_Autoloader, since it ships with Magento and you seem familiar with it)

  3. Re-add the Varien_Autoloader to the stack

There'll be a little extra jiggery-pokery we'll need to do since loading of the classes in the Zend namespace is normally handled by the autoloader we'll be removing. See comments for more details

//we need to manually include Zend_Loader, or else our zend autoloader
//will try to use it, won't find it, and then try to use Zend_Loader to
//load Zend_Loader
require_once('lib/Zend/Loader.php');


//instantiate a zend autoloader first, since we 
//won't be able to do it in an unautoloader universe
$autoLoader = Zend_Loader_Autoloader::getInstance();        

//get a list of call the registered autoloader callbacks
//and pull out the Varien_Autoload.  It's unlikely there
//are others, but famous last words and all that
$autoloader_callbacks = spl_autoload_functions();
$original_autoload=null;
foreach($autoloader_callbacks as $callback)
{
    if(is_array($callback) && $callback[0] instanceof Varien_Autoload)
    {
        $original_autoload = $callback;
    }
}

//remove the Varien_Autoloader from the stack
spl_autoload_unregister($original_autoload);

//register our autoloader, which gets on the stack first
require_once('library/EZComponents/Base/src/base.php');
$autoLoader->pushAutoloader(array('ezcBase', 'autoload'), 'ezc');           

//lets just make sure we can instantiate an EZ class
#$test = new ezcBaseFile();
#var_dump(get_class($test));

//IMPORANT: add the Varien_Autoloader back to the stack
spl_autoload_register($original_autoload);      

Put the above code in an observer method and you should be good to go.

The other approach you could take, one that would fit in more with Magento patterns, would be to create a custom module that implemented an EZComponent loader.

$o = Mypackage_Mymodule_Loader::getModel('ezcBaseFile');

You'd then implement autoloader style require code in your static getModel method, and use it whenever you wanted an ezcBaseFile class. You'd probably want methods for loading a class without instantiating an object in case you wanted to call a static method on an ezcBaseFile base class.

$o = Mypackage_Mymodule_Loader::getLoadclass('ezcBaseFile');
Alana Storm
  • 164,128
  • 91
  • 395
  • 599
  • Thanks a lot @alan-storm. This helped me greatly when trying to get DomPdf setup. I am not sure I fully understand though how to do the second option. – dan.codes Apr 26 '12 at 00:34
  • @dan.codes I wrote this over a year ago — these days I'd just stick with option 1. Option 2 was me being in a very "how to get all my code looking like Magento code" phase. – Alana Storm Apr 26 '12 at 00:39
  • 6
    Since PHP 5.3 you have no need to do the hokey pokey to get your autoloader first. The third parameter is a flag to prepend your autoloader instead of appending. – Lee Saferite Oct 15 '14 at 06:18
0

I took a quick look at the code for Varien's autoloader and it appears to use a call to spl_autoload_register, which is a stack for performing autoloads. While I don't think you'll have much success adding to the default Magento autoloader, this means that you should be able to push another autoloader on top of Magento's.

Hope that helps!

Thanks, Joe

Joe Mastey
  • 26,809
  • 13
  • 80
  • 104
  • Hi Joseph, yes thank you. I tried that, but it didn't work. Maybe I did it wrong. I'll dig into that a 2nd time and give it another try. – volka Nov 04 '10 at 19:23
  • This sounds like a good idea, but when Magento's autoload fails to load a class it raises a warning that halts execution. Since Magento's autoload is on the stack first, this means it never gets to other autoloaders. More info in my answer. – Alana Storm Jan 08 '11 at 23:04
0

I've just integrated the Sailthru_Client class into Magento, thought this might help.

I have sailthru.php, the Sailthru Client API, which contains Sailthru_Client class.

I created magentoroot/lib/Sailthru folder then copy sailthru.php into it, then renamed to Client.php making it magentoroot/lib/Sailthru/Client.php. This pattern is auto-loaded by Varien_Autoload class.

  • I thing this will not work with ezComponents (or better: is not worth the effort) since I'd need to rename hundreds of classes then. And upgrading ezComponents is going to be a mess then. – volka Nov 04 '10 at 19:25
  • I thing this will not work with ezComponents (or better: is not worth the effort) since I'd need to rename hundreds of classes then. And upgrading ezComponents is going to be a mess then. – volka Nov 05 '10 at 09:50