How to Use Spl_Autoload() Instead of _Autoload()

How to use spl_autoload() instead of __autoload()

You need to register autoload functions with spl_autoload_register. You need to provide a "callable". The nicest way of doing this, from 5.3 onwards, is with an anonymous function:

spl_autoload_register(function($class) {
include 'classes/' . $class . '.class.php';
});

The principal advantage of this against __autoload is of course that you can call spl_autoload_register multiple times, whereas __autoload (like any function) can only be defined once. If you have modular code, this would be a significant drawback.


2018 update to this: there shouldn't really be that many occasions when you need to roll your own autoloader. There is a widely accepted standard (called PSR-4) and several conforming implementations. The obvious way of doing this is using Composer.

php spl_autoload_register vs __autoload?

__autoload is generally considered obsolete. It only allows for a single autoloader. Generally you should only use __autoload if you're using a version of PHP without support for spl_autload_register.

spl_autoload_register allows several autoloaders to be registered which will be run through in turn until a matching class/interface/trait is found and loaded, or until all autoloading options have been exhausted. This means that if you're using framework code or other third party libraries that implement their own autoloaders you don't have to worry about yours causing conflicts.

UPDATE:

__autoload is now officially deprecated as of PHP 7.2.0, which means it's now on the chopping block. If you want your code to be compatible with future versions of PHP you definitely should not use __autoload

What is Autoloading; How do you use spl_autoload, __autoload and spl_autoload_register?

spl_autoload_register() allows you to register multiple functions (or static methods from your own Autoload class) that PHP will put into a stack/queue and call sequentially when a "new Class" is declared.

So for example:

spl_autoload_register('myAutoloader');

function myAutoloader($className)
{
$path = '/path/to/class/';

include $path.$className.'.php';
}

//-------------------------------------

$myClass = new MyClass();

In the example above, "MyClass" is the name of the class that you are trying to instantiate, PHP passes this name as a string to spl_autoload_register(), which allows you to pick up the variable and use it to "include" the appropriate class/file. As a result you don't specifically need to include that class via an include/require statement...

Just simply call the class you want to instantiate like in the example above, and since you registered a function (via spl_autoload_register()) of your own that will figure out where all your class are located, PHP will use that function.

The benefit of using spl_autoload_register() is that unlike __autoload() you don't need to implement an autoload function in every file that you create. spl_autoload_register() also allows you to register multiple autoload functions to speed up autoloading and make it even easier.

Example:

spl_autoload_register('MyAutoloader::ClassLoader');
spl_autoload_register('MyAutoloader::LibraryLoader');
spl_autoload_register('MyAutoloader::HelperLoader');
spl_autoload_register('MyAutoloader::DatabaseLoader');

class MyAutoloader
{
public static function ClassLoader($className)
{
//your loading logic here
}

public static function LibraryLoader($className)
{
//your loading logic here
}

With regards to spl_autoload, the manual states:

This function is intended to be used as a default implementation for __autoload(). If nothing else is specified and spl_autoload_register() is called without any parameters then this functions will be used for any later call to __autoload().

In more practical terms, if all your files are located in a single directory and your application uses not only .php files, but custom configuration files with .inc extensions for example, then one strategy you could use would be to add your directory containing all files to PHP's include path (via set_include_path()).

And since you require your configuration files as well, you would use spl_autoload_extensions() to list the extensions that you want PHP to look for.

Example:

set_include_path(get_include_path().PATH_SEPARATOR.'path/to/my/directory/');
spl_autoload_extensions('.php, .inc');
spl_autoload_register();

Since spl_autoload is the default implementation of the __autoload() magic method, PHP will call spl_autoload when you try and instantiate a new class.

Hope this helps...

Should I prefer require instead of require_once inside spl_autoload_register() callback

I've created a primitive benchmark.

I wasn't be able to see significant difference betwen this two approaches (require vs require_once). Maybe problem in "benchmark" itself, feel free to send PR to fix it :)

Most visible changes in execution time had took place when some other process has used disk while test running.

Both approaches had shown ~0.062 for 300 classes on 7200rpm HDD.

> php -v
PHP 7.2.1 (cli) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2017 Zend Technologies

I need spl_autoload_register to override __autoload

When you start using spl_... methods, they usurp any existing __autoload function:

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().

One can see this in a simple example:

<?php

ini_set('display_errors', 1);

function __autoload($className) {
exit("__autoload");
}

spl_autoload_register(function($className) {
exit("spl_autoload");
});

// try to create nonexistent class
new Foo();

?>

The above example outputs "spl_autoload"

Are you sure no other autoloader has been registered at that stage in the script? You could test this by adding the prepend argument (e.g., spl_autoload_register('autoload_lib', true, true); Is autoload_lib callable at that time in the script (has it's source been included?)

__autoload() is no longer supported, use spl_autoload_register() instead in C:\xampp\htdocs\webapp\PHPMailerAutoload.php on line 45

You're using a very old version of PHPMailer – that code has not been in PHPMailer for 3 years. PHP 8.0 is officially supported as of PHPMailer 6.2.0, and make sure you read the upgrade guide.

What does everyone mean by: 'spl:_autoload() is default implementation of __autoload()'

Repeating question mentioned earlier: is spl_autoload() internal function?

That's just the "default value" for spl_autoload_register if you don't pass an parameter. You could also call this function standalone, if you want to. The behaviour of spl_autoload could be configured with spl_autoload_extensions and set_include_path.

Internally spl_autoload takes the full qualified class name(fqcn) as the path to look for a class implementation. (Maybe with string replacements for directory seperators). Afterwards, it searches in every element of the class_include_path after the given file.

spl_autoload_extensions(".php");
spl_autoload_register();
$foo = new \foo\Bar();
// now spl_autoload tries to load the file foo/Bar.php inside your class path.

If you need something more complicated, you have to create your own callback for the autoloader. I.e. something like this

spl_autoload_register(function($class) {
$path = 'classes' . DIRECTORY_SEPERATOR;
// dont care about case
$class = strtolower($class);
// replace _ with DIRECTORY_SEPERATOR
$name = str_replace('_', DIRECTORY_SEPERATOR, $class);
// don't care about windows/unix
$name = str_replace('/', DIRECTORY_SEPERATOR, $name);
$file = $path . $name . '.php';
if (file_exists($file)) {
include ($file);
}
});

Note: The example above doesn't care about the value of spl_autoload_extensions or set_include_path.



Related Topics



Leave a reply



Submit