PHP & Laravel 升版準備及流程分享
隨著公司業務規模不斷的成長,功能及商業需求不斷增加的同時,你手上的專案是否也有一段時間沒有做版本更新了呢?
從商業上的考量來說,版本更新是一件需要花費人力成本和時間才能進行,但無法讓產品有實質收益的作業。
但是當目前的系統版本、套件停止維護或更新、安全性上的考量、又或是在版本更新後能夠有更好的開發環境或執行效能,升級就變成一件有意義(能夠拿來說服老闆)的事情了XD
筆者是在 2022/2 月時加入 AsiaYo 的產品團隊,擔任 Backend Engineer 。
還記得剛進來的第一天 Mentor 及 Leader 交辦給我了兩件任務:
- 寫測試
- 將現有PHP 7.1專案的版本升級 7.3
於是筆者便透過寫測試暸解專案架構的同時,開始研究及嘗試如何幫現有的專案做版本升級。
這次AsiaYo將其中一個PHP 7.1 + Laravel 5.5的專案升級到了PHP 7.3 + Laravel 7。
從剛開始不斷的搜集、閱讀官方文件、尋找可用的工具,慢慢地建立了一個階段性將版本升級的流程。
在接下來的內容中將會把這次升版準備及過程,還有搭配到的小工具在這邊與大家分享。
版本升級準備:
我們在決定版本升級前,先整理了版本升級過程中需要的文件。
包括:
- PHP 官方升版文件
- Laravel 官方升版文件
- 過去其他專案環境升到相同版本號時的 changelog & PR
- packgist.org
我們從上述的文件中先分析了升級可能會需要更新到的程式碼、套件,最後決定在升級 PHP 7.3 的同時,也一併更新目前的 Laravel 版本。
會選定 PHP 7.3 & Laravel 7 的主要考量是版本的穩定性、以及該版號為目前大部分專案環境所使用的版本,我們想要讓所有專案開發體驗一致,進而提升開發效率,因此決定來進行這次的升版作業。
版本升級指引:
Laravel 升級
在開發時,我們選擇一次升級一個Laravel版號進行階段性升版。
(例如: 5.5 → 5.6 → 5.7 → 5.8 → 6.x → 7.x )
這樣做的好處是: 當升級一個版本遇到問題的時候,隨時可以從升級版本的官方文件中找到發現哪裡做了異動。
Laravel 官方升級文件已經把每個版本 PHP 最低版本需求、最基本的 Updating Dependencies 、每項修改對系統的影響層級(High, Medium, Low)、 閱讀文件所需的時間都寫得非常清楚。
(不過實際讀完做升版所花的時間每次都遠高於上面的預估時間)
在這邊筆者也將這次更新 Laravel 幾個較重大的異動做出整理,提供給大家參考。
Laravel 5.6 :
Laravel 5.8 :
Laravel 6.x :
Laravel 7.x :
更多升級相關的變更,可以參考官方文件。
PHP 升級
PHP 升級的部分,我們以升級 7.2 為例,需要閱讀的主要是這三份文件:
我們會需要從 Backward incompatible changes 去檢查原來的函數在參數傳遞或回傳中做了什麼修正、還有從 Deprecated features 去查看專案中是否有用到這些方法及函數。
除了不相容的修正外也需要閱讀 New features 來了解這次升級中帶來了那些好用的新特性,可以在這次升級或日後專案開發中做使用。
筆者在這邊也整理了這次更新 PHP 7.2 & 7.3 中的一些新特性及修改提供大家參考。
PHP 7.2 :
- 新的參數及回傳值類型宣告(
object
) - 允許重寫抽象方法 (Abstract method overriding)
- 使用Argon2算法生成密碼
- 參數類型推導
- 允許分組命名空間的尾部逗號
count()
嚴謹化
PHP 7.2 棄用方法可以參考官方文件
PHP 7.3 :
- Heredoc & Nowdoc 語法更靈活的縮排
- 新增
JSON_THROW_ON_ERROR
參數來取得JSON錯誤 list ()
賦值引用is_countable()
函數 (因應PHP 7.2 count() 嚴謹化的修改)array_key_first()
&array_key_last()
PHP 7.3 棄用方法可以參考官方文件
雖然官方文件不能保證你升版絕對不會踩到坑,不過照著官方文件走過至少能夠確保升版異動的正確性。
“讀官方升版文件,確認專案中有沒有棄用的方法、異動的class或檔案”
這項作業是版本升級中最重要的一件事情!
套件相依性檢查
一邊讀文件,一邊把需要修改的程式碼都調整後,下一步就要來跑 composer 更新。
想當然的… 一定會有一連串套件相依問題噴出來
這個時候就需要透過 packgist.org 來檢查 composer 套件的相依性了。
以 sentry / sentry-laravel 這個套件為例:
從 requires 上可以得知,目前的版本 0.9.2 中 illuminate/support 相容的版號是 5.0.*|5.1.*|5.2.*|5.3.*|5.4.*|5.5.*|5.6.*
而 illuminate/support 是屬於 Laravel 框架本身內建的套件。(上面的版號與 Laravel version 相同)
如果我們今天要升級到 Laravel 5.7 ,那麼照 packgist.org 上所寫至少要升級到 0.10 才可以。
至於套件要升到哪個版本號,筆者的看法是考量有三點。
- 如果有其他相同執行環境使用此套件,版本號一致為原則。
- 若非 1 的情形,選擇能夠相容的最新版號,但如果那個版號是套件最新版本那就選前一個大版號,預防最新版本可能會有未知的 bug 發生。
- 如果發現 2 的版號對系統影響巨大,就考慮升級前版號最接近的版本。
但有時候升版會遇到套件之間的深深互相依賴真的會很頭痛。
像是 php-cs-fixer & phpunit & paratest 三個套件只要更新了其中一個可能就會動到另外兩個,加上升級後測試、 linter 過不了就夠你崩潰一段時間了~
另外,套件升級也需要注意這次升級修改了哪些地方,有沒有在專案中使用到套件已經棄用的方法。
測試
成功將版號升上去,繼續跑測試來看結果。
可以看到有失敗的Test case出現,這個時候就只能一個一個釐清問題去解決了。
在版本升級與測試的過程難免會遇到測試結果失敗的情況,不過也因為過往的開發有補上測試,因此可以在升版過程中,大幅度降低升版的風險。
升級流程
總結來說,每做一次的版本升級都是按照以下流程進行:
“讀官方文件→檢查套件相依性→升級→檢查套件相依性→測試”
在幫專案升級時,也要注意你的 local 環境、線上環境和部署是否也要同步做更新。
像筆者在這次 PHP 升級過程中,因為 local 環境的設定忘了調整,導致多花了不少時間在找 bug…
升版時的輔助小工具:
這次使用了 PHPCompatibility 來掃描了專案是否有PHP新版本中已經棄用的方法存在。
在安裝需求上,只要你的專案是 PHP 5.4 版本以上,並且需要 PHP CodeSniffer2.6.0+ 就能夠使用此套件。
安裝流程可參考下面步驟或官方文件:
composer require –dev phpcompatibility/php-compatibility
安裝完成後,需要在 composer.json 中的 script 加上 phpcs 的 config setting:
“scripts”: {
“post-install-cmd”: “\”vendor/bin/phpcs\” — config-set installed_paths vendor/phpcompatibility/php-compatibility”,
“post-update-cmd” : “\”vendor/bin/phpcs\” — config-set installed_paths vendor/phpcompatibility/php-compatibility”
}
最後在跑 composer run
執行上面的 script 即可。
使用的話只需要執行下面的這段指令:
./vendor/bin/phpcs -p ./app/ ./tests/ ./config/ ./routes/ — standard=PHPCompatibility — runtime-set testVersion 7.3 — report-full=./update.log
簡單說明一下這段指令, PHPCompatibility 主要是會透過 phpcs 來掃描專案中指定的路徑(在這邊我們是設定 ./app/ ./tests/ ./config/ ./routes/ 這幾個資料夾),testVersion 這邊是設定你想要升級的PHP版本號(在這邊我們是設定 7.3 )。
最後會產出一份 ./update.log 的報表,會將掃描過專案後的 warning 及 error report 都放在這個 log 檔案內。
以我們這次試著掃瞄了升級的專案後,專案內的原始碼很幸運的並沒有棄用的方法存在,只有發現 namespace 的命名 warning 。
(不過也有用 phpcompatibility 掃描了 ./vendor 資料夾發現套件中有一些棄用的方法存在,所以也可以透過 phpcompatibility 掃描套件資料夾來評估要不要幫套件升級)
PHP Rector 是一個可以透過套用規則來自動化修改、重構及掃描程式碼的套件,在官方文件中目前已經有超過 500 種規則可以使用。
在這一次我們試著用 PHP Rector 中內建的幾個規則來協助檢查了專案中是否有需要修改的程式碼。
安裝流程可參考下面步驟或官方文件:
composer require rector/rector — dev
安裝完成後,需要建立一個初始化 config 腳本:
./vendor/bin/rector init
下面是筆者整理出來 config 的基本使用以及範例,提供給大家做參考。
使用時只要執行下面的這段指令即可:
./vendor/bin/rector process — dry-run
但需要注意的是它是重構工具,所以記得加上 dry-run ,否則不小心整個專案可能就被你重構完了XD
也因為它主要的用途還是在重構這件事情,所以在這次使用 Rector 都是作為升版檢查的參考使用~
上述的兩個套件筆者使用過的心得是可以作為升版時的輔助使用,但要完全靠套件來做升級並不靠譜。
另外, Laravel 9 的官方文件中也有推薦了一款(用錢可以解決的)自動化升版的工具 Laravel Shift ,只要綁定 github repo 後,就會自動化完成升版的修改及語法優化發到PR上。
除了付費功能,也有提供幾個免費工具,有興趣的話也可以試用看看:
PHPUnit Shift(PHP Unit 6, PHP Unit 8, PHP Unit 9)
總結:
經過前面分享的升級流程後,筆者在這邊總結 PHP 、 Laravel 升版作業的幾個重點:
- 參考過去其他專案升版時的 PR 跟 changelog ,升版後也要紀錄這次升版的 PR 跟 changelog 。
- 搭配幾個輔助套件( phpcompatibility 、 rector )來進行升版作業
- 讀官方升版文件,確認專案中有沒有棄用的方法、異動的 class 或檔案
- 透過 packgist.org 來檢查套件版本的相依性
- 一次升級一版會比較好掌握問題
- 套件更新時肯定會遇到衝突,更新成功後也要檢查修改了什麼
- 平時有寫測試的習慣,升版的時候會大大幫助你
- 在 Docker 環境下進行更新作業才能在新舊版本之間來去自如
非常感謝大家的收看:)
這次也是筆者第一次進行版本更新的作業,如果有任何升版上的疑問或不清楚的地方,歡迎大家在下方留言。
.........
最後是文末跑馬燈!
AsiaYo 後端 Backend/前端 Frontend 工程師持續擴編招募中(CakeResume),我們的工程師文化是:
- Technique enthusiasts 熱愛技術,精進自我
- Play fun 運用所學做出又酷又好玩的東西
- Problem solving 成為一個 problem solver
- Team working 透過團隊集思廣益,選擇最好的開發語言及系統架構
- Give it a try 擁抱改變,錯了就修正
期待你/妳的加入,跟我們一起做出很酷又好玩的東西!