Php 为什么在使用psr-4自动加载Composer时指定名称空间?
我对如何在Composer中使用psr-4自动加载有点困惑。假设我有一个这样的文件夹结构:Php 为什么在使用psr-4自动加载Composer时指定名称空间?,php,namespaces,composer-php,autoload,psr-4,Php,Namespaces,Composer Php,Autoload,Psr 4,我对如何在Composer中使用psr-4自动加载有点困惑。假设我有一个这样的文件夹结构: / |- Core/ | - Router.php |- App/ | - Models | User.php |- composer.json <?php namespace Core; class Router { } <?php namespace App\Models; class User { } $router = new Core\Router();
/
|- Core/
| - Router.php
|- App/
| - Models
| User.php
|- composer.json
<?php
namespace Core;
class Router {
}
<?php
namespace App\Models;
class User {
}
$router = new Core\Router();
$user = new App\Models\User();
$router = new \MyApp\Core\Router;
$user = new \MyApp\App\Models\User;
namespace MyApp;
$router = new Core\Router;
$user = new App\Models\User;
基本上,在项目根目录中:composer.json;一个核心文件夹,包含一个路由器php类;一个应用程序文件夹,其中包含一个模型文件夹,该文件夹包含一个用户类
路由器类如下所示:
/
|- Core/
| - Router.php
|- App/
| - Models
| User.php
|- composer.json
<?php
namespace Core;
class Router {
}
<?php
namespace App\Models;
class User {
}
$router = new Core\Router();
$user = new App\Models\User();
$router = new \MyApp\Core\Router;
$user = new \MyApp\App\Models\User;
namespace MyApp;
$router = new Core\Router;
$user = new App\Models\User;
因此,我可以使用这些类而不需要它们(在运行composer dump autoload
之后),如下所示:
/
|- Core/
| - Router.php
|- App/
| - Models
| User.php
|- composer.json
<?php
namespace Core;
class Router {
}
<?php
namespace App\Models;
class User {
}
$router = new Core\Router();
$user = new App\Models\User();
$router = new \MyApp\Core\Router;
$user = new \MyApp\App\Models\User;
namespace MyApp;
$router = new Core\Router;
$user = new App\Models\User;
这样做没有问题
但是,我也可以在composer.json中执行此操作:
{
"autoload": {
"psr-4": {
"Core\\": "Core",
"App\\Models\\": "App/Models"
}
}
}
{
"autoload": {
"psr-4": {
"": ""
}
}
}
根据文档,它是一个回退目录,相对于根,任何名称空间都可以在其中。因此,通过在composer autoloader中设置这个“空”条目,我相信它会说“从根目录开始,在任何目录中查找任何命名空间中的类”,如果遵循正确的文件夹命名/命名空间结构,我可以自动加载我的任何类
所以我的问题是,如果后者有效且简单得多,我为什么要做前者?这是表演吗?或者还有其他原因吗?PSR-4是一种将名称空间转换为物理目录的标准。为什么不总是执行
“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/"
}
"psr-4": {
"\\Vendor\\Template\\Escaping\\Output\\": "src/"
}
您还可以将该类放入src/AnyClass.php
并定义
"psr-4": {
"\\Vendor\\Template\\Escaping\\Output\\": "src/Vendor/Template/Escaping/Output/"
}
"psr-4": {
"\\Vendor\\Template\\Escaping\\Output\\": "src/"
}
这大大缩短了目录路径,略微提高了速度(我想-虽然没有数字),但由于减少了打开空文件夹的次数,主要是改进了开发过程
在同一个包中同时包含核心
命名空间和应用程序
命名空间,这让我怀疑:为什么没有一个包来存放这些命名空间?通常在使用composer时,您自己的项目只有一个文件夹。然后只需要指定一个名称空间
考虑将文件结构重新安排为
/
|- lib/
| - Core/
| - Router.php
| - App/
| - Models
| User.php
|- composer.json
并将composer.json更改为
{
"autoload": {
"psr-4": {
"MyApp\\": "lib/"
}
}
}
然后您只有一个指定的名称空间,不需要再添加任何名称空间。您可以这样调用您的类:
/
|- Core/
| - Router.php
|- App/
| - Models
| User.php
|- composer.json
<?php
namespace Core;
class Router {
}
<?php
namespace App\Models;
class User {
}
$router = new Core\Router();
$user = new App\Models\User();
$router = new \MyApp\Core\Router;
$user = new \MyApp\App\Models\User;
namespace MyApp;
$router = new Core\Router;
$user = new App\Models\User;
或者像这样:
/
|- Core/
| - Router.php
|- App/
| - Models
| User.php
|- composer.json
<?php
namespace Core;
class Router {
}
<?php
namespace App\Models;
class User {
}
$router = new Core\Router();
$user = new App\Models\User();
$router = new \MyApp\Core\Router;
$user = new \MyApp\App\Models\User;
namespace MyApp;
$router = new Core\Router;
$user = new App\Models\User;
我不知道。。。你为什么要这么做?我不会的。为什么你认为你应该这样做?首先,如果有一天你决定将所有模型移到其他地方,使用前一种方法你只需更改一行,使用后一种方法你将需要重命名所有的名称空间。如果你在custom/library/src中有一个自定义包,那么你可能不想使用custom\library\src
,但是只要库
。这一切都可以归结为项目中的约定,而不是apokyrfos提出的观点。@deceze-我会这么做,因为它很有效而且很简单。我想知道是否有我不应该这样做的原因(下面已经回答了)。很好的观点@apokryfos和Devon,谢谢!很好的解释,谢谢。我错误地认为psr-4必须有匹配的文件夹和名称空间。至于核心和应用程序的独立软件包,这一点很好,尽管它们只是我为这个问题选择的示例;-)一个问题:为什么PSR-4既需要名称空间又需要目录,为什么它们不喜欢只使用名称空间?@AmarjeetChaudhary您可以根据自己的喜好定义PSR-4结构的起始目录,但是您必须以某种方式提供目录,否则您怎么知道从哪里开始查找?定义项目的根目录不是明智的默认设置,因为像README
,composer.json
,.gitignore
这样的元数据通常存储在那里。将任何其他目录定义为默认目录也会带来如何商定名称的问题src
似乎是许多项目的常见选择,但并不是每个人都必须这样做。@sven我可能缺少一些基本概念,但根据这个家伙(),我们在composer.json文件中所做的是,将一些php文件路径转储到composer的autoload.php中,为什么我们不能只通过名称空间来识别这些路径?@AmarjeetChaudhary那个家伙在定义自动加载方面和我做的完全一样。然而,他声称“您必须导入名称空间”(部分“如何自动加载PSR-4方式?”字母“e”),这是错误的-您不必,您可以。导入名称空间与自动加载无关,因此Composer不受影响。导入就像告诉PHP“看,我认为有一个类名为Foo\Bar
,我只在这个文件中编写Bar
”,PHP将把你的Bar
扩展到Foo\Bar
——只有当这个类真正使用时,PHP才会触发自动加载。