PHP namespace (namespace)

PHP namespace (namespace) จะถูกเพิ่มใน PHP 5.3 ถ้าคุณได้เรียนรู้ C # และ Java, namespace ที่ไม่ได้เป็นอะไรสิ่งใหม่ ๆ แต่ใน PHP ซึ่งยังคงมีความสำคัญเป็นสิ่งที่สำคัญมาก

namespaces PHP สามารถแก้ปัญหาทั้งสองต่อไปนี้:

  1. รหัสผู้ใช้เขียน PHP ภายในชั้นเรียน / ฟังก์ชั่น / ค่าคงที่หรือความขัดแย้งของบุคคลที่สามเรียน / ฟังก์ชั่น / ชื่อค่าคงที่ระหว่าง
  2. ในฐานะที่เป็นชื่อตัวระบุยาว (ปกติเพื่อบรรเทาประเภทแรกกำหนด) สร้างชื่อแทน (หรือสั้น) ชื่อของการปรับปรุงการอ่านของรหัสแหล่งที่มา

กำหนด namespaces

โดยค่าเริ่มต้นทั้งหมดคงเรียนและชื่อฟังก์ชั่นที่มีอยู่ในพื้นที่ของโลกเพียงเช่นเดียวกับก่อนที่จะมีการสนับสนุน namespace PHP

ประกาศ namespace โดย namespace คำหลัก ถ้าชื่อไฟล์ที่มีช่องว่างก็จะต้องประกาศ namespace ก่อนรหัสอื่น ๆ ไวยากรณ์เป็นดังนี้;

< ?php  
// 定义代码在 'MyProject' 命名空间中  
namespace MyProject;  
 
// th. 代码 th.  

นอกจากนี้คุณยังสามารถกำหนด namespaces แตกต่างกันในไฟล์เดียวกันในรหัสเช่น:

< ?php  
namespace MyProject1;  
// MyProject1 命名空间中的PHP代码  
 
namespace MyProject2;  
// MyProject2 命名空间中的PHP代码    
 
// 另一种语法
namespace MyProject3 {  
 // MyProject3 命名空间中的PHP代码    
}  
?>  

ก่อนที่จะประกาศใน namespace รหัสทางกฎหมายที่ไม่ซ้ำกันถูกนำมาใช้ในการกำหนดแฟ้มแหล่งที่มาวิธีการเข้ารหัสประกาศคำสั่ง รหัสไม่ใช่ทั้งหมด PHP รวมถึงช่องว่างไม่สามารถปรากฏก่อนการประกาศการ namespace

<?php
declare(encoding='UTF-8'); //定义多个命名空间和不包含在命名空间中的代码
namespace MyProject {

const CONNECT_OK = 1;
class Connection { /* th. */ }
function connect() { /* th. */  }
}

namespace { // 全局代码
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>

ข้อผิดพลาดไวยากรณ์รหัสต่อไปนี้จะเกิดขึ้น:

<html>
<?php
namespace MyProject; // 命名空间前出现了“<html>” 会致命错误 - 命名空间必须是程序脚本的第一条语句
?>

Subnamespaces

ความสัมพันธ์กับไดเรกทอรีและไฟล์มากเหมือน namespaces PHP นอกจากนี้ยังช่วยในการระบุชื่อของ namespace ลำดับชั้น ดังนั้นชื่อของ namespace ที่สามารถกำหนดโดยใช้ลักษณะลำดับชั้น:

<?php
namespace MyProject\Sub\Level;  //声明分层次的单个命名空间

const CONNECT_OK = 1;
class Connection { /* th. */ }
function Connect() { /* th. */  }

?>

ตัวอย่างข้างต้นคงสร้าง MyProject \ ต \ ระดับ \ CONNECT_OK ชนิด MyProject \ ต \ ระดับ \ การเชื่อมต่อและการทำงาน MyProject \ ต \ ระดับ \ Connect


namespaces

PHP ชื่อชั้น namespace สามารถอ้างอิงในสามวิธี:

  1. ชื่อไม่มีเงื่อนไขหรือชื่อของชั้นไม่ได้มีคำนำหน้าเช่น $ A = foo ใหม่ (); หรือ Foo :: StaticMethod (); ถ้า namespace ปัจจุบันคือ currentnamespace, foo จะถูกตีความว่าเป็น currentnamespace \ Foo หาก Foo เป็นรหัสทั่วโลกรหัสไม่ได้มี namespace ใด ๆ ก็จะถูกแยกเป็น Foo Foo คำเตือน: หากฟังก์ชั่น namespace หรือคงที่ไม่ได้กำหนดไว้แล้วชื่อฟังก์ชันหรือชื่อคงไม่มีเงื่อนไขจะได้รับการแก้ไขไปที่ชื่อฟังก์ชั่นระดับโลกหรือชื่ออย่างต่อเนื่อง

  2. ชื่อที่ผ่านการรับรองหรือชื่อมีคำนำหน้าเช่น $ A = ใหม่ subnamespace \ Foo ( ); หรือ subnamespace \ Foo :: StaticMethod (); ถ้า namespace ปัจจุบันคือ currentnamespace แล้ว foo จะถูกแยกเป็น currentnamespace \ subnamespace \ Foo หาก Foo เป็นรหัสทั่วโลกรหัสไม่ได้มี namespace ใด ๆ Foo จะได้รับการแก้ไขเพื่อ subnamespace \ Foo

  3. ครบชื่อผู้ทรงคุณวุฒิหรือรวมคำนำหน้าชื่อผู้ประกอบการทั่วโลกเช่น $ a = ใหม่ \ currentnamespace \ Foo (); หรือ \ currentnamespace \ Foo :: StaticMethod () ; ในกรณีนี้ Foo มักจะได้รับการแก้ไขให้เป็นชื่อของคำรหัส (ชื่อตัวอักษร) currentnamespace \ Foo

นี่คือตัวอย่างของทั้งสามวิธี:

รหัสไฟล์ file1.php

<?php
namespace Foo\Bar\subnamespace; 

const FOO = 1;
function foo() {}
class foo
{
    static function staticmethod() {}
}
?>

รหัสไฟล์ file2.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
?>

โปรดทราบว่าการเข้าถึงใด ๆ ระดับโลก, ฟังก์ชั่นหรือคงที่คุณสามารถใช้ชื่อที่มีคุณสมบัติครบถ้วนเช่น \ strlen () หรือ \ ข้อยกเว้นหรือ \ INI_ALL

namespace เข้าถึงชั้นเรียนทั่วโลกฟังก์ชั่นและค่าคงที่:

<?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
?>

Namespaces และคุณลักษณะภาษาแบบไดนามิก

IMPLEMENT PHP namespace รับผลกระทบจากคุณลักษณะของภาษาแบบไดนามิกของตัวเอง ดังนั้นถ้าคุณต้องการรหัสต่อไปนี้ลง namespaces องค์ประกอบการเข้าถึงแบบไดนามิก

รหัสไฟล์ example1.php:

<?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
?>

คุณต้องใช้ชื่อที่มีคุณสมบัติครบถ้วน (รวมถึงชื่อชั้นของคำนำหน้า namespace) ที่ โปรดทราบว่าเนื่องจากในชื่อแบบไดนามิกชั้นชื่อฟังก์ชันหรือชื่อคงชื่อที่มีคุณภาพและชื่อครบถ้วนไม่แตกต่างกันดังนั้นทับขวาเป็นผู้นำที่ไม่จำเป็น

องค์ประกอบ namespace การเข้าถึงแบบไดนามิก

<?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
?>

คำหลัก namespace และค่าคงที่ __NAMESPACE__

PHP สนับสนุนทั้งสองวิธีในการเข้าถึงปัจจุบัน namespace องค์ประกอบภายในนามธรรม __ คง NAMESPACE__ เมจิกและ namespace คำหลัก

__NAMESPACE__ ค่าคงที่เป็นสตริงที่มีชื่อของ namespace ปัจจุบัน ในทั่วโลก, รหัสไม่รวม namespace ใด ๆ ที่มีสตริงที่ว่างเปล่า

ตัวอย่าง __NAMESPACE__ ในรหัสใน namespace

<?php
namespace MyProject;

echo '"', __NAMESPACE__, '"'; // 输出 "MyProject"
?>

__NAMESPACE__ ตัวอย่างรหัสทั่วโลก

<?php

echo '"', __NAMESPACE__, '"'; // 输出 ""
?>

__NAMESPACE__ คงสร้างแบบไดนามิกเมื่อชื่อเป็นประโยชน์ตัวอย่างเช่น:

ใช้ชื่อ __NAMESPACE__ สร้างแบบไดนามิก

<?php
namespace MyProject;

function get($classname)
{
    $a = __NAMESPACE__ . '\\' . $classname;
    return new $a;
}
?>

คำหลัก namespace สามารถนำมาใช้ในการเข้าถึง namespace ปัจจุบันหรือองค์ประกอบย่อย namespace อย่างชัดเจน มันจะเทียบเท่ากับระดับของผู้ประกอบการเอง

namespace รหัสผู้ประกอบการ namespace

<?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
?>

ผู้ประกอบการ namespace รหัสทั่วโลก

<?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
?>

ใช้ namespaces: นามแฝง / นำเข้า

namespaces สนับสนุน PHP สองโดยใช้นามแฝงหรือนำเข้า: ใช้นามแฝงสำหรับชื่อชั้นหรือนามแฝงสำหรับชื่อใน namespace โปรดทราบว่า PHP ไม่สนับสนุนการนำเข้าฟังก์ชั่นหรือคงที่

ใน PHP นามแฝงสำหรับใช้ประกอบการเพื่อให้บรรลุต่อไปนี้คือการใช้วิธีที่เป็นไปได้ทั้งหมดจะนำเข้าสามตัวอย่าง:

1 โดยใช้การใช้งานที่ผู้ประกอบการนำเข้า / นามแฝง

<?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 บรรทัดที่ประกอบด้วยงบการใช้งานหลาย ๆ

<?php
use My\Full\Classname as Another, My\Full\NSname;

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

การดำเนินการนำเข้าจะดำเนินการที่รวบรวมเวลา แต่ชื่อชั้นแบบไดนามิกชื่อฟังก์ชันหรือชื่อคงไม่ได้

3, นำเข้าและชื่อแบบไดนามิก

<?php
use My\Full\Classname as Another, My\Full\NSname;

$obj = new Another; // 实例化一个 My\Full\Classname 对象
$a = 'Another';
$obj = new $a;      // 实际化一个 Another 对象
?>

นอกจากนี้การดำเนินการนำเข้าจะมีผลต่อชื่อไม่มีเงื่อนไขและมีคุณสมบัติ ครบชื่อที่มีคุณภาพเพราะมันจะถูกระบุก็ไม่ได้รับผลกระทบจากการนำเข้า

4 การนำเข้าและการอย่างเต็มที่ชื่อที่มีคุณสมบัติเหมาะสม

<?php
use My\Full\Classname as Another, My\Full\NSname;

$obj = new Another; // instantiates object of class My\Full\Classname
$obj = new \Another; // instantiates object of class Another
$obj = new Another\thing; // instantiates object of class My\Full\Classname\thing
$obj = new \Another\thing; // instantiates object of class Another\thing
?>

ใช้ namespaces: fallback ฟังก์ชั่นระดับโลก / คงที่

ใน namespace เมื่อ PHP พบชั้นไม่มีเงื่อนไขและฟังก์ชั่นหรือชื่อคงที่จะใช้กลยุทธ์การจัดลำดับความสำคัญที่แตกต่างกันในการแก้ไขชื่อ ชื่อคลาสชื่อ namespace ปัจจุบันมักจะหายไป ดังนั้นในการเข้าถึงภายในของระบบหรือไม่รวมอยู่ใน namespace ของชื่อชั้นที่คุณจะต้องใช้ชื่อที่มีคุณสมบัติครบถ้วนตัวอย่างเช่น:

1, การเข้าถึงการเรียนระดับโลกในการใน namespace

<?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 类
?>

สำหรับฟังก์ชั่นและค่าคงที่ฟังก์ชันไม่มีอยู่หรือถ้าค่าคงที่ namespace ปัจจุบัน, PHP จะถอยกลับไปฟังก์ชั่นระดับโลกหรือค่าคงที่ในพื้นที่

2 ฟังก์ชั่นระดับโลก namespace ลิขสิทธิ์ / คงที่

<?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";
}
?>

พื้นที่ทั่วโลก

หากคุณไม่ได้กำหนด namespace ใด ๆ ทุกคำจำกัดความของการเรียนและการทำงานอยู่ในพื้นที่ทั่วโลกและ PHP เป็นก่อนที่จะนำแนวคิดของ namespaces ที่ ก่อนที่จะนำหน้าชื่อ \ บ่งชี้ว่าชื่อเป็นพื้นที่ชื่อระดับโลกก็ยังเป็นจริงของ namespace อื่น ๆ แม้ว่าชื่อตั้งอยู่

อธิบายการใช้งานพื้นที่ทั่วโลก

<?php
namespace A\B\C;

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

namespace สั่งซื้อ

ตั้งแต่ที่มี namespace ซึ่งคือการใช้ผิดพลาดได้ง่ายที่สุดของเวลาเรียนเพื่อหาเส้นทางของชั้นนี้คือสิ่งที่

<?php
namespace A;
use B\D, C\E as F;

// 函数调用

foo();      // 首先尝试调用定义在命名空间"A"中的函数foo()
            // 再尝试调用全局函数 "foo"

\foo();     // 调用全局空间函数 "foo" 

my\foo();   // 调用定义在命名空间"A\my"中函数 "foo" 

F();        // 首先尝试调用定义在命名空间"A"中的函数 "F" 
            // 再尝试调用全局函数 "F"

// 类引用

new B();    // 创建命名空间 "A" 中定义的类 "B" 的一个对象
            // 如果未找到,则尝试自动装载类 "A\B"

new D();    // 使用导入规则,创建命名空间 "B" 中定义的类 "D" 的一个对象
            // 如果未找到,则尝试自动装载类 "B\D"

new F();    // 使用导入规则,创建命名空间 "C" 中定义的类 "E" 的一个对象
            // 如果未找到,则尝试自动装载类 "C\E"

new \B();   // 创建定义在全局空间中的类 "B" 的一个对象
            // 如果未发现,则尝试自动装载类 "B"

new \D();   // 创建定义在全局空间中的类 "D" 的一个对象
            // 如果未发现,则尝试自动装载类 "D"

new \F();   // 创建定义在全局空间中的类 "F" 的一个对象
            // 如果未发现,则尝试自动装载类 "F"

// 调用另一个命名空间中的静态方法或命名空间函数

B\foo();    // 调用命名空间 "A\B" 中函数 "foo"

B::foo();   // 调用命名空间 "A" 中定义的类 "B" 的 "foo" 方法
            // 如果未找到类 "A\B" ,则尝试自动装载类 "A\B"

D::foo();   // 使用导入规则,调用命名空间 "B" 中定义的类 "D" 的 "foo" 方法
            // 如果类 "B\D" 未找到,则尝试自动装载类 "B\D"

\B\foo();   // 调用命名空间 "B" 中的函数 "foo" 

\B::foo();  // 调用全局空间中的类 "B" 的 "foo" 方法
            // 如果类 "B" 未找到,则尝试自动装载类 "B"

// 当前命名空间中的静态方法或函数

A\B::foo();   // 调用命名空间 "A\A" 中定义的类 "B" 的 "foo" 方法
              // 如果类 "A\A\B" 未找到,则尝试自动装载类 "A\A\B"

\A\B::foo();  // 调用命名空间 "A\B" 中定义的类 "B" 的 "foo" 方法
              // 如果类 "A\B" 未找到,则尝试自动装载类 "A\B"
?>

การแก้ไขชื่อตามกฎเหล่านี้:

  1. ฟังก์ชั่นชื่อครบถ้วนของชั้นและสายคงได้รับการแก้ไขที่รวบรวมเวลา ตัวอย่างใหม่ \ A \ B หายไประดับ A \ บี
  2. ชื่อไม่มีเงื่อนไขและมีคุณสมบัติ (ไม่ใช่ชื่อที่มีคุณสมบัติครบถ้วน) แปลงที่รวบรวมเวลาขึ้นอยู่กับกฎระเบียบการนำเข้าในปัจจุบัน ตัวอย่างเช่นถ้า namespace A \ B \ C จะถูกนำเข้าเป็น C แล้วโทรไปที่ C \ D \ E (ก) จะถูกแปลงเป็น A \ B \ C \ D \ E ()
  3. namespace ภายในชื่อทั้งหมดที่มีคุณภาพไม่ได้แปลตามกฎนำเข้าจะถูกเพิ่มชื่อ namespace ปัจจุบันในด้านหน้าของมัน ยกตัวอย่างเช่นในการ namespace A \ B ภายในโทร C \ D \ E () แล้ว C \ D \ E () จะแปลให้ A \ B \ C \ D \ E ()
  4. ชื่อชั้นไม่ผ่านการรับรองของแปลง (ที่มีชื่อเต็มแทนชื่อของการแนะนำสั้น) ที่รวบรวมเวลาขึ้นอยู่กับกฎระเบียบการนำเข้าในปัจจุบัน ตัวอย่างเช่นถ้า namespace A \ B \ C จะถูกนำเข้าเป็น C ใหม่ C () จะถูกแปลงใหม่ A \ B \ C ()
  5. namespace ภายใน (เช่น A \ B) โทรไปยังชื่อฟังก์ชันไม่มีเงื่อนไขได้รับการแก้ไขที่รันไทม์ ยกตัวอย่างเช่นการเรียกใช้ฟังก์ชัน foo () จะมีมติเช่นนี้
    1. ค้นหาที่เรียกว่า A \ B \ Foo ใน namespace ปัจจุบัน () ฟังก์ชั่น
    2. พยายามที่จะหาและเรียกระดับโลก (Global) ฟังก์ชั่นพื้นที่ foo ()
  6. namespace (ตัวอย่างเช่น A \ B) ภายในเพื่อชื่อไม่เหมาะสมหรือมีคุณสมบัติของชื่อชั้น (ไม่ใช่ชื่อที่มีคุณสมบัติครบถ้วน) โทรได้รับการแก้ไขในเวลาทำงาน นี่คือการเรียกร้องให้ใหม่ C () และใหม่ d \ E () ของกระบวนการความละเอียด: ใหม่ C () แยก:
    1. หา \ คลาส B \ C ใน namespace ปัจจุบัน
    2. ก็พยายามที่จะ AUTOLOAD A \ B \ ซี
    ใหม่ d \ E () แยก:
    1. ในชื่อชั้นนำหน้าด้วยชื่อ namespace ปัจจุบันกลายเป็น: A \ B \ D \ E , แล้วมองหาชั้นเรียน
    2. ก็พยายามที่จะ AUTOLOAD A \ B \ D \ อี
    อ้างอิง namespace ระดับโลกทั่วโลกคุณจะต้องใช้ชื่อที่มีคุณสมบัติครบถ้วนใหม่ \ C ()