我对如何在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": {
"": ""
}
}
}
根据文档是一个回退目录,其中任何命名空间可以相对于根。因此,通过在作曲家自动加载器中使用这个“空”条目,我相信“从根开始,在任何目录中查找任何名称空间中的类”,我可以自动加载我的任何类,如果我遵循正确的文件夹命名/命名空间结构。
所以我的问题是,如果后者有效并且更简单,我为什么要做前者呢?这是表演吗?或者还有其他原因吗?
答案 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是一种将名称空间转换为物理目录的标准。