【问题标题】:How to use roots classes in all namespaces automatically with spl_autoload?如何使用 spl_autoload 在所有命名空间中自动使用根类?
【发布时间】:2015-10-28 21:08:53
【问题描述】:

是否可以在spl_autoload_register 中(自动)使 Class 可访问?

例如,我在 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 类,我必须在文件 user.php 中添加 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 类(自动)吗?我会使用不带 use \Utils as Utils; 且不带反斜杠 (\Utils::)。

【问题讨论】:

    标签: php namespaces autoload spl


    【解决方案1】:

    除了使用use ... as ... 或“反斜杠”(\)之外,没有任何标准可以做到这一点,但是我们可以在spl_autoload_register() 中使用eval()“欺骗 PHP”namespace 中扩展Utils 类

    仅在真正需要时使用,更喜欢使用“反斜杠”(\)或use \Utils as Utils

    示例(在代码中读取 cmets):

    <?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!"
    

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

    注意:use \Utils as Utils 不适用于eval

    【讨论】:

      【解决方案2】:

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

      如果你的类不属于 named 命名空间,那么它在 global 命名空间中,你仍然需要使用 \use .在 python、java、go、.net、c/c++ 等中,importuse 关键字也是如此。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-10-28
        • 2014-03-30
        • 2015-07-28
        • 2015-05-25
        • 1970-01-01
        • 2017-11-03
        • 2021-06-29
        相关资源
        最近更新 更多