Programowanie obiektowe > Lekcja 9
Przestrzenie nazw
Ostatnia modyfikacja: 01.06.2021
To w zasadzie ostatnia kwestia, jaką chcę na ten moment omówić w sprawie podstaw obiektowości. Przestrzenie nazw umożliwiają zadeklarowanie wielu klas o takiej samej nazwie, wprowadzają też swego rodzaju porządek i grupowanie. W jakich sytuacjach to się może przydać? Przede wszystkim, gdy dodajemy do naszego kodu biblioteki innych programistów. Nie mamy wpływu na nazewnictwo w tym kodzie, a więc ryzyko powielenia nazwy klasy wzrasta. Poza tym, dzięki przestrzeniom nazw czytelność kodu jest lepsza - widzimy od razu, która klasa czego dotyczy.
Przestrzeń nazw musimy zadeklarować jako pierwszą instrukcję w pliku (no, prawie, mogą się wcześniej pojawić przykładowo komentarze czy declare()
). Robimy to bardzo prosto, przy użyciu namespace
.
<?php
namespace PHPDevs;
Możemy też zadeklarować podprzestrzeń, na przykład:
<?php
namespace PHPDevs\Course;
Oraz oczywiście kontynuować kolejne poziomy jeszcze „głębiej”. W momencie takiej deklaracji klasy, funkcje i stałe zdefiniowane przez const
w tym pliku nie będą domyślnie widoczne w innej. Zobaczmy to w praktyce.
<?php // lesson.php
namespace PHPDevs\Course;
class Lesson
{
}
<?php // index.php
require_once 'lesson.php';
$lesson = new Lesson();
Efekt?
Fatal error: Uncaught Error: Class 'Lesson' not found in ...
Jak skorzystać z elementów znajdujących się w przestrzeni nazw PHPDevs
poza nią? Musimy je zaimportować.
<?php // index.php
require_once 'lesson.php';
use PHPDevs\Course\Lesson;
$lesson = new Lesson();
W powyższym przykładzie przy użyciu use
wskazujemy klasę do zaimportowania. Po tej operacji odwołujemy się do niej normalnie, po samej nazwie. Możemy też zrobić to bezpośrednio w momencie jej tworzenia, na przykład tak:
<?php
require_once 'lesson.php';
use Lesson;
$lesson = new PHPDevs\Course\Lesson();
Użycie use
jest w większości przypadków po prostu czytelniejsze, tym bardziej, gdy użycie danej klasy powtarza się wiele razy. Podobnie sytuacja wygląda z funkcjami i stałymi, ale żeby je importować, dodajemy odpowiednio słowo function
lub const
.
<?php
use function PHPDevs\Course\getTitle;
getTitle();
// -----
PHPDevs\Course\getTitle();
<?php
use const PHPDevs\Course\NUMBER;
echo NUMBER;
// -----
echo PHPDevs\Course\NUMBER;
Jak zadeklarowana przestrzeń nazw może być tylko jedna, tak importować możemy dowolną ilość razy. Ważne jednak, aby nie powtórzyły się elementy o takiej samej nazwie. A jeśli zdarzyłoby się, że musimy powtórzyć, to i na to jest rozwiązanie: aliasy. Umożliwiają one nadanie jakby innej nazwy, poinformowanie, że tutaj to zaimportowane coś ma nazywać się o tak.
<?php
require_once 'lesson.php';
use PHPDevs\Course\Lesson as PHPLesson;
$lesson = new PHPLesson();
$lesson = new Lesson(); // error
Warto wiedzieć
Standard PSR-12 mówi, że zarówno za deklaracją przestrzeni nazw, jak i blokiem importów musi nastąpić linia przerwy.
Od php >=7 mamy także możliwość importu wielu klas, funkcji czy stałych w jednym use
. Mam jednak wrażenie, że taki zapis jest mało powszechny. Większość i tak importuje jedną rzecz na linię, jak pokazywałem wyżej.
<?php
use PHPDevs\Course\{Lesson, Category};
$lesson = new Lesson();
$category = new Category();
Teoretycznie istnieje też możliwość deklaracji wielu przestrzeni nazw w jednym pliku. Zostało to opisane w dokumentacji. Teoretycznie, ponieważ w praktyce się tego nie spotyka, ale w razie czego warto wiedzieć.
Praktyka?
No właśnie, jak to wszystko wygląda w praktyce? Obecnie każdy poważny projekt korzysta z Composera i autoloadingu wg PSR-4, o którym powiemy sobie już w następnym rozdziale. Polega to w skrócie na tym, że umieszczamy klasy w odpowiednich folderach, tak, aby były zgodne z przestrzeniami nazw, dzięki czemu są automatycznie dodawane. Ręcznie dołączamy tylko jeden plik, reszta robi się sama :) Co za tym idzie, w jednym pliku deklaruje się jedną klasę i jedną przestrzeń nazw. To na spokojnie, zrobimy razem kolejny projekt, będzie to dokładnie widać.
Przestrzenie nazw są rzeczą, którą z pewnością trzeba znać w obecnym stanie programowania w PHP. Ich wykorzystanie wydaje się chyba dość łatwe i nie wymaga specjalnej nauki. Więcej czasu będziesz myślał jak dobrze aplikację podzielić albo jakie nazwy nadać, niż jak tu użyć samego mechanizmu.
Komentarze