【问题标题】:How to use composer psr-4 fallback correctly如何正确使用 composer psr-4 后备
【发布时间】:2018-07-25 08:53:04
【问题描述】:

我有一个目录来保存所有“帮助”类和函数。我们将目录称为 helpers

我想将 PSR-4 后备目录配置为指向这个 helpers 目录:

    "autoload": {
          "psr-4": {
                "": "helpers/"
           }
     }

来自 Composer 文档:

... 将在其中查找任何命名空间的后备目录。

所以我的理解是,如果我在该目录中的文件/类具有符合 PSR-4 的名称,我的应用程序应该能够在那里找到它们。

现在我创建了一个文件 helpers/Logger.php,其类为 Logger

为了 1) 符合 PSR-4 和 2) 正常工作,该类应该使用什么命名空间?

我试过了

namespace Logger;

并将类加载为

$logger = new Logger();

但我收到错误找不到类记录器

深入研究 composer 代码(loadClass() 方法)告诉我它确实找到并包含文件 helpers/Logger.php,但由于某种原因仍然找不到该类。 p>

根据 PSR-4 命名空间应该是这样的:

namespace Helpers;

类应该这样调用:

$logger = new Helpers\Logger();

我有 Class Helpers\Logger not found,但另外文件 helpers/Logger.php 甚至不包括在内。

Composer 的 loadClass() 方法中用于回退的逻辑如下:

    // PSR-4 lookup
    $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;

   ........

    // PSR-4 fallback dirs
    foreach ($this->fallbackDirsPsr4 as $dir) {
        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
            return $file;
        }
    }

所以它实际上会尝试将文件名与完全限定的类名进行匹配。

所以我对 PSR-4 的理解似乎遗漏了一些东西。

但究竟是什么?

编辑

为了检查这一切,我从项目根目录运行了一个简单文件,通过 composer 配置的所有其他库都已正确加载(例如,Pimple 工作正常):

<?php

require_once __DIR__ . '/vendor/autoload.php';
$app = new \Pimple\Container();

/** Register logger */
$app['logger'] = function ($c) {
    return new Helpers\Logger();
};

$app['logger']->info('test');

【问题讨论】:

  • 我不得不问,因为每个人都忘记了。您还记得要求您的自动加载文件吗?
  • 是的,我做到了:require_once __DIR__ . '/vendor/autoload.php'; 但是让我也编辑我的问题以避免混淆。

标签: php namespaces composer-php psr-4


【解决方案1】:

此回退用作全局命名空间的目录定义。所以是的,它可以用于自动加载任何命名空间中的任何类,但您仍然需要为它们遵循 PSR-4 规则。目录结构应该代表命名空间结构。如果你有这样的规则:

"autoload": {
      "psr-4": {
            "": "helpers/"
       }
 }

您的Helpers\Logger 类应该在helpers/Helpers/Logger.php 中,因为这样 Composer 将根据自动加载规则解析类文件路径。

helpers/Helpers/Logger.php
   ^       ^      ^
   |       |      |
   |       |    Class name part
   |       |            
   |     Namespace part
   |
 Static prefix for global namespace

【讨论】:

  • 感谢您的回复,但我仍然感到困惑 - 是否可以避免重复的 Helpers 部分?那么Logger 的类在helpers/Logger.php 中?应该为这个类设置什么命名空间?
  • @MaksymBodnar 只是不要使用后备,你可能不需要它。将命名空间的常规自动加载规则定义为"Helpers\\": "helpers/",并将您的记录器类放入helpers/Logger.php
【解决方案2】:

PSR4 工作时区分大小写,因此如果您将一个类放在文件夹 helpers 中,并且该类本身使用命名空间 Helpers,那将不起作用。

【讨论】:

  • 根据 PSR-4(据我所知)类的完整路径由前缀(在我的情况下是空字符串)、基本目录(在我的情况下是 helpers/ ) 和转换为文件名/类名的命名空间(即Logger)。所以它应该只找到Logger
  • 啊,好吧,那么自动加载器可能会在文件 helpers/Helpers/Logger.php 中查找 Helpers\Logger - 但如果您在启用 XDebug 的情况下运行脚本以查看文件的确切位置,您可能会自行找到应该位于
  • 我想我明白了。我只是好奇为什么不可能有helpers/Logger.phpnamespace Logger?或者这不符合 PSR-4 标准?
  • 为什么不可能呢?只需将其正确地放在您的 composer.json 中,这样它就可以将命名空间 Logger 映射到文件夹 helpers ;) 但是如果您只是将命名空间与正确的文件夹匹配,这会引入比您需要的更多的配置
  • 好吧,我想使用后备功能 - 所以我有一个目录 (helpers) 我可以在其中放置我所有的 helpers 类,而不必添加每个一个作曲家明确地自动加载。但这似乎是不可能的。
猜你喜欢
  • 2015-04-20
  • 1970-01-01
  • 2017-12-10
  • 2014-07-25
  • 1970-01-01
  • 2017-11-20
  • 1970-01-01
  • 2016-01-22
  • 2016-03-22
相关资源
最近更新 更多