Standard PSR-4

Celem ujednolicenia nazewnictwa stosowanego w bibliotekach wprowadzono standard PSR-4 (PSR oznacza PHP Standards Recommendation).

Standard PSR-4 określa zalecaną strukturę kodu, którą musi stosować aplikacja lub biblioteka, aby zagwarantować poprawne działanie autoloadera. Podstawowym wymaganiem jest definicja przestrzeni nazw zgodnie ze schematem:

\<Vendor Name>\( <Namespace> )*\<Class Name>

  • Obszary nazw mogą mieć tyle poziomów zagnieżdżenia, ile potrzeba, ale Nazwa dostawcy (Vendor Name) powinna być przestrzenią nazw najwyższego poziomu.
  • Przestrzenie nazw powinny być odwzorowane na strukturę katalogów. Każdy ukośnik w definicji przestrzeni nazw (\) jest w procesie ładowania plików konwertowany na stałą systemową DIRECTORY_SEPARATOR specyficzną dla systemu operacyjnego.
  • Uzyskana w powyższy sposób nazwa jest uzupełniana rozszerzeniem .php aby uzyskać nazwę pliku w którym zdefiniowano klasę..

Na przykład dla klasy Dostawca\Biblioteka\Klasa należy stworzyć następującą strukturę katalogów:

  /Dostawca
    /Biblioteka
       Klasa.php

Ten sposób przekładania przestrzeni nazw na nazwę pliku został wprowadzony w standardzoe PSR-0. nazw plików Co jednak zrobić, jeśli chcemy na rzykład aby w katalogu /Dostawca/Biblioteka pojawił się podkatalog src, a w nim dopiero moduły? To właśnie definiuje standard PSR-4. Wprowadza on powiązania prefiksu ścieżki z nazwą (przestrzenią nazw).

Na przykład tak (fragment pliku composer.json):

    "autoload": {
        "psr-4": {
            "Application\\": "module/Application/src/"
        }
    },

Teraz autoloader będzie wiedział, że definicję klasy \Application\Module znajdzie w pliku module/Application/src/Module.php.

Przykład autoloadera dla projektu Zend Framework (bez mapy klas tworzonej przez Composera)

<?php

// "Standard" autoloader function.
function standardAutoloadFunc($className)
{
    // Replace the namespace prefix with base directory.
    $prefix = '\\Zend\\Mvc';
    $baseDir = '/path/to/zendframework/zend-mvc/src/';
    if (substr($className, 0, strlen($prefix)) == $prefix) {
        $className = substr($className, strlen($prefix)+1);
        $className = $baseDir . $className;
    }

    // Replace namespace separators in class name with directory separators.
    $className = str_replace('\\', DIRECTORY_SEPARATOR, $className);

    // Add the .php extension.
    $fileName = $className . ".php";

    // Check if file exists and is readable.
    if (is_readable($fileName)) {
        // Include the file.
        require $fileName;
    }
}

// Register the autoloader function.
spl_autoload_register("standardAutoloadFunc");

Ten autoloader sprawdza po kolei podkatalogi w poszukiwaniu miejsca położenia modułu. Jest to oczywiście rozwiązanie wolniejsze niż niż autoloader z mapą klas. Jednak w trakcie opracowywania nowego kodu dla aplikacji może to być wygodniejsze.