Ruang nama PHP

Ruang nama PHP (ruang nama) telah ditambahkan dalam PHP 5.3 Jika anda telah mempelajari C# dan Java, maka ruang nama bukanlah perkara baharu. Walau bagaimanapun, ia masih mempunyai kepentingan yang sangat penting dalam PHP.

Ruang nama PHP boleh menyelesaikan dua jenis masalah berikut:

Antara kod tulisan pengguna dan kelas/fungsi/pemalar dalaman PHP atau kelas/fungsi/ pihak ketiga konflik nama pemalar.

Cipta nama alias (atau pendek) untuk nama pengecam yang sangat panjang (biasanya ditakrifkan untuk mengurangkan jenis masalah pertama), meningkatkan kebolehbacaan kod sumber.

Mentakrifkan ruang nama

Secara lalai, semua nama pemalar, kelas dan fungsi diletakkan dalam ruang global, sama seperti sebelum ruang nama yang disokong PHP.

Dalam menamakan ruang, kami biasanya menggunakan nama atau singkatan syarikat, perusahaan atau individu sebagai pengecam Huruf pertama mesti menggunakan huruf besar dan tidak boleh bermula dengan nombor ruang nama dikenal pasti oleh penyataan ruang nama kata kunci. Jika fail mengandungi ruang nama, ia mesti mengisytiharkan ruang nama sebelum semua kod lain. Format sintaks adalah seperti berikut;

<?php

// Kod ditakrifkan dalam ruang nama 'Projek Saya'
ruang nama MyProject
// . .. kod..

?>

Anda juga boleh mentakrifkan kod ruang nama yang berbeza dalam fail yang sama, seperti:

< ?php

ruang nama MyProject1;
// kod PHP dalam ruang nama MyProject1

ruang nama MyProject2
// kod PHP dalam ruang nama MyProject2

// Satu lagi sintaks

ruang nama MyProject3 {
// kod PHP dalam ruang nama MyProject3

}

?>

Satu-satunya yang sah kod sebelum mengisytiharkan ruang nama ialah pernyataan isytihar yang mentakrifkan pengekodan fail sumber. Semua kod bukan PHP, termasuk ruang putih, tidak boleh muncul sebelum pengisytiharan ruang nama.

<?php
declare(encoding='UTF-8'); //定义多个命名空间和不包含在命名空间中的代码 
namespace MyProject { 
const CONNECT_OK = 1; 
class Connection { /* ... */ } 
function connect() { /* ... */ } 
} 
namespace { // 全局代码 
session_start(); 
$a = MyProject\connect(); 
echo MyProject\Connection::start(); 
} 
?>

Kod berikut akan mempunyai ralat sintaks:

<html>

<?php
ruang nama MyProject; namespace html>" akan menyebabkan ralat maut - ruang nama mestilah pernyataan pertama skrip program
?>

sub-ruang nama

Pengisytiharan sub-ruang nama ialah betul-betul sama seperti contoh sebelumnya. Satu-satunya perbezaan ialah kami menambah simbol untuk memisahkan ruang nama dan ruang kecil Ruang kecil boleh dibahagikan kepada mana-mana peringkat, asalkan ia boleh dibahagikan dengan jelas mengikut fungsi:

<?php

ruang nama MyProjectSubLevel; //Isytiharkan ruang nama tunggal berhierarki

const CONNECT_OK = 1;
Sambungan kelas { /* ... */ }
fungsi Connect() { /* .. . */ }
}

?>

Contoh di atas mencipta MyProjectSubLevelCONNECT_OK yang berterusan, kelas MyProjectSubLevelConnection dan fungsi MyProjectSubLevelConnect.

Penggunaan ruang nama

Nama kelas dalam ruang nama PHP boleh dirujuk dalam tiga cara:

Nama tidak layak, atau nama kelas tanpa awalan, seperti $a=new foo( atau foo::staticmethod();. Jika ruang nama semasa ialah currentnamespace, foo akan diselesaikan kepada currentnamespacefoo. Jika kod yang menggunakan foo bersifat global dan tidak mengandungi kod dalam mana-mana ruang nama, foo akan diselesaikan sebagai foo. Amaran: Jika fungsi atau pemalar dalam ruang nama tidak ditentukan, fungsi tidak layak atau nama pemalar diselesaikan kepada fungsi global atau nama tetap.

Nama yang layak, atau nama termasuk awalan, seperti $a = new subnamespacefoo( atau subnamespacefoo::staticmethod();. Jika ruang nama semasa ialah currentnamespace, foo akan diselesaikan kepada currentnamespacesubnamespacefoo. Jika kod yang menggunakan foo adalah global, kod tidak terkandung dalam mana-mana ruang nama, foo akan diselesaikan kepada subnamespacefoo.

Nama yang layak sepenuhnya, atau nama yang termasuk operator awalan global, contohnya, $a = new currentnamespacefoo( atau currentnamespacefoo::staticmethod();. Dalam kes ini, foo sentiasa diselesaikan kepada nama literal currentnamespacefoo dalam kod.

Berikut ialah contoh menggunakan tiga kaedah ini:

kod fail1.php

<?php
namespace Foo\Bar\subnamespace; 
const FOO = 1; 
function foo() {} 
class foo 
{ 
static function staticmethod() {} 
} 
?>

kod fail fail2.php

<?php
namespace Foo\Bar; 
include 'file1.php'; 
const FOO = 2; 
function foo() {} 
class foo 
{ 
static function staticmethod() {} 
} 
/* 非限定名称 */ 
foo(); // 解析为 Foo\Bar\foo resolves to function Foo\Bar\foo 
foo::staticmethod(); 
// 解析为类 Foo\Bar\foo的静态方法staticmethod。resolves to class Foo\Bar\foo, method staticmethod 
echo FOO; // resolves to constant Foo\Bar\FOO 
/* 限定名称 */ 
subnamespace\foo(); // 解析为函数 Foo\Bar\subnamespace\foo 
subnamespace\foo::staticmethod(); // 解析为类 Foo\Bar\subnamespace\foo, 
// 以及类的方法 staticmethod 
echo subnamespace\FOO; // 解析为常量 Foo\Bar\subnamespace\FOO 
/* 完全限定名称 */ 
\Foo\Bar\foo(); // 解析为函数 Foo\Bar\foo 
\Foo\Bar\foo::staticmethod(); // 解析为类 Foo\Bar\foo, 以及类的方法 staticmethod 
echo \Foo\Bar\FOO; // 解析为常量 Foo\Bar\FOO 
?>

Berhati-hati untuk akses mana-mana kelas, fungsi atau pemalar Global boleh menggunakan nama yang layak sepenuhnya, seperti strlen() atau Exception atau INI_ALL.

Akses kelas global, fungsi dan pemalar di dalam ruang nama:

<?php
namespace Foo;
function strlen() {} 
const INI_ALL = 3; 
class Exception {} 
$a = \strlen('hi'); // 调用全局函数strlen 
$b = \INI_ALL; // 访问全局常量 INI_ALL
$c = new \Exception('error'); // 实例化全局类 Exception 
?>

Ruang nama dan ciri bahasa dinamik

Pelaksanaan ruang nama PHP dipengaruhi oleh The pengaruh ciri-ciri dinamik bahasa itu sendiri. Jadi, jika anda ingin menukar kod di bawah kepada ruang nama, akses elemen secara dinamik.

example1.php kod fail:

<?php
class classname 
{ 
function __construct() 
{ 
echo __METHOD__,"\n"; 
} 
} 
function funcname() 
{ 
echo __FUNCTION__,"\n"; 
} 
const constname = "global"; 
$a = 'classname'; 
$obj = new $a; // prints classname::__construct 
$b = 'funcname'; 
$b(); // prints funcname 
echo constant('constname'), "\n"; // prints global 
?>

Mesti menggunakan nama yang layak sepenuhnya (nama kelas termasuk awalan ruang nama). Ambil perhatian bahawa garis miring ke belakang utama tidak diperlukan kerana tiada perbezaan antara nama layak dan layak sepenuhnya dalam nama kelas dinamik, nama fungsi atau nama tetap.

Akses dinamik kepada elemen ruang nama

<?php
namespace namespacename; 
class classname 
{ 
function __construct() 
{ 
echo __METHOD__,"\n"; 
} 
} 
function funcname() 
{ 
echo __FUNCTION__,"\n"; 
}
const constname = "namespaced"; 
include 'example1.php'; 
$a = 'classname'; 
$obj = new $a; // prints classname::__construct 
$b = 'funcname'; 
$b(); // prints funcname 
echo constant('constname'), "\n"; // prints global 
/* note that if using double quotes, " \namespacename\classname" must be used */ 
$a = '\namespacename\classname'; 
$obj = new $a; // prints namespacename\classname::__construct 
$a = 'namespacename\classname'; 
$obj = new $a; // also prints namespacename\classname::__construct 
$b = 'namespacename\funcname'; 
$b(); // prints namespacename\funcname 
$b = '\namespacename\funcname'; 
$b(); // also prints namespacename\funcname 
echo constant('\namespacename\constname'), "\n"; // prints namespaced 
echo constant('namespacename\constname'), "\n"; // also prints namespaced 
?>

kata kunci ruang nama dan pemalar __NAMESPACE__

PHP menyokong dua abstraksi untuk mengakses dalaman kaedah Elemen ruang nama semasa, __NAMESPACE__ pemalar ajaib dan kata kunci ruang nama.

Nilai pemalar __NAMESPACE__ ialah rentetan yang mengandungi nama ruang nama semasa. Dalam kod global, tidak termasuk dalam mana-mana ruang nama, ia mengandungi rentetan kosong.

__NAMESPACE__ contoh, kod dalam ruang nama

<?php

ruang nama MyProject;

gema '"' , __NAMESPACE__, '"'; // Output "MyProject"

?>

__NAMESPACE__ contoh, kod global

<?php

gema '"', __NAMESPACE__, '"'; // Output ""

?>

Malar __NAMESPACE__ berguna apabila mencipta nama secara dinamik, contohnya:

Buat nama secara dinamik menggunakan __NAMESPACE__

<?php

ruang nama MyProject

function get($classname)
{
$a = __NAMESPACE__ kembalikan $a baharu;
}

?>

Ruang nama kata kunci boleh digunakan untuk mengakses elemen secara eksplisit dalam ruang nama atau sub-ruang nama semasa. Ia bersamaan dengan pengendali diri dalam kelas.

pengendali ruang nama, kod dalam ruang nama

<?php
namespace MyProject; 
use blah\blah as mine; // see "Using namespaces: importing/aliasing" 
blah\mine(); // calls function blah\blah\mine() 
namespace\blah\mine(); // calls function MyProject\blah\mine() 
namespace\func(); // calls function MyProject\func() 
namespace\sub\func(); // calls function MyProject\sub\func() 
namespace\cname::method(); // calls static method "method" of class MyProject\cname 
$a = new namespace\sub\cname(); // instantiates object of class MyProject\sub\cname 
$b = namespace\CONSTANT; // assigns value of constant MyProject\CONSTANT to $b 
?>

pengendali ruang nama, kod global

<?php
namespace\func(); // calls function func() 
namespace\sub\func(); // calls function sub\func() 
namespace\cname::method(); // calls static method "method" of class cname 
$a = new namespace\sub\cname(); // instantiates object of class sub\cname 
$b = namespace\CONSTANT; // assigns value of constant CONSTANT to $b 
?>

Gunakan ruang nama: alias/import

PHP ruang nama menyokong dua cara menggunakan alias atau import: menggunakan alias untuk nama kelas atau menggunakan alias untuk nama ruang nama. Ambil perhatian bahawa PHP tidak menyokong fungsi pengimportan atau pemalar.

Dalam PHP, alias dilaksanakan melalui penggunaan operator Berikut ialah contoh menggunakan ketiga-tiga kaedah import yang mungkin:

1. Gunakan operator untuk mengimport/menggunakan alias

<?php
namespace foo; 
use My\Full\Classname as Another; 
// 下面的例子与 use My\Full\NSname as NSname 相同 
use My\Full\NSname; 
// 导入一个全局类 
use \ArrayObject; 
$obj = new namespace\Another; // 实例化 foo\Another 对象 
$obj = new Another; // 实例化 My\Full\Classname 对象 
NSname\subns\func(); // 调用函数 My\Full\NSname\subns\func 
$a = new ArrayObject(array(1)); // 实例化 ArrayObject 对象 
// 如果不使用 "use \ArrayObject" ,则实例化一个 foo\ArrayObject 对象 
?>

2. Satu baris mengandungi berbilang pernyataan penggunaan

<?php
use My\Full\Classname as Another, My\Full\NSname; 
$obj = new Another; // 实例化 My\Full\Classname 对象 
NSname\subns\func(); // 调用函数 My\Full\NSname\subns\func 
?>

Operasi import dilaksanakan semasa penyusunan, tetapi nama kelas dinamik, nama fungsi atau nama tetap tidak.

3. Import dan nama dinamik

<?php
use My\Full\Classname as Another, My\Full\NSname; 
$obj = new Another; // 实例化一个 My\Full\Classname 对象 
$a = 'Another'; 
$obj = new $a; // 实际化一个 Another 对象 
?>

Selain itu, operasi import hanya mempengaruhi nama yang tidak layak dan nama yang layak. Nama yang layak sepenuhnya tidak terjejas oleh import kerana ia bersifat deterministik.

4. Import dan nama yang layak sepenuhnya

<?php
use My\Full\Classname as Another, My\Full\NSname; 
$obj = new Another; // 实例化对象的类 My\Full\Classname 
$obj = new \Another; // instantiates object of class Another 
$obj = new Another\thing; // 实例化对象的类 My\Full\Classname\thing 
$obj = new \Another\thing; // instantiates object of class Another\thing 
?>

gunakan penggunaan kata kunci:

mesti berada di bahagian atas fail PHP, iaitu teg pembuka PHP < ?php atau Pengisytiharan ruang nama diikuti dengan kata kunci penggunaan untuk mengimport kod.

Apabila menggunakan kata kunci guna untuk mengimport kod, tidak perlu menambah simbol pada permulaan nama kelas, kerana PHP menganggap bahawa ruang nama yang diimport adalah layak sepenuhnya.

Kata kunci penggunaan mesti digunakan dalam skop global (iaitu, ia tidak boleh digunakan dalam kelas atau fungsi)

Kata kunci penggunaan boleh diletakkan di bawah pengisytiharan ruang nama, menggunakan untuk mengimport kod dalam ruang nama lain.

Menggunakan ruang nama: sandaran fungsi/pemalar global

Dalam ruang nama, apabila PHP menemui kelas, fungsi atau nama tetap yang tidak layak, ia Gunakan strategi keutamaan yang berbeza untuk menyelesaikan nama. Nama kelas sentiasa diselesaikan kepada nama dalam ruang nama semasa. Oleh itu, apabila mengakses nama kelas di dalam sistem atau tidak termasuk dalam ruang nama, anda mesti menggunakan nama yang layak sepenuhnya, contohnya:

1 Akses kelas global dalam ruang nama

<?php
namespace A\B\C; 
class Exception extends \Exception {} 
$a = new Exception('hi'); // $a 是类 A\B\C\Exception 的一个对象 
$b = new \Exception('hi'); // $b 是类 Exception 的一个对象 
$c = new ArrayObject; // 致命错误, 找不到 A\B\C\ArrayObject 类 
?>

Untuk fungsi dan Untuk pemalar, jika fungsi atau pemalar tidak wujud dalam ruang nama semasa, PHP akan kembali menggunakan fungsi atau pemalar dalam ruang global.

2. Sandarkan fungsi/pemalar global dalam ruang nama

<?php
namespace A\B\C; 
const E_ERROR = 45; 
function strlen($str) 
{ 
return \strlen($str) - 1; 
} 
echo E_ERROR, "\n"; // 输出 "45" 
echo INI_ALL, "\n"; // 输出 "7" - 使用全局常量 INI_ALL 
echo strlen('hi'), "\n"; // 输出 "1" 
if (is_array('hi')) { // 输出 "is not array" 
echo "is array\n"; 
} else { 
echo "is not array\n"; 
} ?>

Ruang global

Jika tiada ruang nama ditakrifkan, semua kelas dan fungsi ditakrifkan secara global ruang, seperti sebelum ini PHP memperkenalkan konsep ruang nama. Awalan nama menunjukkan bahawa nama itu berada dalam ruang global, walaupun nama itu berada dalam ruang nama lain.

Arahan untuk menggunakan ruang global

Untuk menggunakan ruang nama global, anda hanya perlu menambah simbol sebelum nama kelas Contohnya: buang Exception();

<?php
namespace A\B\C; 
/* 这个函数是 A\B\C\fopen */ 
function fopen() { 
/* ... */ 
$f = \fopen(...); // 调用全局的fopen函数 
return $f; 
?>

Susunan ruang nama

Sejak pengenalan ruang nama, perkara yang paling terdedah kepada ralat ialah apabila menggunakan kelas, apakah laluan carian untuk kelas ini.

<?php

ruang nama A;
gunakan BD, CE sebagai F; / Mula-mula cuba panggil fungsi foo() yang ditakrifkan dalam ruang nama "A"
// Kemudian cuba panggil fungsi global "foo"

foo( // Panggil fungsi ruang global "); foo"

myfoo(); // Panggil fungsi "foo" yang ditakrifkan dalam ruang nama "Amy"

F(); // Mula-mula cuba panggil fungsi yang ditakrifkan dalam ruang nama " A" F"

// Cuba panggil fungsi global "F" sekali lagi

// Rujukan kelas

baharu B(); // Cipta ruang nama yang ditakrifkan dalam ruang nama "A" Objek kelas "B"
// Jika tidak ditemui, cuba muatkan kelas "AB"

baharu D(); // Gunakan peraturan import untuk mencipta objek yang ditakrifkan dalam ruang nama "B" Objek kelas "D"
// Jika tidak ditemui, cuba muatkan kelas "BD"

baharu F( // Gunakan peraturan import untuk mencipta objek yang ditakrifkan dalam ruang nama "); C" Objek kelas "E"
// Jika tidak ditemui, cuba muatkan kelas "CE"

baharu B(); // Cipta objek kelas "B" yang ditakrifkan dalam global space Object
// Jika tidak dijumpai, cuba muatkan kelas "B" secara automatik

new D(); // Buat objek kelas "D" yang ditakrifkan dalam ruang global
// Jika tidak ditemui, cuba muatkan kelas "D" secara automatik

F(); // Cipta objek kelas "F" yang ditakrifkan dalam ruang global
// Jika tidak ditemui, cuba kelas Autoload "F"

// Panggil kaedah statik atau fungsi ruang nama dalam ruang nama lain

Bfoo(); // Fungsi panggilan "foo" dalam ruang nama "AB"

B ::foo(); // Panggil kaedah "foo" kelas "B" yang ditakrifkan dalam ruang nama "A"
// Jika kelas "AB" tidak ditemui, cuba muatkannya secara automatik Kelas "AB"

D::foo(); // Gunakan peraturan import untuk memanggil kaedah "foo" kelas "D" yang ditakrifkan dalam ruang nama "B"
// Jika kelas "BD " Jika tidak dijumpai, cuba memuatkan kelas "BD" secara automatik

Bfoo(); // Panggil fungsi "foo" dalam ruang nama "B"

B::foo(); " kaedah kelas "B" dalam ruang global
// Jika kelas "B" tidak ditemui, cuba muatkan kelas "B" secara automatik

// Statik dalam ruang nama semasa Kaedah atau fungsi

AB::foo(); // Panggil kaedah "foo" kelas "B" yang ditakrifkan dalam ruang nama "AA"
// Jika kelas "AAB" tidak ditemui, maka Cuba muatkan kelas " AAB"

AB::foo(); // Panggil kaedah "foo" kelas "B" yang ditakrifkan dalam ruang nama "AB"
// Jika kelas "AB" tidak dijumpai, cuba muatkan kelas "AB" secara automatik

?>

Leraian nama mengikut peraturan berikut:

1 Panggilan ke fungsi, kelas dan pemalar dengan nama yang layak sepenuhnya diselesaikan pada masa penyusunan. Sebagai contoh, AB baharu memutuskan ke kelas AB.

2. Semua nama yang tidak layak dan nama yang layak (nama tidak layak sepenuhnya) ditukar pada masa penyusunan mengikut peraturan import semasa. Sebagai contoh, jika ruang nama ABC diimport sebagai C, maka panggilan ke CDe() akan ditukar kepada ABCDe().

3. Dalam ruang nama, semua nama yang layak yang tidak ditukar mengikut peraturan import akan didahului dengan nama ruang nama semasa. Sebagai contoh, jika CDe() dipanggil dalam ruang nama AB, CDe() akan ditukar kepada ABCDe().

4. Nama kelas yang tidak layak ditukar pada masa penyusunan mengikut peraturan import semasa (nama penuh digunakan dan bukannya nama import pendek). Sebagai contoh, jika ruang nama ABC diimport sebagai C, maka C() baharu ditukar kepada ABC() baharu.

5. Dalam ruang nama (mis. AB), panggilan fungsi kepada nama yang tidak layak diselesaikan pada masa jalan. Sebagai contoh, panggilan ke fungsi foo() dihuraikan seperti ini:

Cari fungsi bernama ABfoo() dalam ruang nama semasa

Cuba cari dan panggil fungsi dalam ruang global foo ().

6. Panggilan ke nama yang tidak layak atau kelas nama yang layak (nama tidak layak sepenuhnya) dalam ruang nama (mis. AB) diselesaikan pada masa jalan. Berikut ialah proses penghuraian untuk memanggil C() baharu dan DE() baharu: Penghuraian C() baharu: Penghuraian DE baharu(): Untuk merujuk kepada kelas global dalam ruang nama global, nama yang layak sepenuhnya baharu C() mesti digunakan.

Tambahkan nama ruang nama semasa di hadapan nama kelas untuk menjadi: ABDE, dan kemudian cari kelas.

Cuba muatkan kelas ABDE secara automatik.

Cari kelas ABC dalam ruang nama semasa.

Cuba muatkan kelas ABC secara automatik.



Meneruskan pembelajaran
||
<?php namespace MyProject; echo '"', __NAMESPACE__, '"'; // 输出 "MyProject" ?>
  • Cadangan kursus
  • Muat turun perisian kursus