不能将命名空间与自动加载器一起使用
Cannot use namespace with autoloader
使用自动加载器 "spl_autoload_register" 时,我无法使用命名空间实例化 classes。如果不使用命名空间,或者通过简单地排除自动加载器,它可以很好地访问 class 方法。我故意省略了第一个 class 的名称空间以显示错误。所有文件都来自同一文件夹运行。
错误的可能原因:
由于命名空间在没有自动加载器的情况下工作,我怀疑自动加载器从实例化中添加了命名空间路径的反斜杠。如果是这样,这可能是找不到 class 的原因。
观察:
Autoload 加载 classes 没有错误。 Class 如果在实例化期间不使用命名空间路径,则可以访问方法。如果包含没有自动加载的 classes,则可以使用命名空间实例化 Class_2。
如果我注释掉 Class_2 的实例化,那么我会得到如下无误的结果:
Hello from class 1
错误信息:
Hello from class 1PHP Fatal error: Uncaught Error: Class 'Area_2\Class_2' not found in Xxx/run.php:9
自动加载器:
spl_autoload_register(
function ($class_name) {
$directories = ['./'];
$extension = ".class.php";
foreach ( $directories as $dir) {
if (file_exists($dir . $class_name . $extension)) {
require_once($dir . $class_name . $extension);
return;
}
}
}
);
运行 文件:
include 'autoloader.php';
$class_1 = new Class_1();
$class_1->print_1();
$class_2 = new \Area_2\Class_2(); // Error by using namespace.
$class_2->print_2();
Class_1:
class Class_1 {
public function print_1()
{
echo "Hello from class 1";
}
}
Class_2:
namespace Area_2;
class Class_2 {
public function print_2()
{
echo "Hello from class 2";
}
}
您的自动加载器为任何使用命名空间的 classes 假设一个基于目录的系统,即使它不是预期的。原因是命名空间分隔符与目录分隔符相同(或足够相似,系统会自动在两者之间进行转换)。
当你这样做时:
file_exists($dir . $class_name . $extension)
使用 class Area_2\Class_2
、PHP 将其转换为 ./Area_2\Class_2.class.php
。
因此,您的代码需要文件夹。
使用自动加载器 "spl_autoload_register" 时,我无法使用命名空间实例化 classes。如果不使用命名空间,或者通过简单地排除自动加载器,它可以很好地访问 class 方法。我故意省略了第一个 class 的名称空间以显示错误。所有文件都来自同一文件夹运行。
错误的可能原因:
由于命名空间在没有自动加载器的情况下工作,我怀疑自动加载器从实例化中添加了命名空间路径的反斜杠。如果是这样,这可能是找不到 class 的原因。
观察:
Autoload 加载 classes 没有错误。 Class 如果在实例化期间不使用命名空间路径,则可以访问方法。如果包含没有自动加载的 classes,则可以使用命名空间实例化 Class_2。
如果我注释掉 Class_2 的实例化,那么我会得到如下无误的结果:
Hello from class 1
错误信息:
Hello from class 1PHP Fatal error: Uncaught Error: Class 'Area_2\Class_2' not found in Xxx/run.php:9
自动加载器:
spl_autoload_register(
function ($class_name) {
$directories = ['./'];
$extension = ".class.php";
foreach ( $directories as $dir) {
if (file_exists($dir . $class_name . $extension)) {
require_once($dir . $class_name . $extension);
return;
}
}
}
);
运行 文件:
include 'autoloader.php';
$class_1 = new Class_1();
$class_1->print_1();
$class_2 = new \Area_2\Class_2(); // Error by using namespace.
$class_2->print_2();
Class_1:
class Class_1 {
public function print_1()
{
echo "Hello from class 1";
}
}
Class_2:
namespace Area_2;
class Class_2 {
public function print_2()
{
echo "Hello from class 2";
}
}
您的自动加载器为任何使用命名空间的 classes 假设一个基于目录的系统,即使它不是预期的。原因是命名空间分隔符与目录分隔符相同(或足够相似,系统会自动在两者之间进行转换)。
当你这样做时:
file_exists($dir . $class_name . $extension)
使用 class Area_2\Class_2
、PHP 将其转换为 ./Area_2\Class_2.class.php
。
因此,您的代码需要文件夹。