使用SPL_AUTOLOAD_REGISTER时命名空间的工作方式


How Do Namespaces Work When Using SPL_AUTOLOAD_REGISTER?

我今天正在学习如何在PHP中使用名称空间和自动加载,我似乎遇到了障碍。当我不使用spl_autoload_register而是使用require_once时,事情似乎是可行的。

我的文件夹结构是最低限度的:

- index.php
- class/
  - Users.php

在我的index.php文件中,我有:

<?php
require_once('class/Users.php');
echo User::get(1);

在我的class/Users.php文件中,我有:

<?php
Class User {
    function get($id) {
        return $id;
    }
}

这样做非常好,返回1 的ID

理想情况下,我想使用自动加载功能,我发现了spl_autoload_*,这就是我试图做的,但没有成功:

在我的class/Users.php文件中,我有:

<?php
namespace Users; // Added a namespace
Class User {
    function get($id) {
        return $id;
    }
}

在我的index.php文件中,我有:

<?php
// Changed to using spl_autoload_register using an anonymous function to load the class 
spl_autoload_register(function($class){
    include('class/' . $class . '.php');
});
echo Users'User::get(1); // Added the Users namespace

但是我得到一个错误:

`Class 'Users'User' not found in /Applications/MAMP/htdocs/index.php on line 7`

不太确定我做错了什么。

我认为您应该在命名空间路径前面添加。

示例

'Users'User::get(1);

如果您必须使用基本路径,如Traversable(),您还需要执行

new 'Traversable()

调用自动加载器时使用完整的类名作为参数,包括命名空间。在您的示例中,这是Users'User,所以您最终执行

include('class/Users'User.php');

这失败了,因为类定义不在名为Users的目录中(顺便说一句,include会发出一个警告,说它找不到包含扩展文件名的文件,这个警告会让事情变得更清楚——你禁用了错误报告吗?)

当找不到文件时,让自动加载器当场失败可能是个好主意,这样故障模式就更明显了。例如,您可以将其更改为

require('class/' . $class . '.php'); // require will end the script if file not found

或者类似的东西

$result = @include('class/' . $class . '.php'); // see documentation for include
if ($result === false) {
    die("Could not include: 'class/$class.php'");
}