
PHP与边缘计算:在Cloudflare Workers上部署你的脚本
大家好,作为一名和PHP打了多年交道的开发者,我最近一直在探索如何让这门“古老”的语言焕发新的活力。当“边缘计算”这个概念越来越火时,我就在想,我们那些经典的PHP逻辑,能不能也跑到网络的边缘,享受一下低延迟、全球部署的快感?答案是肯定的,而Cloudflare Workers正是实现这个想法的绝佳平台。今天,我就带大家一步步,把一段PHP业务逻辑部署到Cloudflare Workers上。这不仅仅是技术上的迁移,更是一种思维模式的转变。
为什么选择Cloudflare Workers?
首先,我们得搞清楚为什么要这么做。传统的PHP运行在像Nginx+PHP-FPM这样的服务器端环境里。用户请求从浏览器出发,穿过茫茫网络,到达你的数据中心,处理完再返回。这个链路很长,延迟(尤其是对全球用户)是不可避免的。
Cloudflare Workers则完全不同。它基于V8引擎,允许你在Cloudflare全球超过300个数据中心的每一个“边缘节点”上运行JavaScript(现在通过WebAssembly也支持了更多语言)。这意味着你的代码是在离用户物理距离最近的地方执行的,响应速度极快。虽然Workers原生支持的是JavaScript/TypeScript,但通过一个神奇的“编译”工具,我们可以把PHP代码“变成”能在Workers上运行的东西。
踩坑提示:这并不意味着你完整的Laravel或ThinkPHP应用能直接无缝迁移。Workers是一个无状态、轻量级的执行环境,更适合处理请求/响应转换、API聚合、AB测试、简单的业务逻辑等。但许多核心的PHP逻辑是完全可行的。
准备工作:认识我们的“翻译官”——Bref PHP
直接让V8运行PHP是不可能的。我们需要一个“翻译官”,这就是Bref PHP项目。它通过WebAssembly(WASM)技术,将PHP解释器本身编译成WASM模块。然后,在Cloudflare Workers里加载这个WASM模块,并用它来执行我们的PHP代码。听起来很酷对吧?
你需要准备以下工具:
- 一个Cloudflare账户(免费层就足够我们体验)。
- 本地安装好Node.js和npm(用于使用Wrangler,Cloudflare的命令行工具)。
- 一个可以测试的PHP脚本。
第一步:安装并配置Wrangler CLI
Wrangler是和Cloudflare Workers交互的瑞士军刀。我们通过它来创建、开发和部署项目。
# 使用npm全局安装wrangler
npm install -g wrangler
# 登录到你的Cloudflare账户,这会打开浏览器进行授权
wrangler login
登录成功后,你的机器就获得了操作Cloudflare账户的权限。
第二步:初始化一个Worker项目
我们创建一个全新的项目目录并初始化。
# 创建一个项目文件夹并进入
mkdir php-on-edge && cd php-on-edge
# 初始化一个最简单的Worker项目,类型选择“Hello World”即可
wrangler init
在初始化过程中,它会询问你是否要创建TypeScript项目,选择“是”会让后续开发更有优势。完成后,你会看到几个文件,其中src/index.ts是主入口文件。
第三步:引入并配置Bref PHP WASM
这是最核心的一步。我们需要下载PHP的WASM构建文件,并修改Worker代码来加载它。
首先,在项目根目录下载必要的文件:
# 下载PHP WASM运行时和INI配置文件
curl -LO https://github.com/brefphp/php-wasm/releases/download/v0.1.2/php-8.3.wasm
curl -LO https://raw.githubusercontent.com/brefphp/php-wasm/v0.1.2/php.ini
接下来,修改wrangler.toml配置文件,确保WASM模块能被正确上传:
name = "php-on-edge"
compatibility_date = "2024-05-01"
main = "src/index.ts"
# 添加这一部分,声明assets以便上传wasm文件
[[rules]]
globs = ["**/*.wasm", "**/*.ini"]
type = "CompiledWasm"
现在,我们来重写src/index.ts。这个Worker的职责是:初始化PHP WASM运行时,将请求信息传递给我们的PHP脚本,并将PHP脚本的输出作为响应返回。
// src/index.ts
export interface Env {
// 这里可以定义绑定,如KV、D1数据库等,本例暂不需要
}
// 初始化PHP实例。注意:这是一个异步操作,最好在全局范围或使用单例模式。
// 为了简单,我们在每个请求中初始化(生产环境应考虑复用)。
async function getPHP() {
const php = await import('php-wasm');
const phpInstance = await php.default({
phpBinary: new URL('../php-8.3.wasm', import.meta.url), // WASM文件路径
phpIni: new URL('../php.ini', import.meta.url), // INI配置文件路径
});
return phpInstance;
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise {
try {
const php = await getPHP();
// 1. 准备我们要执行的PHP代码。
// 这里我们直接内联了一段PHP脚本。更佳实践是将PHP代码放在单独文件中。
const phpCode = ` 'Hello from PHP at the Edge!',
'timestamp' => time(),
'your_ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown',
'request_method' => $method,
'request_path' => $path,
'php_version' => PHP_VERSION,
];
echo json_encode($response, JSON_PRETTY_PRINT);
?>`;
// 2. 设置PHP环境变量,模拟Web服务器环境。
// 我们将请求的路径信息放入PATH_INFO。
const url = new URL(request.url);
php.setEnv('PATH_INFO', url.pathname);
php.setEnv('REMOTE_ADDR', request.headers.get('CF-Connecting-IP') || '127.0.0.1');
php.setEnv('REQUEST_METHOD', request.method);
// 3. 运行PHP代码并捕获输出。
const output = await php.run(phpCode);
// 4. 将PHP的输出作为HTTP响应返回。
// 注意:我们的PHP代码中已经设置了JSON header,所以这里直接返回。
return new Response(output.stdout, {
headers: { 'Content-Type': 'application/json' },
});
} catch (error: any) {
// 错误处理
console.error('Error executing PHP:', error);
return new Response(JSON.stringify({
error: 'Internal Server Error',
details: error.message
}), {
status: 500,
headers: { 'Content-Type': 'application/json' },
});
}
},
};
实战经验:注意php.run是异步的。PHP脚本中的所有输出(echo, print)都会进入output.stdout。你也可以通过php.setEnv来设置$_GET, $_POST等,这为处理复杂请求提供了可能。
第四步:本地测试与调试
在部署到全球网络之前,务必在本地进行测试。
# 启动本地开发服务器
wrangler dev
执行后,Wrangler会提供一个本地地址(通常是localhost:8787)。用浏览器或curl访问它:
curl http://localhost:8787/hello
你应该会看到一个格式美观的JSON响应,包含了问候语、时间戳、你的IP(本地会是IPv6格式)、请求方法和路径,以及PHP版本信息。这证明你的PHP代码已经在本地Worker环境中成功运行了!
第五步:部署到Cloudflare全球网络
本地测试无误后,就是最激动人心的时刻——部署上线。这一步简单得不可思议。
# 一键部署
wrangler deploy
几十秒后,你的PHP脚本就已经运行在Cloudflare全球所有边缘节点上了。Wrangler会输出你的Worker的专属域名,格式如https://php-on-edge..workers.dev。
立即用curl或浏览器访问这个地址试试吧!感受一下你的PHP逻辑从“中心”到“边缘”的飞跃。你可以用在线测速工具,从全球不同地点ping你的Worker地址,体验一下低延迟的魅力。
进阶思考与踩坑提示
恭喜你完成了基本部署!但要想用于实际项目,还有几点需要考虑:
- 性能与冷启动:WASM版本的PHP解释器初始化需要时间,这会导致第一次请求(冷启动)有延迟。对于对延迟极度敏感的场景,需要利用Workers的
ctx.waitUntil()等机制进行预热或实例复用。 - 扩展支持:目前的PHP WASM构建包含了一些常用扩展(如JSON, cURL, MBString),但不像完整的PHP环境那样支持所有扩展(比如没有MySQLi、PDO等)。你需要通过Workers自身的功能来连接数据库,例如使用其提供的D1数据库或通过TCP连接外部数据库(企业版功能)。
- 代码组织:将PHP代码以内联字符串形式写在TS里非常不优雅。更好的做法是将
.php文件作为项目资源,在部署时一起上传,然后在Worker中读取文件内容来执行。这需要更复杂的Wrangler配置。 - 状态管理:Workers是无状态的。任何需要持久化的数据,都必须借助外部存储,如Cloudflare的KV、R2、D1等。
尽管有这些限制,将PHP部署到边缘仍然为许多场景打开了新的大门:个性化内容片段、实时配置检查、简单的API网关、A/B测试逻辑、机器人检测等等。它让我们能够复用庞大的PHP代码资产和开发者经验,同时享受现代边缘计算架构的红利。
希望这篇教程能为你打开一扇新的大门。动手试试,把你的一个工具函数或一小段业务逻辑迁移上去,亲自体验一下“PHP on the Edge”的感觉吧!

评论(0)