PSR-0和PSR-4有什么区别?


225

最近,我阅读了有关名称空间及其有益之处的信息。我目前正在Laravel中创建一个项目,并试图从类映射自动加载转到命名空间。但是,我似乎无法理解PSR-0和PSR-4之间的实际区别。

我读过的一些资源是...

我的理解:

  • PSR-4不会将下划线转换为目录分隔符
  • 作曲者的某些特定规则导致目录结构变得复杂,这又使PSR-0命名间隔变得冗长,因此创建了PSR-4

解释差异的示例将是可理解的。


3
读取PSR0PSR4。他们解释了每个细节。
Sverri M. Olsen,2014年


4
☝️有人应该输入这个要点作为答案... :)
deceze

1
IMO,PSR中的大多数部分都是关于他们喜欢的东西,而不是正确的……
Yousha Aleayoub

Answers:


283

它们非常相似,因此有点混乱也就不足为奇了。总结是,对于PSR-4删除的PEAR样式类名,PSR-0具有一些向后兼容功能,因此它仅支持命名空间代码。最重要的是,PSR-4并不强制您将整个名称空间作为目录结构,而仅将锚点后的部分作为目录结构。

例如,如果您定义Acme\Foo\名称空间锚定在src/PSR-0中,则意味着它将Acme\Foo\Barsrc/Acme/Foo/Bar.php其中查找,而在PSR-4中它将在in中查找src/Bar.php,从而允许使用较短的目录结构。在另一方面有些人喜欢有充分的目录结构清楚地看到什么是其中的命名空间,所以你也可以说,Acme\Foo\是在src/Acme/Foo与PSR-4这将让你的PSR-0行为相当于如上所述。

总而言之,对于新项目以及大多数意图和目的而言,您可以使用PSR-4,而不必理会PSR-0。


17
src/Bar.php如果您说,它会选择Acme\Foo\ => src/
Seldaek

非常感谢您的解释!
尤川豪2014年

4
PSR-4比PSR-0慢,不是吗?
Nguyen Linh 2015年

2
@NguyenLinh我不这么认为。它执行相同的操作,但是目录级别可能更少,因此实际上可能会更快一些。测量它。您可以创建一个可以在PSR-0和PSR-4之间切换的程序包-我认为您不会看到任何不同。
2015年

44

这是主要区别,

1.例如,如果您定义Acme\Foo\名称空间锚定在中src/

  • 与PSR-0这意味着它会寻找Acme\Foo\Barsrc/Acme/Foo/Bar.php
  • 而在PSR-4将查找Acme\Foo\Barsrc/Bar.php(where Bar class is)

2. PSR-4不会将下划线转换为目录分隔符

3.您希望将PSR-4与名称空间一起使用

4.即使类名与文件名不同,PSR-0也不起作用,例如考虑以上示例:

  • Acme\Foo\Bar ---> src/Acme/Foo/Bar.php (适用于Bar类)
  • Acme\Foo\Bar ---> src/Acme/Foo/Bar2.php(对于Bar类)将不起作用

1
您当然可以在没有名称空间脚本的情况下使用PSR-4,没有这样的限制,我会使用(不是我的选择)
Galvani

在您的1.(第一点)PSR-4案件中Bar是从哪里来的?
cjmling

31

PSR-4类似于“相对路径”,PSR-0,“绝对路径”。

例如

配置:

'App\Controller' => 'dir/'

PSR-0自动加载:

App\Controller\IndexController --> dir/App/Controller/IndexController.php

PSR-4自动加载:

App\Controller\IndexController --> dir/IndexController.php

PSR-0和PSR-4之间在细节上还有更多差异,请参见此处:http : //www.php-fig.org/psr/psr-4/


10

命名空间/文件夹约定。

类应根据其名称空间存储在文件夹中。

通常,您将在根文件夹中创建与供应商/处于同一级别的src /目录,并在其中添加项目。下面是文件夹结构的示例:

.
+-- src
    |
    +-- Book 
    |   +-- History
    |   |   +-- UnitedStates.php - namespace Book\History;
    +-- Vehicle
    |   +-- Air
    |   |   +-- Wings
    |   |   |   +-- Airplane.php - namespace Vehicle\Air\Wings;
    |   +-- Road
    |   |   +-- Car.php - namespace Vehicle\Road;
+-- tests
    +-- test.php
+-- vendor

PSR-0和PSR-4之间的区别

psr-0

不推荐使用。查看vendor/composer/autoload_namespaces.php文件,您可以看到名称空间及其映射到的目录。

composer.json

"autoload": {
        "psr-0": {
            "Book\\": "src/",
            "Vehicle\\": "src/"
        }
} 
  • src / Book /History/UnitedStates.php中寻找Book \ History \ UnitedStates
  • src / Vehicle /Air/Wings/Airplane.php中寻找Vehicle \ Air \ Wings \ Airplane

psr-4

查看vendor/composer/autoload_psr4.php文件,您可以看到名称空间及其映射到的目录。

composer.json

"autoload": {
    "psr-4": {
        "Book\\": "src/",
        "Vehicle\\": "src/"
    }
}   
  • 寻找图书 \历史\在UnitedStates的SRC /History/UnitedStates.php
  • src /Air/Wings/Airplane.php中寻找Vehicle \ Air \ Wings \ Airplane

composer.json

"autoload": {
    "psr-4": {
        "Book\\": "src/Book/",
        "Vehicle\\": "src/Vehicle/"
    }
}    
  • 寻找Book \ History \ UnitedStates src / Book /History/UnitedStates.php
  • src / Vehicle /Air/Wings/Airplane.php中寻找Vehicle \ Air \ Wings \ Airplane

-4

即使我尝试过,但Composer还是一团糟。可悲的是,它是市场上唯一的选择。
为什么一团糟?
如果您控制代码,则Composer的自动完成功能可以正常工作。但是,如果要导入其他项目,则会发现自己有很多样式和创建文件夹的方式。例如,某些项目是/company/src/class.php,而其他项目是company / class.php,而其他项目是company / src / class / class.php

我创建了一个库来解决它:

https://github.com/EFTEC/AutoLoadOne(麻省理工学院免费)。

它通过扫描文件夹的所有类来生成自动包含,因此在每种情况下都可以使用(psr-0 psr-4,不带名称空间的类,具有多个类的文件。)

编辑:再次,无缘无故投票。;-)


在composer.json中阅读有关classmap选项的信息。getcomposer.org/doc/04-schema.md#classmap-可能是您否决答案的原因。
Patrick
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.