說明
目前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_last和error_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!