是什麼?
Zephir,一種開源的高級語言,旨在簡化PHP擴展的創建和可維護性,重點關注類型和內存安全性。
PHP框架(擴展)Phalcon團隊爲了更方便的開發,同時維護了zephir項目,並在Phalcon的v2-v4版本中應用。可惜2020年中,zephir主要維護者Serghei離開後,Phalcon宣佈v5版本將使用原生PHP開發。此後Zephir再沒有大的更新,除2021年3月發佈v0.13兼容PHP8,其它就是一些維護類的更新。
https://blog.phalcon.io/post/the-future-of-phalcon
當前最新release版本爲 0.15,但文檔版本僅更新到 0.12,參考:
https://docs.zephir-lang.com/0.12/en/welcome
小知識:
Zephir 這個名字是單詞 z (end) e (ngine)/ph (p)/i (nte) r (mediate) 的收縮。官方建議讀作zephyr,而他的創造者實際把它讀作zaefire。
爲什麼?
使用zephir有幾個好處:
-
性能提升: 將一些不常變化的類庫編譯爲擴展,避免每次請求都重新加載執行,浪費CPU; 另外zephir會將代碼轉換爲PHP標準的C代碼擴展,編譯器在編譯擴展時會做一些優化;
-
開發簡單: 相比直接使用C開發PHP擴展,以一種類似PHP語法的方式編寫,大大提升開發效率;
-
代碼保護: PHP是解釋型語言,通常是直接暴露源代碼; 通過擴展方式發佈,可以隱藏原始代碼。對於發行軟件可以保護知識產權;對於自研系統,可以避免敏感信息泄露,提升安全性;
當然,使用zephir的一些注意:
-
應該僅將需要優化性能或者保護信息的部分代碼改寫,因爲zephir的開發效率弱於比直接使用PHP;
-
使用zephir開發擴展,相比純PHP系統,增加了項目開發,部署和維護成本;
-
因爲擴展生命週期是進程級別,現在發佈代碼可能需要重啓php-fpm;
-
zephir項目生態上最主要的使用者Phalcon已經棄用,目前僅處於維護狀態,未來有擱淺風險;
總的說來,zephir適合的應用場景較窄,請謹慎選擇!
怎麼做?
版本選擇
0.13及之後版本只支持PHP7.4和PHP8, 0.12支持PHP7.2 - PHP7.4,可以按需要選擇。實際開發大同小異,本文以0.12爲例,環境爲 centos 7 + php7.3。
安裝
安裝zephir:
zephir提供了打包好的phar文件,直接下載使用即可:
wget https://github.com/zephir-lang/zephir/releases/download/0.12.21/zephir.phar
# 提供一個tx雲cos地址:https://public-pkg-1252772859.cos.ap-guangzhou.myqcloud.com/hyperf-box/zephir-v0.12.21.phar
chmod 755 zephir.phar
ln -s /usr/local/bin/zephir zephir.phar
# 查看是否安裝成功
zephir -v
zephir編譯代碼時需要使用zephir-parser擴展。安裝:
# 安裝編譯環境(按需)
sudo yum install php-devel gcc make re2c autoconf automake
# 說明: zephir-parser最新版是 v1.4.1,但該版本與 zephir 0.12不兼容
wget https://github.com/zephir-lang/php-zephir-parser/archive/refs/tags/v1.3.8.tar.gz -O zephir-parser.tgz
# 同樣提供一個tx雲cos地址: https://public-pkg-1252772859.cos.ap-guangzhou.myqcloud.com/hyperf-box/php-zephir-parser-1.3.8.tar.gz
tar zxvf zephir-parser.tgz
cd php-zephir-parser-1.3.8/
# 注意根據實際地址修改 phpize 和 php-config 路徑
/usr/local/bin/phpize
./configure --with-php-config=/usr/local/bin/php-config
make
sudo make install
# 在 php.ini 中啓用擴展
[zephir parser]
extension=zephir_parser.so
# 測試(說明:此版本擴展名稱是 Zephir Parser;v1.4.1 起擴展名稱改爲了 zephir_parser
/usr/local/bin/php -m | grep -i zephir
/usr/local/bin/php --ri "zephir parser"
安裝中細節有疑問的,可以參考官方文檔:
https://docs.zephir-lang.com/0.12/en/installation
https://github.com/zephir-lang/php-zephir-parser
開發
hello world:
# 創建環境
zephir init demo
cd demo
ls
# config.json demo ext
# 有2個目錄: ext 是生成擴展的代碼; demo(與項目同名)目錄是編碼的地方
# 還有一個 config.json 的文件。可以使用配置,更改 Zephir 和/或擴展本身的行爲
# 創建類
cat > demo/Hello.zep
namespace Demo;
class Hello
{
public static function say(string name="world")
{
echo "hello ".name."!\n";
}
}
# 生成擴展代碼
zephir generate
# vim ext/demo/hello.zep.c 可以查看生成的C代碼
# 編譯安裝同標準php擴展,略
# 測試
php -r "Demo\Hello::say('zephir');"
語法學習:
zephir的語法不復雜,有一點像 php + js 結合體,詳細見:
https://docs.zephir-lang.com/0.12/en/language
一些注意:
-
在 zephir 中,每個文件都必須包含且僅包含一個類。每個類都必須有一個命名空間,並且目錄結構必須與所使用的類和命名空間的名稱相匹配。
-
zephir可以使用PHP內置的各種函數; 甚至還可以使用運行時存在的用戶自定義函數和超全局變量等。
-
函數參數即使指定了類型,也不會強校驗,只是會嘗試轉化類型;如上面例子執行
php -r "Demo\Hello::say(123);"
依然可以正常出結果 。如果需要強制校驗,需要在參數後面追加一個歎號(!)。
高級技巧:
編譯配置:
https://docs.zephir-lang.com/0.12/en/config
PHP生命週期事件鉤子:
https://docs.zephir-lang.com/0.12/en/lifecycle
擴展練習:
我們可以嘗試一下zephir編寫一個微型PHP框架擴展,僅包含:配置文件加載(Config類),日誌文件記錄(Logger類)和數據庫查詢(Db類)。
詳見項目: https://gitee.com/dingusxp/zephir-hellophp
經驗
使用zephir改造PHP代碼還是很簡單的。先寫PHP代碼,再照以下步驟轉化:
-
字符串單引號替換爲雙引號;
-
變量去掉 $ 符號;
-
變量預定義,使用 var 或者具體類型(int/string/array等);
-
變量賦值語句前面加上 let;
-
for循環語句轉換爲loop,參考:
foreach ($data as $key => $value)
=>for (key, value in data)
,for ($i = 0; $i < 10; $i++)
=>loop (i in range(0, 9))
; -
異常捕捉語句修改,參考:
catch (Exception $e)
=>catch Exception, e
; -
一般以上步驟完成已經改的七七八八了; 接下來直接執行
zephir generate
嘗試生成擴展(一般不會這麼順利),並按提示修改代碼。
Phalcon的v4最後發行版還是使用zephir,可以學習其源碼:
https://github.com/phalcon/cphalcon/tree/4.1.2-release/phalcon