Przestrzenie nazw i ładowarki

Przestrzenie nazw

Może się zdarzyć tak, że użyjemy takiego samego identyfikatora w dwóch różnych modułach php. Wówczas może dojść do nieoczekiwanych efektów i trudnych w diagnostyce błędów. Dlatego wprowadzono mechanizm przestrzeni nazw (namespaces). Wybierając przestrzeń nazw w jakiej ma operować nasz moduł, świadomie decydujemy jakie identyfikatory są dla niego widoczne.

Polecenie namespace jest umieszczane zawsze na początku modułu.

Przetestujmy, tworząc dwa moduły:

1) test1.php:

<?php
namespace ns1;
class test1 { public function id() { echo 'test1'; } }

2) test2.php:

<?php
namespace ns2;
class test1 { public function id() { echo 'test2'; }}

Stwórzy teraz moduł testowy

namespace ns1;
require("test1.php"); require("test2.php");
test1::id();

Jego uruchomienie powoduje wypisanie napisu 'test1'.

Jeśli w miejsce ns1 wpiszemy ns2, to wynikiem będzie napis 'test2'.

Zastosowanie przestrzeni nazw

Przestrzenie nazw umożliwiają rozwiązywanie kolizji nazw między komponentami kodu i zapewniają możliwość skrócenia długich nazw. Można stwierdzić, że przestrzeń nazw jest "kontenerem" grupy nazw i innych przestrzeni nazw. Przestrzenie nazw mogą bowiem zawierać inne przestrzenie nazw - tworząc drzewo. Jego korzeniem jest przestrzeń nazw global do której należą klasy nie zawarte w przestrzeniach nazw podrzędnych - na przykład Exception iDateTime .

Nazwy zagnieżdżonych przestrzeni nazw oddzielamy znakiem ukośnika (\). Rozpoczęcie nazwy od ukośnika oznacza, że zaczynamy od przestrzeni zawartej w globalnej przestrzeni nazw. Bez ukośnika odwołujemy się do "bieżącej" (czyli takiej w której znajduje się miejsce odwołania) przestrzeni nazw. Na przykład moduł należący do przestrzeni nazw \Aplikacja może odwoływać się do podrzędnej przestrzeni Moduly\Logowanie poprzez powyższą nazwę (zaczynającą się od "Moduly"), albo nazwę "kwalifikowaną" \Aplikacja\Moduly\Logowanie.

Instrukcja use (wstawiana na początku modułu) pozwala na tworzenie aliasu (nazwy skróconej). Dla powyższego przykładu możemy użyć opcjonalnie jednej z dwóch zapisów:

<?php
use \Aplikacja\Modul\Logowanie;

$log1 = new Logowanie();
$log2 = new \Aplikacja\Modul\Logowanie();

Autoloader

Instrukcja use korzysta z wprowadzonego w wersji 5.0 PHP mechanizmu automatycznego ładowania klas (zob.https://pl.wikibooks.org/wiki/PHP/Automatyczne_%C5%82adowanie). Umożliwia on ładowanie modułów zawierających definicję klas bez stosowania require lub include. Ładowanie w chwili użycia obiektu wykonuje funkcja __autoload.

Stwórzmy na przykład moduł definiujący klasę test. Jego nazwa powinna być zgodna z nazwą klasy, czyli test.php:

<?php
class test { public function id() { echo 'test'; }}

Moduł testowy:

<?php
function __autoload($class_name) {
include $class_name . '.php';
}
$obj = new test();
$obj->id();

W wersji php 5.1 wprowadzono możliwość używania wielu „ładowarek”. Informujemy o nich system funkcją spl_autoload_register(). Wywołując ją bez parametrów, nakazujemy użycie standardowej ładowarki:

spl_autoload_register();
test::id();

Jeśli używamy przestrzeni nazw, to standardowa ładowarka zakłada, że umieszczamy moduły w odpowiednich podkatalogach – o nazwie równej nazwie przestrzeni nazw. Możemy też używać innego rozszerzenia, niż php – na przykład class.php:

namespace ns1;
set_include_path('.');
spl_autoload_extensions('.class.php');
spl_autoload_register();
test1::id();

Przykład własnego autoloadera:

define ("CLASS_ROOT", 'p6');
spl_autoload_register(
        function ($class) {
            $filename = CLASS_ROOT.DIRECTORY_SEPARATOR.
                    str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
            if (file_exists($filename)) {
                require $filename;
                return true;
            }
            return false;
        }
);

Autoloader i Composer

Autoloader jest jedną z funkcji Composera. W sekcji „autoload” pliku composer.json definiujemy co ma być ładowane. Używany jest do tego standard PSR-0 lub PSR-4. W obu wypadkach definiowany jest alias, którego możemy używać w miejsce ścieżki do katalogu. Na przykład:

use Jaspersoft\Client\Client;

wskazuje, że chcemy użyć modułu Client.php z przestrzeni nazw Jaspersoft/Client.

Przykład definicji w pliku composer.json:

"autoload": {
"psr-0": { "Album": "module/Album/src/" }
},

Composer na podstawie podanych defincji tworzy autoloadera w pliku vendor/autoload.php.