您好,登錄后才能下訂單哦!
這篇文章主要介紹PHP 7.4的新增特性有哪些,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
PHP 7里程版本PHP 7.4在2019年11月28日正式發(fā)布。因此,現(xiàn)在該讓我們深入研究一些最令人興奮的新增功能和新功能,這些功能將使PHP更快,更可靠。 。
實(shí)際上,即使PHP 7.4顯著提高了性能并提高了代碼的可讀性,PHP 8仍將是PHP性能的真正里程碑,因?yàn)镴IT包含的建議已得到批準(zhǔn)。
無論如何,今天我們正在經(jīng)歷一些我們期望的PHP 7.4最有趣的功能和更改。 因此,在閱讀這篇文章之前,請(qǐng)確保保存以下日期:
6月6日:PHP 7.4 Alpha 1
7月18日:PHP 7.4 Beta 1 –功能凍結(jié)
11月28日:PHP 7.4 GA發(fā)布
您可以在RFC官方頁面上查看功能和添加項(xiàng)的完整列表。
PHP 7.4發(fā)布日期:
PHP 7.4計(jì)劃于2019年11月28日發(fā)布。它是下一個(gè)PHP 7次要版本,應(yīng)再次提高性能并提高代碼的可讀性/可維護(hù)性。
PHP 7.4中的PHP有何新功能?
在本文中,我們討論了PHP 7.4最終版本中應(yīng)在語言中添加的一些更改和功能:
支持?jǐn)?shù)組內(nèi)解包 – 數(shù)組擴(kuò)展Spread運(yùn)算符
箭頭函數(shù) 2.0 (更加簡(jiǎn)短的閉包)
NULL 合并運(yùn)算符
弱引用
協(xié)變返回和逆變參數(shù)
預(yù)加載
新的自定義對(duì)象序列化機(jī)制
性能提升,數(shù)組表達(dá)式中引入 Spread 運(yùn)算符…
自 PHP 5.6 起可用,參數(shù)解包是將數(shù)組和 Traversable 解包為參數(shù)列表的語法。要解壓一個(gè)數(shù)組或 Traversable,必須以 …(3 點(diǎn))為前綴,如下例所示:
function test(...$args) { var_dump($args); } test(1, 2, 3);
然而 PHP 7.4 RFC 建議將此功能擴(kuò)展到數(shù)組中去定義:
$arr = [...$args];
Spread 運(yùn)算符的第一個(gè)好處就是性能,RPC 文檔指出:
Spread 運(yùn)算符應(yīng)該比
array_merge
擁有更好的性能。這不僅僅是 Spread 運(yùn)算符是一個(gè)語法結(jié)構(gòu),而array_merge
是一個(gè)方法。還是在編譯時(shí),優(yōu)化了高效率的常量數(shù)組
Spread 運(yùn)算符的一個(gè)顯著優(yōu)點(diǎn)是它支持任何可遍歷的對(duì)象,而該 array_merge
函數(shù)僅支持?jǐn)?shù)組。以下是數(shù)組中參數(shù)帶有 Spread 運(yùn)算符的示例:
$parts = ['apple', 'pear']; $fruits = ['banana', 'orange', ...$parts, 'watermelon']; var_dump($fruits);
如果在 PHP 7.3 或更早版本中運(yùn)行此代碼,PHP 會(huì)拋出一個(gè) Parse 錯(cuò)誤:
Parse error: syntax error, unexpected '...' (T_ELLIPSIS), expecting ']' in /app/spread-operator.php on line 3
相反,PHP 7.4 將返回一個(gè)數(shù)組
array(5) { [0]=> string(6) "banana" [1]=> string(6) "orange" [2]=> string(5) "apple" [3]=> string(4) "pear" [4]=> string(10) "watermelon" }
RFC 聲明我們可以多次擴(kuò)展同一個(gè)數(shù)組。此外,我們可以在數(shù)組中的任何位置使用 Spread Operator 語法,因?yàn)榭梢栽?spread 運(yùn)算符之前或之后添加常規(guī)元素。因此,以下代碼將按預(yù)期工作:
$arr1 = [1, 2, 3]; $arr2 = [4, 5, 6]; $arr3 = [...$arr1, ...$arr2]; $arr4 = [...$arr1, ...$arr3, 7, 8, 9];
也可以將函數(shù)返回的數(shù)組作為參數(shù),放到新數(shù)組中:
function buildArray(){ return ['red', 'green', 'blue']; } $arr1 = [...buildArray(), 'pink', 'violet', 'yellow'];
PHP 7.4 輸出以下數(shù)組:
array(6) { [0]=> string(3) "red" [1]=> string(5) "green" [2]=> string(4) "blue" [3]=> string(4) "pink" [4]=> string(6) "violet" [5]=> string(6) "yellow" }
我們也可以使用生成器:
function generator() { for ($i = 3; $i <= 5; $i++) { yield $i; } } $arr1 = [0, 1, 2, ...generator()];
但不允許通過引用傳遞的方式。請(qǐng)考慮以下示例:
$arr1 = ['red', 'green', 'blue']; $arr2 = [...&$arr1];
如果我們嘗試通過傳遞引用的方式,PHP 會(huì)拋出以下 Parse 錯(cuò)誤:
Parse error: syntax error, unexpected '&' in /app/spread-operator.php on line 3
如果第一個(gè)數(shù)組的元素是通過引用存儲(chǔ)的,那么它們也通過引用存儲(chǔ)在第二個(gè)數(shù)組中。這是一個(gè)例子:
$arr0 = 'red'; $arr1 = [&$arr0, 'green', 'blue']; $arr2 = ['white', ...$arr1, 'black'];
這是我們用 PHP 7.4 獲得的:
array(5) { [0]=> string(5) "white" [1]=> &string(3) "red" [2]=> string(5) "green" [3]=> string(4) "blue" [4]=> string(5) "black" }
箭頭函數(shù) 2.0 (簡(jiǎn)短閉包)
在 PHP 中,匿名函數(shù)被認(rèn)為是非常冗長(zhǎng)且難以實(shí)現(xiàn)和難以維護(hù)的,RFC 建議引入更簡(jiǎn)單,更清晰的箭頭函數(shù)(或簡(jiǎn)短閉包)語法,這樣我們就可以簡(jiǎn)潔地編寫代碼。在 PHP 7.4 以前:
function cube($n){ return ($n * $n * $n); } $a = [1, 2, 3, 4, 5]; $b = array_map('cube', $a); print_r($b);
PHP 7.4 允許使用更簡(jiǎn)潔的語法,上面的函數(shù)可以重寫如下:
$a = [1, 2, 3, 4, 5]; $b = array_map(fn($n) => $n * $n * $n, $a); print_r($b);
目前,由于語言結(jié)構(gòu),匿名函數(shù)(閉包)可以使用 use
繼承父作用域中定義的變量,如下所示:
$factor = 10; $calc = function($num) use($factor){ return $num * $factor; };
但是在 PHP 7.4 中,父級(jí)作用域的值是通過隱式捕獲的(隱式按值的作用域進(jìn)行綁定)。所以我們可以用一行來完成一下這個(gè)函數(shù)
$factor = 10; $calc = fn($num) => $num * $factor;
父級(jí)作用域定義的變量可以用于箭頭函數(shù),它跟我們使用 use
是等價(jià)的,并且不可能被父級(jí)所修改。新語法是對(duì)語言的一個(gè)很大改進(jìn),因?yàn)樗试S我們構(gòu)建更易讀和可維護(hù)的代碼。
NULL 合并運(yùn)算符
由于日常使用中存在大量同時(shí)使用三元表達(dá)式和 isset () 的情況, 我們添加了 null 合并運(yùn)算符 (??) 這個(gè)語法糖。如果變量存在且值不為 NULL, 它就會(huì)返回自身的值,否則返回它的第二個(gè)操作數(shù)。
$username = $_GET['user'] ?? ‘nobody';
這段代碼的作用非常簡(jiǎn)單:它獲取請(qǐng)求參數(shù)并設(shè)置默認(rèn)值(如果它不存在)。但是在 RFC 這個(gè)例子中,如果我們有更長(zhǎng)的變量名稱呢?
$this->request->data['comments']['user_id'] = $this->request->data['comments']['user_id'] ?? 'value';
長(zhǎng)遠(yuǎn)來看,這段代碼可能難以維護(hù)。因此,旨在幫助開發(fā)人員編寫更直觀的代碼,這個(gè) RFC 建議引入 null 合并等于運(yùn)算符 (null_coalesce_equal_operator)??=
,所以我們可以敲下面這段代碼來替代上面的這段代碼:
$this->request->data['comments']['user_id'] ??= ‘value’;
如果左側(cè)參數(shù)的值為 null
,則使用右側(cè)參數(shù)的值。
注意,雖然 coalesce 運(yùn)算符 ??
是一個(gè)比較運(yùn)算符,但 ??=
它是賦值運(yùn)算符。
類型屬性 2.0
類型的聲明,類型提示,以及指定確定類型的變量傳遞給函數(shù)或類的方法。其中類型提示是在 PHP5 的時(shí)候有的一個(gè)功能,PHP 7.2 的時(shí)候添加了 object
的數(shù)據(jù)類型。而 PHP7.4 更是增加了主類屬性聲明,看下面的例子:
class User { public int $id; public string $name; }
除了 void
和 callable
外,所有的類型都支持
public int $scalarType; protected ClassName $classType; private ?ClassName $nullableClassType;
為什么不支持 void
和 callable
?下面是 RFC 的解釋
The
void
type is not supported, because it is not useful and has unclear semantics.
不支持void
類型,是因?yàn)樗鼪]用,并且語義不清晰。The
callable
type is not supported, because its behavior is context dependent.
不支持callable
類型,因?yàn)槠湫袨槿Q于上下文。
因此,我們可以放心使用 bool
,int
,float
,string
,array
,object
,iterable
,self
,parent
,當(dāng)然還有我們很少使用的 nullable
空允許 (?type
)
所以你可以在 PHP7.4 中這樣敲代碼:
// 靜態(tài)屬性的類型 public static iterable $staticProp; // var 中聲明屬性 var bool $flagl // 設(shè)置默認(rèn)的值 // 注意,只有 nullable 的類型,才能設(shè)置默認(rèn)值為 null public string $str = "foo"; public ?string $nullableStr = null; // 多個(gè)同類型變量的聲明 public float $x, $y;
如果我們傳遞不符合給定類型的變量,會(huì)發(fā)生什么?
class User { public int $id; public string $name; } $user = new User; $user->id = 10; $user->name = []; // 這個(gè)會(huì)產(chǎn)生一個(gè)致命的錯(cuò)誤 Fatal error: Uncaught TypeError: Typed property User::$name must be string, array used in /app/types.php:9
弱引用
在這個(gè) RFC 中,提議引入 WeakReference
這個(gè)類,弱引用允許編碼時(shí)保留對(duì)對(duì)象的引用,該引用不會(huì)阻止對(duì)象被破壞;這對(duì)于實(shí)現(xiàn)類似于緩存的結(jié)構(gòu)非常有用。
該提案的作者 Nikita Popov 給出的一個(gè)例子:
$object = new stdClass; $weakRef = WeakReference::create($object); var_dump($weakRef->get()); unset($object); var_dump($weakRef->get()); // 第一次 var_dump object(stdClass)#1 (0) {} // 第二次 var_dump,當(dāng) object 被銷毀的時(shí)候,并不會(huì)拋出致命錯(cuò)誤 NULL
協(xié)變返回和逆變參數(shù)
協(xié)變和逆變
百度百科的解釋
Invariant (不變): 包好了所有需求類型
Covariant (協(xié)變):類型從通用到具體
Contravariant (逆變): 類型從具體到通用目前,PHP 主要具有 Invariant
的參數(shù)類型,并且大多數(shù)是 Invariant
的返回類型,這就意味著當(dāng)我是 T 參數(shù)類型或者返回類型時(shí),子類也必須是 T 的參數(shù)類型或者返回類型。但是往往會(huì)需要處理一些特殊情況,比如具體的返回類型,或者通用的輸入類型。而 RFC 的這個(gè)提案就提議,PHP7.4 添加協(xié)變返回和逆變參數(shù),以下是提案給出來的例子:協(xié)變返回:
interface Factory { function make(): object; } class UserFactory implements Factory { // 將比較泛的 object 類型,具體到 User 類型 function make(): User; }
逆變參數(shù):
interface Concatable { function concat(Iterator $input); } class Collection implements Concatable { // 將比較具體的 `Iterator`參數(shù)類型,逆變成接受所有的 `iterable`類型 function concat(iterable $input) {/* . . . */} }
預(yù)加載
這個(gè) RFC 是由 Dmitry Stogov 提出的,預(yù)加載是在模塊初始化的時(shí)候,將庫(kù)和框架加載到 OPCache 中的過程,如下圖所示
引用他的原話:
On server startup – before any application code is run – we may load a certain set of PHP files into memory – and make their contents “permanently available” to all subsequent requests that will be served by that server. All the functions and classes defined in these files will be available to requests out of the box, exactly like internal entities.
服務(wù)器啟動(dòng)時(shí) – 在運(yùn)行任何應(yīng)用程序代碼之前 – 我們可以將一組 PHP 文件加載到內(nèi)存中 – 并使得這些預(yù)加載的內(nèi)容,在后續(xù)的所有請(qǐng)求中 “永久可用”。這些文件中定義的所有函數(shù)和類在請(qǐng)求時(shí),就可以開箱即用,與內(nèi)置函數(shù)相同。
預(yù)加載由 php.ini
的 opcache.preload
進(jìn)行控制。這個(gè)參數(shù)指定在服務(wù)器啟動(dòng)時(shí)編譯和執(zhí)行的 PHP 腳本。此文件可用于預(yù)加載其他文件,或通過 opcache_compile_file()
函數(shù)
這在性能上有很大的提升,但是也有一個(gè)很明顯的缺點(diǎn),RFC 提出來了
preloaded files remain cached in opcache memory forever. Modification of their corresponding source files won’t have any effect without another server restart.
預(yù)加載的文件會(huì)被永久緩存在 opcache 內(nèi)存中。在修改相應(yīng)的源文件時(shí),如果沒有重啟服務(wù),修改就不會(huì)生效。
新的自定義對(duì)象序列化機(jī)制
這是尼基塔·波波夫(Nikita Popov)的另一項(xiàng)建議 ,得到了絕大多數(shù)票的批準(zhǔn)。
當(dāng)前,我們有兩種不同的機(jī)制可以在PHP中對(duì)對(duì)象進(jìn)行自定義序列化:
__sleep()
和__wakeup()
魔術(shù)方法
可Serializable
接口
根據(jù)Nikita的說法,這兩個(gè)選項(xiàng)都存在導(dǎo)致復(fù)雜且不可靠的代碼的問題。 您可以在RFC中深入研究此主題。 在這里,我只提到新的序列化機(jī)制應(yīng)該通過提供兩個(gè)結(jié)合了兩個(gè)現(xiàn)有機(jī)制的新魔術(shù)方法__serialize()
和__unserialize()
來防止這些問題。
該提案以20票對(duì)7票獲得通過。
PHP7.4 又將廢棄什么功能呢?
更改連接運(yùn)算符的優(yōu)先級(jí)
目前,在 PHP 中 +
, -
算術(shù)運(yùn)算符和 .
字符串運(yùn)算符是左關(guān)聯(lián)的, 而且它們具有相同的優(yōu)先級(jí)。例如:
echo "sum: " . $a + $b;
在 PHP 7.3 中,此代碼生成以下警告:
Warning: A non-numeric value encountered in /app/types.php on line 4
這是因?yàn)檫@段代碼是從左往右開始的,所以等同于:
echo ("$sum: " . $a) + $b;
針對(duì)這個(gè)問題,這個(gè) RFC 建議更改運(yùn)算符的優(yōu)先級(jí),使 .
的優(yōu)先級(jí)低于 +
,-
這兩個(gè)運(yùn)算符,以便在字符串拼接之前始終執(zhí)行加減法。所以這行代碼應(yīng)該等同于以下內(nèi)容:
echo "$sum: " . ($a + $b);
這個(gè)提案分為兩步走:
從 PHP7.4 開始,當(dāng)遇見 +
-
和 .
在沒有指明執(zhí)行優(yōu)先級(jí)時(shí),會(huì)發(fā)出一個(gè)棄用通知。
而真正調(diào)整優(yōu)先級(jí)的這個(gè)功能,會(huì)在 PHP8 中執(zhí)行棄用左關(guān)聯(lián)三元運(yùn)算符在 PHP 中,三元運(yùn)算符與許多其他語言不同,它是左關(guān)聯(lián)的。而根據(jù) Nikita Popof 的所說:對(duì)于在不同語言之間切換的編程人員來說,會(huì)令他們感到困擾。比如以下的例子,在 PHP 中是正確的:$b = $a == 1 ? 'one' : $a == 2 ? 'two' : $a == 3 ? 'three' : 'other';
它會(huì)被解釋為:$b = (($a == 1 ? 'one' : $a == 2) ? 'two' : $a == 3) ? 'three' : 'other';
對(duì)于這種復(fù)雜的三元表現(xiàn)形式,它很有可能不是我們希望的方式去工作,容易造成錯(cuò)誤。因此,這個(gè) RFC 提議刪除并棄用三元運(yùn)算符的左關(guān)聯(lián)使用,強(qiáng)制編程人員使用括號(hào)。這個(gè)提議分為兩步執(zhí)行:
從 PHP7.4 開始,沒有明確使用括號(hào)的嵌套三元組將拋出棄用警告。
從 PHP 8.0 開始,將出現(xiàn)編譯運(yùn)行時(shí)錯(cuò)誤。
php7.4性能
出于對(duì)PHP 7.4的Alpha預(yù)覽版性能狀態(tài)的好奇,我今天針對(duì)使用Git構(gòu)建的PHP 7.3.6、7.2.18、7.1.29和7.0.32運(yùn)行了一些快速基準(zhǔn)測(cè)試,并且每個(gè)發(fā)行版均以相同的方式構(gòu)建。
在此階段,PHPBench的7.4性能與PHP 7.3穩(wěn)定版相當(dāng),已經(jīng)比PHP 7.0快了約30%…當(dāng)然,與PHP 5.5的舊時(shí)代相比,收益甚至更大。
在微基準(zhǔn)測(cè)試中,PHP 7.4的運(yùn)行速度僅比PHP 7.3快一點(diǎn),而PHP-8.0的性能卻差不多,至少要等到JIT代碼穩(wěn)定下來并默認(rèn)打開為止。
在Phoronix測(cè)試套件的內(nèi)部PHP自基準(zhǔn)測(cè)試中,PHP 7.4的確確實(shí)處于PHP 7.3性能水平之上-至少在此Alpha前狀態(tài)下。 自PHP 7.0起,取得了一些顯著的進(jìn)步,而自PHP5發(fā)行緩慢以來,也取得了許多進(jìn)步。
以上是“PHP 7.4的新增特性有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。