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

时间:2016-03-22 15:43:52

标签: php namespaces composer-php autoload psr-4

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

/
|- Core/
|   - Router.php
|- App/
|   - Models
|       User.php
|- composer.json

基本上,在项目根目录中: composer.json ;包含路由器 php类的核心文件夹;一个 App 文件夹,其中包含模型文件夹,其中包含用户类。

Router类看起来像这样:

<?php
namespace Core;

class Router {
}

并且Users类看起来像这样:

<?php
namespace App\Models;

class User {
}

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

{
    "autoload": {
        "psr-4": {
            "Core\\": "Core",
            "App\\Models\\": "App/Models"
        }
    }
}

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

$router = new Core\Router();
$user = new App\Models\User();

没有任何问题。

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

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

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

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

3 个答案:

答案 0 :(得分:6)

为什么不能总是"psr-4": {"": ""}

原因1:性价比高。定义说,对于需要自动加载的每个类,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/"
}

您还可以将课程设为src/AnyClass.php并定义

"psr-4": {
        "\\Vendor\\Template\\Escaping\\Output\\": "src/"
}

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

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

答案 1 :(得分:2)

通常,在使用composer时,您只有一个用于自己项目的文件夹。然后你只需要指定一个命名空间。

请考虑将文件结构重新排列为

/
|- lib/
|   - Core/
|      - Router.php
|   - App/
|      - Models
|          User.php
|- composer.json

并将您的composer.json更改为

{
    "autoload": {
        "psr-4": {
            "MyApp\\": "lib/"
        }
    }
}

然后你只有一个指定的命名空间,你不需要添加任何进一步的命名空间。你可以像这样打电话给你的课程:

$router = new \MyApp\Core\Router;
$user   = new \MyApp\App\Models\User;

或者像这样:

namespace MyApp;
$router = new Core\Router;
$user   = new App\Models\User;

答案 2 :(得分:-4)

PSR-4是一种将名称空间转换为物理目录的标准。