如何使用 spl_autoload 在所有名称空间中自动使用根 类?

How to use roots classes in all namespaces automatically with spl_autoload?

Class 可以在 spl_autoload_register 内(自动)访问吗?

例如,我在index.php中使用spl_autoload_register

<?php
class Utils {
   public function example() {
      echo 'Hello word!';
   }
}

spl_autoload_register(function($class)
{
    $relative_class = strtolower(str_replace('\', '/', $class));

    $file = './src/' . $relative_class . '.php';

    if (is_file($file)) {
        require_once $file;
    }
});

$user = new \Controllers\Foo\User;

这个 new \Controllers\Foo\User; 自动加载这个文件 ./src/controllers/foo/user.php

user.php:

<?php
namespace Controllers/Foo;

class User
{
    public function foo() {
        //Something...
    }
}

如果我需要使用 Utils class 我必须在文件 [=49= 中添加 new \Controllers\Foo\User ] 像这样:

public function foo() {
   \Utils::example();
}

<?php
namespace Controllers/Foo;

use \Utils as Utils;

class User
{
    public function foo() {
        Utils::example();
    }
}

是否可以在 spl_autoload_register 内(自动)访问 Utils class?我会在没有 use \Utils as Utils; 且没有反斜杠 (\Utils::) 的情况下使用。

你不能。这就是使用命名空间的全部意义所在。您可以引用 class whitout 反斜杠或 use 语句 only 如果它在您正在使用的同一名称空间中。您无法破解自动加载器以自动将目标 class 导入当前命名空间并即时更改其命名空间。

如果您的 class 不属于 named 命名空间,那么它在 global 命名空间中,而您仍然必须与 \use 一起使用。 python、java、go、.net、c/c++等中的importuse关键字也是如此

除了使用 use ... as ... 或 "backslash" (\) 之外,没有任何标准可以做到这一点,但是我们可以 "cheat the PHP"spl_autoload_register() 中使用 eval() 来扩展 namespace.

中的 Utils class

Only use this if really necessary, prefer to use "backslash" (\) or use \Utils as Utils

示例(阅读代码中的注释):

<?php
class Utils {
   public static function example() {
      echo 'Hello World!';
   }
}

spl_autoload_register(function($class)
{
    $relative_class = strtolower(str_replace('\', '/', $class));

    $file = './src/' . $relative_class . '.php';

    if (is_file($file)) {
        $np = explode('\', $class); //Dividi string

        //Check if class exists in namespace (prevent conflicts)
        if (class_exists(implode('::', $np)) === false) {

            //Remove "class name", use only "namespace"
            array_pop($np);

            //evaluate a namespace in eval (extends the Utils class)
            eval(
                'namespace ' . implode('\', $np) . ' {' . PHP_EOL .
                'class Utils extends \Utils {}' . PHP_EOL .
                '}'
            );
        }

        require_once $file;
    }
});

$user = new \Controllers\Foo\User;
$user->foo(); //Show "Hello word!"

我承认这是一个丑陋的黑客,也许我不会使用,但它仍然是一个提示是的。

Note: use \Utils as Utils not work in eval