PHP 8 有哪些值得期待的新特性

新的 PHP 主要版本 PHP8 預(yù)計(jì)將于 2020 年底發(fā)布。

它現(xiàn)在正處于非常活躍的開(kāi)發(fā)中迹淌,所以在接下來(lái)的幾個(gè)月里,開(kāi)發(fā)速度和開(kāi)發(fā)進(jìn)程可能會(huì)有很大的變化己单。

在這篇文章中唉窃,我會(huì)羅列出 PHP8 中會(huì)發(fā)生的一些改變:新功能、性能改進(jìn)和突破性變化纹笼。

因?yàn)?PHP8 是一個(gè)新的主要版本纹份,所以代碼及語(yǔ)法向下兼容性會(huì)更低。

如果您一直保持與最新版本保持同步廷痘,那么升級(jí)應(yīng)該不會(huì)太難蔓涧,因?yàn)榇蠖鄶?shù)突破性的更改在 7.* 版本中都已棄用。

除了突破性的變化笋额,PHP8 還帶來(lái)了一些不錯(cuò)的新特性元暴,比如 JIT 編譯器和 union types,當(dāng)然還有其它更多的特性兄猩。

新特性

從新特性開(kāi)始說(shuō)起茉盏,但是 PHP8 仍在積極開(kāi)發(fā)中,因此這個(gè)清單將隨著時(shí)間的推移而增長(zhǎng)厦滤。

聯(lián)合類(lèi)型 (Union types) RFC

考慮到 PHP 的動(dòng)態(tài)類(lèi)型特性援岩,聯(lián)合類(lèi)型在很多情況下都很有用歼狼。

聯(lián)合類(lèi)型是兩個(gè)或多個(gè)類(lèi)型的集合掏导,這些類(lèi)型指示可以使用這兩個(gè)類(lèi)型中的任何一個(gè)。

public function foo(Foo|Bar $input): int|float;

我怎么感覺(jué)這個(gè)和 C 語(yǔ)言里的聯(lián)合體有點(diǎn)相似羽峰。

請(qǐng)注意趟咆,void 永遠(yuǎn)不能是聯(lián)合類(lèi)型的一部分,因?yàn)樗硎?“根本沒(méi)有返回值”梅屉。

此外值纱,可以使用|NULL或使用現(xiàn)有的坯汤。

public function foo(Foo|null $foo): void;

public function bar(?Bar $bar): void;

JIT RFC

JIT-Just-In-Time 編譯器承諾顯著提高性能虐唠,盡管在 Web 應(yīng)用可能沒(méi)有較大的好處。

在這一點(diǎn)上還沒(méi)有任何準(zhǔn)確的基準(zhǔn)惰聂,但它們肯定會(huì)出現(xiàn)的疆偿。

靜態(tài)返回類(lèi)型 (Static return type) RFC

雖然已經(jīng)可以返回 self 咱筛,但在 PHP8 之前,靜態(tài)不是有效的返回類(lèi)型杆故⊙嘎幔考慮到 PHP 的動(dòng)態(tài)類(lèi)型特性,它對(duì)許多開(kāi)發(fā)人員都很有用处铛。

class Foo
{
    public function test(): static
    {
        return new static();
    }
}

弱映射 (Weak maps) RFC

基于在 PHP 7.4 中添加的 WeakRefs RFC 的基礎(chǔ)上饲趋,在 PHP 8 中 添加了 WeakMap 實(shí)現(xiàn)。WeakMap 包含對(duì)對(duì)象的引用撤蟆,這不會(huì)阻止這些對(duì)象被垃圾回收奕塑。

以 ORM 為例,它們經(jīng)常實(shí)現(xiàn)包含對(duì)實(shí)體類(lèi)的引用的緩存枫疆,以提高實(shí)體之間關(guān)系的性能爵川。

這些實(shí)體對(duì)象不能被垃圾回收,只要該緩存有對(duì)它們的引用息楔,即使緩存是唯一引用它們的東西寝贡。

如果該緩存層改為使用弱引用和映射,則 PHP 將在其他對(duì)象不再引用這些對(duì)象時(shí)對(duì)它們進(jìn)行垃圾回收值依。
特別是在 ORM 的情況下圃泡,它可以在一個(gè)請(qǐng)求中管理數(shù)百個(gè) (如果不是數(shù)千個(gè)) 實(shí)體;弱映射可以提供一種更好愿险、更資源友好的方式來(lái)處理這些對(duì)象颇蜡。

以下是 Weak maps 的用法,RFC 中的一個(gè)示例:

class Foo 
{
    private WeakMap $cache;

    public function getSomethingWithCaching(object $obj): object
    {
        return $this->cache[$obj]
           ??= $this->computeSomethingExpensive($obj);
    }
}

可以在對(duì)象上使用::class RFC

一個(gè)小而有用的新特性:現(xiàn)在可以對(duì)對(duì)象使用::class辆亏,而不必對(duì)它們使用 get_class()风秤。

它的工作方式與 get_class() 相同。

$foo = new Foo();

var_dump($foo::class);

創(chuàng)建 DateTime 對(duì)象的接口

您已經(jīng)可以使用 DateTime::createFromImmutable($immutableDateTime)扮叨,從 DateTimeImmutable 對(duì)象創(chuàng)建DateTime對(duì)象缤弦,但是反過(guò)來(lái)很棘手。

通過(guò)添加 DateTime::createFromInterface() 和 DatetimeImmutable::createFromInterface()彻磁,現(xiàn)在有了一種將 DateTime 和 DateTimeImmutable 對(duì)象相互轉(zhuǎn)換的通用方法碍沐。

DateTime::createFromInterface(DateTimeInterface $other);

DateTimeImmutable::createFromInterface(DateTimeInterface $other);

新的 Stringable 接口 RFC

Stringable 接口可用于鍵入提示任何字符串或?qū)崿F(xiàn)__toString()

此外衷蜓,每當(dāng)類(lèi)實(shí)現(xiàn)__toString()時(shí)累提,它都會(huì)自動(dòng)在幕后實(shí)現(xiàn)接口,不需要手動(dòng)實(shí)現(xiàn)它磁浇。

class Foo
{
    public function __toString(): string
    {
        return 'foo';
    }
}

function bar(Stringable $stringable) { /* … */ }

bar(new Foo());
bar('abc');

新的 str_contains () 函數(shù) RFC

有些人可能會(huì)說(shuō)這是早就應(yīng)該實(shí)現(xiàn)的功能斋陪,但是我們最終不必再依賴(lài) strpos () 來(lái)知道一個(gè)字符串是否包含另一個(gè)字符串。

以前:

if (strpos('string with lots of words', 'words') !== false) { /* … */ }

現(xiàn)在:

if (str_contains('string with lots of words', 'words')) { /* … */ }

新的 fdiv () 函數(shù) PR

新的 fdiv () 函數(shù)的作用類(lèi)似于 fmod () 和 intdiv () 函數(shù),它們?cè)试S被 0 整除无虚。

您將得到 INF鞍匾、-INF 或 NaN ,而不是錯(cuò)誤骑科,具體取決于大小寫(xiě)橡淑。

新的 get_debug_type () 函數(shù) RFC

get_debug_type () 返回一個(gè)變量的類(lèi)型。

聽(tīng)起來(lái)像是 gettype () 可以實(shí)現(xiàn)的功能咆爽。

get_debug_type () 為數(shù)組梁棠、字符串、匿名類(lèi)和對(duì)象返回更有用的輸出斗埂。

例如符糊,在類(lèi) \foo\Bar 上調(diào)用 gettype () 將返回 Object。

使用 get_debug_type () 將返回類(lèi)名呛凶。

可以在 RFC 中找到 get_debug_type () 和 gettype () 之間差異的完整列表男娄。

改進(jìn) traits 里的抽象方法 RFC

traits 可以指定必須由使用它們的類(lèi)實(shí)現(xiàn)的抽象方法。

但是有一個(gè)警告:在 PHP8 之前漾稀,這些方法實(shí)現(xiàn)的簽名沒(méi)有經(jīng)過(guò)驗(yàn)證模闲。

在以下代碼中有效:

trait Test {
    abstract public function test(int $input): int;
}

class UsesTrait
{
    use Test;

    public function test($input)
    {
        return $input;
    }
}

在使用 traits 并實(shí)現(xiàn)其抽象方法時(shí),PHP8 將執(zhí)行正確的方法簽名驗(yàn)證崭捍。

這意味著您需要改寫(xiě)以下內(nèi)容:

class UsesTrait
{
    use Test;

    public function test(int $input): int
    {
        return $input;
    }
}

token_get_all () 的對(duì)象接口 RFC

函數(shù)的作用是:返回值的是一個(gè)數(shù)組尸折。

此 RFC 使用 PhpToken::getall () 方法添加一個(gè) PhpToken 類(lèi)。

此實(shí)現(xiàn)使用對(duì)象殷蛇,而不是普通值实夹。

它消耗更少的內(nèi)存,更容易閱讀粒梦。

變量語(yǔ)法調(diào)整 RFC

來(lái)自 RFC:“統(tǒng)一變量語(yǔ)法 RFC 解決了 PHP 變量語(yǔ)法中的一些不一致問(wèn)題”亮航,這個(gè) RFC 打算解決少數(shù)被忽略的情況。

內(nèi)部函數(shù)的類(lèi)型批注

很多人都參與到為所有內(nèi)部函數(shù)添加適當(dāng)類(lèi)型注釋的工作中匀们。

這是一個(gè)長(zhǎng)期存在的問(wèn)題缴淋,通過(guò)在以前版本中對(duì) PHP 所做的所有更改,最終可以解決這個(gè)問(wèn)題昼蛀。

這意味著內(nèi)部函數(shù)和方法在反射中將具有完整的類(lèi)型信息宴猾。

統(tǒng)一錯(cuò)誤類(lèi)型 RFC

PHP 中的用戶(hù)定義函數(shù)已經(jīng)拋出 TypeErrors圆存,但是內(nèi)部函數(shù)沒(méi)有拋出 TypeErrors叼旋,而是發(fā)出警告并返回 NULL。
從 PHP8 開(kāi)始沦辙,內(nèi)部函數(shù)的行為已經(jīng)保持一致夫植。

重新分類(lèi) zend engine 報(bào)錯(cuò) RFC

  • 許多以前只觸發(fā)警告或通知的錯(cuò)誤已轉(zhuǎn)換為適當(dāng)?shù)腻e(cuò)誤。
  • 以下警告已更改。
  • 未定義變量:錯(cuò)誤異常而不是通知详民。
  • 未定義的數(shù)組索引:警告而不是通知延欠。
  • 被零除:DivisionByZeroError 異常而不是警告。
  • 嘗試遞增 / 遞減非對(duì)象的屬性‘% s’:錯(cuò)誤異常而不是警告沈跨。
  • 試圖修改非對(duì)象的屬性‘% s’:錯(cuò)誤異常而不是警告由捎。
  • 嘗試分配非對(duì)象的屬性‘% s’:錯(cuò)誤異常而不是警告。
  • 從空值創(chuàng)建默認(rèn)對(duì)象:錯(cuò)誤異常而不是警告饿凛。
  • 正在嘗試獲取非對(duì)象的屬性‘% s’:警告而不是通知狞玛。
  • 未定義屬性:% s::$% s:警告而不是通知。
  • 無(wú)法將元素添加到數(shù)組涧窒,因?yàn)橄乱粋€(gè)元素已被占用:錯(cuò)誤異常而不是警告心肪。
  • 無(wú)法取消設(shè)置非數(shù)組變量中的偏移量:錯(cuò)誤異常而不是警告。
  • 不能將標(biāo)量值用作數(shù)組:錯(cuò)誤異常而不是警告纠吴。
  • 只能解包數(shù)組和遍歷:TypeError 異常而不是警告硬鞍。
  • 為 foreach () 提供的參數(shù)無(wú)效:TypeError 異常而不是警告。
  • 偏移類(lèi)型非法:TypeError 異常而不是警告戴已。
  • isset 中的偏移類(lèi)型非法或?yàn)榭眨篢ypeError 異常而不是警告固该。
  • 未設(shè)置中的偏移類(lèi)型非法:TypeError 異常而不是警告。
  • 數(shù)組到字符串的轉(zhuǎn)換:警告而不是通知糖儡。
  • 資源 ID#% d 用作偏移量蹬音,轉(zhuǎn)換為整數(shù) (% d):警告而不是通知。
  • 發(fā)生字符串偏移量轉(zhuǎn)換:警告而不是通知休玩。
  • 未初始化的字符串偏移量:% d:警告而不是通知著淆。
  • 無(wú)法將空字符串分配給字符串偏移量:錯(cuò)誤異常而不是警告

默認(rèn)錯(cuò)誤報(bào)告級(jí)別

現(xiàn)在是 E_ALL,而不是除 E_NOTICE 和 E_DEVERATED 之外的所有內(nèi)容拴疤。

這意味著可能會(huì)彈出許多以前被悄悄忽略的錯(cuò)誤永部,盡管在 PHP8 之前可能已經(jīng)存在。

@運(yùn)算符不再忽略致命錯(cuò)誤

此更改可能會(huì)揭示在 PHP8 之前隱藏的錯(cuò)誤呐矾。請(qǐng)確保在生產(chǎn)服務(wù)器上設(shè)置 display_errors=off 苔埋!

串聯(lián)優(yōu)先級(jí) RFC

雖然在 PHP7.4 中已不推薦使用,但此更改現(xiàn)在生效蜒犯。

如果你這樣寫(xiě)的話(huà):

echo "sum: " . $a + $b;

PHP 以前會(huì)這樣解釋它:

echo ("sum: " . $a) + $b;

PHP 8 將會(huì)這樣解釋它:

echo "sum: " . ($a + $b);

反射方法簽名更改

反射類(lèi)的三個(gè)方法簽名已更改:

ReflectionClass::newInstance($args);
ReflectionFunction::invoke($args);
ReflectionMethod::invoke($object, $args);

現(xiàn)已成為:

ReflectionClass::newInstance(...$args);
ReflectionFunction::invoke(...$args);
ReflectionMethod::invoke($object, ...$args);

升級(jí)指南指定组橄,如果您擴(kuò)展了這些類(lèi),并且仍然希望同時(shí)支持 PHP 7 和 PHP 8罚随,則允許以下簽名:

ReflectionClass::newInstance($arg = null, ...$args);
ReflectionFunction::invoke($arg = null, ...$args);
ReflectionMethod::invoke($object, $arg = null, ...$args);

其他

在 PHP7.* 開(kāi)發(fā)過(guò)程中玉工,被用的 RFC,現(xiàn)在已在 PHP8 中完成淘菩。

image

很多PHPer在進(jìn)階的時(shí)候總會(huì)遇到一些問(wèn)題和瓶頸遵班,業(yè)務(wù)代碼寫(xiě)多了迷茫沒(méi)方向,不知道該從哪兒入手去提升自己∠林#→→管理整理了一些資料腹暖,有 騰訊 等一線(xiàn)大廠(chǎng)進(jìn)階知識(shí)體系 可供參考(相關(guān)學(xué)習(xí)資料以及筆面試題)

覆蓋各個(gè)技術(shù)棧:分布式架構(gòu)、高可擴(kuò)展翰萨、高性能脏答、高并發(fā)、服務(wù)器性能調(diào)優(yōu)亩鬼、TP6以蕴,laravel,YII2辛孵,Redis丛肮,Swoole、Swoft魄缚、Kafka宝与、Mysql優(yōu)化、shell腳本冶匹、Docker习劫、微服務(wù)、Nginx等多個(gè)知識(shí)點(diǎn)高級(jí)進(jìn)階干貨歡迎加入我的官方群點(diǎn)擊此處

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嚼隘,一起剝皮案震驚了整個(gè)濱河市诽里,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌飞蛹,老刑警劉巖谤狡,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異卧檐,居然都是意外死亡墓懂,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)霉囚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)捕仔,“玉大人,你說(shuō)我怎么就攤上這事盈罐“竦” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵盅粪,是天一觀(guān)的道長(zhǎng)钓葫。 經(jīng)常有香客問(wèn)我,道長(zhǎng)湾揽,這世上最難降的妖魔是什么瓤逼? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮库物,結(jié)果婚禮上霸旗,老公的妹妹穿的比我還像新娘。我一直安慰自己戚揭,他們只是感情好诱告,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著民晒,像睡著了一般精居。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上潜必,一...
    開(kāi)封第一講書(shū)人閱讀 49,760評(píng)論 1 289
  • 那天靴姿,我揣著相機(jī)與錄音,去河邊找鬼磁滚。 笑死佛吓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的垂攘。 我是一名探鬼主播维雇,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼晒他!你這毒婦竟也來(lái)了吱型?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤陨仅,失蹤者是張志新(化名)和其女友劉穎津滞,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體灼伤,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡据沈,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了饺蔑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锌介。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖猾警,靈堂內(nèi)的尸體忽然破棺而出孔祸,到底是詐尸還是另有隱情,我是刑警寧澤发皿,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布崔慧,位于F島的核電站,受9級(jí)特大地震影響穴墅,放射性物質(zhì)發(fā)生泄漏惶室。R本人自食惡果不足惜温自,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望皇钞。 院中可真熱鬧悼泌,春花似錦、人聲如沸夹界。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)可柿。三九已至鸠踪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間复斥,已是汗流浹背营密。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留目锭,地道東北人卵贱。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像侣集,于是被迫代替她去往敵國(guó)和親键俱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348