如何正确使用 composer psr-4 fallback

How to use composer psr-4 fallback correctly

我有一个目录将保留所有 "helper" classes 和函数。让我们调用目录 helpers.

我想配置 PSR-4 回退目录指向这个 helpers 目录:

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

来自 Composer 文档:

... fallback directory where any namespace will be looked for.

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

现在我用 class Logger[= 创建了一个文件 helpers/Logger.php 18=]

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

我试过了

namespace Logger;

并将 class 加载为

$logger = new Logger();

但我收到错误 Class 未找到记录器

深入研究作曲家代码(loadClass() 方法)告诉我它实际上找到并包含了文件 helpers/Logger.php,但由于某种原因仍然找不到 class。

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

namespace Helpers;

而class应该这样称呼:

$logger = new Helpers\Logger();

我有 Class Helpers\Logger 没有找到,但是另外 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;
        }
    }

因此它实际上尝试将文件名与完全限定的 class 名称相匹配。

所以我对 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');

PSR4 区分大小写,因此如果您将 class 放在文件夹 helpers 中并且 class 本身使用命名空间 Helpers,则不会不工作。

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

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

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

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