靜態掃描為你的PHP項目上線保駕護航

摘要:在4月20日的阿里雲棲開發者沙龍PHP技術專場上,阿里雲資深研發工程師周夢康(楚松)為大家分享瞭如何藉助靜態掃描來為我們的PHP項目上線保駕護航,他從Why、How和What三個角度為大家分享了靜態掃描的落地實踐和最終成果。

本次直播視頻精彩回顧,戳這裡!

直播回顧:https://yq.aliyun.com/live/965

PPT分享:https://yq.aliyun.com/download/3531

以下內容根據演講視頻以及PPT整理而成。

演講專家簡介:

周夢康(花名:楚松),阿里雲資深研發工程師,《深入PHP內核》作者之一,多個開源項⽬目 tipi、yar-java、doc-php的作者與參與者

本次的分享主要圍繞以下三個方面:

  1. 為什麼要代碼靜態掃描
  2. 怎麼去做代碼靜態掃描
  3. 發佈與集成測試的成果

為什麼要代碼靜態掃描

什麼是靜態掃描

如下圖所示,其實靜態掃描的名稱非常多,這裡統一稱之為靜態掃描。靜態掃描是指在不運行代碼的方式下,通過詞法分析、語法分析、抽象語法樹分析等技術對程序代碼進行掃描,驗證代碼是否滿⾜規範性、安全性、可靠性、可維護性等指標的一種代碼分析技術。

靜態掃描為你的PHP項目上線保駕護航

PHP項目為什麼需要做靜態掃描

這裡主要有三點原因:

1)弱類型與無類型聲明,PHP7引入了類型聲明;

2)解釋性語言實時編譯;

3)豐富的包、遞歸依賴。

靜態掃描為你的PHP項目上線保駕護航

例子:弱類型(泛型返回值)錯把數組當對象

靜態掃描為你的PHP項目上線保駕護航

例子:返回值⽆無類型聲明 錯把對象當數組

靜態掃描為你的PHP項目上線保駕護航

例子:類繼承成員變量量訪問級別覆蓋

靜態掃描為你的PHP項目上線保駕護航

版本兼容性問題

靜態掃描為你的PHP項目上線保駕護航

還有一些版本兼容性問題也需要通過靜態掃描來解決,對於一些“歷史悠久”的公司而言,一定會有一些“老”代碼,雖然這些項目都是使用PHP進行開發,但是有的可能使用了老的版本,而一些工程師在進行開發的時候可能將一些新版本語法的語法糖寫到了老的版本,可能在本地運行沒有任何問題,但是一旦到了線上就會出故障了。還有比如老項目使用的PHP版本中一些函數不存在或者有一些語法不支持等,這些都是兼容性的問題。

PHP的運行時編譯優勢與隱患

靜態掃描為你的PHP項目上線保駕護航

一些特別小的PHP項目修改完之後直接上傳上去覆蓋即可,其他語言的項目可能無法這樣做,必須要整體打包,因此這既是PHP的一個優勢,但也是一個隱患。

PHP可以說是一個“風一樣的美男子”,代碼寫的快,但是類型約束差、風險高,數組使用比較多就可能因為模糊KV多而影響語義,並且整體代碼缺失面向對象的思想;PHP編譯快並且部署快,因此也導致上下文解析存在一些隱患。

靜態掃描為你的PHP項目上線保駕護航

PHP 7新特性參數類型、返回值類型聲明

PHP也在不斷地發展和改進,比如PHP 7就提供了參數類型、返回值類型聲明等新特性。

靜態掃描為你的PHP項目上線保駕護航

靜態掃描為你的PHP項目上線保駕護航

PHP解析小互動

如下圖所示的三段代碼中,為什麼a.php看不到錯誤b.php卻可以?大家可以仔細思考下這部分問題。

靜態掃描為你的PHP項目上線保駕護航

PHP包管理工具的發展

PHP項目的管理越來越複雜,到了2012年之後,Composer變得非常流行,成為了主流的包管理工具。

靜態掃描為你的PHP項目上線保駕護航

PHP項⽬發展背後的潛在風險

使用laravel來新建一個博客,其生成的PHP文件數是5927個,代碼行數達到了47萬行,很難保證其沒有錯誤。因此必須要有自動的語法檢測、類型推斷等,僅依靠人工檢查肯定是心有餘而力不足的。

靜態掃描為你的PHP項目上線保駕護航

怎麼去做代碼靜態掃描

工具選擇-PHPStan

靜態掃描為你的PHP項目上線保駕護航

PHPStan是一種PHP代碼靜態掃描的工具,並且有VS Code的插件,但是似乎有點卡頓。

工具選擇-PHPSA

靜態掃描為你的PHP項目上線保駕護航

PHPSA與PHPStan比較類似,Fork數和Follow都比較多。

工具選擇-Phan

靜態掃描為你的PHP項目上線保駕護航

Phan的Follow數量最多,並且也有VS Code的插件。其原理在於解析AST,也就是在分析PHP在執行詞法分析和語法分析之後生成的抽象語法樹AST。

依託PHP-Parser自己造輪子

靜態掃描為你的PHP項目上線保駕護航

Phan的作者也寫了一個PHP-Parser,其主要就是將PHP語法樹以數組的方式生成出來。

靜態掃描為你的PHP項目上線保駕護航

使用Phan

靜態掃描為你的PHP項目上線保駕護航

首先,Phan是基於抽象語法樹的,其需要依賴於php-ast擴展,安裝完擴展之後就可以安裝工具。

使用Phan簡單掃描

如下圖所示的就是使用Phan進行簡單PHP項目掃描腳本。

靜態掃描為你的PHP項目上線保駕護航

靜態掃描為你的PHP項目上線保駕護航

使用Phan掃描項目

如今,大家的項目都是基於Composer進行自動加載或者包依賴的。前面的例子只是測試幾個腳本,如果想要將其應用到生產中,前面的方式肯定不足夠,因此Phan也支持項目級別的掃描,使用下面的命令就可以掃描和分析出一些錯誤並形成錯誤報告。

靜態掃描為你的PHP項目上線保駕護航

靜態掃描為你的PHP項目上線保駕護航

項目發佈實踐——AoneFlow分支管理

靜態掃描為你的PHP項目上線保駕護航

阿里巴巴的AoneFlow在這一點上或許比GitFlow使用起來更加靈活一些,也方便一些。AoneFlow發佈的時候使用的是release包,最後上線也是release包,發佈完成之後會合併到master主幹分支上去,

項目發佈實踐

靜態掃描為你的PHP項目上線保駕護航

項目發佈的流程可以主要分為兩個方面,包含了預發和正式發佈。預發部分包含了項目構建、預發准入、預發部署、集成測試以及預發驗證五個部分,在預發准入部分嚴格上會有一些審批進行攔截,靜態掃描就放在集成測試這部分中。在正式發佈部分,也包含了項目構建、正式准入、正式部署、合併到master以及線上測試等五個部分。

靜態掃描為你的PHP項目上線保駕護航

集成測試主要包含了單元測試、接口測試、代碼靜態掃描、安全測試以及性能測試等。在將代碼同步到預發服務器的同時,可以將代碼同步到專門做靜態掃描服務器的集群上去,這是因為如果公司項目較少,那麼預發服務器可以作為靜態掃描服務器,不然同步兩次也會浪費時間,但是如果公司有很多類似項目都需要掃描,那麼就無法在每個預發服務器上都將靜態掃描的擴展都安裝一遍,也無法讓每個預發服務器都來彙報整個編譯流程是否OK,應該是與預發部署服務器隔離開的,預發服務器只彙報是否發佈成功。這樣的好處就是靜態代碼掃描的擴展只安裝在集群裡面,所有人的項目都是可以共用的,而且與整個構建系統相關,通過整體流程保證項目穩定性。

PHP是一門藝術

靜態掃描為你的PHP項目上線保駕護航

其實,PHP在我們的項目裡面更像是一門藝術,在早期,PHP較為簡單易用,但是與此同時,因為其不穩定性以及一些潛在隱患問題,也被很多人所詬病。可能在很多人眼裡,PHP還是十幾年前的一個玩具,但是玩具也可以不斷升級,正如樂高也可以做一個真正能夠跑起來的跑車。因此,如果能夠讓PHP發揮更大的作用,更是一門藝術。


分享到:


相關文章: