I'm looking for __autoload magic method inside the YiiBase class, but it isn't. In the official docs said that public static function autoload($className) is
Class autoload loader. This method is provided to be invoked within an
__autoload() magic method.
I'm confused. What class of yii framework contains __autoload magic method? Is it possible to get an example with a component class autoloading?
Yii uses the spl_autoload_register function to set the autoloader function. The spl_autoload_register was introduced in PHP 5.1.2 and makes it possible for us to register multiple autoload functions. It effectively creates a queue of autoload functions, and runs through each of them in the order they are defined. By contrast, __autoload() may only be defined once. In Yii you can find this in YiiBase.php, just after the definition of the YiiBase class, at the very end of the file:
spl_autoload_register(array('YiiBase','autoload'));
Where autoload is a static method definied in the YiiBase class.
Using spl_autoload_register instead of the __autoload() magic function is good for us, because this way Yii's autoloader does not conflict with our own or with another thrid-party's autoloader. The YiiBase class also defines a registerAutoloader function to register another autoloader function before or after Yii's autoloader in the chain. If you take a look at its code, it is pretty straightforward what it does:
public static function registerAutoloader($callback, $append=false)
{
if($append)
{
self::$enableIncludePath=false;
spl_autoload_register($callback);
}
else
{
spl_autoload_unregister(array('YiiBase','autoload'));
spl_autoload_register($callback);
spl_autoload_register(array('YiiBase','autoload'));
}
}
It really just uses spl_autoload_register and/or spl_autoload_unregister (yes, you can also unregister an autoload function!), to put the new autoloader before or after Yii's autoloader, because spl_autoload_register always registers the new autoloader at the end of the chain.
I think that Yii tries to autoload a class whenever you reference it. Yii is simply making use of PHP's __autoload() function. It's a magic method like __get() or __set().
For example, when you write $foo = new Foo(); and class Foo has not been loaded yet, you will get an Error.
But you can prevent that if you define an __autoload($classname) function before. This way, instead of throwing an Error, PHP will first try to run the __autoload($classname) function. In that function, you can do things like: include the variable $classname and so on.
There's more information here: http://www.php.net/manual/en/function.autoload.php
Related
I'm using an autoload for my classes such as:
function my_autoloader($Class){
// classes
include "class/Class_User.php";
// helpers
include "helper/Url_Helper.php";
}
spl_autoload_register('my_autoloader');
All is working great however I have some question. The content of Url_Helper is not a class, there are just a classic php functions I use across the site. The functions in Url_Helper are accessible only AFTER I initiate some (any) class like: $User = new User();
After this the functions get loaded. But if I call a function from Url_Helper and do not use any class at all it doesn't get loaded.
Can you explain me a little bit what's going on in here?
You already debugged it. You say when you load no class, the helpers don't get loaded; this is true. If you want your helpers always to be available, you should include them outside of your 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.
I am wondering is it possible to auto load static class, as like creating object to dynamically autoload library ?
I have done most of the part of php autoloader but really need to tips to autoload static libraries for which I don't want to create object.
Is there anyone have solution ? Please post or else give me best idea to develop the same.
Thanks
Yes SPL Autoloader will load classes and interfaces. Once the autoloader is triggered you can use any reference to an auto-loadable asset to trigger the load
My_Special_Class::SOME_CONSTANT
will trigger a load as well as calling or referencing any visible static method or property.
In fact exploiting this is one way to trigger the auto_loading of namespaced functions. Define a class file like this.
namespace My\Namespace;
abstract class Functions{
const LOADED = true;
}
function func1(){}
function func2(){}
function func3(){}
And in your code when you need the functions defined in My\Namespace simply
if (\My\Namespace\Functions::LOADED){
func1();
func3();
}
The reference to the abstract class triggers the autoloader to include the file that defines the functions.
Does the __autoload() function ( PHP ) have to be a standalone function or can it be used within a class as a public/protected/private function?
I heard that it has to be a stand-alone function and shouldn't be used in a class. Is this true or can it be used in classes?
Thanks in advance!
You can use SPL for that:
class MyAutoloader
{
public static function register()
{
spl_autoload_register(array(new self, 'autoload'));
}
public static function autoload($classname)
{
// auto load code
}
}
See __autoload() documentation, which says:
spl_autoload_register() provides a more flexible alternative for autoloading classes. For this reason, using __autoload() is discouraged and may be deprecated or removed in the future.
If you need some example of how to use method of some class as autoloader mechanism, see this example.
What would be the point in having __autoload() in some random class you make?
__autoload() gets invoked when you try to instantiate an object from a class that hasn't been defined yet (spl_register_autoload() is preferred over __autoload()).
Therefore, it has to be globally available. PHP doesn't know that class XYZ contains a function named __autoload() that you want to invoke.
What you can do is create a class that handles autoloading and then use spl_autoload_register() function to have your class called upon the need for autoloading.
i dont really get the docs for spl_autoload
bool spl_autoload_register ([ callback $autoload_function ] )
from my understanding, it will try to run functions registered when php comes across a class not loaded already. so example,
public function autoload() {
require ('nonLoadedClass.php');
}
spl_autoload_register(autoload);
$x = new nonLoadedClass();
will cause the require to run? so i can also register many autoload functions?
public function autoloadXXX() {...}
public function autoloadYYY() {...}
public function autoloadZZZ() {...}
spl_autoload_register('autoloadXXX');
spl_autoload_register('autoloadYYY');
spl_autoload_register('autoloadZZZ');
in the case of doctrine,
require_once(dirname(__FILE__) . '/lib/vendor/doctrine/Doctrine.php');
spl_autoload_register(array('Doctrine', 'autoload'));
an array is passed, so i guess it will try to run the autoload function within the Doctrine class (which was required)?
spl_autoloader_register registers a callback function/method, that will be called when your code is trying to use a not-known class.
A callback function can be described in several ways :
a simple function name : 'my_function'
a static method of a class : array('MyClass', 'myMethod')
a method of an instance of a class : array($myObject, 'myMethod')
In the case of Doctrine, it seems to be the second solution : if a class that PHP doesn't know is used, the autoloader will call Doctrine::autoload, passing it the class name as a parameter.
so i can also register many autoload
functions?
Yes, you can, with spl_autoload_register :
If there must be multiple autoload
functions, spl_autoload_register()
allows for this. It effectively
creates a queue of autoload functions,
and runs through each of them in the
order they are defined.
But we don't generally define one autoloading function/method for each class we have ; that would be quite inefficient, I suppose.
Instead, we use the class-name, which is received by the autoloading function, to decide which file should be included.
For instance, an autoload function might look like this :
function my_autoloader($className)
{
require LIBRARY_PATH . '/' . $className . '.php';
}
The trick being that if your files are named after the classes they contain, it immediatly becomes much easier ;-)
This is why classes are often named using the PEAR convention : My_Class_Name maps to the file My/Class/Name.php
Your entire statement is correct.
spl_autoload_register allows you to register multiple autoload functions. In the case that you try to create or use an object of a class that has not been loaded into the PHP environment, PHP will run all your autoload functions looking for that class.
The Doctrine example you give is using what is called a callback to register a method inside of a class. A callback is simply an array containing the class name (for static methods) or an instance of that class (for non-static methods), and the method name.
What say is correct. It's called when an unknown class is instantiated. You then get the chance to include/require the necessary file.
When the function resides in a class, you have to pass in an array. In this case it's a static function because they pass in the Doctrine class instead of an instance of the Doctrine class.