Menu

Przestrzenie nazw w PHP: namespace, use i aliasy

Przestrzeń nazw w PHP grupuje klasy, funkcje i stałe pod prefiksem: namespace App\Models; na górze pliku, a potem use App\Models\User; w innym miejscu, aby odwoływać się do klasy krótką nazwą. Poznaj nazwy w pełni kwalifikowane, aliasy use ... as, use function, początkowy ukośnik wsteczny dla klas globalnych i autoloading PSR-4.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Przestrzeń nazw w PHP umieszcza klasy, funkcje i stałe pod prefiksem, żeby ich nazwy nie kolidowały z cudzymi. Deklarujesz ją przez namespace App\Models; jako pierwszą instrukcję pliku, a inne pliki odwołują się do klasy jako \App\Models\User albo importują ją przez use App\Models\User; i piszą samo User.

Wewnątrz przestrzeni nazw User oznacza App\Models\User. User::class daje pełną nazwę jako string, niczego nie tworząc, co przydaje się przy logowaniu i w autoloaderach.

Dwie przestrzenie nazw w jednym pliku

Prawdziwy projekt umieszcza jedną przestrzeń nazw w każdym pliku. Na potrzeby samodzielnego przykładu jeden plik może zawierać kilka przestrzeni nazw, jeśli każda jest otoczona nawiasami klamrowymi. Kod, który nie należy do żadnej przestrzeni nazw, trafia do namespace { }:

Dwie klasy o nazwie Order istnieją obok siebie, bo ich pełne nazwy się różnią. To dokładnie ten problem, który rozwiązują przestrzenie nazw, gdy instalujesz biblioteki: twoje Order, Order biblioteki płatności i Order biblioteki PDF przestają się gryźć.

Import przez use i aliasy przez as

Pisanie wszędzie \Shop\Order wprowadza szum. use na górze pliku (lub bloku przestrzeni nazw) importuje nazwę, aby można było używać krótkiej formy. Gdy dwa importy kończyłyby się tą samą krótką nazwą, as nadaje jednemu z nich inną nazwę:

use tylko tworzy krótką nazwę dla reszty pliku. Nie wczytuje pliku ani nie uruchamia kodu i działa tak samo niezależnie od tego, czy klasa już istnieje. Dozwolone są też importy grupowe: use Shop\{Order, Invoice};.

use function i use const

Funkcje i stałe z przestrzeni nazw importuje się przez use function i use const:

Klasy globalne wymagają ukośnika wstecznego

Wewnątrz przestrzeni nazw niekwalifikowana nazwa klasy jest rozwiązywana względem tej przestrzeni, więc new DateTime() wewnątrz namespace App; szuka App\DateTime. Z funkcjami i stałymi jest inaczej: jeśli App\strlen nie istnieje, PHP wraca do globalnego strlen. Klasy nigdy nie wracają.

catch (\Error $e) potrzebowało ukośnika wstecznego z tego samego powodu: bez niego PHP szukałoby App\Error, nigdy nie dopasowałoby prawdziwego błędu, a skrypt zatrzymałby się z nieprzechwyconym Error. Napraw to początkowym ukośnikiem wstecznym, jak wyżej, albo przez use DateTime; na górze pliku. To samo dotyczy \Exception, \Throwable i każdej innej klasy wbudowanej; ich przechwytywanie opisuje strona try catch.

Autoloading i PSR-4

W projekcie każda klasa leży we własnym pliku, a ścieżka pliku odpowiada przestrzeni nazw. Konwencją jest PSR-4: prefiks przestrzeni nazw odpowiada folderowi bazowemu, a reszta nazwy staje się ścieżką. Autoloader zarejestrowany przez spl_autoload_register() wczytuje plik klasy przy pierwszym jej użyciu. Ten blok zapisuje dwa pliki klas na dysk i wczytuje je automatycznie:

Każdy plik klasy jest wczytywany raz, w chwili, gdy klasa jest po raz pierwszy potrzebna. W prawdziwych projektach nie piszesz tej funkcji sam: Composer generuje ją z kilku linii w composer.json:

{
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

Po composer dump-autoload jedno require __DIR__ . '/vendor/autoload.php'; na początku skryptu wejściowego wczytuje na żądanie każdą klasę App\....

Zasady przestrzeni nazw, które powodują błędy

  • namespace musi być pierwszą instrukcją w pliku. Przed nią mogą być tylko declare(strict_types=1); i komentarze.
  • Importy use działają w obrębie pliku. Import klasy w index.php nie sprawia, że krótka nazwa działa w dołączonym pliku; każdy plik potrzebuje własnych linii use.
  • use należy do najwyższego poziomu pliku lub bloku przestrzeni nazw. W treści klasy use znaczy coś innego: dołącza trait.
  • Stringi nigdy nie są rozwiązywane: $class = 'User'; new $class(); szuka globalnego User. Przechowuj pełną nazwę, najlepiej przez User::class.

Ostatnia zasada zasługuje na szybkie sprawdzenie:

Najczęściej zadawane pytania

Czym jest przestrzeń nazw w PHP?

Prefiksem, który grupuje powiązane klasy, interfejsy, funkcje i stałe, jak folder dla nazw. namespace App\Models; na górze pliku umieszcza jego klasę User pod App\Models\User, więc nie może ona kolidować z klasą User innej biblioteki.

Co robi use w PHP?

use App\Models\User; na górze pliku pozwala w tym pliku pisać User zamiast pełnej nazwy \App\Models\User. Niczego nie wczytuje ani nie dołącza; wczytanie pliku klasy to zadanie autoloadera. use ... as Alias; wybiera inną krótką nazwę.

Dlaczego w przestrzeni nazw dostaję Class not found?

Wewnątrz namespace App; sama nazwa klasy jest rozwiązywana względem przestrzeni nazw, więc new DateTime() szuka App\DateTime. Napisz new \DateTime() albo dodaj use DateTime; na górze. Funkcje i stałe automatycznie wracają do przestrzeni globalnej, klasy nie.

Co oznacza ukośnik wsteczny przed nazwą klasy w PHP?

Początkowy ukośnik wsteczny czyni nazwę w pełni kwalifikowaną, zaczynającą się od przestrzeni globalnej: \Exception to zawsze wbudowany Exception PHP, niezależnie od przestrzeni nazw, w której jest kod. Bez niego nazwa jest rozwiązywana względem bieżącej przestrzeni nazw i importów use.

Jak przestrzenie nazw mają się do folderów i PSR-4?

Samo PHP nie wiąże przestrzeni nazw z folderami. Robi to konwencja PSR-4: prefiks taki jak App\ odpowiada katalogowi takiemu jak src/, więc App\Models\User leży w src/Models/User.php. Autoloader Composera się jej trzyma, dlatego jedno zwykle zgadza się z drugim.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ