(PHP 5 >= 5.1.2)
spl_autoload_register — 注册__autoload()函数
将函数注册到SPL __autoload函数栈中。如果该栈中的函数尚未激活,则激活它们。
如果在你的程序中已经实现了__autoload函数,它必须显式注册到__autoload栈中。因为 spl_autoload_register()函数会将Zend Engine中的__autoload函数取代为spl_autoload()或spl_autoload_call()。
成功时返回 TRUE
, 或者在失败时返回 FALSE
。
版本 | 说明 |
---|---|
5.3.0 | Namespaces support was introduced. |
5.3.0 |
The prepend parameter was added.
|
Example #1 spl_autoload_register() example
<?php
namespace Foobar;
class Foo {
static public function test($name) {
print '[['. $name .']]';
}
}
spl_autoload_register(__NAMESPACE__ .'::Foo::test'); // As of PHP 5.3.0
new InexistentClass;
?>
以上例程的输出类似于:
[[Foobar::InexistentClass]] Fatal error: Class 'Foobar::InexistentClass' not found in ...
sebastian at 34n dot de (2013-05-24 09:49:19)
You can also use it like this:
> spl_autoload_register ( array( new AutoloaderClass, 'method') );
or in PHP > 5.3:
> spl_autoload_register ( [ new My\Namespace\Autoloader, 'method'] );
On this way you dont have to create a variable, which is used once.
a dot schaffhirt at sedna-soft dot de (2013-04-07 13:42:55)
What I said here previously is only true on Windows. The built-in default autoloader that is registered when you call spl_autoload_register() without any arguments simply adds the qualified class name plus the registered file extension (.php) to each of the include paths and tries to include that file.
Example (on Windows):
include paths:
- "."
- "d:/projects/phplib"
qualified class name to load:
network\http\rest\Resource
Here's what happens:
PHP tries to load
'.\\network\\http\\rest\\Resource.php'
-> file not found
PHP tries to load
'd:/projects/phplib\\network\\http\\rest\\Resource.php'
-> file found and included
Note the slashes and backslashes in the file path. On Windows this works perfectly, but on a Linux machine, the backslashes won't work and additionally the file names are case-sensitive.
That's why on Linux the quick-and-easy way would be to convert these qualified class names to slashes and to lowercase and pass them to the built-in autoloader like so:
<?php
spl_autoload_register(
function ($pClassName) {
spl_autoload(strtolower(str_replace("\\", "/", $pClassName)));
}
);
?>
But this means, you have to save all your classes with lowercase file names. Otherwise, if you omit the strtolower call, you have to use the class names exactly as specified by the file name, which can be annoying for class names that are defined with non-straightforward case like e. g. XMLHttpRequest.
I prefer the lowercase approach, because it is easier to use and the file name conversion can be done automatically on deploying.
daniel at amnistechnology dot com (2012-10-17 09:57:12)
Cleverly - and usefully - I have noticed that (on PHP 5.3 at least) these autoloaders "kick in" even when you call a public static method of an as-yet-unloaded all static class.
xianrenb at gmail dot com (2012-09-11 10:50:23)
An example to allow autoloading classes with namespace:
<?php
define('MY_BASE_PATH', (string) (__DIR__ . '/'));
// Set include path
$path = (string) get_include_path();
$path .= (string) (PATH_SEPARATOR . MY_BASE_PATH . 'php_class/');
$path .= (string) (PATH_SEPARATOR . MY_BASE_PATH . 'php_global_class/');
// $path .= (string) (PATH_SEPARATOR . 'additional/path/');
set_include_path($path);
spl_autoload_register(function ($className) {
$className = (string) str_replace('\\', DIRECTORY_SEPARATOR, $className);
include_once($className . '.class.php');
});
?>
Anonymous (2012-02-03 16:52:20)
Note that when specifying the third parameter (prepend), the function will fail badly in PHP 5.2
(delphists) at (apollo) dot (lv) (2011-02-01 01:57:34)
When using spl_autoload_register() with class methods, it might seem that it can use only public methods, though it can use private/protected methods as well, if registered from inside the class:
<?php
class ClassAutoloader {
public function __construct() {
spl_autoload_register(array($this, 'loader'));
}
private function loader($className) {
echo 'Trying to load ', $className, ' via ', __METHOD__, "()\n";
include $className . '.php';
}
}
$autoloader = new ClassAutoloader();
$obj = new Class1();
$obj = new Class2();
?>
Output:
--------
Trying to load Class1 via ClassAutoloader::loader()
Class1::__construct()
Trying to load Class2 via ClassAutoloader::loader()
Class2::__construct()
anthon at piwik dot org (2010-07-04 21:02:15)
Think twice about throwing an exception from a registered autoloader.
If you have multiple autoloaders registered, and one (or more) throws an exception before a later autoloader loads the class, stacked exceptions are thrown (and must be caught) even though the class was loaded successfully.
sebastian dot krebs at kingcrunch dot de (2010-03-24 10:54:17)
It seems, that spl_autoload tests, if the class exists, after calling every registered loader. So it breaks the chain, if the class exists and will not call the other loaders
<?php
function a ($c) {
echo "a\n";
class Bla {} // Usually "include 'path/to/file.php';"
}
function b ($c) {
echo "b\n";
}
spl_autoload_register('a');
spl_autoload_register('b');
$c = new Bla();
?>
Anonymous (2010-03-16 20:30:42)
Be careful using this function on case sensitive file systems.
<?php
spl_autoload_extensions('.php');
spl_autoload_register();
?>
I develop on OS X and everything was working fine. But when releasing to my linux server, none of my class files were loading. I had to lowercase all my filenames, because calling a class "DatabaseObject" would try including "databaseobject.php", instead of "DatabaseObject.php"
I think i'll go back to using the slower __autoload() function, just so i can keep my class files readable
rayro at gmx dot de (2010-01-04 03:14:51)
It is never a good idea and a unconscienable concept to create the classes in the autoload function via eval.
It should be a nice feature with these Exception, but i think anyone is able to handle it without this method although. Atm i dont realize for what this is good for...
As i might note, class_exists() will ever define the classes u only want to check for existance, and will therefor ever return true:
<?php
function EvalIsEvil($class) {
eval('class '.$className.'{}');
}
spl_autoload_register('EvalIsEvil');
if (class_exists($s="IsMyModuleHere")) {
// this is no module, but get there with eval()...
return new $s();
}
?>
a dot schaffhirt at sedna-soft dot de (2009-07-27 19:05:03)
Good news for PHP 5.3 users with namespaced classes:
When you create a subfolder structure matching the namespaces of the containing classes, you will never even have to define an autoloader.
<?php
spl_autoload_extensions(".php"); // comma-separated list
spl_autoload_register();
?>
It is recommended to use only one extension for all classes. PHP (more exactly spl_autoload) does the rest for you and is even quicker than a semantically equal self-defined autoload function like this one:
<?php
function my_autoload ($pClassName) {
include(__DIR__ . "/" . $pClassName . ".php");
}
spl_autoload_register("my_autoload");
?>
I compared them with the following setting: There are 10 folders, each having 10 subfolders, each having 10 subfolders, each containing 10 classes.
To load and instantiate these 1000 classes (parameterless no-action constructor), the user-definded autoload function approach took 50ms longer in average than the spl_autoload function in a series of 10 command-line calls for each approach.
I made this benchmark to ensure that I don't recommend something that could be called "nice, but slow" later.
Best regards,
djames at dealerspan dot com (2009-05-15 09:39:09)
This behaves more like a QUEUE than a STACK, since the registry is accessed in FIFO order. The autoloaders are attempted in the order they are defined.
stanlemon at mac dot com (2007-09-28 10:20:04)
Editorial note: The appropriate PHP bug that requests behavior this function emulates is http://bugs.php.net/bug.php?id=42823 . This function does NOT work if there has been an array($obj, 'nonStaticMethod') registered in the autoload stack--while the autoload will be removed, it will be re-registered incorrectly.
The spl_autoload_register() method registers functions in its stack in the order that spl_autoload_register() was called, and subsequently if you want an autoload function to override previous autoload functions you will either need to unregister the previous ones or change the order of the autoload stack.
For example, say in your default implementation of an autoload function you throw an exception if the class cannot be found, or perhaps a fatal error. Later on in your code you add a second implementation of an autoload function which will load a library that the previous method would fail on. This will not call the second autoloader method first, but rather will continue to error out on the first method.
As previously mentioned, you can unregister the existing autoloader that errors out, or you can create a mechanism for unregistering and re-registering the autoloaders in the order you want.
Here is a sample/example of how you might consider re-registering autoloaders so that the newest autoloader is called first, and the oldest last:
<?php
// Editorial notes: Small bug and compatibility fixes
// added to the function
function spl_autoload_preregister( $autoload ) {
// No functions currently in the stack.
if ( ($funcs = spl_autoload_functions()) === false ) {
spl_autoload_register($autoload);
} else {
// Unregister existing autoloaders...
$compat =
version_compare(PHP_VERSION, '5.1.2', '<=') &&
version_compare(PHP_VERSION, '5.1.0', '>=');
foreach ($funcs as $func) {
if (is_array($func)) {
// :TRICKY: There are some compatibility issues and some
// places where we need to error out
$reflector = new ReflectionMethod($func[0], $func[1]);
if (!$reflector->isStatic()) {
throw new Exception('
This function is not compatible
with non-static object methods due to PHP Bug #44144.
');
}
// Suprisingly, spl_autoload_register supports the
// Class::staticMethod callback format, although call_user_func doesn't
if ($compat) $func = implode('::', $func);
}
spl_autoload_unregister($func);
}
// Register the new one, thus putting it at the front of the stack...
spl_autoload_register($autoload);
// Now, go back and re-register all of our old ones.
foreach ($funcs as $func) {
spl_autoload_register($func);
}
}
}
?>
Note: I have not tested this for overhead, so I am not 100% sure what the performance implication of the above example are.
harvey dot NO_SPAM dot robin at gmail dot com (2007-02-10 05:54:22)
This function is smart enough not to add the same loader twice. This seems to work for all of the different loader formats. Example:
<?php
class ALoader
{
static function load($class) { return true; }
}
function anotherLoader($class) {
return true;
}
$F = new ALoader;
spl_autoload_register(array('ALoader', 'load'));
spl_autoload_register(array('ALoader', 'load'));
spl_autoload_register(array($F, 'load'));
spl_autoload_register('anotherLoader');
spl_autoload_register('anotherLoader');
var_dump(spl_autoload_functions());
/*
* Results on PHP5.2 CLI, linux.
* array(2) {
* [0]=>
* array(2) {
* [0]=>
* string(7) "ALoader"
* [1]=>
* string(4) "load"
* }
* [1]=>
* string(13) "anotherLoader"
* }
*/
?>
florent at mediagonale dot com (2006-11-14 01:19:28)
If your autoload function is a class method, you can call spl_autoload_register with an array specifying the class and the method to run.
* You can use a static method :
<?php
class MyClass {
public static function autoload($className) {
// ...
}
}
spl_autoload_register(array('MyClass', 'autoload'));
?>
* Or you can use an instance :
<?php
class MyClass {
public function autoload($className) {
// ...
}
}
$instance = new MyClass();
spl_autoload_register(array($instance, 'autoload'));
?>