【问题标题】:PHP Autoload Classes Is Not Working With NamespacesPHP 自动加载类不使用命名空间
【发布时间】:2021-06-29 09:22:20
【问题描述】:

我尝试编写以下代码,但无法弄清楚为什么它在 spl_autoload_register() 中找不到具有命名空间的类?

我得到的错误是:

警告:require_once(src/test\StringHelper.php):打开失败 流:没有这样的文件或目录

Autoloader.php 文件:

<?php

spl_autoload_register(function($classname){
    require_once "src/$classname.php"; // NOT WORKING DYNAMICALLY

//    require_once "src/StringHelper.php"; // WORKING WHEN HARD CODED
});

$stringHelper1 = new test\StringHelper(); // Class with namespace defined
echo $stringHelper1->hello() . PHP_EOL; // returns text

src 文件夹内的StringHelper.php:

<?php namespace test;

class StringHelper{

    function hello(){
        echo "hello from string helper";
    }
}

如果这有所作为,我也会使用 XAMPP。

【问题讨论】:

  • 因为$classname 是包含命名空间的fully qualified name。如果你只需要,你需要去掉类名
  • @mario 抱歉,我之前在使用“/”进行测试时尝试过此操作,但仍然没有成功,因此被删除并忘记更新错误消息。
  • @apokryfos 请您发布一个代码示例供我查看?谢谢
  • @Jeto - 这个答案是关于从类实例中获取名称,而不是字符串(这会给他们)。接受的答案甚至使用反射来获取名称。

标签: php oop xampp namespaces php-7


【解决方案1】:

正如 cmets 中已经指出的,除了类名之外,您需要删除所有内容,如下所示:

$classname = substr($classname, strrpos($classname, "\\") + 1);

在您的自动加载函数的上下文中:

spl_autoload_register(function($classname){

    $classname = substr($classname, strrpos($classname, "\\") + 1);
    require_once "src/{$classname}.php"; 
});

让我们更进一步,利用自动加载函数总是接收限定命名空间这一事实,而不是,例如,相对命名空间

<?php

namespace Acme;

$foo = new \Acme\Foo(); // Fully qualified namespace 
$foo = new Acme\Foo();  // Qualified namespace
$foo = new Foo();       // Relative namespace

在所有三个实例中,我们的自动加载函数总是以Acme\Foo 作为参数。考虑到这一点,实现将命名空间和任何子命名空间映射到文件系统路径的自动加载器策略相当容易 - 特别是如果我们在文件系统层次结构中包含顶级命名空间(在本例中为Acme) .

例如,给定我们某个项目中的这两个类...

<?php

namespace Acme;

class Foo {}

Foo.php

<?php

namespace Acme\Bar;

class Bar {}

Bar.php

...在此文件系统布局中...

my-project
`-- library
    `-- Acme
        |-- Bar
        |   `-- Bar.php
        `-- Foo.php

...我们可以在命名空间类和它的物理位置之间实现一个简单的映射,如下所示:

<?php

namespace Acme;

const LIBRARY_DIR = __DIR__.'/lib'; // Where our classes reside

/**
 * Autoload classes within the current namespace
 */
spl_autoload_register(function($qualified_class_name) {

    $filepath = str_replace(

        '\\', // Replace all namespace separators...
        '/',  // ...with their file system equivalents
        LIBRARY_DIR."/{$qualified_class_name}.php"
    );

    if (is_file($filepath)) {

        require_once $filepath;
    }
});

new Foo();
new Bar\Bar();

另外请注意,您可以注册多个自动加载函数,例如,处理不同物理位置的不同顶级命名空间。不过,在实际项目中,您可能希望熟悉 Composer 的自动加载机制:

在某些时候,您可能还想看看 PHP 的自动加载规范:

【讨论】:

    猜你喜欢
    • 2013-05-16
    • 2013-11-25
    • 2014-04-13
    • 2012-10-22
    • 2011-08-06
    • 2015-07-15
    • 2012-05-21
    相关资源
    最近更新 更多