PHP名稱空間與自動載入簡述

閏了個土發表於2018-04-27

圖片來自www.ngchina.com.cn網

名稱空間(PHP 5 >= 5.3.0, PHP 7)

什麼是名稱空間?從廣義上來說,名稱空間是一種封裝事物的方法。在很多地方都可以見到這種抽象概念。例如,在作業系統中目錄用來將相關檔案分組,對於目錄中的檔案來說,它就扮演了名稱空間的角色。具體舉個例子,檔案 foo.txt 可以同時在目錄/home/greg 和 /home/other 中存在,但在同一個目錄中不能存在兩個 foo.txt 檔案。另外,在目錄 /home/greg 外訪問 foo.txt 檔案時,我們必須將目錄名以及目錄分隔符放在檔名之前得到 /home/greg/foo.txt。這個原理應用到程式設計領域就是名稱空間的概念。

在PHP中,名稱空間用來解決在編寫類庫或應用程式時建立可重用的程式碼如類或函式時碰到的兩類問題:

  1. 使用者編寫的程式碼與PHP內部的類/函式/常量或第三方類/函式/常量之間的名字衝突。
  2. 為很長的識別符號名稱(通常是為了緩解第一類問題而定義的)建立一個別名(或簡短)的名稱,提高原始碼的可讀性。

PHP 名稱空間提供了一種將相關的類、函式和常量組合到一起的途徑。

舉栗子:

file.php 檔案
<?php
// 使用namespace關鍵字定義名稱空間,
// 且之前不能有東西
namespace Test;  
const IN = 'oooo';
function tete()
{
    return __METHOD__;
}
class lala
{
    function init()
    {
        return __METHOD__;
    }
}
autoload.php 檔案
<?php
include 'file.php';
// 函式和常量是不支援use匯入規則的,只有類能支援匯入規則。
// 如果只是使用use Test就會報錯 The use statement with non-compound name 'Test' has no effect in..
use Test\lala;   // 也可以use Test\lala as lululu;
echo Test\IN."\n";
$te = new lala(); // new lululu(); // 也可以使用這樣的方式來避免兩個相同的類名稱
複製程式碼

總結:

  • 雖然任意合法的PHP程式碼都可以包含在名稱空間中,但只有以下型別的程式碼受名稱空間的影響,它們是:類(包括抽象類和traits)、介面、函式和常量。
  • 名稱空間通過關鍵字namespace 來宣告。如果一個檔案中包含名稱空間,它必須在其它所有程式碼之前宣告名稱空間,除了一個以外:declare關鍵字。
  • 與目錄和檔案的關係很象,PHP 名稱空間也允許指定層次化的名稱空間的名稱。如「namespace MyProject\Sub\Level;」
  • 也可以在同一個檔案中定義多個名稱空間,但是要使用大括號的形式。例如:
namespace MyProject {
    const CONNECT_OK = 1;
    class Connection { /* ... */ }
    function connect() { /* ... */  }
}

namespace AnotherProject {
    const CONNECT_OK = 1;
    class Connection { /* ... */ }
    function connect() { /* ... */  }
}
複製程式碼

以上這些是簡單的概述,詳情請移步php官網

自動載入

在編寫物件導向(OOP) 程式時,很多開發者為每個類新建一個 PHP 檔案。 這會帶來一個煩惱:每個指令碼的開頭,都需要包含(include)一個長長的列表(每個類都有個檔案)。例如:

<?php

include "test1.php";
include "test2.php";
include "test3.php";
......
複製程式碼

那如何避免這種情況呢? 在 PHP 5 中,已經不再需要這樣了。 spl_autoload_register() 函式可以註冊任意數量的自動載入器,當使用尚未被定義的類(class)和介面(interface)時自動去載入。通過註冊自動載入器,指令碼引擎在 PHP 出錯失敗前有了最後一個機會載入所需的類。舉一個栗子:

lala.php 檔案
<?php
class lala
{
    function init()
    {
        return __METHOD__;
    }
}

autoload.php 檔案
<?php
spl_autoload_register(function ($class_name){
    // 在這裡引入將要載入的類檔案
    // 但是有一點,載入的類檔案的檔名稱必須是和類名稱一樣
    require_once $class_name.'.php'; 
});
$tt = new lala();
$tt->init();
複製程式碼

現在隨便一個很小的專案都需要幾十個甚至幾百個類,當然了不同功能的類還需要區分在不同的資料夾中,這樣載入就有點麻煩了。 在這裡我們引入PSR-4自動載入規範。結合上面我們所講到的名稱空間,在規範內就可以輕鬆解決我們內心的擔憂。

.目錄結構
├── App
│   └── MyClass.php
└── test.php
MyClass.php檔案
<?php 
namespace App;
class MyClass {
	public function WhoAmI() {
		return __METHOD__;
	}
}

test.php檔案
<?php
spl_autoload_register(function($class_name) {
	require_once str_replace('\\','/',$class_name).'.php';
});
use App\MyClass as MC;
$obj = new MC();
echo $obj->WhoAmI()."\n";  // App\MyClass::WhoAmI
複製程式碼

這只是一個簡單的例子,想要了解實際專案中的自動載入的概念,可以移步composer。當然了首先要知道PSR-4的相關規範......

時2018年4月24日寫

相關文章