目录结构
learner@debian:~$ tree ~/bin
/home/learner/bin
└── php
├── Body
│ ├── Brain.php
│ └── Cell
│ └── Neuron.php
└── main.php
3 directories, 3 files
第一个代码示例
~/bin/php/main.php:
<?php
spl_autoload_register(function ($class) {
$path = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
echo "----- Autoload $class from $path -----\n";
include $path;
});
use Body\Brain;
$brain = new Brain();
?>
~/bin/php/Body/Brain.php:
<?php
namespace Body;
use Body\Cell\Neuron;
class Brain
{
public function __construct()
{
$this->brain = new Neuron();
$this->brain->talk();
}
}
?>
~/bin/php/Body/Cell/Neuron.php:
<?php
namespace Body\Cell;
class Neuron
{
public function talk()
{
echo "I am Neuron!\n";
}
}
?>
我可以通过以下方式从我的主目录执行 main.php 并且它工作正常:
learner@debian:~$ php ~/bin/php/main.php
----- Autoload Body\Brain from Body/Brain.php -----
----- Autoload Body\Cell\Neuron from Body/Cell/Neuron.php -----
I am Neuron!
我很惊讶这行得通。我希望它
$this->brain = new Neuron();
在
~/bin/php/Body/Brain.php
. 当遇到这一行时,自动加载器会尝试执行,但里面include 'Body/Cell/Neuron.php'
没有调用这样的子目录。Body
~/bin/php/Body
第二个代码示例
让我通过展示另一个使用include
语句而不是自动加载器的代码示例来向您展示为什么我希望第一个代码示例失败。
~/bin/php/main.php 修改为:
<?php
include 'Body/Brain.php';
use Body\Brain;
$brain = new Brain();
?>
看到上面的代码现在缺少自动加载器,并且现在正在使用相同的包含语句,该语句之前由自动加载器执行。
~/bin/php/Body/Brain.php 修改为:
<?php
namespace Body;
include 'Body/Cell/Neuron.php';
use Body\Cell\Neuron;
class Brain
{
public function __construct()
{
$this->brain = new Neuron();
$this->brain->talk();
}
}
?>
请注意,相同的 include 语句已添加到此代码中,该语句之前由自动加载器执行以加载Body\Cell\Neuron
。
尝试执行此代码会导致失败。
learner@debian:~$ php ~/bin/php/main.php
PHP Warning: include(Body/Cell/Neuron.php): failed to open stream: No such file or directory in /home/learner/bin/php/Body/Brain.php on line 4
PHP Warning: include(): Failed opening 'Body/Cell/Neuron.php' for inclusion (include_path='.:/usr/share/php:/usr/share/pear') in /home/learner/bin/php/Body/Brain.php on line 4
PHP Fatal error: Class 'Body\Cell\Neuron' not found in /home/learner/bin/php/Body/Brain.php on line 12
预计会出现此故障,因为在执行
include 'Body/Cell/Neuron.php';
时~/bin/php/Body/Brain.php
,它没有找到调用的Body
子目录~/bin/php/Body
。
问题
我知道我可以通过编辑
~/bin/php/Body/Brain.php
使用
include 'Cell/Neuron.php';
而不是
include 'Body/Cell/Neuron.php';
. 但是,我的问题不是关于为什么第二个代码示例不起作用,而是关于为什么第一个代码示例起作用。
- 当 PHP 解释器无法
include 'Body/Cell/Neuron.php'
在~/bin/php/Body/Brain.php
第二个代码示例中执行时,自动加载器如何成功地从第一个代码示例中的同一个 PHP 文件执行相同的包含? - 还是我弄错了?是不是在第一个代码示例中,自动加载器总是从哪里执行包含语句,
~/bin/php/main.php
而不管类首先在哪里被使用,所以在哪里include 'Body/Cell/Neuron.php'
完成~/bin/php/main.php
并且它成功了,因为确实有一个调用的Body
子目录~/bin/php
?如果是这种情况,我在哪里可以阅读官方文档中的相关信息? - 总结一下我们的理解,您能告诉我注册的自动加载器功能通常是从哪里执行的吗?从定义函数的脚本?从注册函数的脚本?或者来自遇到新类的脚本?