What Are the Differences Between PSR-0 and PSR-4?
Asked Answered
A

5

269

Recently I've read about namespaces and how they are beneficial. I'm currently creating a project in Laravel and trying to move from class map autoloading to namespacing. However, I can't seem to grasp what the actual difference is between PSR-0 and PSR-4.

Some resources that I've read are...

What I understand:

  • PSR-4 does not convert underscores to directory separators
  • Certain specific rules of composer cause the directory structure to become complex which in turn makes PSR-0 namespacing verbose and thus PSR-4 was created

Examples explaining the difference would be appreciated.

Araiza answered 21/7, 2014 at 15:12 Comment(4)
Read PSR0 and PSR4. They explain every single detail.Eldreda
sitepoint.com/battle-autoloaders-psr-0-vs-psr-4Legionary
☝️ Somebody should type up the gist of this as an answer... :)Legionary
IMO, most parts in PSR is about what they LIKE not what is RIGHT...Radioelement
B
318

They are very similar so it is not surprising that it's a bit confusing. The summary is that PSR-0 had some backwards compatibility features for PEAR-style classnames that PSR-4 dropped, as such it only supports namespaced code. On top of that PSR-4 does not force you to have the whole namespace as a directory structure, but only the part following the anchor point.

For example if you define that the Acme\Foo\ namespace is anchored in src/, with PSR-0 it means it will look for Acme\Foo\Bar in src/Acme/Foo/Bar.php while in PSR-4 it will look for it in src/Bar.php, allowing for shorter directory structures. On the other hand some prefer to have the full directory structure to clearly see what is in which namespace, so you can also say that Acme\Foo\ is in src/Acme/Foo with PSR-4 which will gives you the equivalent of the PSR-0 behavior described above.

Long story short for new projects and for most intents and purposes, you can use PSR-4 and forget all about PSR-0.

Biogenesis answered 21/7, 2014 at 16:7 Comment(3)
It picks src/Bar.php if you say Acme\Foo\ => src/Biogenesis
PSR-4 is slower than PSR-0, isn't it?Radloff
@NguyenLinh I don't think so. It does the same thing, but possibly with fewer levels of directories, so it might actually be a bit faster. Measure it. You can create a package that you can switch between PSR-0 and PSR-4 - I don't think you will see a difference.Raybin
A
57

Here are the major differences,

1. For example if you define that the Acme\Foo\ namespace is anchored in src/,

  • with PSR-0 it means it will look for Acme\Foo\Bar in src/Acme/Foo/Bar.php
  • while in PSR-4 it will look for Acme\Foo\Bar in src/Bar.php(where Bar class is).

2. PSR-4 does not convert underscores to directory separators

3. You would prefer using PSR-4 with namespaces

4. PSR-0 will not work even if the class name is different from file name, like considering above example:

  • Acme\Foo\Bar ---> src/Acme/Foo/Bar.php (for Bar class) will work
  • Acme\Foo\Bar ---> src/Acme/Foo/Bar2.php (for Bar class) will not work
Ajaajaccio answered 23/1, 2016 at 8:34 Comment(2)
You certainly can use PSR-4 along with no namespace scripts, there is no such a restriction and I do use it (not my choice)Downs
In your 1. (first point) where did Bar come from for PSR-4 case?Caracaraballo
C
42

PSR-4 is something like 'relative path', PSR-0, 'absolute path'.

e.g.

config:

'App\Controller' => 'dir/'

PSR-0 autoload:

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

PSR-4 autoload:

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

And there are some more difference in details between PSR-0 and PSR-4, see here: http://www.php-fig.org/psr/psr-4/

Cynthia answered 13/12, 2016 at 3:8 Comment(0)
S
34

Namespace/ folder convention.

Classes should be stored in folders according to their namespaces.

In general, you will create an src/ directory in your root folder, sitting at the same level as vendor/, and add your projects there. Below is an example of the folder structure:

.
+-- 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

Difference between psr-0 and psr-4

psr-0

It is deprecated. Looking at vendor/composer/autoload_namespaces.php file you can see the namespaces and the directories that they are mapped to.

composer.json

"autoload": {
        "psr-0": {
            "Book\\": "src/",
            "Vehicle\\": "src/"
        }
} 
  • Looking for Book\History\UnitedStates in src/Book/History/UnitedStates.php
  • Looking for Vehicle\Air\Wings\Airplane in src/Vehicle/Air/Wings/Airplane.php

psr-4

Looking at vendor/composer/autoload_psr4.php file you can see the namespaces and the directories that they are mapped to.

composer.json

"autoload": {
    "psr-4": {
        "Book\\": "src/",
        "Vehicle\\": "src/"
    }
}   
  • Looking for Book\History\UnitedStates in src/History/UnitedStates.php
  • Looking for Vehicle\Air\Wings\Airplane in src/Air/Wings/Airplane.php

composer.json

"autoload": {
    "psr-4": {
        "Book\\": "src/Book/",
        "Vehicle\\": "src/Vehicle/"
    }
}    
  • Looking for Book\History\UnitedStates src/Book/History/UnitedStates.php
  • Looking for Vehicle\Air\Wings\Airplane in src/Vehicle/Air/Wings/Airplane.php
Springwood answered 8/5, 2018 at 5:10 Comment(1)
Struggled with this for some time until this post. Thank you so much for including concise examples!Chickpea
C
-7

Even when I tried but Composer is a mess. Sadly, it's the only alternative.of the market.
Why is a mess?.
The Composer's autocomplete works fine if you are in control of the code. However, if you are importing a different project, you find yourself with lots of styles and ways to create folders. For example, some projects are /company/src/class.php while others are company/class.php and others are company/src/class/class.php

I created a library that solves it:

https://github.com/EFTEC/AutoLoadOne (it's free, MIT).

It generates an autoinclude by scanning all the classes of a folder, so it works in every case (psr-0 psr-4, classes without namespace, file with multiple classes..

edit: And again, downvoted without any reason. ;-)

Compensable answered 25/6, 2018 at 2:36 Comment(2)
Read up about the classmap option in composer.json. getcomposer.org/doc/04-schema.md#classmap - might be the reason for downvoting your answer.Rarefied
@Rarefied I looked at his library. It's an interesting approach. I mean, for me it's too much just to avoid composer's classmaps, but it's ok.Villar

© 2022 - 2024 — McMap. All rights reserved.