2025 年 Node.js 和 PHP 官宣牵手?php-node 不做选择题?
大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
2025 年 5 月 27 日 platformatic 宣布推出了 @platformatic/php-node,这是一款革命性的全新 Node.js 模块,旨在弥合 PHP 和 Node.js 之间的差距。使用 php-node,开发者可以将 PHP 直接嵌入到 Node.js 应用程序中,并利用 PHP 作为强大的请求处理器,从而能够在一个统一、紧密结合的环境中充分利用两种语言的优势。
什么是 @platformatic/php-node
php-node 是一个基于 Rust、Node.js 原生的模块,其有助于在 Node.js 环境中执行 PHP 应用程序。工作原理是将请求分派到 Node.js 平台提供的工作池中以多线程方式运行的 PHP 实例。这意味着开发者可以享受 Node.js 的性能和可扩展性,同时利用 PHP 广泛的生态和功能。不仅如此,其默认在多线程中运行 PHP 请求,从而受益于多核处理器,而无需额外工作。
php-node 的核心是 Node.js 和 PHP 之间的桥梁。当请求需要 PHP 处理时,php-node 会将其无缝路由到 Node.js 工作线程池中的 PHP 工作线程。PHP 工作线程执行代码并将结果返回给 Node.js,然后 Node.js 再将其交付给客户端。这个过程高效透明,让开发者可以专注于应用程序的构建。
Php-node 提供了一个基于 Rust 和 napi.rs 构建的 PHP 封装器,将请求和响应转换为一个与语言无关的系统,称为 lang_handler,该系统有助于跨语言和线程传输请求。
通过使用 Rust 和 lang_handler,PHP 的复杂性被清晰地隔离到一个专为请求处理而设计的简洁小巧的接口中。提供了一组 Request 和 Response 类型,以及 Rust 中的通用 Handler 特性,从而可以提供一致的接口来处理请求和响应,同时将请求的处理方式留给其他代码定义。Handler 是任何实现了 Handler 特性的对象,该特性需要提供 handle(Request) -> Response 方法。
lang_handler 请求通过 PhpRequestTask 处理,该任务既可以在 JavaScript 线程上同步使用,也可以通过 napi.rs 提供的 Task API 在 Node.js 平台工作池中异步运行请求任务。napi.rs 负责在线程之间传输工作并将结果转换回 JavaScript。其提供了一个基于 Promise 的简单接口,可以通过 Rust 作为中介语言无缝地操作,并返回到 JavaScript 宿主语言。
下图表示其结构和数据流:
php-node 的主要功能包括:
- 无缝集成:轻松将 PHP 嵌入 Node.js 应用程序
- 多线程处理:利用 Node.js 平台工作池实现 PHP 的并行执行
- 性能提升:结合 Node.js 的速度和 PHP 的功能,提升应用程序性能
- 统一开发环境:使用 Node.js 和 PHP 的单一开发环境,减少认知负担,加快交付速度
php-node 的典型用例包括:
- 将旧版 PHP 应用程序迁移到 Node.js
- 构建充分利用两种语言优势的混合应用程序
- 创建需要 PHP 处理的高性能 Web 服务
如何使用 php-node
首先需要安装相应依赖:
// Linux
sudo apt-get update
sudo apt-get install -y libssl-dev libcurl4-openssl-dev libxml2-dev \
libsqlite3-dev libonig-dev re2c
// macOS
brew install openssl@3 curl sqlite libxml2 oniguruma
// npm
npm install @platformatic/php-node
下面是最简单的示例:
import { Php, Request } from "@platformatic/php-node";
const php = new Php();
// 构造一个新的 PHP 实例来分派请求
const request = new Request({
url: "http://example.com/foo/bar",
headers: {
"X-Test": ["Hello, from Node.js!"],
},
});
const response = await php.handleRequest(request);
console.log(response.body.toString());
请求也可以同步处理,但不建议这样做,因为其会在 PHP 请求的整个生命周期内阻塞 Node.js 线程,这对于一次性脚本可能有用。之所以包含它,只是因为简单,但不建议在 HTTP 请求中使用。
import { Php, Request } from "@platformatic/php-node";
const php = new Php();
const request = new Request({
url: "http://example.com/foo/bar",
});
const response = php.handleRequestSync(request);
console.log(response.body.toString());
要访问请求层面的信息也是非常简单,例如获取 request.headers:
import { Request } from "@platformatic/php-node";
const request = new Request({
url: "http://example.com/foo/bar",
});
console.log(request.headers); // [Headers]
或者 request.status:
import { Response } from "@platformatic/php-node";
const response = new Response({
status: 500,
});
console.log(response.status); // 500
或者遍历所有的 headers 信息:
import { Headers } from "@platformatic/php-node";
const headers = new Headers();
headers.set("Content-Type", "application/json");
headers.add("Accept", "application/json");
headers.add("Accept", "text/html");
headers.forEach((value, name, headers) => {
// ('application/json', 'Content-Type', headers)
// ('application/json', 'Accept', headers)
// ('text/html', 'Accept', headers)
});
参考资料
https://blog.platformatic.dev/seamlessly-blend-php-with-nodejs