新闻详情

新闻详情

首页 / 资讯中心 / 详情

使用 prql-php:通过 PHP FFI 调用 PRQL 编译器将 PRQL 查询编译为 SQL

发布时间:2026/11/5 5:26:18来源:尧图网络
使用 prql-php:通过 PHP FFI 调用 PRQL 编译器将 PRQL 查询编译为 SQL
后端【免费下载链接】prqlPRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement项目地址https://gitcode.com/gh_mirrors/pr/prql点击查看免费下载PRQLPipelined Relational Query Language是一种面向数据转换的现代化语言旨在以管道式、可读性强的语法替代复杂 SQL。prql-php是 PRQL 项目为 PHP 提供的官方绑定bindings它通过 PHP FFIForeign Function Interface将 Rust 编写的prqlc编译器暴露给 PHP 应用。本文将以 prqlc/bindings/php/README.md 为骨架结合 PHP 绑定源码 与底层 C FFI 实现完整讲解prql-php的环境安装、Compiler类四大编译方法、编译选项与错误消息结构、底层 FFI 调用链以及面向开发者的构建、测试与代码规范流程。读完本文你将能够在自己的 PHP 项目中直接编译 PRQL 查询并获得对应的 SQL并能深入理解这条从 PHP 到 Rust 再到 SQL 的完整链路。prql-php 是什么prql-php提供的是prqlcRust crate 的 PHP 绑定。它没有用纯 PHP 重新实现 PRQL 编译器而是通过 PHP 8 内置的 FFI 扩展直接加载prqlc-c编译产物一个共享库从而在 PHP 进程中完成 PRQL → SQL 的编译。从 php.md 的入口该文档通过 mdBook 的{{#include}}指令直接引用了 prqlc/bindings/php/README.md可以看到prql-php对外暴露的核心是一个Compiler类包含四个主要方法compile把 PRQL 字符串一步编译为 SQL 字符串prqlToPL把 PRQL 编译为 PLPipeline Language中间表示输出 JSONplToRQ把 PL JSON 转换为 RQRelational Query中间表示输出 JSONrqToSQL把 RQ JSON 转换为最终的 SQL 字符串。需要说明的是该绑定仍处于早期阶段README 明确标注 Its still at an early stage尚未发布到 Composer 官方仓库且项目欢迎社区贡献。因此在实际使用时需要从本仓库源码自行构建。环境要求与安装启用 PHP FFI 扩展prql-php依赖 PHP 的 FFI 扩展。需要在php.ini配置文件中开启ffi.enable true从 composer.json 可以看到库的运行时依赖为php: ^8.1和ext-ffi: *即要求 PHP 8.1 及以上版本并且必须安装ext-ffi扩展。构建并准备共享库由于prql-php通过 FFI 加载 Rust 编译产物使用前必须先在本地构建prqlc-c动态库。项目根目录的 Taskfile.yaml 中定义了build-php任务它完成三件事cargo build --package prqlc-c --release—— 以 release 模式编译prqlc-ccrate把生成的libprqlc_c.*Linux 下为libprqlc_c.so与prqlc.h头文件复制到prqlc/bindings/php/lib/目录在prqlc/bindings/php下执行composer install安装 PHP 依赖。在 Compiler.php 的构造函数中可以看到库的加载逻辑默认从__DIR__ . /../lib即prqlc/bindings/php/lib查找头文件prqlc.h与共享库并按操作系统区分动态库文件名Windowslibprqlc_c.dllmacOSDarwinlibprqlc_c.dylib其他Linux 等libprqlc_c.so构造函数支持传入?string $lib_path自定义库所在目录方便将库部署到其他位置。快速上手编译第一条 PRQL 查询README 给出了最简用法。在项目内安装依赖并构建好共享库后编写如下 PHP 代码?php use Prql\Compiler\Compiler; $prql new Compiler(); $result $prql-compile(from employees); echo $result-output;compile(from employees)会把这条 PRQL 管道查询编译为 SQL结果对象的output属性保存生成的 SQL 字符串直接输出即可。这是最常用的入口一条 PRQL 查询、一步拿到 SQL。更完整一点配合Options使用?php use Prql\Compiler\Compiler; use Prql\Compiler\Options; $options new Options(); $options-format false; // 不美化 SQL 格式 $options-signature_comment false; // 不在 SQL 后追加编译器签名注释 $options-target sql.mssql; // 指定 SQL Server 方言 $prql new Compiler(); $result $prql-compile(from employees | take 10, $options); if (count($result-messages) 0) { echo $result-output; }这条示例并非凭空捏造——它正是 CompilerTest.php 中testCompileWorks测试用例的复刻测试断言其输出为SELECT * FROM employees ORDER BY (SELECT NULL) OFFSET 0 ROWS FETCH FIRST 10 ROWS ONLY可以看到take 10在 SQL Server 方言下被翻译为FETCH FIRST 10 ROWS ONLY。Compiler 类四个编译方法与分层管线一步到位的 compilecompile(string $prql_query, ?Options $options null): Result是最常用的 API。在底层它并不是一个独立的编译流程而是prqlToPL、plToRQ、rqToSQL三段式管线的打包版本。对照 prqlc-c 的 C FFI 层compile的 Rust 实现正是依次调用prqlc::prql_to_pl→prqlc::pl_to_rq→prqlc::rq_to_sql且省去了中间两次 JSON 序列化开销。这解释了为何 PHP 层提供两种使用方式日常编译用compile需要调试中间表示或做二次处理时用后三个方法。分步调试prqlToPL / plToRQ / rqToSQLPRQL 的编译是一条清晰的三段式流水线对应编译器架构中的三层 IR方法输入输出对应 IR 阶段prqlToPLPRQL 源码字符串PL 序列化为 JSON解析与语义分析后的管道语言PLplToRQPL JSONRQ 序列化为 JSON解析变量引用、校验函数调用、确定 frame 后的关系查询RQrqToSQLRQ JSONSQL 字符串面向具体方言的 SQL 生成从 prqlc-c 的 C FFI 层 可以看到三者对应的 C 符号分别为prql_to_pl、pl_to_rq、rq_to_sqlCompiler.php 中的同名方法正是通过 FFI 对这些符号的封装。CompilerTest.php 中的testOtherFunctions给出了完整的分步用法先用prqlToPL得到 PL JSON再用plToRQ得到 RQ JSON接着用rqToSQL得到 SQL并断言该结果与直接用compile得到的结果完全一致assertEquals($via_json, $direct)从测试层面印证了分步调用 一步调用的等价性。Result 与错误消息四个方法统一返回Result对象其结构在 Result.php 中定义包含两个公开属性string $output编译产物SQL 字符串或在 PL/RQ 阶段为 JSON 字符串array $messages编译过程中产生的消息数组元素类型为Message。Message.php 定义了Message的字段kind消息类型、code机器可读的错误标识、reason纯文本错误说明、hint修复建议、span源码中的字符偏移区间、display带注解的代码片段、location行列号。消息类型为 MessageKind.php 中的枚举Error/Warning/Lint其中Error是目前唯一被实际实现并产出的类型见 C 层注释 Currently only Error is implemented。在 Compiler.php 的convertResult/convertMessage中可以看到PHP 层会把 C 结构体逐字段转换为 PHP 对象SpanSpan.php字符偏移起止与SourceLocationSourceLocation.php起止行列在指针为空时映射为null。一个典型的错误处理写法?php use Prql\Compiler\Compiler; $prql new Compiler(); $result $prql-compile(invalid); foreach ($result-messages as $message) { echo $message-reason, PHP_EOL; if ($message-location ! null) { echo at line {$message-location-start_line}, col {$message-location-start_col}, PHP_EOL; } }对应测试 testInvalidQuery 正是断言对invalid这种非法查询会返回恰好 1 条消息。Options 编译选项详解Options类Options.php控制 SQL 生成阶段的三个行为与 C FFI 层 Options 结构体 一一对应属性类型默认值作用formatbooltrue是否对生成的 SQL 进行美化拆分成多行、优化缩进与空格target?stringnull等价于sql.any编译目标方言如sql.mssql、sql.duckdb、sql.postgres等signature_commentbooltrue是否在生成的 SQL 末尾追加编译器签名注释target的语义在 C 层有明确说明默认值sql.any表示根据查询头query header中的target参数自动决定 SQL 方言。从 prqlc-c 的 convert_options 可以看到PHP 传入的target字符串最终会通过Target::from_str解析为 Rust 侧的方言枚举解析失败会直接产生编译错误。PHP 侧的optionsInit方法Compiler.php负责把Options对象拷贝为 C 结构体并在optionsDestroy中释放target字符串占用的 FFI 内存——这是使用 FFI 时需要注意的 C 侧内存管理细节库已经帮你处理妥当。底层原理PHP 到 Rust 的 FFI 调用链prql-php之所以能零成本复用 Rust 编译器靠的是prqlc-c这个 C ABI 中间层。整条链路可以概括为PHP 调用 Compiler::compile() → PHP FFI::cdef() 绑定 libprqlc_c 动态库 → C 符号 compile()Rust #[no_mangle] 导出 → prqlc::prql_to_pl() → prqlc::pl_to_rq() → prqlc::rq_to_sql() → CompileResult 结构体output messages 数组 → PHP convertResult() 转换为 Result 对象几个关键设计点C ABI 导出prqlc-c使用#[no_mangle] pub unsafe extern C fn导出compile、prql_to_pl、pl_to_rq、rq_to_sql、result_destroy等符号见 prqlc-c/src/lib.rs头文件驱动绑定PHP 侧通过\FFI::cdef($header_source, $library)解析 prqlc.h 头文件来声明函数与结构体布局因此库目录中必须同时存在头文件与动态库内存所有权Rust 侧分配的内存由result_destroy统一释放lib.rs#L199-L245PHP 侧在每次调用后立即调用它避免泄漏。文档注释明确要求每个返回CompileResult的函数调用后result_destroy必须恰好被调用一次字符串传递Rust 假设输入是零终止字符串*const c_charPHP 侧由 FFI 自动处理转换。开发指南环境、构建、测试与代码规范搭建开发环境README 推荐使用 nix flake 快速获得带 PHP、ext-ffi与 Composer 的开发环境。首先在 nix 中启用实验性的 flakes 特性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该 flake 会自动带入ext-ffi扩展——正如 composer.json 中require声明的ext-ffi: *所要求的那样。当然如果你已经有配置好ext-ffi的 PHP 8.1 环境也可以跳过 nix直接在本地执行composer install。构建与测试项目的 Taskfile.yaml 提供了两个与 PHP 绑定相关的任务task build-php task test-phpbuild-php负责编译 Rust 动态库并把产物与头文件复制到lib/test-php则在prqlc/bindings/php目录下运行vendor/bin/phpunit tests。测试套件CompilerTest.php覆盖了四类断言环境自检extension_loaded(ffi)为真且lib/下存在动态库与prqlc.h头文件testFfiExtensionIsLoaded、testPrqlLibraryFileExists、testPrqlHeaderFileExists错误路径非法查询返回非空messages正确性指定sql.mssql方言编译from employees | take 10得到预期 SQL管线一致性分步调用prqlToPL → plToRQ → rqToSQL的结果与compile一步调用完全相等。代码规范prql-php的 PHP 代码遵循 PSR-12 编码标准通过 PHP_CodeSniffer 检查./vendor/bin/phpcs --standardPSR12 src tests从 composer.json 的require-dev可以看到开发依赖为phpunit/phpunit: ^10与squizlabs/php_codesniffer: ^3.7。库的自动加载遵循 PSR-4命名空间Prql\Compiler\映射到src/目录。现状、限制与适用场景成熟度README 明确说明绑定仍处于早期阶段尚未发布到 Composer 官方仓库因此不能直接composer require prql/compiler需要基于本仓库自行构建并引入平台限制需要 PHP 8.1、ext-ffi扩展以及对应平台的libprqlc_c动态库Linux.so/ macOS.dylib/ Windows.dll典型场景在 PHP 应用中动态生成 SQL例如把业务上易于表达、维护的 PRQL 管道编译成 SQL 交给数据库执行或借助prqlToPL/plToRQ调试、检查 PRQL 的中间表示进一步阅读绑定目录的总体说明见 web/book/src/project/bindings/README.md其他语言的绑定实现C、Python、JS、Java、.NET、Elixir位于 prqlc/bindings 下可作为横向对比参考。总而言之prql-php用不到两百行 PHP 代码通过 FFI 把完整的prqlc编译器带进了 PHP 生态一条 PRQL 管道、一个Compiler实例就能在你的 PHP 应用中产出跨方言的 SQL。赞分享后端【免费下载链接】prqlPRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement项目地址https://gitcode.com/gh_mirrors/pr/prql点击查看免费下载相关推荐深入PRQL编译器架构从源码到SQL的魔法转换深入PRQL编译器架构从源码到SQL的魔法转换 PRQL编译器采用分层架构设计将查询转换过程分解为解析、语义分析和SQL生成三个阶段。本文详细解析了PRQL后端PRQL 语言与编译器深度解析基于 prql 仓库的管道式 SQL 替代方案实战指南PRQL 语言与编译器深度解析基于 prql 仓库的管道式 SQL 替代方案实战指南 PRQL P ipelined R elational Q uery后端PRQL性能优化技巧10个方法提升你的查询编译和执行效率PRQL性能优化技巧10个方法提升你的查询编译和执行效率 PRQLPipelined Relational Query Language是一个现代化的数据后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

【外设】之大彩串口显示屏 2026/11/4 15:56:54

【外设】之大彩串口显示屏

大彩串口屏初步使用 1 .官网下载 STM32 屏幕 GUI 设计资料 http://www.gz-dc.com/category/typeid/4112 找到 STM32 Keil 工程,移植相关代码因项目而异进行移植,由于项目简单,本人只对用到的指令接口进行修改。 比如:注意事项&…

阅读更多 →
无法下载Windows系统iso文件 2026/11/4 22:55:41

无法下载Windows系统iso文件

当我遇到这个问题的时候,我打开了一个网站: 登录 然后我打算下载的时候: 突然那个官方的连接就可以下载了:

阅读更多 →
【清华代码熊】DeepSeek V4.1 Flash 后训练详解 2026/11/4 17:01:23

【清华代码熊】DeepSeek V4.1 Flash 后训练详解

📌 上期解析了 DeepSeek V4.1 Flash 模型架构改进,本期解析 DeepSeek V4.1 Flash 预训练/后训练技术: 🌟 预训练:45T 文本 多模态混合语料、直接训练 sparse attention(取消 DeepSeek V4 的 dense 冷启动&…

阅读更多 →
Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ... 2026/11/4 12:33:12

Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ...

文章主要内容和创新点 主要内容 本文聚焦于多模态大语言模型(MLLM)强化学习(RL)训练中的效率问题,提出了一个名为Shuffle-R1的框架。研究发现,当前RL训练存在两个关键缺陷: 优势值坍缩(Advantage Collapsing):批次中大多数优势值集中在零附近,导致有效梯度信号被淹…

阅读更多 →
PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction 2026/11/5 4:24:57

PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction

一、文章主要内容总结 本文聚焦于利用大型语言模型(LLMs)实现个人身份信息(PII)脱敏的研究,旨在解决传统脱敏方法(如基于规则的系统、领域特定命名实体识别(NER)模型)泛化能力差、跨格式/跨语境适应性弱的问题。 研究通过全面评估多种LLM架构(包括密集型LLM(D-LLM…

阅读更多 →
LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model 2026/11/5 4:24:57

LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model

文章主要内容和创新点 主要内容 本文聚焦于二进制图像-文本相关性评估任务(判断图像与文本“相关”或“不相关”),针对该任务中文本格式多样、相关性定义随场景变化等挑战,提出了基于多模态大语言模型(MLLM)的解决方案LLaVA-RE。 模型设计:LLaVA-RE基于LLaVA 1.5架构,…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉