PHP新特性之名稱空間、性狀和生成器

蕭瀟發表於2017-08-03

1.名稱空間

名稱空間是什麼?

1).名稱空間在PHP 5.3中被引入,類似於資料夾的功能。例如Symfony框架中的Request和Response,位於Symfony的名稱空間下。
2).名稱空間始終應該在<?php標籤的下面一行。
3).PHP檔案的名稱空間和作業系統的物理檔案系統不同,這是一個虛擬的概念,沒有必要和檔案系統的目錄結構完全對應。雖然如此,絕大多數PHP元件為了相容廣泛使用的PSR4自動載入標準,會把子名稱空間放到檔案系統的子目錄中去。
4).名稱空間只是PHP語言的一種記號,PHP直譯器會將這種記號作為字首新增到類、介面、函式和常量的名稱前面。

為什麼需要名稱空間?

1).名稱空間使得程式可以像沙盒一樣執行,可以和其他開發者編寫的程式碼一起使用。確保了自己的程式碼和專案可以和專案的第三方依賴一起使用。

宣告名稱空間

1).頂層名稱空間經常用於設定頂層廠商名。
2).廠商的名稱空間必須具有全域性唯一性,子名稱空間就沒有那麼重要,但有助於組織專案的程式碼。

匯入和別名

1).從PHP5.3開始可以匯入PHP類、介面和其他名稱空間,併為其建立別名。從PHP5.6開始可以匯入PHP函式和常量,併為其建立別名。
2).使用use關鍵字匯入程式碼時無須在開頭加上\符號,因為PHP假定匯入的是完全限定名稱空間。use關鍵字必須出現在全域性作用域中即不能出現在類或者函式中,因為這個關鍵字是在編譯的時候使用的,不過,use關鍵字可以在名稱空間宣告語句後使用,匯入其他名稱空間的程式碼。
從PHP5.6開始我們可以匯入函式和常量。

<?php
use func Namespace\functionName;

functionName();複製程式碼

也可以匯入常量,

use constant Namespace\CONS_NAME;
echo CONS_NAME;複製程式碼

函式和常量的別名與類名的建立方式一樣。

最佳實踐

1).PHP允許在一個PHP檔案中定義多個名稱空間。但是這麼做容易讓人困惑,違背了一個檔案一個類的良好實踐。
2).在一個名稱空間中引用全域性的名稱空間的程式碼時,需要加上\字首,告訴PHP需要在全域性中查詢該類,例如PHP原生的異常類。

自動載入

1).名稱空間為PHP-FIG制定的PSR4自動載入器奠定了堅實的基礎。

2.使用介面

1).就像我可以選擇開不一樣的車。因為他們都有方向盤、油門和剎車,並且燃料都是汽油。

3.性狀

1).形狀是類的部分實現(常量、屬性和方法),可以混入一個或者多個現有的PHP類中,性狀有兩個作用,表明類可以做什麼(類似介面),提供模組化實踐(類似類)。
2).性狀使得兩個無關的類可以使用相同屬性和方法。
3).PHP直譯器會把性狀複製貼上到類的定義體中。

4.建立生成器

1)在普通函式中一次或者多次使用yield關鍵字,不返回值,只生成值,這個函式就是一個生成器。例如:

<?php
function myGenerator() {
    yield 'value1'yield 'value2';
}複製程式碼

呼叫生成器函式的時候,PHP會返回一個屬於Generator類的物件,這個物件可以使用foreach()函式迭代,每次迭代,PHP會要求這個物件的例項計算並提供下一個要迭代的值,生成器的優雅之處就是在每產出一個值之後,生成器內部狀態會一直停頓和恢復之間切換,直到抵達定義體的末尾或者遇到空的return;語句為止,例如:

<?php
foreach (myGenerator() as $yieldedValue) {
    echo $yieldedValue, PHP_EOL;
}複製程式碼

以上例子會輸出

value1
value2複製程式碼

2).生成器是如何節約記憶體的?生成一個範圍內的數值(錯誤方式)

function makeRange($length) {
    $dataset = [];
    for ($i=0; $i < $length; $i++) {
      $dataset[] = $i;
    }
    return $dataset;
}

$customRange = makeRange(1000000);
foreach ($customeRange as $i) {
    echo $i, PHP_EOL;
}複製程式碼

預先建立了一個包含很大整陣列成的陣列,再看使用生成器的例子。

function makeRange($length) {
    for ($i = 0; $i < $length; $i++) {
        yield $i;
    }
}

foreach(makeRange(1000000) as $i) {
    echo $i, PHP_EOL;
}複製程式碼

在實際的例如迭代一個4GB大小的檔案中功能中,迭代器大展身手。

function getRows($file) {
    $handle = fopen($file, 'rb');
    if ($handle === false) {
        throw new Exception();
    }
    //feof()函式檢測是否到達檔案末尾
    while (feof($handle) === false) {
        //fgetcsv()一次讀取csv檔案的一行
        yield fgetcsv($handle);
    }
    fclose($handle)
}

foreach (getRows('data.csv') as $row) {
    print_r($row);
}複製程式碼

3).生成器沒有為PHP新增新功能,需要實現在資料集中執行快進、快退和查詢,最好自己編寫類實現Iterator介面,或者使用PHP標準庫中的某個原生迭代器。
原生迭代器連結

專題系列

PHP專題系列目錄地址:github.com/xx19941215/…
PHP專題系列預計寫二十篇左右,主要總結我們日常PHP開發中容易忽略的基礎知識和現代PHP開發中關於規範、部署、優化的一些實戰性建議,同時還有對Javascript語言特點的深入研究。

相關文章