runphp 0f96ce0bae build(backend): 添加 make clean 步骤以清理构建产物在构建脚本中添加 `make clean` 命令,确保每次构建后清理临时文件和目标文件, преди 6 месеца
..
model 013eac43a0 feat(news): 添加新闻模块 преди 7 месеца
.gitignore 013eac43a0 feat(news): 添加新闻模块 преди 7 месеца
Makefile 18618905b5 build(backend): 添加新闻扩展的 FFI 构建脚本 преди 6 месеца
README.md 013eac43a0 feat(news): 添加新闻模块 преди 7 месеца
build.sh 0f96ce0bae build(backend): 添加 make clean 步骤以清理构建产物在构建脚本中添加 `make clean` 命令,确保每次构建后清理临时文件和目标文件, преди 6 месеца
go.mod 013eac43a0 feat(news): 添加新闻模块 преди 7 месеца
go.sum 013eac43a0 feat(news): 添加新闻模块 преди 7 месеца
main.go f739525cce 补充资讯前台和阅读数量 преди 6 месеца

README.md

News FFI 模块开发指南

本目录包含 news 插件的核心数据逻辑,该逻辑通过 Go 语言实现并通过 FFI (Foreign Function Interface) 提供给 PHP 使用。

模块架构

  • main.go: Go 语言实现的 CRUD (增删改查) 服务,处理所有新闻和新闻分类的数据操作。
  • lib_news.so: 由 main.go 编译成的共享库文件,PHP FFI 实际加载和调用的对象。
  • Makefile: 自动化编译脚本。

数据库配置

本模块的数据库连接信息不是硬编码在 Go 代码中的。它通过一个可导出的 Initialize 函数,在运行时由 PHP 动态注入。PHP 端 (NewsFfiService.php) 会从项目的 .env 文件中读取配置,并在第一次使用本模块时进行初始化。

重要:开发与调试工作流

由于 PHP-FPM 会在内存中缓存加载的 .so 库文件,因此每次修改 main.go 文件后,必须严格遵循以下步骤才能使改动生效:

  1. 修改 Go 代码: 在 main.go 文件中进行你的修改。

  2. 重新编译 .so 文件: 在当前目录 (backend/extension/news/ffi/) 下,运行 make 命令。

    make
    

    这将调用 Docker 来编译 Go 代码,并生成最新的 lib_news.so 文件。

  3. 重启 PHP-FPM 服务: 这是最关键且最容易忘记的一步。必须重启 PHP-FPM 容器来清除旧的 FFI 缓存,并强制它加载新的 .so 文件。

    docker-compose restart php
    

⚠️ 警告: 如果你编译后没有重启 PHP-FPM,你的任何 Go 代码改动都不会生效,并且可能会遇到 Failed resolving C function 之类的错误。

架构决策考量 (Architectural Considerations)

将核心数据逻辑用 Go 实现并通过 FFI 暴露给 PHP,是基于代码安全和技术战略的综合考量。

核心优势:代码保护

这是采用 FFI 方案最主要的目的。

  • 编译型 vs. 解释型: PHP 作为一种解释型语言,其源代码 (.php 文件) 在部署时是完全可见的。而 Go 是一种编译型语言,我们最终部署的是由源代码编译成的二进制共享库 (.so 文件),无需提供 .go 源文件。
  • 逆向工程难度: 从二进制的 .so 文件反向工程出可读的 Go 源代码是极其困难的,需要专业的工具和深厚的底层知识。这为项目中最核心的业务逻辑提供了非常高级别的知识产权(IP)保护。
  • 结论: 此架构为核心代码资产上了一把非常坚固的"锁",防止商业逻辑被轻易复制或泄露。

性能考量

对于当前模块执行的数据库增删改查(CRUD)这类 I/O 密集型 (I/O-Bound) 任务,性能并非首要考量,其特点如下:

  • 瓶颈在于I/O: 此类任务的绝大部分时间都消耗在等待数据库返回结果的网络延迟和磁盘读写上,而不是 CPU 计算。因此,无论是用 PHP 还是 Go 来执行,最终的性能瓶颈都在于 MySQL 服务器。
  • FFI 调用开销: PHP 与 Go 之间的函数调用会产生一定的开销(例如数据类型的转换)。对于我们这种单次调用、内部执行重逻辑的场景,这点开销几乎可以忽略不计。
  • 结论: 在当前场景下,使用 Go FFI 的性能与纯 PHP 实现基本持平,没有显著的提升或下降。选择此方案并非为了追求性能,而是为了实现上述的代码保护目标。

: 如果未来有 计算密集型 (CPU-Bound) 的任务(如复杂的算法、图像处理等),将其用 Go 实现则会带来数量级的性能提升。