When a php script is executed/interpreted, the definition of classed in the script is loaded first so you can create an instance of the class and call its functions such as:
<?php $a=new Myprogrammingnotes; $a->sayhello(); class Myprogrammingnotes { public function sayhello() { echo "hello, world<br>"; } }
If you create an instance of some class but the definition of the class has not been loaded, you will get an error.
<?php $a=new Myprogrammingnotes; $a->print();
Fatal error: Class ‘Myprogrammingnotes’ not found in C:\test\index.php on line 2
You can save the definition of the needed class in another file and include it in current script:
<?php //myclass.php class Myprogrammingnotes { function sayhello() { echo "hello, world<br>"; } }
<?php //index.php include "myclass.php"; $a=new Myprogrammingnotes; $a->sayhello();
This is the legacy way to define a class and use it in a script. But you have another option: you do not need to include the class-definition file manually but use an autoload mechanism of php to load the class-definition file automatically.
Now, consider the above script that caused the error. In fact, when you try to new an instance of an undefined class (in this case, Myprogrammingnotes), php interpreter will try to find and call a fixed-name function __autoload(note that there are two underlines at the beginning). Only after it cannot find the function will it report the Class ‘Myprogrammingnotes’ not found error. So, you have the opportunity of providing an __autoload function and loading the class definition of Myprogrammingnotes in __autoload:
<?php $a=new Myprogrammingnotes; $a->sayhello(); function __autoload($classname) { include "myclass.php"; }
Now the script runs without problem. Note that the __autoload function has a parameter $classname, which can be used in the function to make it more flexible:
<?php $a=new Myprogrammingnotes; $a->sayhello(); function __autoload($classname) { include "$classname.php"; }
Now, you only need to save your class-definition file as classname.php, then you will have the ability of using any class in index.php without including its definition file manually.
Sounds good enough,right? But why need spl_autoload_register? Consider two programmers are cooperating on a project, each wants to load some definition files of his own classes using this autoload mechanism but the loading logic is different, e.g., programmer A puts his class-definition files in directory A\ and programmer B puts his class-definition files in directory B\. Then programmer A wants the following __autoload function:
<?php //a.php $a=new AClass; $a->sayhello(); function __autoload($classname) { include "A/$classname.php"; }
while programmer B wants the following __autoload:
<?php //b.php $b=new BClass; $b->sayhello(); function __autoload($classname) { include "B/$classname.php"; }
This is not allowed if both a.php and b.php are loaded(re-declaration of __autoload). This problem can be resolved by getting rid of one of the __autoload and putting the two pieces of logic in the same __autoload function like:
<?php //a.php $a=new AClass; $a->sayhello(); function __autoload($classname) { if($classname[0]=='A') include "A/$classname.php"; if($classname[0]=='B') include "B/$classname.php"; }
This solution is obviously not flexible and lack of scalability. Better solution is to allow each programmer to create his own auto-load function. This is where spl_autoload_register plays its role.
<?php //a.php spl_autoload_register('a_autoload'); $a=new AClass; $a->sayhello(); function a_autoload($classname) { include "A/$classname.php"; }
<?php //b.php spl_autoload_register('b_autoload'); $b=new BClass; $b->sayhello(); function b_autoload($classname) { include "B/$classname.php";
Now, A has his own autoload function a_autoload and B has his own autoload function b_autoload. They only need to call spl_autoload_register to register their respective autoload functions(this is not re-declaration of spl_autoload_register but call of spl_autoload_register thus allowed). spl_autoload_register will put the function(its parameter) into a function queue.
So the complete handling logic when creating an instance of undefined class is: if the function queue created by spl_autoload_register is not empty, call the functions in the queue in order; if the queue is empty, call __autoload; if __autoload is not defined, report the class not found error.
Note that __autoload is deprecated as of php 7.2 and removed as of php 8.0 so you’d better only use spl_autoload_register now.