PRQL PHP 绑定指南:使用 prql-php 通过 FFI 将 PRQL 编译为 SQL
后端【免费下载链接】prqlPRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement项目地址https://gitcode.com/gh_mirrors/pr/prql点击查看免费下载prql-php 是 PRQL 编译器在 PHP 生态中的官方绑定通过 PHP FFIForeign Function Interface直接调用 Rust 编写的prqlc核心库为 PHP 应用提供 PRQL → SQL 的编译能力。本文基于 prql-php 官方 README 及仓库源码讲解环境准备、Compiler 类四大核心 API、Options 与 Result 数据结构并结合源码级实现细节说明其底层工作原理帮助你在 PHP 8.1 项目中快速集成并正确处理编译结果与错误信息。一、prql-php 是什么prql-php是 PRQL 项目为 PHP 语言提供的官方编译器绑定位于 prqlc/bindings/php 目录。PRQLPipelined Relational Query Language是一种现代化的数据转换语言旨在作为 SQL 的可读替代品。在 PHP 中你可以用管道风格的 PRQL 语法编写查询再交由prql-php在运行时编译成目标数据库可执行的 SQL。从实现方式看prql-php走的是FFI 路线它不把编译器逻辑用 PHP 重写而是直接加载 Rust 编译产物libprqlc_c共享库通过 PHP 内置的 FFI 扩展调用 C ABI 导出的编译函数。这意味着 PHP 侧只负责参数编组、内存管理与结果封装核心编译能力与官方prqlc完全一致。需要注意的现状以当前仓库为准该绑定仍处于早期阶段README 明确说明 still at an early stage尚未发布到 Composer需要从仓库源码自行构建集成依赖 PHP FFI 扩展并要求 PHP 8.1见 composer.json 中php: ^8.1与ext-ffi: *声明支持通过 PSR-4 自动加载命名空间为Prql\Compiler\。在开始使用前建议先了解 PRQL 语言本身的语法可参考 语言文档以及prqlc编译器总体架构见 ARCHITECTURE.md。二、安装与运行环境准备2.1 启用 PHP FFI 扩展prql-php依赖 PHP 的 FFI 扩展。PHP 8 及以上版本默认内置该扩展但出于安全考虑FFI 默认处于禁用状态需要显式开启编辑php.ini将ffi.enable设置为true重启 PHP-FPM / CLI 进程使配置生效。以命令行快速验证扩展是否加载php -m | grep ffi # 或 php -r var_dump(extension_loaded(ffi));扩展未启用时实例化Compiler会直接失败因为类内部依赖\FFI::cdef()加载共享库见 Compiler.php 构造方法。仓库测试 CompilerTest.php 的第一步就是断言ffi扩展已加载。2.2 构建 libprqlc_c 共享库Compiler构造时会在lib目录中查找 C 头文件prqlc.h和平台对应的共享库操作系统期望文件WindowsPHP_OS_FAMILY Windowslib/libprqlc_c.dllmacOSPHP_OS_FAMILY Darwinlib/libprqlc_c.dylibLinux / 其他lib/libprqlc_c.so这个平台判断逻辑直接体现在 Compiler.php 中。若找不到库或头文件构造会抛出InvalidArgumentExceptionCannot load header file.。构建产物来自prqlc-ccrate其 C ABI 入口实现在 prqlc/bindings/prqlc-c/src/lib.rsC 头文件模板为 prqlc/bindings/prqlc-c/prqlc.h。仓库根目录的 Taskfile.yaml 提供了build-php任务一条命令即可完成整个构建流程task build-php该任务实际执行见 Taskfile.yamlcargo build --package prqlc-c --release # 1. 以 release 模式编译 Rust 库 mkdir -p prqlc/bindings/php/lib/ # 2. 创建 lib 目录 cp target/release/libprqlc_c.* prqlc/bindings/prqlc-c/prqlc.h prqlc/bindings/php/lib/ # 3. 复制共享库与头文件到 lib/ cd prqlc/bindings/php composer install # 4. 安装 PHP 依赖如果你不使用 Task也可以手动执行上述命令效果等同。2.3 使用 nix 搭建开发环境README 推荐使用 nix flake 快速获得带 ext-ffi 的 PHP 8.1 开发环境。首先启用 nix 的实验特性mkdir -p ~/.config/nix echo experimental-features nix-command flakes ~/.config/nix/nix.conf然后在prqlc/bindings/php/目录内进入开发 shellnix shell github:loophp/nix-shell#env-php81 --impure该 shell 会自动拉入 ext-ffi 扩展——因为 composer.json 中声明了ext-ffi: *依赖。三、快速上手第一个编译示例按照 README 的 Usage 示例最小可运行代码如下?php use Prql\Compiler\Compiler; $prql new Compiler(); $result $prql-compile(from employees); echo $result-output;这段代码的输出是一段等价 SQL例如SELECT * FROM employees把这段代码放到启用 FFI、且lib/中已具备共享库的环境中即可运行。下面我们深入剖析这个Compiler类。四、Compiler 类四个核心编译 APICompiler是prql-php的唯一入口类final class Compiler见 Compiler.php。它把prqlc的编译流水线暴露为四个方法对应 PRQL 编译管线的四个阶段compile()一步完成 PRQL → SQL 的完整编译prqlToPL()PRQL → PLPipeline Language解析后的抽象语法树JSON 序列化plToRQ()PL → RQRelational Query经过名称解析与类型推断的关系查询中间表示JSON 序列化rqToSQL()RQ → SQL 字符串。四个方法均以string接收输入返回Result对象。4.1 compile()PRQL 一步编译为 SQLpublic function compile(string $prql_query, ?Options $options null): Result$prql_queryPRQL 查询字符串为空字符串时抛出InvalidArgumentException(No query given.)见 Compiler.php$options可选的Options对象控制 SQL 输出格式与方言返回Result其中output为编译出的 SQL。从 C 侧看compile对应prqlc-c的compile导出函数。源码注释明确指出它是prql_to_pl、pl_to_rq、rq_to_sql三个步骤的封装且中间不经过 JSON 序列化见 prqlc-c/src/lib.rs因此在语义上等价于把下游三个方法串起来但性能更优。4.2 prqlToPL()查看解析树public function prqlToPL(string $prql_query): Result把 PRQL 源码解析为 PL AST并以 JSON 形式放入Result-output。对应 C 侧prql_to_pllib.rs内部调用prqlc::prql_to_pl后经prqlc::json::from_pl序列化。$pl $prql-prqlToPL(from employees | select first_name); // $pl-output 为 PL 的 JSON 表示4.3 plToRQ()PL 中间表示转 RQpublic function plToRQ(string $pl_json): Result接收上一步输出的 PL JSON执行变量引用解析、函数调用校验、frame 推断等语义处理见 lib.rs 注释输出 RQ 的 JSON。$rq $prql-plToRQ($pl-output);4.4 rqToSQL()RQ 转 SQLpublic function rqToSQL(string $rq_json, ?Options $options null): Result接收 RQ JSON结合Options生成最终 SQL见 lib.rs。$sql $prql-rqToSQL($rq-output);4.5 分步管线与一步编译的一致性仓库测试 CompilerTest.php 专门验证了这一点先用prqlToPL → plToRQ → rqToSQL分步编译一个含let绑定的查询再用compile一步编译同一查询最后断言两者输出完全相等assertEquals($via_json, $direct)。这证明四条 API 共享同一条编译流水线你可以在一步到位与逐步检查中间产物之间自由选择。五、Options控制 SQL 输出Options类Options.php封装了 SQL 后端的编译选项三个公共属性与 C 侧Options结构体一一对应属性类型默认值含义$formatbooltrue是否将生成的 SQL 通过格式化器拆分多行并美化缩进与间距$target?stringnull编译目标方言如sql.mssqlnull表示使用默认方言$signature_commentbooltrue是否在生成的 SQL 末尾追加编译器签名注释典型用法use Prql\Compiler\Options; $options new Options(); $options-format false; // 关闭 SQL 美化输出单行紧凑 SQL $options-signature_comment false; // 去掉签名注释 $options-target sql.mssql; // 指定 SQL Server 方言 $result $prql-compile(from employees | take 10, $options);当$options为null时Compiler会内部 new 一个默认Options见 Compiler.php 的optionsInit因此不传参数也能工作。5.1 内存管理细节Options从 PHP 对象映射到 C 结构体时$target字符串需要复制为 C 字符串缓冲区\FFI::new(char[$len], false)\FFI::memcpy编译结束后由optionsDestroy显式\FFI::free释放见 Compiler.php。这是 FFI 绑定中典型的手动内存管理也解释了为什么$target不能为null时跳过分配。5.2 方言示例SQL Server测试 CompilerTest.php 给出了一个可复现的方言示例将from employees | take 10以sql.mssql目标编译formatfalse、signature_commentfalse得到SELECT * FROM employees ORDER BY (SELECT NULL) OFFSET 0 ROWS FETCH FIRST 10 ROWS ONLY这展示了take在 SQL Server 方言下如何被翻译为标准的OFFSET ... FETCH FIRST语法。支持的具体目标方言可在 prqlc 的 Target 定义 与 方言文档 中进一步查阅。六、Result、Message 与错误处理6.1 Result 结构编译结果统一封装为ResultResult.phpfinal class Result { public string $output; // 编译输出SQL 或中间表示 JSON public array $messages; // Message 对象数组错误/警告/提示 }注意compile不会因为 PRQL 语法错误而抛异常——错误信息放在$messages数组中$output在出错时通常为空。因此正确用法是先检查$messages再使用$output。6.2 Message结构化错误信息每个MessageMessage.php包含属性类型含义$kindMessageKind消息类型Error/Warning/Lint$code?string机器可读的错误标识符$reasonstring错误的纯文本描述$hint?string修复建议列表$span?Span源码中的字符偏移范围start/end$display?string带原因和提示的源码标注文本$location?SourceLocation源码中的行列位置start_line/start_col/end_line/end_colMessageKind是 PHP 8.1 枚举MessageKind.php包含Error、Warning、Lint三个 case。C 侧返回的kind字段为整数0Error、1Warning、2LintPHP 侧在convertMessage中做映射见 Compiler.php。需要注意的是目前消息只完整实现了Error一类Message.php 注释 Currently only Error is implemented。SpanSpan.php以字符偏移标识错误来源范围SourceLocationSourceLocation.php进一步给出行列号便于在编辑器中定位。6.3 错误处理示例$prql new Compiler(); $res $prql-compile(invalid); // 故意传入非法查询 foreach ($res-messages as $msg) { if ($msg-kind MessageKind::Error) { printf([%s] %s\n, $msg-code ?? error, $msg-reason); if ($msg-location ! null) { printf( at line %d, col %d\n, $msg-location-start_line, $msg-location-start_col); } if ($msg-hint ! null) { printf( hint: %s\n, $msg-hint); } } }测试 CompilerTest.php 中compile(invalid)会得到一个包含 1 条 message 的结果正是这一行为的验证。七、开发与测试7.1 构建与测试README 给出的两条命令即可完成构建与测试task build-php task test-php其中test-php任务在prqlc/bindings/php目录下执行vendor/bin/phpunit tests见 Taskfile.yaml。PHPUnit 测试套件覆盖了以下场景CompilerTest.phpFFI 扩展已加载lib/libprqlc_c.so|.dylib|.dll共享库存在lib/prqlc.h头文件存在非法查询返回错误消息而非崩溃指定方言编译take得到预期 SQL分步管线与一步compile输出一致。运行测试前记得先执行composer installbuild-php已包含该步骤以获取 PHPUnit 等开发依赖。7.2 代码规范代码风格遵循 PSR-12可用 phpcs 校验./vendor/bin/phpcs --standardPSR12 src tests此外仓库还配置了 phpstan.neon 用于静态分析。八、在 PHP 项目中集成由于绑定尚未发布到 Composer集成方式为源码引入将prqlc/bindings/php/目录纳入项目vendor 或子模块方式均可执行composer install其 PSR-4 自动加载配置会将Prql\Compiler\映射到src/见 composer.json按第二节步骤构建libprqlc_c并放入lib/Compiler默认从__DIR__ . /../lib查找也可通过构造函数参数$lib_path指定自定义路径见 Compiler.php确保运行环境ffi.enabletrue且 PHP ≥ 8.1。一个更完整的示例?php require vendor/autoload.php; use Prql\Compiler\Compiler; use Prql\Compiler\Options; use Prql\Compiler\MessageKind; $prql new Compiler(); // 或 new Compiler(/absolute/path/to/lib) $options new Options(); $options-format true; $options-target sql.postgres; $result $prql-compile(from employees | filter age 30 | select {name, age}, $options); if (count($result-messages) 0) { echo $result-output; // 得到 PostgreSQL 方言的 SQL } else { foreach ($result-messages as $msg) { if ($msg-kind MessageKind::Error) { fwrite(STDERR, $msg-display ?? $msg-reason . PHP_EOL); } } }九、总结与限制prql-php以极薄的 FFI 封装让 PHP 应用获得与官方编译器完全一致的 PRQL 编译能力。其 API 设计围绕Compiler类的四个方法展开compile面向日常使用其余三个方法面向需要逐阶段检查中间表示的调试与集成场景Options控制方言与格式ResultMessage提供结构化的错误信息与源码定位。使用前请留意以下限制绑定仍处于早期阶段未发布至 ComposerAPI 可能随prqlc演进而变化需要手动构建并放置libprqlc_c共享库各平台文件名不同依赖 FFI 扩展需在php.ini中显式开启ffi.enable错误消息目前主要支持Error类型Warning与Lint的枚举已定义但未完全实现。如果你希望深入了解编译流水线本身PL/RQ 中间表示、SQL 方言生成建议继续阅读 prqlc 架构文档、C 绑定实现 prqlc-c/src/lib.rs 以及 PHP 绑定源码目录。赞分享后端【免费下载链接】prqlPRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement项目地址https://gitcode.com/gh_mirrors/pr/prql点击查看免费下载相关推荐使用 prql-php通过 PHP FFI 调用 PRQL 编译器将 PRQL 查询编译为 SQL使用 prql php通过 PHP FFI 调用 PRQL 编译器将 PRQL 查询编译为 SQL PRQLPipelined Relational Que后端PRQL 官方 minimal-cpp 示例解析在 C 中通过 prqlc-c FFI 编译 PRQL 查询PRQL 官方 minimal cpp 示例解析在 C 中通过 prqlc c FFI 编译 PRQL 查询 PRQLPipelined Relatio后端PRQL Elixir Bindings在 Elixir 中编译 PRQL 查询为 SQL 的完整指南PRQL Elixir Bindings在 Elixir 中编译 PRQL 查询为 SQL 的完整指南 PRQLPipelined Relational Q后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

MOS管、三极管、IGBT选型指南:从原理到实战的功率器件设计要点

MOS管、三极管、IGBT选型指南:从原理到实战的功率器件设计要点

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 10:18:30 阅读更多 →
RK1828边缘部署视频大模型的系统级轻量化实战

RK1828边缘部署视频大模型的系统级轻量化实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 10:18:30 阅读更多 →
【Springboot毕设全套源码+文档】基于Java+spring boot的在线拍卖系统设计与实现(丰富项目+远程调试+讲解+定制)

【Springboot毕设全套源码+文档】基于Java+spring boot的在线拍卖系统设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/9/24 10:17:29 阅读更多 →

最新新闻

永久在线自建CRM实操:DeskcommCRM部署与团队协作指南

永久在线自建CRM实操:DeskcommCRM部署与团队协作指南

DeskcommCRM这名字在V2EX、少数派和太多自建爱好者的收藏夹里出现过,但真正聊透它的人并不多。它本质上不是你在美剧里看到的那种繁琐的企业级客户关系管理系统,而是一个把“桌面通讯”和“客户跟进”捏在一起的轻量级自部署系统。这两年很流行一个说法叫…

2026/9/25 12:41:17 阅读更多 →
IFIX历史报警存储查询:基于ODBC+Access的落库与检索方案

IFIX历史报警存储查询:基于ODBC+Access的落库与检索方案

简介:基于 IFIX 组态软件的历史报警数据存储与查询实操文档,面向工业监控实施与运维人员、组态软件学习者,解决报警记录经 ODBC 写入 Access 并按时间段查询的问题。内容从 ODBC 数据源创建讲起,逐步覆盖 SCU 报警 ODBC 服务配置、…

2026/9/25 12:41:17 阅读更多 →
Win10共享文件夹“输入网络凭证”弹窗解决指南:从原理到实操

Win10共享文件夹“输入网络凭证”弹窗解决指南:从原理到实操

如果你在Win10上设置共享文件夹,访问时却被弹窗拦下“输入网络凭证”,这篇文章就是为你准备的。作为常年折腾局域网共享和文件服务器的老用户,我太清楚这种弹窗的烦人之处——它不是你的电脑坏了,也不是对方电脑坏了,而…

2026/9/25 12:41:16 阅读更多 →
Atlas 300V 24G推理加速卡部署YOLO:从模型转换到性能优化

Atlas 300V 24G推理加速卡部署YOLO:从模型转换到性能优化

这两年只要跑AI推理任务的圈子,几乎绕不开一个名字:atlas。周围人也经常问:atlas 300v 24g 是运算加速卡吗?答案是肯定的,但它和你印象里的通用GPU加速卡不太一样。这篇文章我就结合自己实际部署YOLO的经验&#xff0c…

2026/9/25 12:41:16 阅读更多 →
SQL Server XEvents 实战:替代 Profiler 的高性能跟踪方案

SQL Server XEvents 实战:替代 Profiler 的高性能跟踪方案

简介:本资源是一款面向SQL Server数据库管理员与开发者的轻量级数据库跟踪实践工具包,聚焦于性能监控、SQL语句审计与结构逆向分析等核心运维场景。压缩包共28个文件,总大小仅71KB,包含9个C#源码文件(如Form1.cs、MyMo…

2026/9/25 12:41:16 阅读更多 →
Scylla脱壳原理与IAT重建实战指南

Scylla脱壳原理与IAT重建实战指南

1. 为什么Scylla是逆向新手绕不开的第一块“磨刀石”你刚装好x64dbg,双击打开一个加了壳的PE文件,界面一闪——停在了OEP(原始入口点)之前的某个跳转指令上,堆栈空空如也,IAT(导入地址表&#x…

2026/9/25 12:40:16 阅读更多 →

日新闻

AI元人文:从工具使用到思维重构的深度探索

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:00:41 阅读更多 →
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:00:41 阅读更多 →
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/25 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/25 11:15:26 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →