为什么在使用Composer的psr-4自动加载时指定命名空间?

Dav*_*rth 5 php namespaces autoload composer-php psr-4

我对如何在Composer中使用psr-4自动加载感到困惑.假设我有一个像这样的文件夹结构:

/
|- Core/
|   - Router.php
|- App/
|   - Models
|       User.php
|- composer.json
Run Code Online (Sandbox Code Playgroud)

基本上,在项目根目录中:composer.json ; 包含Router php类的Core文件夹; 一个App文件夹,其中包含一个包含User类的Models文件夹.

Router类看起来像这样:

<?php
namespace Core;

class Router {
}
Run Code Online (Sandbox Code Playgroud)

Users类看起来像这样:

<?php
namespace App\Models;

class User {
}
Run Code Online (Sandbox Code Playgroud)

所以我可以使用Composer psr-4自动加载器自动加载这些类,我可以在composer.json中执行此操作:

{
    "autoload": {
        "psr-4": {
            "Core\\": "Core",
            "App\\Models\\": "App/Models"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我可以使用这些类而不需要它们(运行后composer dump-autoload),如下所示:

$router = new Core\Router();
$user = new App\Models\User();
Run Code Online (Sandbox Code Playgroud)

这没有问题.

但是,我也可以在composer.json中执行此操作:

{
    "autoload": {
        "psr-4": {
            "": ""
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

根据文档是相对于根的任何命名空间的回退目录.因此,通过在作曲家自动加载器中使用这个"空"条目,我相信" 从根开始,在任何目录中查找任何名称空间中的类 ",如果我按照正确的文件夹命名/我可以自动加载任何类命名结构.

所以我的问题是,如果后者有效并且更简单,我为什么要做前者呢?这是表演吗?还是有其他原因吗?

Sve*_*ven 6

你为什么不经常这样做"psr-4": {"": ""}

原因1:性价比高.定义说,对于需要自动加载的每个类,Composer应该查看根目录.这些类不仅是包中的类,还包括所有其他类.

Composer试图通过记住毫无结果的搜索来优化这一努力,但只有在加载具有相同前缀的另一个类时才会付出代价.

原因2:PSR-4的本质是您不必将整个命名空间路径映射到目录路径.假设你有一个处理一组非常特定的类的\Vendor\Template\Escaping\Output\*包,而没有别的东西(有了小包使得在不添加太多代码的情况下更容易重用它们),你可以将它们放入src/Vendor/Template/Escaping/Output/AnyClass.php并定义

"psr-4": {
        "\\Vendor\\Template\\Escaping\\Output\\": "src/Vendor/Template/Escaping/Output/"
}
Run Code Online (Sandbox Code Playgroud)

您还可以将类放入src/AnyClass.php并定义

"psr-4": {
        "\\Vendor\\Template\\Escaping\\Output\\": "src/"
}
Run Code Online (Sandbox Code Playgroud)

这显着缩短了目录路径,略微提高了速度(我认为 - 虽然没有数字),但主要是由于空文件夹打开较少而改进了开发.

在同一个包中同时拥有Core命名空间和App命名空间会让我产生怀疑:为什么每个包都没有一个包?