Disable Zend Autoloader - php

How can I disable the Zend_Loader_Autoloader?

You could manually force the Autoloader to unload, but this may lead to trouble with components depending on it being registered: make sure your other loader covers that.
spl_autoload_unregister(array('Zend_Loader_Autoloader','autoload'));
I stripped this from the constructor of Zend_Loader_Autoloader, and changed it to work outside of the class, and to unregister instead of register the loader.

If you're using the Zend_Application, in your index.php, after creating the instance of ZA, you can get/set the autoloader you want ZF to use:
$app = new Zend_Application(APPLICATION_ENV, APPLICATION_PATH . '/configs/config.ini');
$app->getAutoloader()->setDefaultAutoloader('yourAutoloader');
$app->bootstrap()->run();
HTH

I assume you're using Zend_Application, which automatically sets up the PHP environment, autoloading and bootstrapping. It's very handy. Sadly, setting up Zend_Autoloader is hard coded into the constructor, and I can't see any way to override it:
public function __construct($environment, $options = null)
{
$this->_environment = (string) $environment;
require_once 'Zend/Loader/Autoloader.php';
$this->_autoloader = Zend_Loader_Autoloader::getInstance();
//snip
}
My first suggestion would be to find a way to make Zend_Autoloader and your other autoloader work in harmony. I've been using Zend_Autoloader with the new Doctrine::IsolatedClassLoader with no problems. The advice about being explicit about autoloader namespaces or using pushAutoloader() is valid, and should work.
However, if that is not an option, you should probably abandon using Zend_Application, and handle environment setup and bootstrapping yourself. While an inconvenience, it's shouldn't be too difficult. Most ZF tutorials prior to version 1.8 (which is when Zend_Application was introduced) provided examples.
Here's a (now outdated) set of slides detailing some of this:
Getting Started With Zend Framework for v1.6

What about in your bootstrap.php
protected function _initAutoloader()
{
$this->getApplication()
->getAutoLoader()
->unregisterNamespace("Zend");
// or
$this->getApplication()
->getAutoloader()
->removeAutoloader();
}

Zend_Loader::registerAutoload('Zend_Loader', false);
Its in the framework documentation http://framework.zend.com/manual/en/zend.loader.html#zend.loader.load.autoload
However, I don't think you should have any problems leaving the zend autoloader enabled as long as you register your autoload callback using spl_autoload_register() so it gets added to the autoload stack.
Using spl_autoload_register, all callbacks will be called to try to satisfy the request. I don't know if the chain will be interrupted once a callback is successful. If it does then its probably controlled by returning true or false in the callbacks.

I'd suggest using "push autoloader" method of Autoloader, which can recieve other autoloader instance and call it when Namespaces match. Therefore you can use your autoloader along with the zend's one...

Related

initiliazing static variables with composer

In https://stackoverflow.com/a/3313137/569976 ircmaxell says the following:
I use a public static method init() on my static classes that require initialization (or at least need to execute some code). Then, in my autoloader, when it loads a class it checks is_callable($class, 'init'). If it is, it calls that method. Quick, simple and effective...
That post, however, is from 2010 and a lot has changed since then. My question is... does Composer support anything like this?
Composer's autoloader isn't going to automatically call init methods for you, but that doesn't stop you from using your own autoloader instead.
https://getcomposer.org/doc/01-basic-usage.md#autoloading
Note: Composer provides its own autoloader. If you don't want to use that one, you can just include vendor/composer/autoload_*.php files, which return associative arrays allowing you to configure your own autoloader.

Doctrine classloader overwrites my __autoload function

I may generally misunderstand something about setting up a custom classloader.
What happens is that once i initialize it:
use Doctrine\Common\ClassLoader;
require_once(DOCTRINE_PATH . '/Common/ClassLoader.php');
classLoader=new ClassLoader('Doctrine', DOCTRINE_PATH);
classLoader->register();
My previously defined function
function __autoload(){}
No longer works.
What am i missing here?
After diving a bit deeper into the autoload documentation, i found that in order to have multiple autoloaders at the same time, the use of
function __autoload(){}
is not a valid route to take. Instead, one has to define a custom autoload function, such as
function MyAutoLoader()
and then use
spl_autoload_register('MyAutoLoader');
to register it onto the autoload stack.
Finally, using this method, my autoloader is no longer overwritten by implementing the Doctrine classloader.

Proper way to include SPL Class Loader

Problem
I am using the SPL Class Loader provided by PSR Group. However, I've come to a chicken-egg paradox.
That is, this will autoload classes preventing explicitly including them. But I first need to include/require this class and the code for instantiating the object
$classLoader = new SplClassLoader('Doctrine\Common', '/path/to/doctrine');
$classLoader->register();
Question
What is common solution for including the autoloader code?
In the case of a front-end controller, I could add the code there. But I'm not always using the front-end controller patter. I suppose I could also use PHP's auto_prepend_file. Interested in the communities input.
You explicitly require the autoloader on the bootstrap stage (the stage where the application is started up).
All subsequent functions/classes are then autoloaded.

How to register Yii's autoloader in an external application?

I want to try Yii, but I don't want use it as my main framework. In other words, I want to use my own framework while also using some of Yii's features. I figured that in order to be able to instantiate Yii's classes from my application, I'd just need to register Yii's autoloader from my application, probably in a way similar to this:
spl_autoload_register
(
function ($classname)
{
YiiBase::autoload($className);
}
);
Of course, I'm gonna need to require or include the YiiBase class, so before I call the previous function, I do this:
$yiiBase = $_SERVER['DOCUMENT_ROOT'].'/yii/framework/YiiBase.php';
require_once($yiiBase);
But I get a "Cannot redeclare class YiiBase" error. What am I missing?
1) Do not include YiiBase.php direcly, include yii.php. Because yii.php contains a class Yii which is used in all over framework code (even in YiiBase methods).
$yii = $_SERVER['DOCUMENT_ROOT'].'/yii/framework/yii.php';
require_once($yii);
( and YiiBase.php is included in yii.php by default)
2) register your autoload handler in this way.
(Yii has built-in functionality to add custom autoload handlers ).
$my_autoload = function($class) { ... };
// OR
// $my_autoload = array('MyClass', 'my_autoload')
YiiBase::registerAutoloader($my_autoload, true);
The second parameter true tells whether to append/prepend the new autoloader after/before the default Yii autoloader
if the YiiBase.php included, then Yii's default autoloader will also gets included. No need to call YiiBase::autoload() explicitly in you code. Ref: check the last line in YiiBase.php file
You can take a look at some approaches of people integrating Yii with wordpress, you may not need to do ->run() the application, unless you need the controllers/routing, it also depends on what parts of the framework you pretend to use.
To do it for Yii2, this article explains it under the heading "Using Yii in Third-Party Systems" in the middle of the page.
Here is the relevant part to include on startup of your external application:
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
$yiiConfig = require(__DIR__ . '/../config/yii/web.php');
new yii\web\Application($yiiConfig); // Do NOT call run() here
Obviously, __DIR__ . '/../ may need to be adjusted to fit your directory layout.

Is autoloader different for framework vs. normal library

According to the PCR-0 proposal, all the autoloader needs is autoload() function. Zend has a few autoloading classes
Zend_Loader()
Zend_Loader_Autoloader()
Zend_Loader_Autoloader_Resource()
Zend_Loader_Autoloader_Interface()
I'm guessing it has all these classes because it's a framework, so it needs to load its own classes, as well as library classes for any libraries that the developer may add and which don't have their own autoloader.
I have a library (normal library, not a framework). Right now it doesn't have an autoloader so I use Zend's Zend_Loader_Autoloader_Resource ->addResourceType(). If I write an autoloader for it, which autoloader will be used: Zend's or the library? and do I have to implement an autoloader as complex as Zend's or a simple one like the PCR-0 example.
What happens in these cases
both framework and library have their own autoloader
framework has autoloader, but the library doesn't
framework has NO autoloader, and library has
I'd suggest sticking to direct path->class mapping and implementing your own autoloader like this:
class MyLib_Autoloader
{
public function __construct() {
spl_autoload_register(array($this, 'autoload'));
}
public function autoload($className)
{
if (substr($className, 0, 6) == 'MyLib_') {
include dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR strtr($className, '_', DIRECTORY_SEPARATOR) . '.php';
return true;
}
return false;
}
}
This will check if the class is from your namespace and load the file. Assumes your autoloader is in /some/path/MyLib/ -> the include path will be /some/path/MyLib/../MyLib/ClassName.php. You can also add more logic to strip the initial MyLib from the class name and get rid of that '..'.
Make sure to use only require. It's faster and the autoload function is not called more than once for each classname! :) No need to include_once/require_once/etc. Go with the fastest.
Usage is as simple as:
include '/some/path/MyLib/Autploader.php';
$loader = new MyLib_Autoloader();
The main question is : who/how will your library be used ?
If that is by you only, then use Zend's autoloader, this will save you time. You don't need to reinvent the wheel.
If you have to make you library public and used on different projects, then that may be a problem because it will force the users of your library to have Zend Framework too. So in that case, either you make your own autoloader, either you pick one of a framework/library but include it in your library (watch out for the licenses).
Now regarding the utilisation of the autoloaders : only the autoloaders that are registered will be called. If you have your own autoloader, but you didn't mention how to setup it in your documentation, the users of your code will never think of set it up, and then it won't be used.
So the basic answer is to say : use many autoloaders, register them all, and they will be all called and everything will work fine. But that may lead to conflicts, because one autoloader will try to load something that is supposed to be handled by another autoloader, so you have to be careful with that, and not abuse of them.

Categories