Przestrzenie nazw (ang. namespaces) zostały wprowadzone w celu zapobieganiu kolizji między identycznymi nazwami klas w dołączanych do programu bibliotekach, modułach itp. Przestrzenie nazw pozwalają zachować ład w kodzie i wpływają na jego czytelność gdyż informują czego dana klasa dotyczy.
DEKLARACJA
Przestrzeń nazw musi być zadeklarowana na początku pliku przed innymi wyrażeniami:
1 2 3 4 5 |
<?php namspace Name; // ... |
Nazwa może być dowolna. Najczęściej stosowaną praktyką jest wprowadzanie przestrzeni nazw zgodnych z lokalizacją pliku klasy, w folderach / podfolderach:
1 2 3 4 5 6 7 8 9 10 |
<?php // path/to/File.php namespace Path\To; class File { // ... } |
Konkretny przykład:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php // Test.php namespace App; class Test { public function message() { echo '<p>Hello World!</p>'; } } ?> |
W klasie Test deklarujemy przestrzeń nazw – App. Klasa posiada trywialną funkcję do wyświetlania komunikatu z powitaniem.
Tworzymy drugi plik – index.php, w którym dołączamy klasę Test.
Aby można było z niej skorzystać musimy również zadeklarować przestrzeń nazw App.
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php // index.php namespace App; include_once('Test.php'); $test = new Test(); $test->message(); ?> |
Spróbuj teraz usunąć z pliku index.php deklarację przestrzeni nazw i odśwież stronę. Wyświetli się wyjątek:
Fatal error: Uncaught Error: Class 'Test’ not found in …
Klasa Test nie jest widoczna, pomimo tego, że jest dołączona do programu: include_once(’Test.php’);
IMPORTOWANIE PRZESTRZENI NAZW
Aby dołączyć do klasy zewnętrzną bibliotekę, moduł, klasę z własną przestrzenią nazw, używamy metody use:
1 2 |
use Path\To\FileClassName; $object = new FileClassName(); |
Przykład:
Utwórz klasę Test2 z funkcję, która wyświetli losową liczbę. Klasa ta będzie należeć do przestrzeni nazw Next\Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php // Test2.php namespace Next\Example; class Test2 { public function doSomething() { echo '<p>'.rand().'</p>'; } } ?> |
Dołącz klasę do pliku index.php z poprzedniego przykładu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?php // index.php namespace App; include_once('Test.php'); include_once('Test2.php'); $test = new Test(); $test->message(); use Next\Example\Test2; $test2 = new Test2(); $test2->doSomething(); ?> |
Poprawny jest również zapis bez deklaracji use, bezpośrednio w instancji tworzącej obiekt:
1 |
$test2 = new \Next\Example\Test2(); |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php namespace App; include_once('Test.php'); include_once('Test2.php'); // ... $test2 = new \Next\Example\Test2(); $test2->doSomething(); ?> |
ALIASY
Może się zdarzyć, że jedna z importowanych klas ma identyczną nazwę jak klasa występująca w kodzie programu. W takiej sytuacji można skorzystać z tzw. aliasów i uniknąć niechcianych konfliktów.
Schemat tworzenia aliasu:
1 2 3 4 5 6 |
<?php use Path\To\FileClassName as NewClassName; $object = new NewClassName(); // ... |
Przykład:
1 2 3 4 5 6 7 8 9 |
<?php include_once('Test2.php'); use Next\Example\Test2 as Tester; $test2 = new Tester(); $test2->doSomething(); ?> |
Jak widać, przy tworzeniu instancji obiektu używamy nowej nazwy, czyli aliasu Tester 🙂
AUTOLOADER
Jak zauważyłeś, wszystkie przykłady w tym rozdziale korzystają z metody include_once, która dołącza pliki klas do programu. Takich plików może być sporo i nie jest to zbyt eleganckie rozwiązanie. Program zacznie się rozrastać i tych plików zacznie przybywać. Poza tym klasy będą zapewne przechowywane w różnych katalogach i podkatalogach, tak więc struktura zacznie się komplikować. Na szczęście wymyślono coś takiego jak autoloader 🙂 – mechanizm do automatycznego ładowania klas. W momencie użycia obiektu, funkcja spl_autoload_register() importuje daną klasę. Jeśli klasy posiadają przestrzenie nazw i/lub są importowane z użyciem metody use, to autoloader szuka plików klas właśnie po ścieżkach zawartych w tych instrukcjach 🙂
Przykład:
Dla maksymalnego uproszczenia zrezygnowałem z przestrzeni nazw i importowania klasy metodą use. Klasa Test i plik index.php muszą być w tym samym katalogu.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php // Test.php class Test { public function message() { echo '<p>Hello World!</p>'; } } ?> |
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php // index.php spl_autoload_register(function ($class_name) { include $class_name . '.php'; }); $test = new Test(); $test->message(); ?> |
W celach testowych spróbuj zaimportować klasę z użyciem use. Pamiętaj, że struktura katalogów i podkatalogów w metodzie use musi istnieć na dysku, inaczej autoloader będzie strzelał błędami.
Więcej informacji o automatycznym ładowaniu klas znajdziesz na stronie php.net/manual/en/language.oop5.autoload.php →