Przestrzenie nazw w PHP (namespaces)

Logo PHP7

W tym wpisie wyjaśnię co to są przestrzenie nazw (ang. namespaces) używane zarówno w PHP, jak i w wielu innych językach programowania.

Wiele funkcji w PHP korzysta z domyślnej przestrzeni nazw. Wystarczy, że wpiszemy w kodzie strip_tags(), echo(), print() i dana funkcja zostanie wykonana. W przestrzeni globalnej możemy tworzyć także swoje funkcje, zmienne i klasy.

Załóżmy, że chcemy stworzyć klasę MojaKlasa w pliku classes/MojaKlasa.php

Tworzymy plik w katalogu /classes/MojaKlasa.php i dodajemy do niego następującą przykładową stałą i klasę:

<?php

const MYCONST = 'classes/MojaKlasa.php';

class mojaKlasa{
  public static function Test(){
    return 'test funkcji';
  }
}

Plik ten dołączamy do głównego pliku naszego projektu (w głównym katalogu) o nazwie index.php, oto jego zawartość:

<?php

require_once(__DIR__.'/classes/MojaKlasa.php');

echo MYCONST;

echo MojaKlasa::Test();

Po otworzeniu na serwerze pliku index.php zobaczmy na ekranie komunikat:

classes/MojaKlasa.php
test funkcji

W tym przykładzie nie została zadeklarowana żadna przestrzeń nazw, a więc ta klasa i stała jest dostępna w przestrzeni globalnej.

A co w przypadku gdy nasz projekt się rozrasta i z jakiegoś powodu musimy dodać inną klasę lub stałą o takiej samej nazwie?

Skopiujmy nasz katalog classes i zmieńmy jego nazwę na classes_outer.

Następnie w pliku index.php dodajmy odwołanie do nowej klasy:

require_once(__DIR__.'/classes_outer/MojaKlasa.php');

Po odświeżeniu strony w przeglądarce dostaniemy komunikat w stylu: ” Cannot declare class mojaKlasa, because the name is already in use”.

Przestrzeń nazw (namespace)

W tym przypadku użyteczne będą przestrzenie nazw. Aby je stworzyć na samym początku pliku z klasą należy dodać wyrażenie:

namespace NAZWA_PRZESTRZENI;

Deklaracja ta powinna być na samym początku pliku. Cały kod pliku znajdujący się za nią będzie należał do danej przestrzeni nazw. W jednym pliku PHP możemy zadeklarować kilka przestrzeni w ten sposób:

<?php
namespace Przestrzen1;

// blok kodu dla Przestrzen1

namespace Przestrzen2;

// blok kodu dla Przestrzen2

namespace Przestrzen3;

// blok kodu dla Przestrzen3

Jednak nie jest to polecane.

Często stosowanym rozwiązaniem jest nadawanie przestrzeni nazw wg lokalizacji danego pliku, czyli np. dla pliku classes/users/actions/register.php będzie to MyApp\Users\Actions\Register

Wróćmy do naszego przykładu. Zmodyfikujmy plik classes_outer/MojaKlasa.php

<?php

namespace outer;

const MYCONST = 'classes_outer/MojaKlasa.php';

class mojaKlasa{
  static public function Test(){
    return 'test funkcji w innej klasie';
  }
}

Dodaliśmy przestrzeń nazw:

namespace outer;

Spróbujmy otworzyć plik index.php w przeglądarce. Tym razem nie wyświetla się żaden błąd. Widzimy, że komunikaty pochodzą z pierwszej dodanej klasy z pliku classes/MojaKlasa.php

Załóżmy, że chcemy teraz użyć drugiej klasy. W tym celu zmodyfikujmy plik index.php

<?php

require_once(__DIR__.'/classes/MojaKlasa.php');

require_once(__DIR__.'/classes_outer/MojaKlasa.php');

echo outer\MYCONST;

echo('<br>');

echo outer\MojaKlasa::Test();

Po odświeżeniu strony w przeglądarce zobaczymy, że zostały teraz wykorzystane wartości z pliku classes_outer/MojaKlasa.php

Co zostało zmienione? Wywołując stałą oraz klasę dodaliśmy wyrażenie outer\

Powoduje ono, że skrypt będzie szukał tej stałej i klasy nie w zakresie globalnym ale w danej przestrzeni nazw.

Metoda use

Mamy do dyspozycji także metodę use dzięki której nie musimy za każdym razem pisać przestrzeni nazw, wystarczy raz ją zadeklarować:

use outer;

Dyrektywa ta zacznie obowiązywać od miejsca użycia jej w kodzie. Możliwe jest zadeklarowanie używania naraz kilku różnych przestrzeni nazw w ten sposób:

use przestrzen1, przestrzen2, przestrzen3;

Aliasy nazw

Kolejne udogodnienie to tzw. aliasy nazw. Wróćmy do przykładu z przestrzenią nazw MyApp\Users\Actions\Register

Chcąc wykorzystać ją w kodzie, musimy użyć dość długiego wyrażenia np:

$user = new MyApp\Users\Actions\Register\User;

Korzystając z aliasu nazw możemy dodać:

use MyApp\Users\Actions\Register\User as U;

Od tej chwili możemy używać w kodzie formy:

$user = new U;

Podsumowanie

Jak widzicie, przestrzenie nazw to nic skomplikowanego, a naprawdę mogą pomóc utrzymać nasz kod w porządku.

Kod przykładu jest dostępny na GitHub: https://github.com/kamilwyremski/namespaces

Ta strona używa ciasteczek (cookies), dzięki którym nasz serwis może działać lepiej. Więcej informacji

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close