PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

spl_autoload_unregister> <spl_autoload_functions
Last updated: Fri, 22 Aug 2008

view this page in

spl_autoload_register

(PHP 5 >= 5.1.2)

spl_autoload_registerRegister given function as __autoload() implementation

Descripción

bool spl_autoload_register ([ callback $autoload_function ] )

Register a function with the spl provided __autoload stack. If the stack is not yet activated it will be activated.

If your code has an existing __autoload function then this function must be explicitly registered on the __autoload stack. This is because spl_autoload_register() will effectively replace the engine cache for the __autoload function by either spl_autoload() or spl_autoload_call().

Lista de parámetros

autoload_function

The autoload function being registered. If no parameter is provided, then the default implementation of spl_autoload() will be registered.

Valores retornados

Devuelve TRUE si todo se llevó a cabo correctamente, FALSE en caso de fallo.

Ejemplos

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;

?>

El resultado del ejemplo seria algo similar a:

[[Foobar::InexistentClass]]
Fatal error: Class 'Foobar::InexistentClass' not found in ...



spl_autoload_unregister> <spl_autoload_functions
Last updated: Fri, 22 Aug 2008
 
add a note add a note User Contributed Notes
spl_autoload_register
emailmatthijs at gmail dot com
18-Aug-2008 10:41
This is my version of making it possible to throw exceptions within autoload functions. I liked the functions which used __construct and __callStatic to throw the exceptions, but I did not want to relay on __callStatic because it only exists since PHP version 5.3.0. I tested all three examples below in PHP version 5.2.6. The class named Test and Test_Interface did both not exists.

<?php
new Test();

Test::test();

class
Test implements Test_Interface {}
?>

In all three cases it succesfully throwed the exception without any fatal errors.

<?php
function __autoload($sClass)
{
    try
    {
        throw new
Exception('It works');
    }
    catch (
Exception $oException)
    {
       
throwAutoloadException($sClass, $oException);
    }
}

function
throwAutoloadException($sClass, Exception $oException)
{
   
// The use of eval is risky, because it could be easily exploited. To prefend
    // that the use of eval in this method could be exploited we make sure that the
    // variable contains only the allowed characters of a class name.
   
if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $sClass))
    {
        eval(
'class '.$sClass.'
        {
            static public function throwException()
            {
                throw unserialize(\''
.serialize($oException).'\');
            }
        }
       
        '
.$sClass.'::throwException();');
    }
}
?>
mailinglist dot php at hydras-world dot com
26-Jun-2008 08:07
The automatic generation of classes can be further improved to cater for files that don't actually contain the class they were supposed to contain:

<?php

// code to set include_path...

class AutoloadException extends Exception { }

class
AutoloadClass {

    public static function
autoload($sClassName) {

        @include_once(
$sClassName . '.class.php');

       
// does the class requested actually exist now?
       
if (class_exists($sClassName)) {
           
// yes, we're done
           
return;
        }
       
       
// no, create a new one!
       
eval("class $sClassName {
            function __construct() {
                throw new AutoloadException('Class $sClassName not found');
            }

            static function __callstatic(\$m, \$args) {
                throw new AutoloadException('Class $sClassName not found');
            }
        }"
);
    }
}

spl_autoload_register(array('AutoloadClass', 'autoload'));

?>

You might be able to expand the example above to automatically generate interfaces too...

Enjoy!

DominicC
webtweakers at gmail dot com
21-Feb-2008 07:53
For a while I was using the class autoload solution of sandrejev at gmail dot com, 08-Nov-2006 11:23, on this page http://www.php.net/manual/en/language.oop5.autoload.php.

As it appears, this method works fine most of the time, except in two specific cases:

1. It does not handle static classes correctly (also see the note of ostapk, 19-Dec-2007 02:46, same page and the article at onphp (s)he refers to).

2. When you accidentally have a variable in your stack that contains single quotes, PHP will choke with the following cryptic message:

Parse error: parse error, unexpected T_STRING in autoload.inc.php(64) : eval()'d code on line 26

I came up with this solution, which seems to solve these problems:

<?php

// code to set include_path...

class AutoloadException extends Exception { }

class
AutoloadClass {

    public static function
autoload($sClassName) {

       
$bIsExisting = @include_once($sClassName . '.class.php');
        if (
$bIsExisting) return;

        eval(
"class $sClassName {
            function __construct() {
                throw new AutoloadException('Class $sClassName not found');
            }

            static function __callstatic(\$m, \$args) {
                throw new AutoloadException('Class $sClassName not found');
            }
        }"
);

    }

}

spl_autoload_register(array('AutoloadClass', 'autoload'));

?>

Now, my application, that indeed uses run-time defined (static) classes that are actually allowed not to exist, runs correctly again. The AutoloadException can be caught to handle this case without stopping code execution with a Fatal Error.
stanlemon at mac dot com
28-Sep-2007 02:20
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
10-Feb-2007 10:54
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
14-Nov-2006 06:19
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'));
?>

spl_autoload_unregister> <spl_autoload_functions
Last updated: Fri, 22 Aug 2008
 
 
show source | credits | stats | sitemap | contact | advertising | mirror sites