ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Protocol Buffers PHP 双实现详解:纯 PHP 包与 C 扩展的安装、使用与测试实战

Protocol Buffers PHP 双实现详解:纯 PHP 包与 C 扩展的安装、使用与测试实战 Protocol Buffers PHP 双实现详解纯 PHP 包与 C 扩展的安装、使用与测试实战【免费下载链接】protobufProtocol Buffers - Googles data interchange format项目地址: https://gitcode.com/GitHub_Trending/pr/protobufProtocol Buffersprotobuf仓库在php/目录下同时提供了 PHP 消息编解码的两种运行时实现一个纯 PHP 包php/src和一个原生 C 扩展php/ext。两者提供完全相同的运行时 API 并共享同一套生成的代码意味着同一条.proto定义无需重新生成即可在两种实现之间切换。读完本文你将掌握 C 扩展的源码构建与 PECL 安装流程、composer 包的安装方式、protoc --php_out的代码生成方法以及如何在仓库内用 Bazel composer PHPUnit 对两套实现分别跑通测试。一、双实现的定位同一 API两种性能取舍php/README.md开宗明义纯 PHP 包对应 php/src面向更广泛的 PHP 平台提供可用性无需编译跨平台成本低C 原生扩展对应 php/ext面向更高性能场景通过 PECL/源码编译安装。两种实现都基于 protoc 生成的 PHP 代码来定义 message 与 enum 类型且共享同一份生成代码——当需要在纯 PHP 与 C 扩展之间切换时不需要重新执行代码生成。这一点在php/src/Google/Protobuf/Internal下的类结构中可以印证纯 PHP 实现以Message为所有消息类的父类见 Message.php而 C 扩展在 def.c 中通过 Zend 对象接口zend_class_entry、对象 handler直接实现同名类两套类名、方法签名保持一致从而做到运行时 API 对齐。README 还特别强调php/目录内的构建流程只负责安装扩展或包本身要获得 PHP 代码生成功能必须另外安装 protoc 编译器参见仓库根目录 README.md 中关于 protoc 的说明。关于版本支持README 指出支持的 PHP 语言版本及其支持级别变化策略需参考外部“Supported PHP versions”文档Google Cloud PHP 的官方支持矩阵此处不展开外链。从仓库当前配置看纯 PHP 包在 composer.json 中声明了硬性要求require: { php: 8.2.0 }即当前仓库版本的 PHP 实现要求 PHP 8.2 及以上开发测试则依赖phpunit/phpunit 11.5.50 12.0.0。二、C 扩展安装2.1 前置工具README 列出的构建前置工具为gcc、libtool、make、pear、pecl、phpize。在 Ubuntu 上一键安装sudo apt-get install -y php-pear php-dev libtool make gcc其他平台请使用对应的包管理器先装好上述工具再执行后续步骤。2.2 从源码构建Building extensionREADME 给出的经典流程是cd ext/google/protobuf pear package sudo pecl install protobuf-{VERSION}.tgz对应到当前仓库C 扩展源码位于 php/ext/google/protobuf其中包含完整的 PECL 打包材料config.m4GNU 平台构建脚本、config.w32Windows 构建脚本、generate_package_xml.sh与template_package.xml打包元数据以及核心的 C 源文件protobuf.c、def.c、message.c、arena.c、convert.c、map.c和基于 upb 运行时的php-upb.c。值得注意的是仓库测试用的构建脚本 tests/compile_extension.sh 展示了更贴合日常开发的完整构建链路可视为源码构建的“可运行版”先把 UTF-8 校验所需的third_party/utf8_range拷贝进ext/google/protobuf/third_party/与发布到 PECL 时相同通过phpize生成configure并用--with-php-config$(which php-config)指向当前 PHP 解释器非 release 模式额外加上CFLAGS-g -O0 -Wall -DPBPHP_ENABLE_ASSERTS以便调试断言用sha256sum $(which php)加上 configure 参数生成“指纹”写入BUILD_STAMP只有解释器或构建参数变化时才重新执行phpize --clean phpize ./configure避免每次全量重配最后make -j8编译并用make -j8 test跑扩展自带的.phpt测试如ext/google/protobuf/tests/unnecessary_zval.phpt。这套指纹化机制意味着在同一台机器上切换测试轮次时构建系统会自动判断是否需要重新 configure值得在自建 CI 时借鉴。2.3 从 PECL 安装protobuf 每次发版时会把扩展上传到 PECL直接安装预打包版本即可sudo pecl install protobuf-{VERSION}发版侧的实现可见 php/release.sh它把php/src与composer.json.dist同步到独立的 protobuf-php 发行仓库并打版本 tag——这也解释了为什么发布用的 composer 清单是composer.json.dist而非仓库根上的composer.json后者额外包含测试脚本与开发依赖。三、纯 PHP 包composer 安装README 的说明非常直接在项目的composer.json的require段加入google/protobuf即可。从 composer.json 可以看到包的完整定义包名为google/protobuf类型library许可 BSD-3-Clause自动加载采用 PSR-4 映射Google\Protobuf\→src/Google/ProtobufGPBMetadata\Google\Protobuf\→src/GPBMetadata/Google/Protobuf其中GPBMetadata命名空间存放各 well-known proto 文件的元数据初始化类如Timestamp.php、Duration.php、Struct.php、GPBEmpty.php等见 php/src/GPBMetadata/Google/Protobuf生成的消息类正是通过它们向全局DescriptorPool注册文件描述符。另外两点与 README 呼应的细节README 提到纯 PHP 实现需要安装bcmath扩展。composer.json 中以suggest形式声明了ext-bcmath并注明其用途是“支持 JSON 反序列化”。也就是说 bcmath 是 JSON 编解码路径上的依赖缺失时 JSON 相关功能可能不可用包的require已收紧到php 8.2.0低于此版本的项目无法使用当前版本的包。四、protoc 生成 PHP 代码无论装了 C 扩展还是 composer 包若要从.proto文件生成 PHP 代码还需要安装 protoc安装方式见仓库主 README.md。最新版 protoc 支持--php_out选项protoc --php_outout_dir test.proto仓库自身正是这样生成测试代码的。php/generate_test_protos.sh 的工作流程完整展示了生成命令的实际用法# 优先使用仓库内已构建的 protoc否则用 Bazel 构建 :protoc find php/tests/proto -type f -name *.proto | \ xargs $PROTOC --php_outphp/tmp -Isrc -Iphp/tests关键参数与技巧-Isrc -Iphp/tests把src目录存放google/protobuf/*.proto标准库 proto加入 include 路径使测试 proto 能 import 标准定义--php_outphp/tmp生成物统一落到php/tmp并在 composer.json 的autoload-dev中通过: tmp直接映射为类路径增量优化若php/tmp已存在且没有比php/tests/proto和$PROTOC更新的文件脚本直接跳过 protoc避免重复生成--aggregate_metadatafoo#bar:php/tmp聚合模式选项可把多个 proto 文件的元数据合并到少量 metadata 类中测试脚本提供了aggregate_metadata_test验证。测试用 proto 集合位于 php/tests/proto覆盖 php 命名空间、前缀、保留字大小写、特殊字符、wrapper setter 等生成器边界场景如test_php_namespace.proto、test_reserved_message_lower.proto、test_special_characters.proto这些正是验证--php_out输出正确性的真实用例。五、已知问题清单Known IssuesREADME 明确列出了当前实现的已知局限工程选型时应逐条评估缺少对 well-known types 的原生支持不支持 proto2未提供清空/拷贝消息clear/copy的 API未提供基于 stream 的编解码 APImap 字段在存在循环引用时可能无法被垃圾回收C 扩展中的消息没有 debug 信息未测试 HHVMC 扩展未在 Windows、macOS、PHP 7.0 上测试消息名不能为Empty。六、开发测试实战如何分别验证两套实现README 的 Development 章节给出了“先测原生 PHP、再测 C 扩展”的顺序。下面将其与仓库中当前实际存在的脚本和 composer 脚本对齐说明。6.1 测试纯 PHP 实现README 原始步骤Linux# 安装依赖 apt-get install bazel composer php-dev # 获取 protobuf 源码 git clone https://github.com/protocolbuffers/protobuf.git cd protobuf # 构建 protoc bazel build :protoc # 测试原生 php cd php composer install composer test其中composer test在 composer.json 中的定义是test: ./generate_test_protos.sh vendor/bin/phpunit tests即“先生成测试 proto再对tests目录跑 PHPUnit”——生成的测试代码直接落在php/tmp并被 dev 自动加载无需手工配置 include 路径。6.2 测试 C 扩展README 给出的老流程是先cd tests ./test.sh 5.6按系统安装的 PHP 运行时版本选择 5.5/5.6/7.x 及对应 zts 变体并可用./gdb_test.sh用 gdb 调试扩展。在当前仓库中C 扩展测试已被整合进 composer 脚本test_c: ./generate_test_protos.sh ./tests/compile_extension.sh \ php -dextensionext/google/protobuf/modules/protobuf.so \ vendor/bin/phpunit --bootstrap tests/force_c_ext.php tests三个环节各司其职generate_test_protos.sh生成测试代码与纯 PHP 测试共享tests/compile_extension.sh 完成 phpize → configure → make →make test的完整构建即第二节 2.2 中解析过的流程产物为ext/google/protobuf/modules/protobuf.so用php -dextension...protobuf.so显式加载刚编译出的扩展并以 tests/force_c_ext.php 作为 PHPUnit bootstrap 强制使用 C 扩展实现从而与composer test的纯 PHP 跑法形成对照。另外仓库还保留了两套更深入的调试手段与 README 提到的 gdb 调试思路一致composer test_valgrind在ZEND_DONT_UNLOAD_MODULES1 USE_VALGRIND1 USE_ZEND_ALLOC0环境下以valgrind --leak-checkfull运行同一套测试用于排查内存泄漏tests/gdb_test.sh 与tests/memory_leak_test.sh/multirequest.sh分别用于 gdb 交互调试与多请求/内存泄漏场景验证。七、小结选型与落地要点平台优先选纯 PHP性能优先选 C 扩展二者 API 相同、生成代码可复用切换成本仅为“换加载方式”无需重新protoc版本前提当前仓库要求 PHP ≥ 8.2纯 PHP 路径建议安装ext-bcmath以支持 JSON 反序列化生成代码与运行时解耦--php_out生成的类只依赖Google\Protobuf\Internal运行时与GPBMetadata元数据-Isrc保证 well-known proto 可被导入验证闭环日常用composer test验纯 PHP、composer test_c验 C 扩展需要深挖时用 valgrind 与 gdb 脚本全部入口都已在php/composer.json的scripts中定义好。【免费下载链接】protobufProtocol Buffers - Googles data interchange format项目地址: https://gitcode.com/GitHub_Trending/pr/protobuf创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表