2-1-0-命名空間


一、
命名空間劃分了訪問路徑

要解決的問題:
1、用戶編寫的代碼與PHP內部的類/函數/常量或第三方類/函數/常量之間的名字衝突。
2、爲很長的標識符名稱(通常是爲了緩解第一類問題而定義的)創建一個別名(或簡短)的名稱,提高源代碼的可讀性

PHP 命名空間提供了一種將相關的類、函數和常量組合到一起的途徑。
命名空間的調用關係:


二、
定義命名空間:
雖然任意合法的PHP代碼都可以包含在命名空間中,但只有以下類型的代碼受命名空間的影響,它們是:類(包括抽象類和traits)、接口、函數和常量。
命名空間通過關鍵字namespace 來聲明。如果一個文件中包含命名空間,它必須在其它所有代碼之前聲明命名空間,除了一個以外:declare關鍵字。 所有非 PHP 代碼包括空白符都不能出現在命名空間的聲明之前。
與PHP其它的語言特徵不同,同一個命名空間可以定義在多個文件中,即允許將同一個命名空間的內容分割存放在不同的文件中。

與目錄和文件的關係很象,PHP 命名空間也允許指定層次化的命名空間的名稱。因此,命名空間的名字可以使用分層次的方式定義。
也可以在同一個文件中定義多個命名空間。在同一個文件中定義多個命名空間有兩種語法形式。 推薦第二種。

創建(聲明)一個命名空間需要使用namespace關鍵字,當前腳本文件的第一個命名空間前面不能有任何代碼
將全局的非命名空間中的代碼與命名空間中的代碼組合在一起,只能使用大括號形式的語法。全局代碼必須用一個不帶名稱的 namespace 語句加上大括號括起來
在一個命名空間裏引入這個腳本,腳本里的元素不會歸屬到這個命名空間。如果這個腳本里沒有定義其它命名空間,它的元素就始終處於公共空間中

"use" statements are required to be placed after the "namespace my\space" but before the "{".

命名空間一方面定義了自己的空間,方便其他調用,另一方面對其他進行了引用。
命名空間將代碼劃分出不同的空間(區域),每個空間的常量、函數、類(爲了偷懶,我下邊都將它們稱爲元素)的名字互不影響, 這個有點類似我們常常提到的‘封裝'的概念。

類名可以通過三種方式引用:
    非限定名稱,或不包含前綴的類名稱,例如 $a=new foo(); 或 foo::staticmethod();。如果當前命名空間是 currentnamespace,foo 將被解析爲 currentnamespace\foo。如果使用 foo 的代碼是全局的,不包含在任何命名空間中的代碼,則 foo 會被解析爲foo。 警告:如果命名空間中的函數或常量未定義,則該非限定的函數名稱或常量名稱會被解析爲全局函數名稱或常量名稱。
    
    限定名稱,或包含前綴的名稱,例如 $a = new subnamespace\foo(); 或 subnamespace\foo::staticmethod();。如果當前的命名空間是 currentnamespace,則 foo 會被解析爲 currentnamespace\subnamespace\foo。如果使用 foo 的代碼是全局的,不包含在任何命名空間中的代碼,foo 會被解析爲subnamespace\foo。     
    
     完全限定名稱,或包含了全局前綴操作符的名稱,例如, $a = new \currentnamespace\foo(); 或 \currentnamespace\foo::staticmethod();。在這種情況下,foo 總是被解析爲代碼中的文字名(literal name)currentnamespace\foo。
     注意訪問任意全局類、函數或常量,都可以使用完全限定名稱,例如 \strlen() 或 \Exception 或 \INI_ALL。
    
PHP支持兩種抽象的訪問當前命名空間內部元素的方法,__NAMESPACE__ 魔術常量和namespace關鍵字。
常量__NAMESPACE__的值是當前命名空間名稱的字符串。在全局的,不包括在任何命名空間中的代碼,它包含一個空的字符串。

關鍵字 namespace 可用來顯式訪問當前命名空間或子命名空間中的元素。它等價於類中的 self 操作符。

別名和導入:
允許通過別名引用或導入外部的完全限定名稱
 所有支持命名空間的PHP版本支持三種別名或導入方式:爲類名稱使用別名、爲接口使用別名或爲命名空間名稱使用別名。
 PHP 5.6開始允許導入函數或常量或者爲它們設置別名。
 在PHP中,別名是通過操作符 use 來實現的.     
 
 
 名稱解析規則
 
 
    
三、
代碼示例:
/*The following code will define two constants in the "test" namespace.*/

<?php
namespace test;
define('test\HELLO', 'Hello world!');
define(__NAMESPACE__ . '\GOODBYE', 'Goodbye cruel world!');
?>


<?php
namespace test;
define('MESSAGE', 'Hello world!');

    define(__NAMESPACE__ .'\foo','111');
    define('foo','222');

    echo foo."<br/>";  // 111.當前目錄下
    //var_dump(foo)."<br/>";
    echo \foo."<br/>";  // 222.根目錄下,全局性的
    echo \test\foo."<br/>";  // 111.
    echo test\foo;  // fatal error. assumes \test\test\foo
?>


/*下面的例子創建了常量MyProject\Sub\Level\CONNECT_OK,類 MyProject\Sub\Level\Connection和函數 MyProject\Sub\Level\connect。*/
<?php
namespace MyProject\Sub\Level;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */}
?>


/*定義多個命名空間和不包含在命名空間中的代碼,除了開始的declare語句外,命名空間的括號外不得有任何PHP代碼。 */
/*注意這是定義*/
<?php
declare(encoding='UTF-8');
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
}

namespace { // global code
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>


/*命名空間一方面定義了自己的空間,方便其他調用,另一方面對其他進行了引用。*/
//food.php
<?php
namespace Food;

require ('Apple.php');
require('Orange.php');

use Apples;
use Oranges;

  Apples\eat();
  Oranges\eat();
?>

//Apple.php
<?php
namespace Apples;

function eat()
{
  echo "eat apple";
}
?>

//Orange.php
<?php
namespace Oranges;

function eat()
{
  echo "eat Orange";
}
?>


/*類名引用flie1.php  */
<?php
namespace Foo\Bar\subnamespace;

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

<?php
namespace Foo\Bar;
include 'file1.php';

const FOO = 2;
function foo() {}
class foo
{
    static function staticmethod() {}
}

/* 非限定名稱 */
foo(); // 解析爲 Foo\Bar\foo
foo::staticmethod(); // 解析爲類 Foo\Bar\foo的靜態方法staticmethod。
echo FOO."<br/>"; // resolves to constant Foo\Bar\FOO

/* 限定名稱 */
subnamespace\foo(); // 解析爲函數 Foo\Bar\subnamespace\foo
subnamespace\foo::staticmethod(); // 解析爲類 Foo\Bar\subnamespace\foo,
                                  // 以及類的方法 staticmethod
echo subnamespace\FOO."<br/>"; // 解析爲常量 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
?>



/*在命名空間內部訪問全局類、函數和常量*/
<?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
?>


/*關鍵字 namespace 可用來顯式訪問當前命名空間或子命名空間中的元素。它等價於類中的 self 操作符。*/
<?php
namespace MyProject;
use blah\blah as mine; // see "Using namespaces: importing/aliasing"
blah\mine(); // calls function MyProject\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
?>


/*全局代碼*/
<?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
?>


四、
函數:

define()
在運行時定義一個常量。 成功時返回 TRUE, 或者在失敗時返回 FALSE。


<br> 可插入一個簡單的換行符。
<br> 標籤是空標籤(意味着它沒有結束標籤,因此這是錯誤的:<br></br>)。在 XHTML 中,把結束標籤放在開始標籤中,也就是 <br />。
php常用的是."<br />"

PHP5.3開始const關鍵字可以用在類的外部。const和define都是用來聲明常量的(它們的區別不詳述),但是在命名空間裏,define的作用是全局的,而const則作用於當前空間。我在文中提到的常量是指使用const聲明的常量。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章