为什么在 Composer 中使用 psr-4 自动加载时指定命名空间?
Why specify the namespace when using psr-4 autoloading with Composer?
我对应该如何在 Composer 中使用 psr-4 自动加载感到有点困惑。假设我有这样的文件夹结构:
/
|- Core/
| - Router.php
|- App/
| - Models
| User.php
|- composer.json
基本上,在项目根目录中:composer.json;包含 Router php class 的 Core 文件夹; App 文件夹包含 Models 文件夹,后者包含 User class.
路由器 class 看起来像这样:
<?php
namespace Core;
class Router {
}
而用户 class 看起来像这样:
<?php
namespace App\Models;
class User {
}
所以我可以使用 Composer psr-4 自动加载器自动加载这些 classes,我可以在 composer.json:
中执行此操作
{
"autoload": {
"psr-4": {
"Core\": "Core",
"App\Models\": "App/Models"
}
}
}
所以我可以像这样使用 classes 而不需要它们(在 运行 composer dump-autoload
之后):
$router = new Core\Router();
$user = new App\Models\User();
没有问题。
不过,我也可以在composer.json中这样做:
{
"autoload": {
"psr-4": {
"": ""
}
}
}
根据文档,这是一个后备目录,其中可以是任何命名空间,相对于根目录。因此,通过在作曲家自动加载器中添加这个 "empty" 条目,我相信它说“ 从根目录开始,在任何目录中查找任何名称空间 class 中的 ” ,如果我遵循正确的文件夹命名/命名空间结构,我可以自动加载我的任何 classes。
所以我的问题是,如果后者有效且简单得多,我为什么要执行前者?是性能问题吗?还是另有原因?
PSR-4 是一种将命名空间转换为物理目录的标准。
为什么你不应该总是做 "psr-4": {"": ""}
?
理由一:性价比高。定义说对于每个需要自动加载的 class,Composer 应该查看根目录。这些 class 不仅是您包裹中的那些,还有所有其他 class。
Composer 尝试通过记住无结果的搜索来稍微优化这项工作,但这只有在您加载另一个具有相同前缀的 class 时才有效。
原因 2:PSR-4 的本质是您不必将整个命名空间路径映射到目录路径。假设你有一个包处理一组非常具体的 classes,比如 \Vendor\Template\Escaping\Output\*
,没有别的(拥有小包可以更容易地重用它们而无需添加太多代码),你 可以将它们放入src/Vendor/Template/Escaping/Output/AnyClass.php
并定义
"psr-4": {
"\Vendor\Template\Escaping\Output\": "src/Vendor/Template/Escaping/Output/"
}
你也可以把class放到src/AnyClass.php
中定义
"psr-4": {
"\Vendor\Template\Escaping\Output\": "src/"
}
这显着缩短了目录路径,略微提高了速度(我认为 - 虽然没有数字),但由于打开空文件夹的次数减少,主要改进了开发。
在同一个包中同时拥有 Core
命名空间和 App
命名空间让我很怀疑:为什么没有一个包分别对应这些?
通常在使用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;
我对应该如何在 Composer 中使用 psr-4 自动加载感到有点困惑。假设我有这样的文件夹结构:
/
|- Core/
| - Router.php
|- App/
| - Models
| User.php
|- composer.json
基本上,在项目根目录中:composer.json;包含 Router php class 的 Core 文件夹; App 文件夹包含 Models 文件夹,后者包含 User class.
路由器 class 看起来像这样:
<?php
namespace Core;
class Router {
}
而用户 class 看起来像这样:
<?php
namespace App\Models;
class User {
}
所以我可以使用 Composer psr-4 自动加载器自动加载这些 classes,我可以在 composer.json:
中执行此操作{
"autoload": {
"psr-4": {
"Core\": "Core",
"App\Models\": "App/Models"
}
}
}
所以我可以像这样使用 classes 而不需要它们(在 运行 composer dump-autoload
之后):
$router = new Core\Router();
$user = new App\Models\User();
没有问题。
不过,我也可以在composer.json中这样做:
{
"autoload": {
"psr-4": {
"": ""
}
}
}
根据文档,这是一个后备目录,其中可以是任何命名空间,相对于根目录。因此,通过在作曲家自动加载器中添加这个 "empty" 条目,我相信它说“ 从根目录开始,在任何目录中查找任何名称空间 class 中的 ” ,如果我遵循正确的文件夹命名/命名空间结构,我可以自动加载我的任何 classes。
所以我的问题是,如果后者有效且简单得多,我为什么要执行前者?是性能问题吗?还是另有原因?
PSR-4 是一种将命名空间转换为物理目录的标准。
为什么你不应该总是做 "psr-4": {"": ""}
?
理由一:性价比高。定义说对于每个需要自动加载的 class,Composer 应该查看根目录。这些 class 不仅是您包裹中的那些,还有所有其他 class。
Composer 尝试通过记住无结果的搜索来稍微优化这项工作,但这只有在您加载另一个具有相同前缀的 class 时才有效。
原因 2:PSR-4 的本质是您不必将整个命名空间路径映射到目录路径。假设你有一个包处理一组非常具体的 classes,比如 \Vendor\Template\Escaping\Output\*
,没有别的(拥有小包可以更容易地重用它们而无需添加太多代码),你 可以将它们放入src/Vendor/Template/Escaping/Output/AnyClass.php
并定义
"psr-4": {
"\Vendor\Template\Escaping\Output\": "src/Vendor/Template/Escaping/Output/"
}
你也可以把class放到src/AnyClass.php
中定义
"psr-4": {
"\Vendor\Template\Escaping\Output\": "src/"
}
这显着缩短了目录路径,略微提高了速度(我认为 - 虽然没有数字),但由于打开空文件夹的次数减少,主要改进了开发。
在同一个包中同时拥有 Core
命名空间和 App
命名空间让我很怀疑:为什么没有一个包分别对应这些?
通常在使用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;