__autoload
魔术方法该方法使用PHP5和PHP7,并且在PHP7.2以后的版本已经被移除,因为该方法有一个致命缺陷,该方法不能重复定义,也就是说我们只能定义一种加载文件的模式,当我们应用其他插件扩展的时候就有问题。
示例如下:
|-- autoload_project
|-- test_a
|-- TestB.php
|-- index.php
|-- TestA.php
|-- TestC.php
#file path: /autoload_project/index.php
function __autoload($name) {
var_dump($name);
var_dump("-------");
$filename = __DIR__ . '/'.$name.".php";
if (file_exists($filename))
require $filename;
}
$a = new TestA();
$a->printInfo();
echo "index";
#file path: /autoload_project/TestA.php
class TestA {
function __autoload($name) {
var_dump($name);
var_dump("+++++++++++++++");
$filename = __DIR__ . '/testA/'.$name.".php";
if (file_exists($filename))
require $filename;
}
function printInfo() {
$b = new TestB();
$b->printInfo();
echo "testA";
}
}
#file path: /autoload_project/test_a/TestB.php
class TestB {
function __autoload($name) {
var_dump($name);
var_dump("+++++++++++++++");
$filename = __DIR__ . '/../'.$name.".php";
if (file_exists($filename))
require $filename;
}
function printInfo() {
$b = new TestC();
$b->printInfo();
echo "testA child testB";
}
}
#file path: /autoload_project/TestC.php
class TestC {
function printInfo() {
echo "testC";
}
}
执行结果如下:
string(5) "TestA" string(7) "-------" string(5) "TestB" string(7) "-------"
Fatal error: Class 'TestB' not found in D:\WWW\autoload\TestA.php on line 23
可以看到index中找TestA类时,执行了index中的__autoload
方法,这一步没问题,但是TestA类执行printInfo
方法的时候,加载TestB类的时候,应该要使用TestA类的__autoload
方法,但是实际情况是执行了index中的__autoload
方法
为了解决这种问题,引入了第二种自动加载的方法
spl_autoload_register
方法
spl_autoload_register
方法就是解决了__autoload
只能定义一次的问题。它实际上创建了 autoload 函数的队列,按定义时的顺序逐个执行。
上面例子的代码可以修改为如下:
#file path: /autoload_project/index.php
function loadfuncIndex($name) {
$filename = __DIR__ . '/'.$name.".php";
if (file_exists($filename))
require $filename;
}
spl_autoload_register("loadfuncIndex");
$a = new TestA();
$a->printInfo();
echo "index";
#file path: /autoload_project/TestA.php
class TestA {
public static function loadfuncA($name) {
$filename = __DIR__ . '/testA/'.$name.".php";
if (file_exists($filename))
require $filename;
}
function printInfo() {
spl_autoload_register("TestA::loadfuncA");
$b = new TestB();
$b->printInfo();
echo "testA";
}
}
#file path: /autoload_project/test_a/TestB.php
class TestB {
public function loadfuncB($name) {
$filename = __DIR__ . '/../'.$name.".php";
if (file_exists($filename))
require $filename;
}
function printInfo() {
spl_autoload_register(array($this, "loadfuncB"));
$b = new TestC();
$b->printInfo();
echo "testA child testB";
}
}
输出结果如下:
testCtestA child testBtestAindex
spl_autoload_register
的使用方式spl_autoload_register(funName); // 直接注册一个普通加载函数
spl_autoload_register(obj::method); // 注册一个静态加载方法
spl_autoload_regitser(array(obj, method));
spl_autoload_regitser(function($name){ }); //匿名函数
现在最常见的自动导入是结合命名空间来使用,命名空间相关请参见回顾明明空间