Korzystając z composera co chwilę natrafiamy na PSR-0 lub PSR-4. Niektórzy kojarzą nawet, że chodzi o standardy autoloadera w PHP. Oba stnadardy mówią gdzie i jak szukać plików z klasami. Ale na czym to dokładnie polegają i czym się różnią?
PSR-0 czyli proste znajdywanie plików
PSR-0 to standard pozwalający w prosty sposób przekładać nazwę klasy na ścieżkę do plików. Jeśli mamy jedną ścieżkę do naszych klas, to przyjmujemy standardowe nazwenictwo:
\Twórca\Przestrzenie_Nazw\Nazwa_Klasy
Sprawa jest prosta. Wszystkie znaki \ (backslash) zamieniamy na kolejne podkatalogi. Znak _ (podkreślenie) też, ale tylko ten w nazwie klasy Przestrzeni nazw może być kilka. Na końcu dodajemy rozszerzenie „.php” i gotowe. W ten sposób nasz powyższy przykład zamienia się w:
<ścieżka_do_projektu>/Twórca/Przestrzenie_Nazw/Nazwa/Klasy.php
Proste i efektywne. Łatwo zrozumieć i zaimplementować. Działa również w PHP5.2, gdzie za przestrzenie nazw służyły nam podkreślenia.
Wady PSR-0
Prostota PSR-0 stała się jednak ograniczeniem. Instalując moduły przez composera wrzucamy je wszystkie do jednego katalogu vendor – to nasza ścieżka do projektu. Dalej mieliśmy podkatalogi twórców, przestrzenie nazw oznaczające projekty, moduły aż w końcu klasy.
Wszystko to działałoby gdyby na świecie istniały jedynie klasy PHP. Ale publikując paczkę dodajemy do niej dokumentację, przykłady, testy jednostkowe, style, grafiki… dużo różnych dodatków. Gdzie je zmieścić?
Nasza paczka może mieć podkatalogi np. doc, examples, license, css, js, img i wreszcie src na kod PHP. Ale wtedy musimy podkatalog src umieścić w nazwie klasy. Mielibyśmy np. klasę:
\Adam\ProjektPierwszy\src\ModułPierwszy\Klasa
Aby temu zaradzić, możemy przyjąć że ścieżka do projektu prowadzi od razu do podkatalogu src w naszej paczce. Wtedy trzymając się standardu skończymy z powtarzaniem nazw producenta i modułu w podkatalogach. Np. jeśli wgraliśy paczkę do katalogu:
/vendor/Adam/ProjektPierwszy/src/
… i ten katalog ustawimy jako ścieżkę do projektu to musimy utworzyć w nim podkatalogi z nazwą dostawcy i nazwą co najmniej jednej przestrzeni nazw bo PSR-0 tego wymaga. Skończymy z bardzo długą ścieżką do klasy:
/vendor/Adam/ProjektPierwszy/src/Adam/ProjektPierwszy/ModułPierwszy/Klasa
Gorzej! PSR-0 nakazuje nam zawsze trzymać pliki w tym samym katalogu. Nie możemy korzystać z kolejki automatycznych dołączeń (spl_autoload_register())
PSR-4 rozwiązuje problem
W nowszym standardzie plik może być w kilku lokalizacjach. Korzystamy też z kolejki autoloaderów.
Nazwy klas zapisujemy identycznie jak w PSR-0 ale znak podkreślenia nie ma już specjalnego znaczenia. Zrywamy więc z kompatybilnością z PHP 5.2 i starszymi.
Najważniejsza zmiana to sposób traktowania ścieżki do projektu. Tym razem zamiast jednej możemy mieć wiele ścieżek, każda zdefiniowana dla jakiegoś prefiksu nazwy klasy. Np.
\Adam\ProjektPierwszy => /vendor/Adam/ProjektA/src/php \Adam\ProjektDrugi => /vendor/Adam/ProjektB/classes/
Co więcej, możemy przypisać kilka ścieżek do jednego prefiksu:
\Adam\ModułPierwszy => /vendor/Adam/ProjektA/src/php \Adam\ModulPierwszy => /vendor/Adam/PoprawkiDoProjektuA/php/classes
Autoloader gdy już dopasuje prefiks nazwy do jakiejś ścieżki traktuje resztę nazwy w klasyczny sposób – rozbija na podkatalogi i szuka pliku php.
Tym razem jednak autoloader może nie znaleźć pliku za pierwszym razem. Dopiero, gdy przeszuka wszystkie ścieżki dla naszego prefiksu może zgłosić niepowodzenie.
W powyższym przykładzie, jeśli będziemy szukać klasy o nazwie:
\Adam\ModułPierwszy\SubModul\Klasa
to autoloader będzie spodziewał się, że znajdzie plik Klasa.php w jednej z dwóch lokalizacji:
/vendor/Adam/ProjektA/src/php/SubModul/Klasa.php /vendor/Adam/PoprawkiDoProjektuA/php/classes/SubModul/Klasa.php
Kilka dodatkowych warunków w PSR-4 mówi o tym, że wielkość liter w nazwach klas jest rozróżniana (inaczej niż w PSR-0) oraz, że dla każdej klasy musi być zdefiniowany jakiś katalog pasujący do jej prefiksu.
Świetny artykuł, wreszcie zrozumiałem to co chciałem zrozumieć.
Motyla noga nie zrozumiałem tego co chciałem zrozumieć, nie da się jakoś prościej tego wyjaśnić?
Prościej nie umiem, starałem się jak mogłem. Przyjrzyj się dokładnie ścieżkom, które podałem w przykładach.