Use PHP7

reallyli發表於2019-02-16

說明

目前RC3中,PHP 7.2計劃於11月30日釋出。新版本將提供新的特性,功能和改進,使我們能夠編寫更好的程式碼。在這篇文章中,我將介紹一些PHP 7.2中最有趣的語言特性。

引數型別宣告

從PHP 5開始,我們可以在函式的宣告中指定期望傳遞的引數型別。如果給定的值是不正確的型別,那麼PHP會丟擲一個錯誤。引數型別宣告(也稱為型別提示)指定預期要傳遞給函式或類方法的變數的型別。

例如下面這個例子:

class MyClass {
    public $var = `Hello World`;
}

$myclass = new MyClass;

function test(MyClass $myclass){
    return $myclass->var;
}

echo test($myclass);

在這個程式碼中,測試函式需要MyClass的一個例項。不正確的資料型別將導致以下致命錯誤:

Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of MyClass, string given, called in /app/index.php on line 12 and defined in /app/index.php:8

由於PHP 7.2 型別提示可以與物件資料型別一起使用,並且這種改進允許宣告通用物件作為函式或方法的引數。這裡是一個例子:

class MyClass {
    public $var = ``;
}

class FirstChild extends MyClass {
    public $var = `My name is Jim`;
}
class SecondChild extends MyClass {
    public $var = `My name is John`;
}

$firstchild = new FirstChild;
$secondchild = new SecondChild;

function test(object $arg) {
    return $arg->var;
}

echo test($firstchild);

echo test($secondchild);

在這個例子中,我們呼叫了兩次測試函式,每次呼叫都傳遞一個不同的物件。在以前的PHP版本中這是不可能的。

Docker命令
在Docker中使用PHP 7.0和PHP 7.2測試型別提示

物件返回型別宣告

如果引數型別宣告指定函式引數的預期型別,則返回型別宣告指定返回值的預期型別。

返回型別宣告指定了一個函式應該返回的變數的型別。
從PHP 7.2開始,我們被允許為物件資料型別使用返回型別宣告。這裡是一個例子:

class MyClass {
    public $var = `Hello World`;
}

$myclass = new MyClass;

function test(MyClass $arg) : object {
    return $arg;
}

echo test($myclass)->var;

以前的PHP版本會導致以下致命錯誤:

Fatal error: Uncaught TypeError: Return value of test() must be an instance of object, instance of MyClass returned in /app/index.php:10

當然,在PHP 7.2中,這個程式碼回應了“Hello World”。

引數型別加寬

PHP目前不允許子類和它們的父類或介面之間的引數型別有任何差異。這意味著什麼?
考慮下面的程式碼:

<?php
class MyClass {
    public function myFunction(array $myarray) { /* ... */ }
}

class MyChildClass extends MyClass {
    public function myFunction($myarray) { /* ... */ }
}

這裡我們省略了子類中的引數型別。在PHP 7.0中,這段程式碼會產生以下警告:

Warning: Declaration of MyChildClass::myFunction($myarray) should be compatible with MyClass::myFunction(array $myarray) in %s on line 8

PHP 7.2以來,我們被允許在不破壞任何程式碼的情況下省略子類中的型別。這個建議將允許我們升級類來在庫中使用型別提示,而不需要更新所有的子類。

在列表語法中尾隨逗號

陣列中最後一項之後的尾隨逗號是PHP中的有效語法有時為了方便追加新專案並避免由於缺少逗號而導致解析錯誤,鼓勵使用該語法。自PHP 7.2以來,我們被允許分組名稱空間中使用尾隨逗號

請參閱列表語法中的尾隨逗號以便在此RFC處獲得更近的檢視以及一些程式碼示例。

安全改進

密碼雜湊中的Argon2

Argon2是一個強大的雜湊演算法,被選為2015年密碼雜湊大賽的冠軍,PHP 7.2將它作為Bcrypt演算法的安全替代品。
新的PHP版本引入了PASSWORD_ARGON2I常量,現在可以在password_*函式中使用它:

password_hash(`password`, PASSWORD_ARGON2I);

與僅使用一個成本因素的Bcrypt不同,Argon2需要三個成本因素區分如下:

  • 甲儲存器成本它定義了應雜湊期間被消耗KIB的數(預設值是1 << 10,或1024 KIB,或1 MIB)
  • 甲時間成本定義雜湊演算法的迭代次數(預設為2)
  • 一個並行因子,用於設定雜湊期間將使用的並行執行緒數(預設值為2)

三個新的常量定義了預設的成本因素:

  • PASSWORD_ARGON2_DEFAULT_MEMORY_COST
  • PASSWORD_ARGON2_DEFAULT_TIME_COST
  • PASSWORD_ARGON2_DEFAULT_THREADS

這裡是一個例子:

$options = [`memory_cost` => 1<<11, `time_cost` => 4, `threads` => 2];
password_hash(`password`, PASSWORD_ARGON2I, $options);

有關更多資訊,請參閱Argon2密碼雜湊

Libsodium作為PHP Core的一部分

從版本7.2開始,PHP將鈉庫納入核心。Libsodium 是一個跨平臺和跨語言的庫,用於加密,解密,簽名,密碼雜湊等等。以前通過 PECL 提供。有關Libsodium功能的文件列表,請參閱庫快速入門指南。另請參閱PHP 7.2:將現代加密技術新增到其標準庫中的第一種程式語言。

棄用

以下是PHP 8.0 不推薦使用的函式和功能列表,不晚於PHP 8.0:

該__autoload功能已被取代由spl_autoload_register在PHP 5.1。現在,在編譯期間遇到棄用通知。

在$ php_errormsg中時,丟擲一個非致命錯誤變數是在區域性範圍內建立。由於應該使用PHP 7.2 error_get_lasterror_clear_last

create_function()允許建立一個帶有生成函式名稱的函式,一系列引數和正文程式碼作為引數提供。由於安全問題和效能不佳,已將其標記為已棄用,並鼓勵使用附件。

已將 mbstring.func_overload ini設定為非零值已被標記為已棄用。

(unset)cast 是一個總是返回null的表示式,被認為是無用的。

如果提供了第二個引數,parse_str()會將查詢字串解析為陣列,如果不使用,則解析為本地符號表。由於出於安全原因不鼓勵在函式範圍內設定變數,使用不帶第二個引數的 parse_str() 將丟擲棄用通知。

gmp_random() 被認為是平臺相關的,將被棄用。使用 gmp_random_bits()gmp_random_rage()來代替。

each() 被用來像 foreach() 那樣迭代一個陣列,但是 foreach() 有幾個原因是可取的,包括快10倍。現在,在迴圈的第一個呼叫中將會拋棄。

所述斷言函式檢查給定的斷言,並採取適當的行動,如果結果是FALSE。帶有字串引數的 assert() 的使用現在已被棄用,因為它會開啟一個 RCE 漏洞。該 zend.assertion INI 選項可用於防止斷言表示式的評價。

$ errcontext是包含生成錯誤時存在的區域性變數的陣列。它作為使用 set_error_handler() 函式設定的錯誤處理程式的最後一個引數傳遞。

結尾說明

翻譯自 https://kinsta.com/blog/php-7-2/

Script Maker Day Day Up!

相關文章