233

I am learning advanced PHP standards and trying to implement new and useful methods. Earlier I was using __autoload just to escape including multiple files on each page, but recently I have seen a tip on __autoload manual

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.

but I really can't figure out how to implement spl_autoload and spl_autoload_register

Machavity
  • 30,841
  • 27
  • 92
  • 100
xkeshav
  • 53,360
  • 44
  • 177
  • 245

4 Answers4

397

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.

starball
  • 20,030
  • 7
  • 43
  • 238
Brownbay
  • 5,400
  • 3
  • 25
  • 30
  • 48
    This may be one of the best answers in the history of answers ever. Respect. I had one of those "OMG! It all makes sense now!" moments because of you, my good man. I think I might just start a fan club. –  Nov 28 '13 at 02:03
  • 3
    To make this the best answer of all answers ever even in alternate universes, please add that spl_autoload very, um, "helpfully" (?) converts all filenames to lowercase (see my comment to @user below). Can't use spl_autoload_register() vanilla if you like your CapitalLettersAndStuff. –  Nov 28 '13 at 04:16
  • 6
    @Just Plain High I'm not having that issue and all of my class files are camelcased. BTW, this is a wonderful answer. It helped me get my head around a simple concept that I could just not understand until I read this post! My 85(and growing) line include file that includes all my class files is now 7 lines! – kyle May 12 '14 at 22:28
  • 2
    This is indeed a good answer but I'm missing one thing. What is the actual default functionality? With classes I know, it uses the namespace as path and class name as file name. Although I can't figure out how it works with functions. – SiXoS Jun 18 '14 at 22:00
  • 1
    In addition to the "camelBack" bug, I have found two details that are required for success: 1)that your included class names must have a single separator or SPL_autoload fails. For example, I was using inc\class.myclass.php when I was using __autoload. Once I switched to SPL_autoload I had to remove the leading "class.". 2) It was not obvious to me that set_include_path() requires an ABSOLUTE path, not relative. So setting it to "inc\" failed as it needed to be "\home\username\projects\thisproject\inc". – frozenjim Dec 26 '14 at 19:30
  • 2
    Isn't one of the *huge* benefits to using `spl_autoload_register()` (and `__autoload()` in general) that it lazy loads include files/classes? This is implied by the answer, but not explicitly stated. To me, this is critical information that would be perfect for inclusion in your answer! :) – rinogo Feb 27 '15 at 05:57
  • Just wanted to point out case sensitivity. `$className = strtolower( $className );` may come in handy if your file names are lowecase. – henrywright May 27 '15 at 15:45
  • 1
    but then we would require a single include to the `MyAutoloader.php` in every file, right?? – azerafati Jul 22 '15 at 12:04
  • 1
    Thank you for such a clear answer. The official docs were not as good explaining the parameter passed to `spl_autoload_register`. It makes a lot more sense now. – Mentakatz Mar 17 '17 at 16:24
  • Should you always do "soft including" in `spl_autopload_register`? Like, you assume that there might be more autoloaders, so just using `include` will raise a warning every time your autoloader happens to be before some other one, which is valid for some class. By "soft including" I mean checking if file exists first. – Robo Robok Jul 28 '17 at 18:42
  • @azerafati - That is correct. Wasted some time finding that out for myself when I feel it should have been included (no pun intended) in the answer. – EternalHour Dec 11 '17 at 03:08
  • A little late but make sure that the new extension string parameter for spl_autoload_extensions() contains no spaces. spl_autoload_extensions('.php,.inc') – Amarjit Aug 01 '18 at 15:25
15

Since PHP 5.3, you can use spl_autoload_register() with namespaces, which means that you can organize your project and autoload your php classes without any require or include and without redefining an __autoload() function.

To demonstrate this behaviour, just create a file called index.php :

<?php
spl_autoload_register();
var_dump(new Main\Application);

Then create a folder named Main located right next to the index.php file. Finally, creates a file called Application.php located into Main and paste the following code into it :

<?php namespace Main;
class Application{}
Renjith K N
  • 2,613
  • 2
  • 31
  • 53
user1974206
  • 159
  • 1
  • 2
  • 9
    A note from my fiddling with all this: spl_autoload() - and thus spl_autoload_register() - converts filenames to *lowercase* (despite bug reports, pleas and furious voting). This means *you* might be looking for "Main\Application" but spl_autoload is looking for "main\application". If you like camels, like I do, you're going to have to write your own function. There is a nice starter example here: https://github.com/ircmaxell/PHP-CryptLib/blob/37febc046ad23beec1a728f950903b8c3f5aa383/lib/CryptLib/bootstrap.php –  Nov 28 '13 at 04:09
  • 1
    Pros: spl_autoload_register() is the fastest method of autoloading Cons: it will work only with lowercase files/classes, and namespaces too, which at this day and age just sux big time (no option to tell it to use CamelCase etc.). But if you can live with namespace/classname.php structure, don't look any further. – stamster Sep 19 '16 at 14:32
  • 1
    `spl_autoload_register()` default implementation is unable to find inherited classes. So using defaults, lowercase files and directories reflecting namespace path, everything works fine unless I have a class which extends another class (parent). PHP then throws error that it cannot find that parent class, even they're all in the same directory/namespace! What is confusing is that literally only first level classes are found, so I had to put another `spl_autoload_register()` with anonymous function rule just after 1st one in order o manually include missing parent / inherited classes. – stamster Jul 27 '17 at 21:54
4

Here is the way I do use Autoload. In the given example I wanto to load classes form 3 diferent directories.

function namespaceAutoload($rawClass){
    $class = str_replace('\\', DIRECTORY_SEPARATOR, $rawClass);

    $possiblePaths[] = '..\sys\class\file.php';
    $possiblePaths[] = '..\sys\class\lib\file.php';
    $possiblePaths[] = '..\sys\class\class.file.inc.php';

    foreach ($possiblePaths as $templatePath) {
        $path = str_replace(["\\", "file"], [DIRECTORY_SEPARATOR, $class], $templatePath);
        if (file_exists($path)) {
            require_once "$path";
            break;
        }
    }
}

spl_autoload_register("namespaceAutoload"); 

I the given example, the PHP will look for the namespace\class in these three directories using these three different filename formats.

ruleboy21
  • 5,510
  • 4
  • 17
  • 34
  • Havent been able to get this to work with namespaced classes calling it Dynamically I.e. " $obj = new $fully_qualified_class_name;" Anything you could add to this? – Brendan Jackson Aug 02 '23 at 13:06
0

Working with OOP in php, spl_autoload_register() lets you register multiple function, classes, trait etc to your php script.

Heres a use case on /test folder structure

/.htaccess
/index.php
/autoload.php
/controller/test.php

Inside autoload.php file:

spl_autoload_register(function ($classname) {
    include_once dirname(__FILE__) . "/" . str_replace("\\", "/", $classname) . '.php';
});

Inside .htaccess

DirectoryIndex index.php

# php_value auto_prepend_file 
php_value auto_prepend_file "/xampp/htdocs/test/autoload.php"

Inside controller/test.php

namespace controller;

class test {
   public static function sayHello () {
     echo "hello";
   }
}

Inside index.php

use controller/test;

echo test::sayHello();

The autoload.php can be included or like the example above prepend on all script. It loads the class test and lets you use it directly without having to include the test.php script by pathname.

Johnson Fashanu
  • 897
  • 8
  • 6