PHPPamokos.lt


9. Namespaces

Dirbant su didesniais projektais (o būtent tokiuose ir būtinas OOP), vienaip ar kitaip atsiranda tikimybė, kad klasių pavadinimai gali sutapti - jei, sakykime, importuojate kieno nors kito sukurtą klasę, ir kaip tyčia jis pavadino ją taip pat kaip ir jūs vieną iš savųjų. Konfliktas - ką daryti? Būtent apie tai kalbėsime šioje pamokoje - mums padės namespaces.

Ši galimybė pasirodė tik versijoje PHP 5.3 ir ji leidžia atskirti klases į tam tikrą kaip katalogą, ir tada jau kreiptis į tas funkcijas, nurodant pilną jų kelią kartu su tuo "katalogu", kuris ir vadinamas namespace - lietuviškai labiau gal skambėtų kaip "vardų erdvė", bet aišku dažniau girdėsite sakant "neimspeisas".

Kaip tai atrodo? Kuriant konkretų klasės failą (prisiminkite nerašytą taisyklę: vienas failas - viena klasė), tiesiog pačioje jo pradžioje įrašome vieną eilutę:

classes/phppamokos/lessons.php:
namespace phppamokos;

class Lessons {
	// ... pats klasės apibrėžimas
}
classes/phppamokos/users.php:
namespace phppamokos;

class Users {
	// ... pats klasės apibrėžimas
}

Svarbi pastaba - namespace nusako failo "vardų erdvę", ne klasės. Jei tame faile bus kuriamos kelios klasės, tada namespace vis tiek bus tas pats. Nebent komanda namespace bus pakartota dar kartą failo viduje - tada prieš tai buvusi "erdvė" baigsis ir prasidės nauja.

Tiesiog sugalvokite savo namespace pavadinimą - jis greičiausiai daromas, atsižvelgiant į klasių rinkinio paskirtį: sakykime, kuriate klasių paketą PHPpamokos projektui, tai visas jas galima įkelti į to paties pavadinimo namespace, kurį naudosite kiekvieno klasės failo pradžioje.

Ką tai duoda praktikoje? Pačiose klasėse jų veikimas nesikeis - tie patys metodai ir savybės, ir visi kiti dalykai, kuriuos jau išmokome šiame kurse. Keisis klasių objektų sukūrimas ir tai, kaip į tas klases kreipiasi iš išorės. Norint sukurti, sakykime, klasės Users objektą, reikia nurodyti pilną kelią, įtraukiant namespace pavadinimą per atgalinius pasviruosius brūkšnelius ar, liaudiškai, "slešus":

$users = new phppamokos\Users;
$lessons = new phppamokos\Lessons;

Realiuose projektuose žengiama dar toliau - kaip namespace parenkamas dviejų lygių pavadinimas, kurio dalys vėlgi atskiriamos "slešu". Pirmoji dalis yra klasės autoriaus pavadinimas (įmonė, žmogus ar koks nors jo GitHub vartotojo vardas - svarbiausia kad be tarpų), o antroji dalis yra to klasių paketo pavadinimas. Tiesa, klasių paketu viso kurso metu vadinu tiesiog klasių rinkinį, kuris turi vientisą prasmę ir turi tikimybę būti gan nesunkiai pernaudotas kituose projektuose, o gal net ir platinamas internete per kokį Composer. Dažniausiai klasių paketas yra diegiamas kaip atskiras katalogas, ir to katalogo pavadinimas ir yra paketo pavadinimas, kuris ir eina į namespace.

Taigi, "profesionalesnis" namespace panaudojimas atrodo taip:

classes/phppamokos/lessons.php:
namespace Reikiapuslapio\LessonCMS;

Šiuo atveju Reikiapuslapio - mano įmonės pavadinimas, o LessonCMS tai, sakykime, pavadinimas sistemos, kuri buvo kuriama phppamokos projektui, bet potencialiai gali būti pernaudojama ir kitur kaip turinio valdymo sistema, dėl to turi bendresnį pavadinimą.

Ir toks lygių suskirstymas neapribojamas dviem lygiais - kartais verta sudaryti iš tikrųjų ilgą struktūrą.

namespace Reikiapuslapio\LessonCMS\Lessons\Tests\Results;

Namespace, Use ir klasių "matomumas"

Jeigu mes kreipiamės į kažkokią funkciją ar objektą ar klasę, PHP ieško jų dabartinėje "vardų erdvėje". Jei jokių namespace nenurodyta, tai laikoma, kad reikia ieškoti "globalioje" erdvėje, t.y. visur kur nėra namespace. Panašiai kaip su failais kompiuteryje iš komandinės eilutės: jei nenurodome pilno kelio prie failo ir norime paleisti pvz kokį mp3 failą, tai kompiuteris bandys jį paleisti iš dabartinio katalogo, ir jei neras - mes klaidą.

Tad, jeigu esate vienoje "vardų erdvėje" ir norite iškviesti funkciją iš kitos "erdvės", reikia nurodyti pilną kelią su Namespace, kitaip PHP parodys klaidą.

Tiesa, yra ir patogesnis variantas - nurodyti, kokį namespace naudojame dabartiniame faile. Tai daroma su komanda use.

classes/phppamokos/users.php:
namespace reikiapuslapio\phppamokos;

class Users {
	// ... pats klasės apibrėžimas
}
index.php:
$users = new Users; // išmes klaidą, nes nėra nurodytas namespace
$users = new reikiapuslapio\phppamokos\Users; // veiks, nes nurodytas pilnas kelias, bet nepatogu
index_correct.php:
use reikiapuslapio\phppamokos;
$users = new Users; // veiks, nes use nurodo, kokiame namespace ieškoti klasės

Galima nurodyti neribotą skaičių komandų use - tai yra gan dažnai naudojama šiuolaikiniuose frameworkuose, norint vienoje klasėje panaudoti kelias klases iš kitų paketų.

use reikiapuslapio\phppamokos;
use reikiapuslapio\otherpackage;

Taip pat galima priskirti pavadinimą konkrečiam use panaudojimui, ir tada kviečiant klases, naudoti tik tą pavadinimą:

use reikiapuslapio\phppamokos\lessons\tests as tests;
$users = new tests\Results; 

Apibendrinant, namespaces reikalingi tada, kai bandome dirbti su didesnės struktūros projektais arba bandome kurti savo klasę/paketą jau egzistuojančiai didesnei sistemai - tada labai praverčia atskirti savo kodą į atskirą namespace, kad niekam netrukdytume.



(c) 2015-2018. Visais klausimais kreipkitės povilas@laraveldaily.com