【问题标题】:Using PHP namespaces on a subnamespace在子命名空间上使用 PHP 命名空间
【发布时间】:2015-09-30 12:05:18
【问题描述】:

美好的一天。我正在研究一个示例,以准确了解名称空间是什么,以及它们的限制是什么。 我有这个结构(windows):

D:\server\sistemas\tests\phpNS\exec.php

D:\server\sistemas\tests\phpNS\Extra\Call.php

D:\server\sistemas\tests\phpNS\Extra\exec.php -->(另一个副本)

D:\server\sistemas\tests\phpNS\Lib\Base.php

每一个的代码:

exec.php

<?php 
spl_autoload_register();

$a = new Extra\Call();
?>

调用.php

<?php
namespace Extra{
    spl_autoload_register();

    class Call{
        public function __construct(){
            $inst = new \Libs\Base();
            var_dump($inst);
        }
    }
}
?>

Base.php

<?php
namespace Libs{
    class Base{
        public $dac;
        public $doc;
        public function __construct(){

        }
    }
}
?>

如果我在这种情况下工作,一切都很好。问题是当我执行 Extra\exec.php

额外\exec.php

<?php 
namespace Extra{
    spl_autoload_register();

    $a = new Call();
}
?>

假定此文件的文件系统上下文是 Extra,这就是我使用该命名空间但无法正常工作的原因。我收到了这个错误。

致命错误:spl_autoload(): Class Extra\Call 无法在第 5 行的 D:\server\sistemas\tests\phpNS\Extra\exec.php 中加载

然后我记得 php 类是由尾部反斜杠 (\Iterator) 调用的,所以我也尝试了这个:

额外\exec.php

<?php
    spl_autoload_register();

    $a = new \Extra\Call();

?>

但我得到了相同的结果...我做错了什么,如果我想在这个或任何 n 深度目录中使用这个文件该怎么办?

【问题讨论】:

  • 使用autoloader components 之一对您有帮助吗?例如The PSR-4 Class Loader。另外:Aura.Autoload : Provides a full PSR-4 and limited PSR-0 autoloader。两者都简化了类的autoloading 的管理。我都使用过,目前正在使用Aura
  • 嗯,它似乎可以工作。但这意味着我需要使用 symfony 才能做到这一点?我只是确保我可以在任何 n 深度目录级别使用命名空间,因为如果我需要使用空白 index.php 中的 htaccess rewriterules 功能,并且遇到这个问题,我无法将文件重定向到项目结构,不会出现未加载类错误。
  • 对不起瑞恩,也许我做错了什么。我已经在 exec.php 上重写了我的代码(这个很好) $dir = _ DIR _."/Libs/Aura.Autoload-2.x/src/Loader.php";需要一次($dir); $loader = 新 \Aura\Autoload\Loader; $loader->register(); $loader->addPrefix('Extra\Call', '\Extra\Call.php'); $a = new Extra\Call();我按照说明进行操作,并且正在加载 Aura,或者至少,我认为正在加载,但没有加载我的课程。你能帮我解决这个问题吗?
  • Zipped Source code for a working Aura autoloader on windows。下载并解压到任意目录。您需要更改的唯一文件是:根目录中的__bootstrap__.php。您需要将APP_ROOT_DIR 定义更改为该目录所在的路径。然后test_loader*.php 文件应该开始加载classes 目录中的类。如果需要,我稍后会提供完整的解释。这些文件的评论相当不错。也许?
  • +1 非常感谢 Ryan 付出的努力和时间,我非常感谢。我会检查它,只要我可以离开办公室。目前我看到了一些代码,看起来不错。我稍后会发给你。再次感谢 =)

标签: php namespaces


【解决方案1】:

首先,不建议您将namespace 声明用作块。最好简单地声明namespace,然后进入您的类并为每个文件放置一个类。这就是你声明\Extra\Call

的方式
namespace Extra;

class Call{
    public function __construct(){
        $inst = new \Libs\Base();
        var_dump($inst);
    }
}

您通常将spl_autoload_register(); 与可调用函数的名称一起使用,但您没有提供任何可以充当自动加载器的函数。您的自动加载函数应该将您尝试加载的类的名称作为其唯一参数。然后它应该找到您的类文件和includerequire 该文件。这是一个例子from the PHP docs

spl_autoload_register(function ($class) {
    include 'classes/' . $class . '.class.php';
});

【讨论】:

  • 好吧,这没有任何意义。因为我不只是与一个类一起工作我在另一个类中实例化一个类。即使它有效,我仍然依赖于 require 和/或 include(_once)。因为如果我使用 1000 个类,我应该在 autoload 函数上加载 1000 个类……意味着我们回到了过去,只是使用“整洁”的代码,但在性能方面我并没有变得更好。跨度>
  • @Artynok 首先,自动加载仅在您需要时加载文件。你不能告诉我每个文件都需要 1000 个类。其次,您可以设置自动加载以遵循您的目录结构。最后,这与其说是性能问题,不如说是理智问题。我永远不必猜测在哪里可以找到我的课程。
  • 首先命名空间不是块?是的,它们可以用作块,并显示在the php manual 第二,正如您所解释的那样,自动加载功能使用一个必需的文件或类......如果我需要许多类或文件来解决这种情况会怎样?最后,您刚刚回答了理论,您从未使用过我的案例来尝试解释如何使用它
  • @Artynok 很公平。您可以对多个类使用阻塞。但同一手册页指出,这不是推荐的做法。至于需要多个类,这就是自动加载的作用。它加载您需要的所有类,仅此而已。至于不给你提供更具体的例子,没有更多数据我无法评论
【解决方案2】:

鉴于 Machavity 明确需要的事实,我在这里给出“更具体的例子”,这是他回答的结果: 正如你所说,我需要使用在 spl_autoload_register 中注册一个自动加载功能,所以好吧,我做到了,它可以工作......但只适用于根目录中的 exec.php。

exec.php

spl_autoload_register(function ($class) {
    include $class . '.php';
});

$a = new Extra\Call();

但这不适用于 Extra\exec.php。我必须获取基本名称并使用命名空间来加载类。但它一直失败的原因是要求我提供不存在的 Extra\Libs\Base.php

额外\exec.php

spl_autoload_register(function ($class) {
    $f = basename($class);
    include __DIR__."\\".$f . '.php';
});

$a = new \Extra\Call();

这意味着我需要根据每个位置获取所有根结构并执行许多丑陋的技巧。正如我所说,您甚至从未使用过我的案例来得出这个结论,因此我已将您的答案标记为无用。

【讨论】:

    最近更新 更多