Eksempler på bruk av navneområde i php. Navneområder i PHP, forklart. Navneområder: Flere beskrivelser

Jeg har nylig innkapslet prosjektet mitt i et navneområde og møtte problemet med mangel på riktig dokumentasjon. Alt vi klarte å finne dateres tilbake til omtrent 2009, og det er nesten 2012... I materialet som ble funnet, er det mange ikke-arbeidsplasser som bruker noe som ikke er i den gjeldende versjonen av php. I denne forbindelse vil jeg gjerne kaste lys over dette spørsmålet.
Så, hva er et navneområde eller navneområde? Den store wikipedia definerer dem slik:

Navneområde er et sett, som betyr en modell, abstrakt lagring eller miljø opprettet for den logiske grupperingen av unike identifikatorer (det vil si navn). En identifikator definert i et navneområde er knyttet til det navneområdet. Den samme identifikatoren kan defineres uavhengig i flere mellomrom. En verdi assosiert med en identifikator definert i ett navneområde kan (eller kanskje ikke) ha samme (eller snarere forskjellig) betydning som den samme identifikatoren definert i et annet navneområde. Navneområde-bevisste språk definerer regler som indikerer hvilket navneområde en identifikator tilhører (det vil si dens definisjon).wiki

Alt klart? Det er faktisk enkelt. Før versjon 5.3 var det bare to mellomrom i php - global (der hovedkoden din ble utført) og lokal (hvor funksjonsvariabler ble definert).

Siden versjon 5.3 har alt endret seg. Nå kan du definere navneområdet der dine klasser, metoder osv. skal eksistere.


Jeg håper det ble litt klarere.

Jeg kalte spesielt klassene det samme. Siden de er definert i forskjellige rom, er de to forskjellige klasser, til tross for de samme navnene. Hovedskriptet fungerer fortsatt i det globale rommet, ingenting har endret seg her og klasser og funksjoner kan fortsatt defineres i det. Så hva er plass til da? Først av alt, for å sikre at når du inkluderer en fil med et eller annet rammeverk eller bibliotek, vil ikke klassene dine overstyre rammeverkets klasser eller omvendt.

For å bruke klasser som er definert i ditt navneområde, må du importere rommet du definerer inn i det globale på riktig sted (jeg foretrekker vanligvis å gjøre dette i begynnelsen av filen) For å gjøre dette, bruk bruk nøkkelordet

Merk følgende: av en eller annen grunn tillater ikke php bruk av søkeordet bruk i tilstand blokker og løkker

La oss ta eksemplet fra bildene og implementere det i kode:

Merk følgende: nøkkelordet navneområde må være plassert helt i begynnelsen av filen, umiddelbart etter
filen A.php
B.php-fil
En alternativ syntaks er mulig:
Det anbefales å deklarere hvert navneområde i en separat fil. Selv om det er mulig i ett, er det strengt tatt ikke anbefalt!
La oss nå gå til den tredje filen, der hovedskriptet vårt vil fungere
index.php
Det ser ut til at dette er en fordel, bare mer kode legges til, men dette er ikke helt sant, litt lenger vil jeg gi et eksempel på en autoload-klasse, som linjene som forbinder filer med klasser vil være unødvendige.
La oss nå se på klassene våre.

Merk følgende: ved å bruke scope resolution-operatoren (::) i php-navneområder ikke tillatt! Det eneste den er egnet for er å få tilgang til statiske klassemetoder og konstanter. Først ønsket de å bruke det til navnerommet, men så bestemte de seg for det på grunn av problemer som oppsto. Derfor, en konstruksjon som A::A::say(); er ugyldig og vil resultere i en feil.

For navneområder må du bruke omvendt skråstrek "\"
Merk følgende: For å unngå misforståelser er det nødvendig å unnslippe dette tegnet når det brukes i strenger: "\\"

Navneområder kan nestes inne i hverandre, la oss legge til A.php-filen vår:
og i indeksen vil vi skrive følgende:

Et viktig poeng er å bruke aliaser for importerte mellomrom. Du kan skrive A\subA::say(); Du vil være enig i at det er vanskelig å skrive hele stier til mellomrom hver gang; for å unngå dette ble aliaser introdusert. Ved kompilering vil følgende skje: i stedet for aliassuben vil A\subA bli erstattet, så vi får kallet A\subA::say();

Hva skjer da når man kaller funksjoner definert i det globale rommet? PHP ser først etter en funksjon i området der du jobber, og hvis den ikke finner den, går den til det globale omfanget. For umiddelbart å indikere at du bruker en global funksjon, må du gå foran den med en omvendt skråstrek.

For å unngå problemer med autoloading av klasser fra spaces, må filsystemet organiseres på samme måte som organiseringen av spaces. For eksempel har vi en rotmappe klasser, der våre klasser vil bli lagret, så kan våre områder organiseres som følger
klasser\A\A.php
classes\A\sub\A.php (underunderrom vil bli plassert i en egen fil)
klasser\B\B.php

PHP har en magisk konstant __NAMESPACE__ som inneholder navnet på det gjeldende rommet.

Og nå om autoloading.

Klassen nedenfor er ikke min, jeg bare fikk den til å fungere og forbedret den litt, hentet herfra.
Merk følgende: For at klassene dine skal lastes inn, må klassenavnet samsvare med filnavnet!

".$fil ." i " .$filbane)); if (fil_eksisterer($filbane)) (if(Autoloader::debug) Autoloader::StPutFile(("tilkoblet " .$filbane)); $flagg = FALSE; require_once($filbane); break; ) Autoloader::recursive_autoload($file, $path2, &$flag); ) ) closedir($handle); ) ) privat statisk funksjon StPutFile($data) ( $dir = $_SERVER["DOCUMENT_ROOT"] ." /Log/Log.html"; $file = fopen($dir, "a"); flock($file, LOCK_EX); fwrite($fil, ("║" .$data ."=>" .date(" d.m.Y H:i:s") ."

" .PHP_EOL)); flock($fil, LOCK_UN); fclose ($fil); ) ) \spl_autoload_register("dittNavnSpace\Autoloader::autoload"); )
Hvis du ser på navnene på klassene som kommer inn for lasting, vil du se at hver klasse innledes med et prefiks fra navneområdet som er spesifisert i bruk. Dette er grunnen til at jeg anbefaler å bruke plasseringen av filer i kataloger som ligner på navneområdet; dette øker søket til en eller to iterasjoner.

Nå kan indeksen vår skrives slik:
Nå vil alle klassene og grensesnittene du skal bruke, lastes automatisk.

For å demonstrere noen av de dynamiske egenskapene til språket med mellomrom, la oss erklære en annen klasse:
test.php

Index.php
sayName("test"); //eller du kan gjøre denne testen\sayName("test2"); //eller som dette $obj::sayName("test"); //eller du kan gjøre denne testen::sayName("test2");

Jeg håper at artikkelen min vil være nyttig for noen.

PHP, fra og med versjon 5.3, ga oss navneområder. Siden den gang har det vært litt treg og litt heftig diskusjon om hvordan man bruker dette navnerommet?
Noen rammeverk, som Symphony, Laravel og, selvfølgelig, Zend, har tatt i bruk denne teknologien.
Alt dette passet mer eller mindre inn i MVC-ordningen. Det gjenstår en, sannsynligvis evig, debatt: hva skal være det viktigste ekteskapsparet i applikasjonen - modell og kontroller?
Noen forteller oss at modellen skal være kraftig og feit og med henne en slank og tynn kontroller. I et ord - matriarkat.
Andre, tvert imot, mener at Kontrolløren må styre og kommandere alt, så han viser seg å være solid og velnært. Og med seg har han en tynn, slank modell, hvis oppgave koker ned til å gi og bringe. Dette er patriarkatet.
Så hva er bedre i MVC-ordningen? Patriarkat eller matriarkat?
La oss se på dette fra perspektivet om å bygge en familieenhet basert på demokrati. Og la Namespace hjelpe oss med dette.

Vi liker ikke tykke, klumpete kontroller som, som en okse i en kinabutikk, kan knuse hele applikasjonen hvis du er uforsiktig.
Vi liker heller ikke fete modeller. Vel, hvem liker dem? De må være pallen verdig!
La oss prøve, ved hjelp av Namespace, som med en god matchmaker, å skape en harmonisk familie.

La oss først lage applikasjonsrammeverket. Så banalt det enn er, la det være en blogg.

Vi har laget en grunnleggende struktur hvor:

  • Bloggen er applikasjonens lagringsplass;
  • Visninger og maler - lagring av visninger og maler;
  • Utility - depot for delte biblioteker;
  • index.php - bootstrap-skript;
  • Innlegg - det er her familieidyllen til kontrolleren og modellen skal finne sted.

Med index.php er alt enkelt:

løpe(); /* * slutten av index.php */

Vi bestemmer de nødvendige banene og lager en autoloader.
Autoloaderen laster de nødvendige klassene, som er plassert i et mappehierarki i henhold til klassenavneområdet. For eksempel vil BlogPostServicesView-klassen bli søkt etter i Blog/Post/Services.
Og her er det første møtet med Namespace.
Når vi starter index.php, oppretter vi en forekomst av Blog-applikasjonen, klassen som lastes inn fra Blog/Blog.php.
La oss se på ham.

post = new Post(); ) public function run() ( $this->post->view->all(); ) )//end class Blog

Når vi oppretter Blog-klassen, injiserer vi en Post-klasse i den med Namespace BlogPost, og autoloaderen laster den fra Blog/Post/Post.php.
Sannsynligvis kan denne klassen kalles en kontroller,

view = new View(); ) )//sluttklasse Post

Post-enheten inkluderer:
- strukturen til selve dataposten - BlogPostEntitiesPostEntity.php

Tjenester som betjener kontrollforespørsler – BlogPostServicesView.php (for eksempel en av tjenestene)

db = ny DB(); )//end __construct public function all() ( $posts = $this->db->survey(); Contemplate::compose(array("header" => "header", "main" => "main", "footer" => "bunntekst",), array("posts" => $posts, "title" => "Viper site",)); ) )//end class PostView

Databaseinteraksjonssystemet - BlogPostRepositoriesDB.php - her er det, vår tynne, elegante modell,
Bare gi det, ta det, og ikke noe mer!

dbh = new PDO("mysql:host=localhost;dbname=test", $user, $pass, array(PDO::ATTR_PERSISTENT => true)); ) catch (PDOException $e) ( ekko "Feil!: " . $e->getMessage() . "
"; die(); ) )//end __construct public function survey() ( $query_view = $this->dbh->prepare("SELECT * from posts"); $query_view->execute(); return $query_view- >fetchAll(PDO::FETCH_CLASS, "BlogPostEntitiesPostEntity"); )//slutt undersøkelse )//sluttklasse Db

Som et resultat klarte vi å lage en applikasjonsstruktur der alle komponenter henger godt sammen, samtidig som vi oppnådde en tydelig separasjon av klasser, hvor hver klasse utfører sin egen oppgave. Kontrolleren vår er tynn og samtidig kraftig. Modellen matcher ham. Perfekt familie!
Og alt takket være Namespace.

Jeg argumenterer ikke, i mange tilfeller er rammeverket praktisk. Men se, Namespace minner deg ikke om noe?
En klar inndeling i klasser, et strengt og samtidig fleksibelt hierarki av kataloger og klasser, fullstendig underordnet utvikleren.
Noen ganger er det ikke noe så betydelig tillegg i form av hundrevis av filer og klasser i form av et rammeverk.
Fraværet av en prokrustesk seng av regler for samspillet mellom klasser og komponenter.

Artikkelen ble inspirert av tanker om dette emnet av Taylor Otwell, forfatteren av Laravel-rammeverket, som mange takk til ham.
Adressen til eksempelkildekoden på GitHub.

Hallo. I dagens artikkel skal vi se på, hva er navneområder i PHP.

Hvis du har brukt det lenge OOP, så har du sannsynligvis møtt en situasjon der du, når du kobler til et tredjepartsbibliotek, opplevde en feil på grunn av det faktum at du allerede bruker de samme klassenavnene i koden din som i biblioteket. Dette kan spesielt skje hvis du bruker vanlige navn som "modell", "db" og så videre. Jeg skal fortelle deg nå hvordan du fikser dette.

Navneområde- dette er en slags lagring laget for den abstrakte grupperingen av unike identifikatorer (navn).

De. hvis du bruker navneområder, så kan du trygt koble til tredjepartsbiblioteker og ikke være redd for at de skal ha samme navn som i koden din. La oss avslutte med teorien og gå videre til praksis.

La oss lage en fil min klasse.php med dette innholdet

navneområde mitt\oneProject;
klasse MyClass ( )
?>

Her har vi laget en klasse i navnerommet mitt\oneProject. Du må forresten skrive nøyaktig skråstreken. Ikke bli forvirret!

Nå i fil index.php la oss skrive følgende

require_once("minklasse.php");
$mc = new MyClass(); // Feil: klassen ble ikke funnet
$mc = ny mitt\oneProject\MyClass(); // alt fungerer
?>

Som du kan se, nå er det ikke mulig å lage en klasse bare slik, du må spesifisere i hvilken navneområde han ligger nede.

Vi kan spesifisere flere samtidig navneområder i én fil

navneområde Prosjekt;

Const CONNECT_OK = 1;
klasse Tilkobling ( )
funksjon koble () ( )

NamespaceAnotherProject;

Const CONNECT_OK = 1;
klasse Tilkobling ( )
funksjon koble () ( )
?>

Til tross for at vi har helt identiske navn på klasser, funksjoner og konstanter, vil vi ikke ha en navnekonflikt, fordi de ligger i forskjellige rom.

Vi kan også bruke brakett-syntaks.

navneområdeprosjekt (

Const CONNECT_OK = 1;
klasse Tilkobling ( )
funksjon koble () ( )
}

Navneområde AnotherProject (

Const CONNECT_OK = 1;
klasse Tilkobling ( )
funksjon koble () ( )
}
?>

Hvis du kombinerer koden til globalt navneområde med kode i andre mellomrom, så brukes kun syntaksen med parenteser.

navneområdeprosjekt (

Const CONNECT_OK = 1;
klasse Tilkobling ( )
funksjon koble () ( )
}

Navneområde ( // global kode
session_start();
$a = Prosjekt\connect();
echo Project\Connection::start();
}
?>

Ikke glem at å definere et navneområde alltid bør være den første linjen med kode. Hvis du skriver slik vil det oppstå en feil

For å finne ut hvilket navneområde du befinner deg i, kan du bruke konstanten __NAMESPACE__

navneområde Prosjekt;
ekko """, __NAMESPACE__, """; // vil skrive ut "Prosjekt"
?>

Ved å bruke denne konstanten kan du for eksempel konstruere navn dynamisk

navneområde Prosjekt;

Funksjon inkl($klassenavn) (
$a = __NAMESPACE__ . "\\" . $klassenavn;
returner ny $a;
}
?>

Så det var alt for i dag. Du kan få mer informasjon og praktisk kunnskap ved å ta kurset

Jeg har nylig innkapslet prosjektet mitt i et navneområde og møtte problemet med mangel på riktig dokumentasjon. Alt vi klarte å finne dateres tilbake til omtrent 2009, og det er nesten 2012... I materialet som ble funnet, er det mange ikke-arbeidsplasser som bruker noe som ikke er i den gjeldende versjonen av php. I denne forbindelse vil jeg gjerne kaste lys over dette spørsmålet.
Så, hva er et navneområde eller navneområde? Den store wikipedia definerer dem slik:

Navneområde er et sett, som betyr en modell, abstrakt lagring eller miljø opprettet for den logiske grupperingen av unike identifikatorer (det vil si navn). En identifikator definert i et navneområde er knyttet til det navneområdet. Den samme identifikatoren kan defineres uavhengig i flere mellomrom. En verdi assosiert med en identifikator definert i ett navneområde kan (eller kanskje ikke) ha samme (eller snarere forskjellig) betydning som den samme identifikatoren definert i et annet navneområde. Navneområde-bevisste språk definerer regler som indikerer hvilket navneområde en identifikator tilhører (det vil si dens definisjon).wiki

Alt klart? Det er faktisk enkelt. Før versjon 5.3 var det bare to mellomrom i php - global (der hovedkoden din ble utført) og lokal (hvor funksjonsvariabler ble definert).

Siden versjon 5.3 har alt endret seg. Nå kan du definere navneområdet der dine klasser, metoder osv. skal eksistere.


Jeg håper det ble litt klarere.

Jeg kalte spesielt klassene det samme. Siden de er definert i forskjellige rom, er de to forskjellige klasser, til tross for de samme navnene. Hovedskriptet fungerer fortsatt i det globale rommet, ingenting har endret seg her og klasser og funksjoner kan fortsatt defineres i det. Så hva er plass til da? Først av alt, for å sikre at når du inkluderer en fil med et eller annet rammeverk eller bibliotek, vil ikke klassene dine overstyre rammeverkets klasser eller omvendt.

For å bruke klasser som er definert i ditt navneområde, må du importere rommet du definerer inn i det globale på riktig sted (jeg foretrekker vanligvis å gjøre dette i begynnelsen av filen) For å gjøre dette, bruk bruk nøkkelordet

Merk følgende: av en eller annen grunn tillater ikke php bruk av søkeordet bruk i tilstand blokker og løkker

La oss ta eksemplet fra bildene og implementere det i kode:

Merk følgende: nøkkelordet navneområde må være plassert helt i begynnelsen av filen, umiddelbart etter
filen A.php
B.php-fil
En alternativ syntaks er mulig:
Det anbefales å deklarere hvert navneområde i en separat fil. Selv om det er mulig i ett, er det strengt tatt ikke anbefalt!
La oss nå gå til den tredje filen, der hovedskriptet vårt vil fungere
index.php
Det ser ut til at dette er en fordel, bare mer kode legges til, men dette er ikke helt sant, litt lenger vil jeg gi et eksempel på en autoload-klasse, som linjene som forbinder filer med klasser vil være unødvendige.
La oss nå se på klassene våre.

Merk følgende: ved å bruke scope resolution-operatoren (::) i php-navneområder ikke tillatt! Det eneste den er egnet for er å få tilgang til statiske klassemetoder og konstanter. Først ønsket de å bruke det til navnerommet, men så bestemte de seg for det på grunn av problemer som oppsto. Derfor, en konstruksjon som A::A::say(); er ugyldig og vil resultere i en feil.

For navneområder må du bruke omvendt skråstrek "\"
Merk følgende: For å unngå misforståelser er det nødvendig å unnslippe dette tegnet når det brukes i strenger: "\\"

Navneområder kan nestes inne i hverandre, la oss legge til A.php-filen vår:
og i indeksen vil vi skrive følgende:

Et viktig poeng er å bruke aliaser for importerte mellomrom. Du kan skrive A\subA::say(); Du vil være enig i at det er vanskelig å skrive hele stier til mellomrom hver gang; for å unngå dette ble aliaser introdusert. Ved kompilering vil følgende skje: i stedet for aliassuben vil A\subA bli erstattet, så vi får kallet A\subA::say();

Hva skjer da når man kaller funksjoner definert i det globale rommet? PHP ser først etter en funksjon i området der du jobber, og hvis den ikke finner den, går den til det globale omfanget. For umiddelbart å indikere at du bruker en global funksjon, må du gå foran den med en omvendt skråstrek.

For å unngå problemer med autoloading av klasser fra spaces, må filsystemet organiseres på samme måte som organiseringen av spaces. For eksempel har vi en rotmappe klasser, der våre klasser vil bli lagret, så kan våre områder organiseres som følger
klasser\A\A.php
classes\A\sub\A.php (underunderrom vil bli plassert i en egen fil)
klasser\B\B.php

PHP har en magisk konstant __NAMESPACE__ som inneholder navnet på det gjeldende rommet.

Og nå om autoloading.

Klassen nedenfor er ikke min, jeg bare fikk den til å fungere og forbedret den litt, hentet herfra.
Merk følgende: For at klassene dine skal lastes inn, må klassenavnet samsvare med filnavnet!

".$fil ." i " .$filbane)); if (fil_eksisterer($filbane)) (if(Autoloader::debug) Autoloader::StPutFile(("tilkoblet " .$filbane)); $flagg = FALSE; require_once($filbane); break; ) Autoloader::recursive_autoload($file, $path2, &$flag); ) ) closedir($handle); ) ) privat statisk funksjon StPutFile($data) ( $dir = $_SERVER["DOCUMENT_ROOT"] ." /Log/Log.html"; $file = fopen($dir, "a"); flock($file, LOCK_EX); fwrite($fil, ("║" .$data ."=>" .date(" d.m.Y H:i:s") ."

" .PHP_EOL)); flock($fil, LOCK_UN); fclose ($fil); ) ) \spl_autoload_register("dittNavnSpace\Autoloader::autoload"); )
Hvis du ser på navnene på klassene som kommer inn for lasting, vil du se at hver klasse innledes med et prefiks fra navneområdet som er spesifisert i bruk. Dette er grunnen til at jeg anbefaler å bruke plasseringen av filer i kataloger som ligner på navneområdet; dette øker søket til en eller to iterasjoner.

Nå kan indeksen vår skrives slik:
Nå vil alle klassene og grensesnittene du skal bruke, lastes automatisk.

For å demonstrere noen av de dynamiske egenskapene til språket med mellomrom, la oss erklære en annen klasse:
test.php

Index.php
sayName("test"); //eller du kan gjøre denne testen\sayName("test2"); //eller som dette $obj::sayName("test"); //eller du kan gjøre denne testen::sayName("test2");

Jeg håper at artikkelen min vil være nyttig for noen.

(PHP 5 >= 5.3.0, PHP 7)

Før du diskuterer bruken av navnerom, er det viktig å forstå hvordan PHP vet hvilket navneavstandselement koden din ber om. En enkel analogi kan gjøres mellom PHP-navneområder og et filsystem. Det er tre måter å få tilgang til en fil i et filsystem:

  1. Relativt filnavn som foo.txt. Dette løser seg til currentdirectory/foo.txt hvor gjeldende katalog er katalogen som for øyeblikket er opptatt. Så hvis gjeldende katalog er /hjem/foo, bestemmer navnet til /home/foo/foo.txt.
  2. Relativt banenavn som underkatalog/foo.txt. Dette løser seg til gjeldende katalog/underkatalog/foo.txt.
  3. Absolutt banenavn som /main/foo.txt. Dette løser seg til /main/foo.txt.
Det samme prinsippet kan brukes på navneavstandselementer i PHP. Et klassenavn kan for eksempel refereres til på tre måter:
  1. Ukvalifisert navn, eller et klassenavn uten prefiks som $a = ny foo(); eller foo::staticmethod(); gjeldende navneområde, dette løser seg gjeldende navneområde\foo foo. En advarsel: ukvalifiserte navn for funksjoner og konstanter vil løses til globale funksjoner og konstanter hvis navneavstandsfunksjonen eller konstanten ikke er definert. Se Bruke navnerom: fallback til global funksjon/konstant for detaljer.
  2. Kvalifisert navn, eller et klassenavn med prefiks som $a = nytt undernavnsområde\foo(); eller undernavnrom\foo::staticmethod();. Hvis gjeldende navneområde er gjeldende navneområde, dette løser seg gjeldende navneområde\undernavnområde\foo. Hvis koden er global kode uten navneavstand, løser dette seg undernavnrom\foo.
  3. Fullt kvalifisert navn, eller et prefiksnavn med global prefiksoperatør som $a = new \currentnamespace\foo(); eller \currentnamespace\foo::staticmethod();. Dette løses alltid til det bokstavelige navnet spesifisert i koden, gjeldende navneområde\foo.

Her er et eksempel på de tre typene syntaks i faktisk kode:

navneområde Foo\Bar\undernavnrom;

const FOO = 1;
funksjon foo()()
klasse foo
{
}
?>

navneområde Foo\Bar;
inkluderer "fil1.php" ;

const FOO = 2;
funksjon foo()()
klasse foo
{
statisk funksjon staticmethod()()
}

/* Ukvalifisert navn */
foo(); foo::staticmethod(); ekko FOO ;

/* Kvalifisert navn */
undernavnrom\foo(); // løser seg til funksjon Foo\Bar\subnamespace\foo
undernavnrom\foo::staticmethod(); // løser seg til klassen Foo\Bar\subnamespace\foo,
// metode statisk metode
echo subnamespace\FOO; // løses til konstant Foo\Bar\subnamespace\FOO

/* Fullt kvalifisert navn */
\foo\bar\foo(); // løser seg til funksjon Foo\Bar\foo
\foo\bar\foo::statisk metode(); // løser seg til klassen Foo\Bar\foo, metode staticmethod
echo\Foo\Bar\FOO; // løses til konstant Foo\Bar\FOO
?>

Merk at for å få tilgang til en hvilken som helst global klasse, funksjon eller konstant, kan et fullt kvalifisert navn brukes, som f.eks \strlen() eller \Unntak eller \INI_ALL. ?>