Namespace PHP (namespace) telah ditambahkan di PHP 5.3. Jika Anda telah mempelajari C# dan Java, namespace bukanlah hal baru. Namun, itu masih memiliki arti yang sangat penting dalam PHP.
Namespace PHP dapat memecahkan dua jenis masalah berikut:
Konflik nama antara kode yang ditulis pengguna dan kelas/fungsi/konstanta internal PHP atau kelas/fungsi/konstanta pihak ketiga.
Buat nama alias (atau pendek) untuk nama pengenal yang sangat panjang (biasanya didefinisikan untuk meringankan jenis masalah pertama) untuk meningkatkan keterbacaan kode sumber.
Secara default, semua nama konstanta, kelas, dan fungsi ditempatkan di ruang global, sama seperti namespace yang didukung PHP sebelumnya.
Namespace dideklarasikan menggunakan kata kunci namespace. Jika suatu file berisi namespace, ia harus mendeklarasikan namespace tersebut sebelum semua kode lainnya. Format sintaksnya adalah sebagai berikut;
<?php // Tentukan kode di namespace 'Proyek Saya' Proyek Saya;
Anda juga dapat menentukan kode namespace berbeda dalam file yang sama, seperti:
<?php namespace Proyek Saya;const CONNECT_OK = 1;Koneksi kelas { /* ... */ }fungsi terhubung() { /* ... */ }namespace Proyek Lain;const CONNECT_OK = 1;Koneksi kelas { /* .. .
Tidak disarankan menggunakan sintaksis ini untuk mendefinisikan beberapa namespace dalam satu file. Disarankan untuk menggunakan bentuk sintaks kurung kurawal berikut.
<?phpnamespace Proyek Saya { const CONNECT_OK = 1; kelas Koneksi { /* ... */ } fungsi koneksi() { /* ... */ }}namespace Proyek Lain { const CONNECT_OK = 1; . */ } fungsi menghubungkan() { /* ... */ }}?>
Untuk menggabungkan kode non-namespace global dengan kode namespace, hanya sintaks braket keriting yang dapat digunakan. Kode global harus diapit dalam pernyataan namespace tanpa nama diikuti dengan tanda kurung kurawal, misalnya:
<?phpnamespace Proyek Saya {const CONNECT_OK = 1;Koneksi kelas { /* ... */ }fungsi terhubung() { /* ... */ }}namespace { // Kode global session_start();$a = Proyek Saya connect();echo Proyek SayaKoneksi::mulai();}?>
Satu-satunya kode legal sebelum mendeklarasikan namespace adalah pernyataan deklarasi yang mendefinisikan pengkodean file sumber. Semua kode non-PHP, termasuk spasi, tidak dapat muncul sebelum deklarasi namespace.
<?phpdeclare(encoding='UTF-8'); //Tentukan beberapa namespace dan namespace kode yang tidak termasuk dalam namespace MyProject {const CONNECT_OK = 1;class Connection { /* ... */ }function connect () { / * ... */ }}namespace { // Kode global session_start();$a = Proyek Sayakoneksi();echo Proyek SayaKoneksi::mulai();}?>
Kode berikut akan menyebabkan kesalahan sintaksis:
<html><?phpnamespace MyProject; // "<html>" yang muncul sebelum namespace akan menyebabkan kesalahan fatal - namespace harus berupa pernyataan pertama skrip program?>
Sama seperti hubungan antara direktori dan file, namespace PHP juga memungkinkan Anda menentukan nama namespace hierarki. Oleh karena itu, nama namespace dapat didefinisikan secara hierarki:
<?phpnamespace MyProjectSubLevel; //Deklarasikan namespace tunggal hierarki const CONNECT_OK = 1;class Connection { /* ... */ }function Connect() { /* ... */ }?>
Contoh di atas membuat konstanta MyProjectSubLevelCONNECT_OK, kelas MyProjectSubLevelConnection dan fungsi MyProjectSubLevelConnection.
Nama kelas di namespace PHP dapat direferensikan dalam tiga cara:
Nama yang tidak memenuhi syarat, atau nama kelas tanpa awalan, seperti $a=new foo(); atau foo::staticmethod();. Jika namespace saat ini adalah namespace saat ini, foo akan diselesaikan menjadi namespace saat inifoo. Jika kode yang menggunakan foo bersifat global dan tidak berisi kode di namespace mana pun, maka foo akan diselesaikan sebagai foo. Peringatan: Jika suatu fungsi atau konstanta dalam namespace tidak terdefinisi, fungsi atau nama konstanta yang tidak memenuhi syarat akan diselesaikan menjadi fungsi global atau nama konstanta.
Nama yang memenuhi syarat, atau nama yang menyertakan awalan, seperti $a = new subnamespacefoo(); atau subnamespacefoo::staticmethod();. Jika namespace saat ini adalah currentnamespace, foo akan diselesaikan menjadi currentnamespacesubnamespacefoo. Jika kode yang menggunakan foo bersifat global, kode tidak terdapat dalam namespace apa pun, foo akan diselesaikan ke subnamespacefoo.
Nama yang sepenuhnya memenuhi syarat, atau nama yang menyertakan operator awalan global, misalnya, $a = new currentnamespacefoo(); atau currentnamespacefoo::staticmethod();. Dalam hal ini, foo selalu diselesaikan dengan nama literal currentnamespacefoo dalam kode.
Berikut ini contoh penggunaan ketiga metode tersebut:
file1.php kode file
<?phpnamespace FooBarsubnamespace; const FOO = 1;fungsi foo() {}kelas foo{ fungsi statis metode statis() {}}?>
kode file file2.php
<?phpnamespace FooBar;include 'file1.php';const FOO = 2;function foo() {}class foo{ static function staticmethod() {}}/* Nama tidak memenuhi syarat*/foo(); // Menguraikannya adalah fungsi FooBarfoofoo::staticmethod(); // Diuraikan ke dalam kelas FooBarfoo dan metodenya adalah staticmethodecho FOO; Memutuskan ke konstanta FooBarFOO/* nama yang memenuhi syarat*/subnamespacefoo(); // Memutuskan ke fungsi FooBarsubnamespacefoosubnamespacefoo::staticmethod(); foo, // dan metode kelas staticmethodecho subnamespaceFOO; // diuraikan ke konstanta FooBarsubnamespaceFOO /* Nama yang sepenuhnya memenuhi syarat */FooBarfoo(); // Memutuskan ke fungsi FooBarfooFooBarfoo::staticmethod(); Metode staticmethodecho FooBarFOO; //Diselesaikan sebagai konstanta FooBarFOO?>
Perhatikan bahwa untuk mengakses kelas, fungsi, atau konstanta global apa pun, Anda dapat menggunakan nama yang sepenuhnya memenuhi syarat, seperti strlen() atau Exception atau INI_ALL.
Akses kelas global, fungsi dan konstanta dalam namespace:
<?phpnamespace Foo;function strlen() {}const INI_ALL = 3;class Exception {}$a = strlen('hi'); // Panggil fungsi global strlen$b = INI_ALL; // Akses konstanta global INI_ALL$ c = new Exception('error'); // Membuat instance Pengecualian kelas global?>
Implementasi namespace PHP dipengaruhi oleh sifat dinamis dari bahasa itu sendiri. Jadi jika Anda ingin mengubah kode di bawah ini menjadi namespace, akses elemennya secara dinamis.
contoh1.php kode file:
<?phpclass classname{ function __construct() { echo __METHOD__,"n";fungsi funcname(){ echo __FUNCTION__,"n";}const constname = "global";$a = 'nama kelas';$obj = baru $a; // mencetak nama kelas::__construct$b = 'nama fungsi';$b(); // mencetak nama fungsicho konstanta('constname'), "n"; // mencetak global?>
Anda harus menggunakan nama yang sepenuhnya memenuhi syarat (nama kelas termasuk awalan namespace). Perhatikan bahwa garis miring terbalik di depan tidak diperlukan karena tidak ada perbedaan antara nama yang memenuhi syarat dan yang sepenuhnya memenuhi syarat dalam nama kelas dinamis, nama fungsi, atau nama konstanta.
Mengakses elemen namespace secara dinamis
<?phpnamespace namespacename;class classname{ function __construct() { echo __METHOD__,"n}}function funcname(){ echo __FUNCTION__,"n";}const constname = "namespaced";include 'example1.php' ;$a = 'nama kelas';$obj = baru $a; // Keluaran nama kelas::__konstruksi$b = 'funcname';$b(); // Nama fungsi keluaran echo konstan('constname'), "n"; // Keluaran global/* Jika tanda kutip ganda digunakan, metode penggunaannya adalah "\namespacename\classname "* /$a = 'namespacenameclassname';$obj = $a baru; // Keluaran namespacenameclassname::__construct$a = 'namespacenameclassname';$obj = $a baru; // Keluaran namespacenameclassname::__construct$b = 'namespacenamefuncname';$b(); // Keluaran namespacenamefuncname$b = 'namespacenamefuncname';$b(); 'namespacenameconstname'), "n"; // Keluaran konstanta namespacedecho('namespacenameconstname'), "n"; Keluaran diberi spasi nama?>
PHP mendukung dua metode abstrak untuk mengakses elemen dalam namespace saat ini, konstanta ajaib __NAMESPACE__ dan kata kunci namespace.
Nilai konstanta __NAMESPACE__ adalah string yang berisi nama namespace saat ini. Dalam kode global, tidak termasuk dalam namespace apa pun, kode tersebut berisi string kosong.
Contoh __NAMESPACE__, kode dalam namespace
<?phpnamespace Proyek Saya;echo '"', __NAMESPACE__, '"'; // Keluaran "Proyek Saya"?>
Contoh __NAMESPACE__, kode global
<?phpecho '"', __NAMESPACE__, '"'; // Keluaran ""?>
Konstanta __NAMESPACE__ berguna saat membuat nama secara dinamis, misalnya:
Buat nama secara dinamis menggunakan __NAMESPACE__
<?phpnamespace Proyek Saya;fungsi get($namakelas){ $a = __NAMESPACE__ '\'
Namespace kata kunci dapat digunakan untuk secara eksplisit mengakses elemen dalam namespace atau subnamespace saat ini. Ini setara dengan operator mandiri di kelas.
operator namespace, kode di namespace
<?phpnamespace MyProject;use blahblah sebagai milik saya; // lihat "Menggunakan namespace: mengimpor/aliasing"blahmine(); // memanggil fungsi blahblahmine()namespaceblahmine(); memanggil fungsi MyProjectblahmine()namespacefunc(); // memanggil fungsi MyProjectfunc()namespacesubfunc(); MyProjectsubfunc()namespacecname::method(); // memanggil metode statis "metode" kelas MyProjectcname$a = new namespacesubcname(); // membuat instance objek kelas MyProjectsub cname$b = namespaceCONSTANT; // memberikan nilai konstanta MyProjectCONSTANT ke $b?>
operator namespace, kode global
<?phpnamespacefunc(); // memanggil fungsi func()namespacesubfunc(); // memanggil fungsi subfunc()namespacecname::method(); class cname$a = namespace barusubcname(); // membuat instance objek dari kelas subcname$b = namespaceCONSTANT; // memberikan nilai konstanta CONSTANT ke $b?>
Dukungan namespace PHP memiliki dua cara menggunakan alias atau impor: menggunakan alias untuk nama kelas, atau menggunakan alias untuk nama namespace.
Di PHP, aliasing diimplementasikan melalui operator use. Berikut adalah contoh penggunaan ketiga metode impor yang mungkin:
1. Gunakan operator penggunaan untuk mengimpor/menggunakan alias
<?phpnamespace foo;use MyFullClassname as Another;// Contoh berikut sama dengan menggunakan MyFullNSname sebagai NSname use MyFullNSname;// Impor kelas global menggunakan ArrayObject;$obj = namespace baruLainnya; // Buat instance fooObjek lain $obj = baru Lainnya; // Buat instance MyFullClassname objek NSnamesubnsfunc(); Panggil fungsi MyFullNSnamesubnsfunc$a = new ArrayObject(array(1)); // Buat instance objek ArrayObject // Jika Anda tidak menggunakan "use ArrayObject", buat instance objek fooArrayObject? >
2. Satu baris berisi beberapa pernyataan penggunaan
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // Buat instance objek MyFullClassname NSnamesubnsfunc(); subnsfungsi?>
Operasi impor dilakukan selama kompilasi, namun nama kelas dinamis, nama fungsi, atau nama konstanta tidak.
3. Impor dan nama dinamis
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // Membuat instance objek MyFullClassname $a = 'Another';$obj = new $a; sebuah objek lain?>
Selain itu, operasi impor hanya mempengaruhi nama yang tidak memenuhi syarat dan memenuhi syarat. Nama-nama yang memenuhi syarat tidak terpengaruh oleh impor karena bersifat deterministik.
4. Impor dan nama yang memenuhi syarat
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // Buat instance MyFullClassname class $obj = new Another; benda; // Buat instance KelasNamaKelasSayalengkap $obj = baru Lainnyabenda; // Buat instancekelas benda lain?>
Dalam namespace, ketika PHP menemukan kelas, fungsi, atau nama konstanta yang tidak memenuhi syarat, PHP menggunakan strategi prioritas yang berbeda untuk menyelesaikan nama tersebut. Nama kelas selalu ditentukan dengan nama di namespace saat ini. Oleh karena itu ketika mengakses nama kelas yang bersifat internal sistem atau tidak terdapat pada namespace, harus menggunakan nama yang sepenuhnya memenuhi syarat, misalnya:
1. Akses kelas global di namespace
<?phpnamespace ABC;class Exception extends Exception {}$a = new Exception('hi'); // $a adalah objek kelas ABCException $b = new Exception( 'hi'); // $b adalah objek kelas Pengecualian $c = new ArrayObject; // Kesalahan fatal, kelas ABCArrayObject tidak ditemukan?>
Untuk fungsi dan konstanta, jika fungsi atau konstanta tersebut tidak ada di namespace saat ini, PHP akan kembali menggunakan fungsi atau konstanta tersebut di ruang global.
2. Cadangkan fungsi/konstanta global di namespace
<?phpnamespace ABC;const E_ERROR = 45;fungsi strlen($str){ return strlen($str) - 1;}echo E_ERROR, "n"; // Keluaran "45"echo INI_ALL, " n"; // Keluaran "7" - gunakan konstanta global INI_ALLecho strlen('hi'), "n"; // Keluaran "2"if (is_array('hi')) { // Output "bukan array" echo "adalah arrayn";} else { echo "bukan arrayn";}?>
Jika tidak ada namespace yang ditentukan, semua kelas dan fungsi didefinisikan dalam ruang global, sama seperti sebelum PHP memperkenalkan konsep namespace. Mengawali nama dengan menunjukkan bahwa nama tersebut berada di ruang global, meskipun nama tersebut berada di ruang nama lain.
Gunakan instruksi luar angkasa global
<?phpnamespace ABC;/* Fungsi ini adalah ABCfopen */function fopen() { /* ... */ $f = fopen(...); Fungsi fopen mengembalikan $f;} ?>
Sejak diperkenalkannya namespace, hal yang paling rawan kesalahan adalah saat menggunakan suatu kelas, apa jalur pencarian untuk kelas tersebut.
<?phpnamespace A;gunakan BD, CE sebagai F;// Pemanggilan fungsi foo(); // Pertama coba panggil fungsi foo() yang didefinisikan dalam namespace "A" // Lalu coba panggil global function" foo"foo(); // Memanggil fungsi ruang global "foo" myfoo(); // Memanggil fungsi "foo" yang didefinisikan dalam namespace "Amy" F(); Pertama coba panggil fungsi "F" yang didefinisikan dalam namespace "A" // Kemudian coba panggil fungsi global "F" // Referensi kelas baru B(); // Buat kelas "B" yang didefinisikan dalam namespace "A" Sebuah objek dari class "AB" new D(); // Jika tidak ditemukan, coba muat otomatis kelas "AB" new D(); // Menggunakan aturan impor, buat objek kelas "D" yang didefinisikan dalam namespace "B " // Jika tidak ditemukan Jika ditemukan, coba muat kelas "BD" baru secara otomatis F(); // Menggunakan aturan impor, buat objek kelas "E" yang didefinisikan dalam namespace "C" // Jika tidak ditemukan, coba muat otomatis kelas "CE" new B(); dari kelas "B" yang didefinisikan dalam ruang global // Jika tidak ditemukan, coba muat otomatis kelas "B" new D(); // Buat objek kelas "D" yang didefinisikan dalam ruang global // Jika tidak ditemukan, cobalah muat otomatis kelas "D" baru F(); // Buat objek kelas "F" yang didefinisikan dalam ruang global // Jika tidak ditemukan, coba muat otomatis kelas "F" // Panggil metode statis atau fungsi namespace di namespace lain Bfoo() ; // Memanggil fungsi "foo" dalam namespace "AB" B::foo(); // Memanggil metode "foo" dari kelas "B" yang didefinisikan dalam namespace "A" // Jika kelas "AB" adalah tidak ditemukan , lalu coba memuat kelas "AB" secara otomatis D::foo(); // Gunakan aturan impor untuk memanggil metode "foo" dari kelas "D" yang ditentukan dalam namespace "B" // Jika kelas "BD " " Jika tidak ditemukan, coba muat kelas "BD"Bfoo(); // Panggil fungsi "foo" di namespace "B" B::foo(); berfungsi di ruang global Kelas "B" Metode "foo" // Jika kelas "B" tidak ditemukan, coba muat otomatis kelas "B" // Metode atau fungsi statis di namespace saat ini AB::foo(); Metode "foo" dari kelas "B" yang didefinisikan di A" // Jika kelas "AAB" tidak ditemukan, coba muat otomatis kelas "AAB"AB::foo() ; // Panggil metode "foo" dari kelas "B" yang didefinisikan dalam namespace "A" // Jika kelas "AB" tidak ditemukan, coba muat otomatis kelas "AB"?>
Resolusi nama mengikuti aturan berikut:
Panggilan ke nama fungsi, kelas, dan konstanta yang sepenuhnya memenuhi syarat diselesaikan pada waktu kompilasi. Misalnya, new AB memutuskan ke kelas AB .
Semua nama yang tidak memenuhi syarat dan nama yang memenuhi syarat (bukan nama yang sepenuhnya memenuhi syarat) dikonversi pada waktu kompilasi sesuai dengan aturan impor saat ini. Misalnya, jika namespace ABC diimpor sebagai C , maka panggilan ke CDe() akan diterjemahkan ke ABCDe() .
Dalam namespace, semua nama yang memenuhi syarat yang tidak dikonversi sesuai dengan aturan impor akan diberi nama namespace saat ini di depannya. Misalnya, jika CDe() dipanggil dalam namespace AB , CDe() akan dikonversi menjadi ABCDe() .
Nama kelas yang tidak memenuhi syarat dikonversi pada waktu kompilasi sesuai dengan aturan impor saat ini (nama lengkap digunakan sebagai pengganti nama impor pendek). Misalnya, jika namespace ABC diimpor sebagai C, new C() dikonversi menjadi new ABC() .
Dalam namespace (misalnya AB), pemanggilan fungsi ke nama yang tidak memenuhi syarat diselesaikan pada waktu proses. Misalnya, panggilan ke fungsi foo() diurai seperti ini:
Temukan fungsi bernama ABfoo() di namespace saat ini
Cobalah untuk menemukan dan memanggil fungsi foo() di ruang global .
Panggilan ke nama yang tidak memenuhi syarat atau kelas nama yang memenuhi syarat (nama yang tidak sepenuhnya memenuhi syarat) dalam namespace (misalnya AB ) diselesaikan pada saat runtime. Berikut proses parsing pemanggilan new C() dan new DE() : Parsing new C() :
Temukan kelas ABC di namespace saat ini.
Cobalah untuk memuat kelas secara otomatis ABC .
Analisis DE() baru :Tambahkan nama kelas dengan nama namespace saat ini menjadi: ABDE dan kemudian cari kelas itu.
Coba muat otomatis kelas ABDE .
Untuk merujuk ke kelas global di namespace global, nama yang sepenuhnya memenuhi syarat new C() harus digunakan.