Lekcja 30 (OOP 10): Przestrzenie Nazw (Namespaces) i Autoloading (PSR-4)

Witaj w dziesiątej i ostatniej lekcji naszego modułu o Programowaniu Obiektowym i pracy z bazami danych w PHP! W poprzedniej lekcji nauczyliśmy się, jak Cechy (Traits) pozwalają na horyzontalne współdzielenie funkcjonalności między klasami. Dzisiaj zajmiemy się kluczowymi aspektami organizacji kodu w większych projektach PHP: Przestrzeniami Nazw (Namespaces) oraz Automatycznym Ładowaniem Klas (Autoloading), ze szczególnym uwzględnieniem standardu PSR-4.

W miarę rozrastania się aplikacji, liczba klas, interfejsów, cech i funkcji może stać się bardzo duża. Może to prowadzić do konfliktów nazw (dwie różne klasy o tej samej nazwie) oraz do problemów z zarządzaniem zależnościami i dołączaniem plików (require/include). Przestrzenie nazw pomagają rozwiązać problem konfliktów nazw, grupując kod w logiczne hierarchie. Autoloading natomiast automatyzuje proces dołączania plików z definicjami klas, gdy są one po raz pierwszy potrzebne, co znacznie upraszcza zarządzanie projektem i poprawia jego wydajność.

Czym Są Przestrzenie Nazw (Namespaces)?

Przestrzeń nazw (Namespace) w PHP to mechanizm pozwalający na enkapsulację (grupowanie) elementów kodu, takich jak klasy, interfejsy, cechy, funkcje i stałe, pod unikalną nazwą. Działa to podobnie do folderów w systemie plików – tak jak możesz mieć plik readme.txt w wielu różnych folderach, tak możesz mieć klasę User w wielu różnych przestrzeniach nazw.

Główne cele i korzyści z używania przestrzeni nazw:

Definiowanie Przestrzeni Nazw

Przestrzeń nazw deklaruje się na samym początku pliku PHP (przed jakimkolwiek innym kodem, z wyjątkiem opcjonalnej deklaracji declare(strict_types=1);) za pomocą słowa kluczowego namespace.

<?php
// Plik: src/MojaAplikacja/LogikaBiznesowa/Uzytkownik.php

declare(strict_types=1); // Opcjonalne, ale zalecane

namespace MojaAplikacja\LogikaBiznesowa;

class Uzytkownik
{
    public string $nazwa;

    public function __construct(string $nazwa)
    {
        $this->nazwa = $nazwa;
        echo "Utworzono Uzytkownik z przestrzeni MojaAplikacja\LogikaBiznesowa: " . $this->nazwa . "<br>";
    }
}

function pomocniczaFunkcja(): void
{
    echo "To jest pomocnicza funkcja z przestrzeni MojaAplikacja\LogikaBiznesowa<br>";
}

const WERSJA_MODULU = "1.0";

// Kod poniżej tej deklaracji należy do przestrzeni MojaAplikacja\LogikaBiznesowa
?>

Nazwy przestrzeni nazw są hierarchiczne i używają odwrotnego ukośnika (\) jako separatora (podobnie jak w systemach Windows, ale jest to standard w PHP dla namespaces). Konwencją jest używanie nazw w stylu StudlyCaps (CamelCase z wielką literą na początku) dla każdego segmentu przestrzeni nazw.

Jeśli w pliku nie zadeklarowano żadnej przestrzeni nazw, kod należy do globalnej przestrzeni nazw.

Używanie Klas z Przestrzeni Nazw

Aby użyć klasy (lub innego elementu) zdefiniowanej w przestrzeni nazw, musimy odwołać się do niej za pomocą jej pełnej kwalifikowanej nazwy (Fully Qualified Name - FQN), która zawiera całą ścieżkę przestrzeni nazw.

<?php
// Plik: public/index.php (lub inny plik używający klasy Uzytkownik)

require_once __DIR__ . 
'/../src/MojaAplikacja/LogikaBiznesowa/Uzytkownik.php
'; // Na razie ręczne dołączanie

// Użycie pełnej kwalifikowanej nazwy
$user1 = new \MojaAplikacja\LogikaBiznesowa\Uzytkownik("Ania");

\MojaAplikacja\LogikaBiznesowa\pomocniczaFunkcja();
echo "Wersja modułu: " . \MojaAplikacja\LogikaBiznesowa\WERSJA_MODULU . "<br>";

// Jeśli jesteśmy w globalnej przestrzeni nazw, początkowy \ jest opcjonalny dla FQN,
// ale jest dobrą praktyką, aby go używać dla jasności.
?>

Importowanie i Aliasowanie (use)

Ciągłe używanie pełnych kwalifikowanych nazw może być uciążliwe. PHP pozwala na importowanie klas, interfejsów, cech, funkcji (od PHP 5.6) i stałych (od PHP 5.6) z innych przestrzeni nazw za pomocą słowa kluczowego use. Można również nadać im aliasy.

<?php
// Plik: src/MojaAplikacja/Kontrolery/PanelUzytkownikaKontroler.php

namespace MojaAplikacja\Kontrolery;

// Importowanie klasy Uzytkownik
use MojaAplikacja\LogikaBiznesowa\Uzytkownik;

// Importowanie i aliasowanie klasy Uzytkownik
use MojaAplikacja\LogikaBiznesowa\Uzytkownik as KlientBiznesowy;

// Importowanie funkcji (od PHP 5.6)
use function MojaAplikacja\LogikaBiznesowa\pomocniczaFunkcja;

// Importowanie funkcji i aliasowanie (od PHP 5.6)
use function MojaAplikacja\LogikaBiznesowa\pomocniczaFunkcja as wykonajPomocniczeZadanie;

// Importowanie stałej (od PHP 5.6)
use const MojaAplikacja\LogikaBiznesowa\WERSJA_MODULU;

// Importowanie stałej i aliasowanie (od PHP 5.6)
use const MojaAplikacja\LogikaBiznesowa\WERSJA_MODULU as MODUL_LOGIKI_WERSJA;

class PanelUzytkownikaKontroler
{
    public function pokazPanel(): void
    {
        $user = new Uzytkownik("Kasia"); // Używamy zaimportowanej nazwy
        echo "Kontroler używa: " . $user->nazwa . "<br>";

        $klient = new KlientBiznesowy("Zosia"); // Używamy aliasu
        echo "Kontroler używa klienta (alias): " . $klient->nazwa . "<br>";

        pomocniczaFunkcja(); // Wywołanie zaimportowanej funkcji
        wykonajPomocniczeZadanie(); // Wywołanie zaimportowanej funkcji pod aliasem

        echo "Wersja modułu logiki (zaimportowana stała): " . WERSJA_MODULU . "<br>";
        echo "Wersja modułu logiki (alias stałej): " . MODUL_LOGIKI_WERSJA . "<br>";
    }
}

// Aby to zadziałało, plik Uzytkownik.php musi być dostępny (np. przez autoloader)
// require_once __DIR__ . 
'/../LogikaBiznesowa/Uzytkownik.php
'; // Symulacja dla przykładu

$kontroler = new PanelUzytkownikaKontroler();
$kontroler->pokazPanel();
?>

Deklaracje use umieszcza się zazwyczaj na początku pliku, po deklaracji namespace (jeśli istnieje), a przed definicjami klas/interfejsów/itp.

Ważne: use importuje tylko nazwę, a nie samą klasę. Plik z definicją klasy nadal musi być załadowany (np. przez autoloader lub ręczne require).

Podprzestrzenie Nazw (Sub-namespaces)

Przestrzenie nazw mogą być zagnieżdżane, tworząc hierarchię, np. MojaFirma\Projekt\Modul\Komponent. Każdy segment oddzielony \ to kolejny poziom w hierarchii.

Automatyczne Ładowanie Klas (Autoloading)

W małych projektach można ręcznie dołączać pliki z definicjami klas za pomocą require_once. Jednak w dużych aplikacjach staje się to niepraktyczne i podatne na błędy. Autoloading to mechanizm, który automatycznie ładuje plik z definicją klasy (lub interfejsu/cechy), gdy jest ona po raz pierwszy używana w kodzie.

PHP dostarcza funkcję spl_autoload_register(), która pozwala zarejestrować jedną lub więcej funkcji (autoloaderów). Gdy kod próbuje użyć nieznanej klasy, PHP wywołuje po kolei zarejestrowane autoloadery, przekazując im nazwę tej klasy. Zadaniem autoloadera jest znalezienie i dołączenie pliku zawierającego definicję tej klasy.

<?php
// Plik: autoload_przyklad.php

spl_autoload_register(function (string $nazwaKlasy) {
    echo "Próba załadowania klasy: {$nazwaKlasy}<br>";
    // Prosta logika: zamień \ na / i dodaj .php
    // Przykład: MojaAplikacja\Logika\Uzytkownik -> MojaAplikacja/Logika/Uzytkownik.php
    $sciezkaDoPliku = __DIR__ . 
'/src/
' . str_replace("\\", "/", $nazwaKlasy) . ".php";

    if (file_exists($sciezkaDoPliku)) {
        echo "Znaleziono plik: {$sciezkaDoPliku}, dołączam...<br>";
        require_once $sciezkaDoPliku;
    } else {
        echo "Nie znaleziono pliku dla klasy: {$nazwaKlasy} w {$sciezkaDoPliku}<br>";
    }
});

// Załóżmy, że mamy pliki:
// src/MojaAplikacja/Logika/Uzytkownik.php (z klasą Uzytkownik w namespace MojaAplikacja\Logika)
// src/MojaAplikacja/Narzedzia/Logger.php (z klasą Logger w namespace MojaAplikacja\Narzedzia)

// Symulacja istnienia tych plików dla przykładu (normalnie byłyby to osobne pliki)
// if (!class_exists("MojaAplikacja\Logika\Uzytkownik")) { /* ... definicja ... */ }

// Użycie klas spowoduje wywołanie autoloadera
// (Zakładając, że pliki src/MojaAplikacja/Logika/Uzytkownik.php i src/MojaAplikacja/Narzedzia/Logger.php istnieją
// i zawierają odpowiednie klasy w odpowiednich przestrzeniach nazw)

// Dla tego przykładu, stwórzmy tymczasowe pliki:
$srcDir = __DIR__ . 
'/src
';
if (!is_dir($srcDir)) mkdir($srcDir, 0777, true);
if (!is_dir($srcDir . 
'/MojaAplikacja/Logika
')) mkdir($srcDir . 
'/MojaAplikacja/Logika
', 0777, true);
if (!is_dir($srcDir . 
'/MojaAplikacja/Narzedzia
')) mkdir($srcDir . 
'/MojaAplikacja/Narzedzia
', 0777, true);

file_put_contents($srcDir . 
'/MojaAplikacja/Logika/Uzytkownik.php
', "<?php namespace MojaAplikacja\\Logika; class Uzytkownik { public function __construct() { echo 'Uzytkownik z Logika załadowany<br>'; } } ?>");
file_put_contents($srcDir . 
'/MojaAplikacja/Narzedzia/Logger.php
', "<?php namespace MojaAplikacja\\Narzedzia; class Logger { public function __construct() { echo 'Logger z Narzedzia załadowany<br>'; } } ?>");


echo "Przed użyciem klas...<br>";
$user = new \MojaAplikacja\Logika\Uzytkownik();
$logger = new \MojaAplikacja\Narzedzia\Logger();
echo "Po użyciu klas.<br>";

// Cleanup tymczasowych plików (dla przykładu)
// unlink($srcDir . 
'/MojaAplikacja/Logika/Uzytkownik.php
');
// unlink($srcDir . 
'/MojaAplikacja/Narzedzia/Logger.php
');
// rmdir($srcDir . 
'/MojaAplikacja/Logika
');
// rmdir($srcDir . 
'/MojaAplikacja/Narzedzia
');
// rmdir($srcDir . 
'/MojaAplikacja
');
// rmdir($srcDir);

/*
Przykładowy wynik:
Przed użyciem klas...
Próba załadowania klasy: MojaAplikacja\Logika\Uzytkownik
Znaleziono plik: /path/to/script/src/MojaAplikacja/Logika/Uzytkownik.php, dołączam...
Uzytkownik z Logika załadowany
Próba załadowania klasy: MojaAplikacja\Narzedzia\Logger
Znaleziono plik: /path/to/script/src/MojaAplikacja/Narzedzia/Logger.php, dołączam...
Logger z Narzedzia załadowany
Po użyciu klas.
*/
?>

Standard PSR-4 Autoloader

Aby zapewnić interoperacyjność między różnymi bibliotekami i frameworkami PHP, grupa PHP-FIG (PHP Framework Interoperability Group) opracowała standardy rekomendacji (PSR - PHP Standard Recommendation). PSR-4 to standard opisujący, jak autoloadery powinny mapować przestrzenie nazw na ścieżki w systemie plików.

Główne zasady PSR-4:

  1. Pełna kwalifikowana nazwa klasy (FQN) ma postać: \<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>.
  2. Podczas ładowania pliku dla FQN, autoloader mapuje prefix przestrzeni nazw na katalog bazowy w systemie plików.
  3. Część FQN następująca po prefixie przestrzeni nazw (czyli sub-przestrzenie nazw i nazwa klasy) jest mapowana na ścieżkę pliku wewnątrz katalogu bazowego. Separatory \ w przestrzeni nazw są zamieniane na separatory katalogów (DIRECTORY_SEPARATOR).
  4. Nazwa pliku musi odpowiadać nazwie klasy (z uwzględnieniem wielkości liter) i mieć rozszerzenie .php.

Przykład mapowania PSR-4:

Załóżmy, że mamy następujące mapowanie w naszym autoloaderze:

Wtedy:

Jeśli mamy inny prefix, np.:

To klasa \Acme\Log\Writer\File będzie szukana w /var/www/projekt/vendor/acme/log/src/Writer/File.php.

Composer i Autoloading PSR-4

Najpopularniejszym narzędziem do zarządzania zależnościami w PHP jest Composer. Composer automatycznie generuje autoloader zgodny z PSR-4 (oraz innymi standardami jak PSR-0, classmap, files) na podstawie konfiguracji w pliku composer.json.

Przykład fragmentu composer.json definiującego autoloading PSR-4 dla projektu:

{
    "name": "mojafirma/moj-projekt",
    "description": "Opis mojego projektu.",
    "autoload": {
        "psr-4": {
            "MojaAplikacja\\": "src/",
            "MojaFirma\\Testy\\": "tests/"
        }
    },
    "require": {
        "php": ">=8.1"
        // ... inne zależności
    }
}

W tym przykładzie:

Po zdefiniowaniu tego w composer.json i uruchomieniu composer install lub composer dump-autoload, Composer wygeneruje plik vendor/autoload.php. Wystarczy wtedy dołączyć ten jeden plik na początku aplikacji, aby uzyskać w pełni funkcjonalny autoloader dla wszystkich zdefiniowanych przestrzeni nazw oraz zależności.

<?php
// Plik: public/index.php (główny punkt wejścia aplikacji)

// Dołącz autoloader wygenerowany przez Composera
require_once __DIR__ . 
'/../vendor/autoload.php
';

// Teraz możesz używać klas z przestrzeni MojaAplikacja\ bez ręcznego require
use MojaAplikacja\Kontrolery\DomowyKontroler;
use MojaAplikacja\Logika\UslugaUzytkownika;

$kontroler = new DomowyKontroler();
$usluga = new UslugaUzytkownika();

// ... reszta logiki aplikacji
?>

Używanie Composera i jego autoloadera jest standardem w nowoczesnym programowaniu PHP i znacznie upraszcza zarządzanie dużymi projektami oraz zależnościami od zewnętrznych bibliotek.

Podsumowanie Lekcji

W tej obszernej lekcji nauczyliśmy się, jak kluczowe dla organizacji kodu w PHP są Przestrzenie Nazw (Namespaces) i Automatyczne Ładowanie Klas (Autoloading). Zrozumieliśmy, że przestrzenie nazw pozwalają unikać konfliktów nazw i grupować kod w logiczne hierarchie, co jest niezbędne w większych projektach i przy korzystaniu z zewnętrznych bibliotek. Nauczyliśmy się definiować przestrzenie nazw, używać klas z nich za pomocą pełnych kwalifikowanych nazw oraz importować je i aliasować za pomocą instrukcji use.

Następnie zgłębiliśmy mechanizm autoloadingu, który automatyzuje proces dołączania plików z definicjami klas. Poznaliśmy funkcję spl_autoload_register() i zobaczyliśmy, jak stworzyć prosty autoloader. Skupiliśmy się na standardzie PSR-4, który definiuje sposób mapowania przestrzeni nazw na strukturę katalogów, co jest fundamentem interoperacyjności w ekosystemie PHP. Na koniec dowiedzieliśmy się, jak Composer, popularny menedżer zależności, automatyzuje generowanie autoloadera zgodnego z PSR-4 na podstawie konfiguracji w pliku composer.json, co jest standardową praktyką w nowoczesnych aplikacjach PHP.

To była ostatnia lekcja w tym module. Gratulacje! Zdobyliście solidne podstawy Programowania Obiektowego w PHP, włączając w to klasy, obiekty, dziedziczenie, polimorfizm, interfejsy, cechy, a także kluczowe aspekty organizacji kodu jak przestrzenie nazw i autoloading. Ta wiedza stanowi fundament do tworzenia złożonych, dobrze zorganizowanych i łatwych w utrzymaniu aplikacji PHP oraz do efektywnego korzystania z nowoczesnych frameworków i bibliotek.


Zadanie praktyczne

Zorganizuj prosty projekt z użyciem przestrzeni nazw i stwórz podstawowy autoloader PSR-4 (bez Composera, dla celów edukacyjnych).

  1. Stwórz następującą strukturę katalogów w swoim projekcie:
    projekt/
    |-- src/
    |   |-- MojaBiblioteka/
    |   |   |-- Narzedzia/
    |   |   |   |-- Kalkulator.php
    |   |   |-- Dane/
    |   |   |   |-- RepozytoriumUzytkownikow.php
    |-- public/
    |   |-- index.php
    |-- autoloader.php
                    
  2. W pliku src/MojaBiblioteka/Narzedzia/Kalkulator.php zdefiniuj klasę Kalkulator w przestrzeni nazw MojaBiblioteka\Narzedzia. Dodaj jej prostą metodę publiczną, np. dodaj(int $a, int $b): int.
  3. W pliku src/MojaBiblioteka/Dane/RepozytoriumUzytkownikow.php zdefiniuj klasę RepozytoriumUzytkownikow w przestrzeni nazw MojaBiblioteka\Dane. Dodaj jej prostą metodę, np. znajdzUzytkownika(int $id): string.
  4. W pliku autoloader.php napisz funkcję autoloadującą zgodną z PSR-4. Załóż, że prefix przestrzeni nazw MojaBiblioteka\ mapuje się na katalog src/MojaBiblioteka/ (względem katalogu, w którym jest autoloader.php, czyli ../src/MojaBiblioteka/). Zarejestruj tę funkcję za pomocą spl_autoload_register().
  5. W pliku public/index.php:
    • Dołącz plik autoloader.php (require_once __DIR__ . '/../autoloader.php ';).
    • Użyj (zaimportuj) klasy Kalkulator i RepozytoriumUzytkownikow.
    • Stwórz instancje tych klas i wywołaj ich metody, aby sprawdzić, czy autoloading działa poprawnie.

Kliknij, aby zobaczyć przykładowe rozwiązanie

src/MojaBiblioteka/Narzedzia/Kalkulator.php:

<?php
namespace MojaBiblioteka\Narzedzia;

class Kalkulator
{
    public function dodaj(int $a, int $b): int
    {
        return $a + $b;
    }
}
?>

src/MojaBiblioteka/Dane/RepozytoriumUzytkownikow.php:

<?php
namespace MojaBiblioteka\Dane;

class RepozytoriumUzytkownikow
{
    public function znajdzUzytkownika(int $id): string
    {
        return "Użytkownik o ID: " . $id . " (dane z repozytorium)";
    }
}
?>

autoloader.php:

<?php
spl_autoload_register(function (string $className) {
    // Definiujemy mapowanie prefixu przestrzeni nazw na katalog bazowy
    // Klucz to prefix (zakończony \), wartość to ścieżka do katalogu bazowego (zakończona /)
    $prefixes = [
        "MojaBiblioteka\\" => __DIR__ . 
'/src/MojaBiblioteka/
' // __DIR__ odnosi się do katalogu, w którym jest autoloader.php
                                           // więc musimy cofnąć się do src/MojaBiblioteka
    ];

    // Iterujemy po zarejestrowanych prefixach
    foreach ($prefixes as $prefix => $baseDir) {
        // Sprawdzamy, czy nazwa klasy zaczyna się od danego prefixu
        $len = strlen($prefix);
        if (strncmp($prefix, $className, $len) !== 0) {
            // Nie, przejdź do następnego prefixu
            continue;
        }

        // Pobierz względną nazwę klasy (bez prefixu przestrzeni nazw)
        $relativeClass = substr($className, $len);

        // Zastąp separatory przestrzeni nazw separatorami katalogów w względnej nazwie klasy,
        // dodaj .php
        $file = $baseDir . str_replace("\\", "/", $relativeClass) . ".php";

        // Jeśli plik istnieje, załaduj go
        if (file_exists($file)) {
            require $file;
            return; // Zakończ, klasa załadowana
        }
    }
    // Opcjonalnie: można tu dodać logowanie, jeśli klasa nie została znaleziona przez żaden prefix
    // error_log("Nie udało się załadować klasy: " . $className);
});
?>

public/index.php:

<?php
declare(strict_types=1);

echo "<h2>Testowanie Autoloadera PSR-4</h2>";

// Dołącz nasz autoloader
require_once __DIR__ . 
'/../autoloader.php
';

// Import klas
use MojaBiblioteka\Narzedzia\Kalkulator;
use MojaBiblioteka\Dane\RepozytoriumUzytkownikow;

// Test Kalkulatora
$kalkulator = new Kalkulator();
$wynikDodawania = $kalkulator->dodaj(15, 7);
echo "Wynik dodawania (15 + 7): " . $wynikDodawania . "<br>";

// Test RepozytoriumUzytkownikow
$repo = new RepozytoriumUzytkownikow();
$daneUzytkownika = $repo->znajdzUzytkownika(101);
echo $daneUzytkownika . "<br>";

echo "<p>Jeśli widzisz wyniki powyżej, autoloader działa poprawnie!</p>";

/*
Upewnij się, że ścieżka w autoloader.php do katalogu src jest poprawna.
Jeśli autoloader.php jest w głównym katalogu projektu, to:
$prefixes = [
    "MojaBiblioteka\\" => __DIR__ . 
'/src/MojaBiblioteka/
'
];

Jeśli struktura jest taka jak w zadaniu (autoloader.php w głównym katalogu, a src jest podkatalogiem):
projekt/
|-- src/
|-- public/
|-- autoloader.php

To ścieżka w autoloader.php powinna być: `__DIR__ . 
'/src/MojaBiblioteka/
'`
Natomiast w `public/index.php` dołączenie autoloadera: `require_once __DIR__ . 
'/../autoloader.php
';` jest poprawne.
*/
?>

Zadanie do samodzielnego wykonania

Rozbuduj poprzednie zadanie o kolejną przestrzeń nazw i klasę, a następnie zmodyfikuj autoloader, aby obsługiwał oba mapowania.

  1. Dodaj nowy katalog i plik: src/InnaFirma/Logowanie/Logger.php.
  2. W pliku Logger.php zdefiniuj klasę Logger w przestrzeni nazw InnaFirma\Logowanie. Dodaj jej prostą metodę log(string $wiadomosc): void, która wyświetla wiadomość.
  3. Zmodyfikuj plik autoloader.php tak, aby obsługiwał dwa mapowania PSR-4:
    • MojaBiblioteka\ mapowane na src/MojaBiblioteka/
    • InnaFirma\ mapowane na src/InnaFirma/
  4. W pliku public/index.php zaimportuj i użyj klasy Logger, aby przetestować nowe mapowanie w autoloaderze.


FAQ - Przestrzenie Nazw i Autoloading

Czy mogę zdefiniować wiele przestrzeni nazw w jednym pliku PHP?

Tak, ale jest to rzadko stosowane i generalnie niezalecane dla przejrzystości. Można to zrobić używając składni z klamrami: namespace MojaPrzestrzen { /* kod */ } namespace InnaPrzestrzen { /* kod */ }. Standardową praktyką jest jednak jedna przestrzeń nazw (lub jej brak dla kodu globalnego) na plik.

Jak odwołać się do klasy z globalnej przestrzeni nazw, będąc wewnątrz innej przestrzeni nazw?

Aby odwołać się do klasy z globalnej przestrzeni nazw (np. wbudowanej klasy PHP jak \DateTime lub klasy zdefiniowanej bez namespace), należy poprzedzić jej nazwę odwrotnym ukośnikiem: $data = new \DateTime();. Bez początkowego \, PHP szukałoby klasy DateTime w bieżącej przestrzeni nazw.

Czy use wpływa na wydajność?

Samo użycie instrukcji use ma znikomy wpływ na wydajność. Jest to głównie udogodnienie dla programisty, które jest rozwiązywane na etapie kompilacji skryptu. Autoloading może mieć pewien narzut przy pierwszym ładowaniu klasy, ale jest on zazwyczaj akceptowalny i kompensowany przez lepszą organizację i unikanie ładowania nieużywanych plików.

Co to jest PSR-0 i czym różni się od PSR-4?

PSR-0 to starszy standard autoloadingu. Główna różnica polega na tym, że PSR-0 wymagał, aby podkreślenia w nazwach klas były mapowane na separatory katalogów (np. Pear_Style_ClassName). PSR-4 jest nowszy, prostszy i bardziej elastyczny, nie narzuca takiej konwencji dla podkreśleń i pozwala na bardziej bezpośrednie mapowanie prefixu przestrzeni nazw na katalog bazowy. Większość nowoczesnych projektów używa PSR-4.

Czy muszę używać Composera, aby korzystać z autoloadingu PSR-4?

Nie, nie musisz. Możesz napisać własny autoloader zgodny z PSR-4, tak jak pokazano w zadaniu praktycznym. Jednak Composer znacznie upraszcza ten proces, szczególnie w projektach z wieloma zależnościami, i jest zalecanym narzędziem w większości przypadków.

Czy wielkość liter ma znaczenie w przestrzeniach nazw i nazwach klas w PHP?

Nazwy klas, interfejsów i cech w PHP są niewrażliwe na wielkość liter (case-insensitive), np. new mojaKlasa() zadziała, jeśli klasa jest zdefiniowana jako MojaKlasa. Jednak nazwy przestrzeni nazw SĄ wrażliwe na wielkość liter w niektórych systemach plików (np. Linux) i dla spójności oraz zgodności z PSR-4, zawsze należy używać dokładnej wielkości liter zadeklarowanej w przestrzeni nazw i nazwie pliku.

Czy mogę używać aliasów dla przestrzeni nazw, a nie tylko dla klas?

Nie bezpośrednio dla całej przestrzeni nazw w taki sposób, jak dla klasy (use Moja\Długa\Nazwa as Krotka; $obj = new Krotka\Klasa(); nie zadziała). Aliasujesz pełną kwalifikowaną nazwę klasy, interfejsu, cechy, funkcji lub stałej. Możesz jednak zaimportować wiele klas z tej samej przestrzeni nazw: use Moja\Biblioteka\{KlasaA, KlasaB, Narzedzia\KlasaC as MojeNarzedzie}; (składnia grupowa od PHP 7.0).