使用Zephir开发PHP扩展

是什么?

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代码,再照以下步骤转化:

  1. 字符串单引号替换为双引号;

  2. 变量去掉 $ 符号;

  3. 变量预定义,使用 var 或者具体类型(int/string/array等);

  4. 变量赋值语句前面加上 let;

  5. for循环语句转换为loop,参考: foreach ($data as $key => $value) => for (key, value in data)for ($i = 0; $i < 10; $i++) => loop (i in range(0, 9))

  6. 异常捕捉语句修改,参考: catch (Exception $e) => catch Exception, e

  7. 一般以上步骤完成已经改的七七八八了; 接下来直接执行 zephir generate尝试生成扩展(一般不会这么顺利),并按提示修改代码。

Phalcon的v4最后发行版还是使用zephir,可以学习其源码:

https://github.com/phalcon/cphalcon/tree/4.1.2-release/phalcon

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章