摘要:PHP 語(yǔ)言的創(chuàng)始人 Rasmus Lerdorf 生于 1968 年,今年已 51 歲,他在 1995 年以 Personal Home Page Tools 為名發(fā)布了 PHP 1.0。他的輝煌隨著雅虎在搜索領(lǐng)域的頹敗而黯淡。
1997 年,以色列程序員 Zeev Suraski 及 Andi Gutmans 加入了 Zend 公司 的 PHP 語(yǔ)言開(kāi)發(fā),發(fā)布了 PHP 3, PHP 4, PHP 5,注意沒(méi)有 PHP 6,再到現(xiàn)在的 PHP 7。 1975 年出生的 Zeev Suraski 在 Zend 工作了 20 年。也許是在語(yǔ)言、架構(gòu)和庫(kù)的工作上找不到發(fā)展方向了。
前幾天 Zeev Suraski 宣布從 Zend 離職,業(yè)界比較驚訝,PHP 7 優(yōu)化的開(kāi)發(fā)者鳥(niǎo)哥說(shuō)是這是早已預(yù)定好的事。原來(lái) Zeev Suraski 辭職,他想做 P++,那 P++ 是啥?他通過(guò)《P++ idea: FAQ》進(jìn)行了回答,筆者作了全文翻譯。

原文翻譯:
這是一份對(duì)在 internals@(internals@:PHP 內(nèi)部開(kāi)發(fā)人員郵件列表。這里涉及 PHP 的開(kāi)發(fā)機(jī)制,當(dāng)內(nèi)部討論成熟后,會(huì)公開(kāi)在 externals,通常用來(lái)提交 RFC 和發(fā)布版本通知。) 上提出的想法的常見(jiàn)問(wèn)題澄清,它試圖解決許多在隨后討論中被反復(fù)提出的問(wèn)題。
注:P++ 是一個(gè)臨時(shí)代碼命名,未來(lái)可能會(huì)變化。
這到底是怎么回事?
試圖將冗長(zhǎng)的郵件內(nèi)容濃縮為幾點(diǎn):
PHP 世界有兩個(gè)大的陣營(yíng)。第一個(gè)大致喜歡 PHP 的動(dòng)態(tài)性,帶有強(qiáng)烈的 BC偏見(jiàn)(BC:即 Backward Compatibility,向后兼容,也叫向下兼容,兼容過(guò)去的版本,即升級(jí)的軟件要考慮舊版本的兼容性,比如,Office 2019 的 Word 默認(rèn)使用 .docx 文件格式,但也可以打開(kāi) Office 2017/2013/2010,甚至是 2003 的 .doc 格式。相對(duì)的概念叫做 FC,即 Forward Compatibility,向前兼容,也叫向上兼容,即升級(jí)的軟件會(huì)考慮對(duì)未來(lái)的兼容性。這在軟件中通常為一個(gè)確定的接口和約定,未來(lái)依然遵循,即可實(shí)現(xiàn)向前兼容。),并特別強(qiáng)調(diào)簡(jiǎn)單性,另一個(gè)更喜歡減掉包袱,擁有更高級(jí)、更復(fù)雜功能的更嚴(yán)格的語(yǔ)言。
這里沒(méi)有“對(duì)”或“錯(cuò)”。這兩種流派都有效,并具有非常堅(jiān)定的追隨者。然而,創(chuàng)建一種同時(shí)迎合這兩個(gè)陣營(yíng)的語(yǔ)言則是一項(xiàng)挑戰(zhàn),這也是 internals@ 上爭(zhēng)論的一貫的原因。
該提議是創(chuàng)建一種新的 PHP 方言(代碼名 P++),與 PHP 并存,但不受語(yǔ)言背后的歷史哲學(xué)約束。換句話說(shuō),這種新方言本質(zhì)上可能更加嚴(yán)格,它可能會(huì)更加大膽地消除向后兼容,并刪除被認(rèn)為是“包袱”的元素(例如短標(biāo)簽),并添加更復(fù)雜的特性,尤其是那些非常適合嚴(yán)格類(lèi)型化的語(yǔ)言的,而無(wú)需為 PHP 方言引入相同的復(fù)雜性。
這不是 PHP 代碼分支。代碼庫(kù)將是同一個(gè),在該代碼庫(kù)上工作的開(kāi)發(fā)人員是相同的。絕大多數(shù)代碼都是相同的。只有兩種方言之間的特定差異點(diǎn)才會(huì)有不同的實(shí)現(xiàn)。它有點(diǎn)類(lèi)似于 PHP 7 中的 strict_types 所做的,只是在更大的范圍內(nèi)。
我們真的要做的就是因?yàn)橛行┤瞬荒芊艞壎虡?biāo)簽嗎?
這與短標(biāo)簽無(wú)關(guān),“棄用短標(biāo)簽 RFC(RFC:即 Request for Comments,語(yǔ)言特性的加入,以及標(biāo)準(zhǔn)化變更管理的方法,通常加入新特性時(shí),會(huì)為新特性提交 RFC 并給出例子,變更委員會(huì)評(píng)估通過(guò)后,語(yǔ)言會(huì)合入實(shí)現(xiàn)的源碼,并入新版本。)”不是這個(gè)想法的主要?jiǎng)恿?。這個(gè)提案的目標(biāo)是更有野心,它是為 PHP 提供一個(gè)清晰的愿景,并希望通過(guò)向兩個(gè)陣營(yíng)提供他們想要的東西來(lái)最終解決兩方的緊張關(guān)系。
為什么要分叉 PHP?
這不是分叉。 代碼庫(kù)將完全相同,它將由相同的人開(kāi)發(fā)版本。二進(jìn)制文件將完全相同,如果你安裝 PHP,你也將安裝 P++,反之亦然。相同的二進(jìn)制將運(yùn)行 PHP,P++ 或組合 PHP/P++ 的應(yīng)用程序。
雖然目前還不清楚如何將一個(gè)文件“標(biāo)記”為 P++ 文件,但它可能是文件頂部的某種特殊標(biāo)記,例如:
<?p++?>
<?php 'Hello, world!'; ?>
此外,我們可能會(huì)找到將整個(gè)命名空間標(biāo)記為 P++ 的方法,因此,框架不必將每個(gè)單獨(dú)的文件明確標(biāo)記為 P++。
這意味著我們的開(kāi)發(fā)工作量增加了一倍,而 internals@ 的貢獻(xiàn)者已經(jīng)很低(low)了。 我們?nèi)绾翁幚恚?/p>
值得慶幸的是,這并不意味著是那樣(工作量增加了一倍)。絕大多數(shù)代碼將在 PHP 模式和 P++ 模式之間共享——包括源代碼和運(yùn)行時(shí)。
無(wú)論運(yùn)行的文件是 PHP 還是 P++文件,數(shù)據(jù)結(jié)構(gòu)、關(guān)鍵子系統(tǒng)、擴(kuò)展、Web服務(wù)器接口、OPcache 以及其他所有代碼都將是完全相同的代碼。唯一的額外開(kāi)發(fā)開(kāi)銷(xiāo)會(huì)是 PHP 和 P++ 之間的差異部分。
確實(shí),這意味著我們必須維護(hù)某些代碼片段的兩個(gè)版本,并且我們?cè)诟鱾€(gè)地方都會(huì)有一些 if() 語(yǔ)句,因?yàn)榕c PHP 相比,P++ 可能會(huì)有額外的檢查。 但是,如果我們要轉(zhuǎn)向更嚴(yán)格的 PHP 版本,這些元素?zé)o論如何都必須引入。此外,即使是嚴(yán)格陣營(yíng)中的人,也不建議我們?cè)跊](méi)有提供遷移途徑的情況下轉(zhuǎn)向未來(lái)嚴(yán)格版本——實(shí)際上,這種方法所涉及的努力和幾乎任何其他的方法都是相似的。
當(dāng)我們轉(zhuǎn)向更嚴(yán)格的 PHP 8/9時(shí), 為什么不只是開(kāi)發(fā)一個(gè)永久維護(hù)的 PHP 7.4 長(zhǎng)期維護(hù)版?
這種方法存在許多問(wèn)題。 即使我們忽視這樣一個(gè)事實(shí),即這會(huì)讓龐大的動(dòng)態(tài)偏好陣營(yíng)懸而未決——沒(méi)有任何特性或性能更新,從開(kāi)發(fā)工作的角度來(lái)看,這是不切實(shí)際的。 這與這個(gè)提議不同,事實(shí)上,這確實(shí)意味著事實(shí)上的分叉。
我需要在 PHP 和 P++ 之間做出選擇嗎?
是,也不是。 如上所述,當(dāng)你安裝一個(gè),你就有了另一個(gè),所以就應(yīng)用而言,你可以在一臺(tái)服務(wù)器上運(yùn)行這兩種方言。 然而,實(shí)際上,項(xiàng)目和個(gè)人通??赡苓x擇并標(biāo)準(zhǔn)化其中一個(gè),類(lèi)似于嚴(yán)格類(lèi)型的情況。
我能在同一個(gè)應(yīng)用程序中混合使用 PHP 和 P++ 嗎?
是的。 雖然我們需要確定精確的機(jī)制,但代碼是 PHP 還是 P++ 的指定將在文件級(jí)別,而不是在請(qǐng)求級(jí)別。 單個(gè)執(zhí)行(請(qǐng)求)可以加載許多不同的文件,這些文件可以來(lái)自?xún)煞N方言。PHP文件中的代碼將表現(xiàn)為 PHP 語(yǔ)義——而來(lái)自 P++ 文件的代碼將表現(xiàn)為 P++ 語(yǔ)義。 這也是,與 strict_types 類(lèi)似。
雖然這開(kāi)始聽(tīng)起來(lái)可能聽(tīng)很尷尬,但可能會(huì)有非常實(shí)用的用例。例如,PHP 應(yīng)用程序使用的只含 P++ 的框架,反之亦然。 對(duì)于那些熟悉 C 和 C++ 的人來(lái)說(shuō),這有點(diǎn)類(lèi)似。
這是否意味著 PHP 將不再發(fā)展? 所有新功能都會(huì)用于 P++ 嗎?
不,這只是意味著它會(huì)以不同的方式發(fā)展。 嚴(yán)格性和類(lèi)型相關(guān)的功能可能只適用于 P++,并且只能在 P++ 文件中使用。向后兼容偏差將保留在 PHP 中(這并不意味著向后兼容永不會(huì)被打破,只是每個(gè)這樣的案例必須有良好的投資回報(bào)案例)。
但是,與此無(wú)關(guān)的功能,例如引擎的性能改進(jìn)(如 JIT ),擴(kuò)展的開(kāi)發(fā),或新的異步相關(guān)的功能,PHP 和 P++ 都可以使用。
這個(gè)方法有什么好處?
這種方法有很多好處。 首先,它為 internals@ 的兩個(gè)陣營(yíng)提供了一個(gè)很好的解決方案。 那些喜歡 PHP 動(dòng)態(tài)特性的人可以保留它,而那些喜歡更嚴(yán)格類(lèi)型語(yǔ)言的人也可以獲得它,而不受任何 PHP 限制。 而替代方案是零和游戲,一個(gè)陣營(yíng)的勝利是另一個(gè)的失敗,反之亦然。
除了設(shè)計(jì)一個(gè)好的技術(shù)解決方案(使我們能夠以最少的努力支持整個(gè)受眾)之外,還可以終結(jié)近年來(lái) internals@ 上爭(zhēng)論的關(guān)鍵根源。
最后,雖然本文檔的大多數(shù)讀者可能是技術(shù)人員,但應(yīng)該注意的是,啟動(dòng) P++ 將從一個(gè)新的基點(diǎn)譯注4不計(jì)過(guò)去重新開(kāi)始,可能具有巨大的定位和品牌優(yōu)勢(shì)。未使用 PHP 的公司、開(kāi)發(fā)經(jīng)理和個(gè)人開(kāi)發(fā)者更有可能注意到 P++ 的推出,而不是 PHP 8.0 或 PHP 9.0 的推出。
我們不是冒著分裂用戶(hù)群的風(fēng)險(xiǎn)嗎?
在某種程度上,我們是。但這不是這一想法的缺陷, 而是現(xiàn)實(shí)已經(jīng)存在的表現(xiàn)。
如上所述,那里有很多人喜歡 PHP 的動(dòng)態(tài)本質(zhì),并且謹(jǐn)慎地看待嘗試使其越來(lái)越多地面向類(lèi)型。
與此同時(shí),還有另外一群看著 PHP 的人,自己在想:“為什么它變得如此緩慢,以至于我最終要放棄這動(dòng)態(tài)的廢材(原文:dynamic nonsense)?”
這里沒(méi)有對(duì)或錯(cuò)。這兩種觀點(diǎn)都有效。當(dāng)我們研究在這兩個(gè)相互矛盾的觀點(diǎn)之間架起橋梁的可能的解決方案時(shí),沒(méi)有太多可用的方案:
堅(jiān)持使用動(dòng)態(tài)PHP。這將不會(huì)被更嚴(yán)格語(yǔ)言的支持者所接受。
向嚴(yán)格的PHP發(fā)展。動(dòng)態(tài)語(yǔ)言的支持者不會(huì)接受這一點(diǎn)。
分叉代碼庫(kù)。無(wú)論如何完成,都是所有參與者的凈損失選項(xiàng)。 這樣做沒(méi)有技術(shù)優(yōu)勢(shì),即使我們想要(我們不想要),我們也沒(méi)有足夠的貢獻(xiàn)者去做。
提出一些創(chuàng)意解決方案,以滿(mǎn)足雙方觀眾的需求。 這就是該提案試圖做的。它在保持項(xiàng)目本身統(tǒng)一的同時(shí),也確保兩種方言之間的永久互操作性。這雖然會(huì)有一定程度的碎片化,但它仍然是滿(mǎn)足每個(gè)人的主要需求的最小可能。
這與 Nikita(一位 internals@ 上的發(fā)言者,提議在版本中加入特性。順便提一句,美劇《Nikita》值得一看。)版本的想法有何不同?
這兩個(gè)想法之間有許多相似之處,但也存在一些實(shí)質(zhì)性差異。 請(qǐng)注意,這是基于對(duì)版本方法的有限理解,因此部分可能缺乏,不準(zhǔn)確或不正確。
在這個(gè)提議中,有一個(gè)明確的目標(biāo)是保持當(dāng)前動(dòng)態(tài)類(lèi)型的 PHP,作為一個(gè)長(zhǎng)期的,完全支持的,平等的對(duì)等方言。 發(fā)版本的方法將當(dāng)前行為視為“遺留”。 這意味著它可能會(huì)被勸止(使用),然后在某些時(shí)候棄用和刪除。
推出策略完全不同。 P++ 提案旨在首先關(guān)注兼容性破壞元素,例如嚴(yán)格的操作、類(lèi)型轉(zhuǎn)換邏輯的更改、數(shù)組索引處理、需要變量聲明等等,并且旨在在 P++ 的第一期提供它們。這樣做的目的是允許新項(xiàng)目/框架重新開(kāi)始,而不需知道在引入更多兼容性更改時(shí),他們可能不得不在一兩年內(nèi)進(jìn)行重大改寫(xiě)。 版本化提案似乎沒(méi)有這樣的目標(biāo),而是旨在逐步添加/更改 PHP 中的元素。
與推出方式相關(guān),版本化方法不允許只有兩種方言,而是任何數(shù)量的方言。我們可能有 PHP2020 方言,以及 PHP2022 方言和 PHP2027 方言。 如果我們?nèi)勘A羲鼈?,?shí)際上這可能會(huì)增加我們的維護(hù)復(fù)雜性。
該提議還提到了 PHP 與 P++(保守與積極)的不同打破向后兼容策略,而版本化方案可能根本不會(huì)涉及該主題。
版本提案與此提案的定位/營(yíng)銷(xiāo)方面并不完全相同。
重要的是,要注意這兩個(gè)想法不一定是相互排斥的。 我們可以介紹 P++ 并使用版本進(jìn)行改進(jìn),特別是當(dāng)證明很難將所有重要的變化都放到 P++ 的第一期中。
有哪些挑戰(zhàn)?
在我們能運(yùn)行第一個(gè) P++ 應(yīng)用程序之前,不乏挑戰(zhàn)。
我們需要獲得支持。這意味著,兩派的人都需要放棄讓 PHP 完全動(dòng)態(tài)或完全類(lèi)型化的夢(mèng)想,而忽略那些與他們想法不同的人。這似乎是一個(gè)非常重大的挑戰(zhàn)。
為獲得成功,P++ 第一個(gè)版本應(yīng)該處理來(lái)自 PHP 的所有,或至少大多數(shù)兼容性破壞的更改,以便切換(可能相當(dāng)痛苦)的開(kāi)發(fā)人員不必在未來(lái)重新審核/徹底重構(gòu)他們的代碼。一些人表示擔(dān)心,由于我們的開(kāi)發(fā)人員能力有限,他們可能過(guò)于樂(lè)觀,無(wú)法在一期發(fā)布。一旦我們對(duì)列表的內(nèi)容有了更好的了解,我們就必須對(duì)此進(jìn)行評(píng)估。 請(qǐng)注意,這并不意味著我們需要在第一個(gè)期中實(shí)現(xiàn)我們可能對(duì) P++ 提出的所有想法,只是我們應(yīng)該優(yōu)先考慮會(huì)觸發(fā)大量最終用戶(hù)代碼重寫(xiě)的元素,并嘗試在我們的第一版之前處理它們。
當(dāng)然,最具挑戰(zhàn)性的——我們需要為這種新方言找到一個(gè)合理的名字。