在云函数场景下运行 PHP,不少开发者会优先考虑国内平台——京东云 FunctionCompute 就是一个选择。不过,它跟本地开发环境有不少差异,尤其是 PHP 版本、入口结构、依赖打包和密钥管理这几个方面,稍不注意就会踩坑。下面把几个关键点捋清楚,帮你少走弯路。

京东云 FunctionCompute 的 PHP 运行时支持哪些版本
截至 2024 年,京东云官方明确支持的 PHP 运行时只有 php7.4 和 php8.1,php8.2+ 或 php7.3 及更早版本都不在支持之列。如果你本地用的是 php8.3 开发,直接打包上传,冷启动几乎必失败,日志里通常只显示一句 Failed to start runtime,连个具体原因都不给,排查起来很头疼。
几点实操建议:
- 开发阶段最好用 Docker 拉取京东云镜像先验证一下环境:
docker run -it jdcloudfunction/php74:latest php --version composer.json里的"php": "^8.1"必须降级为"php": "8.1.*",否则composer install --no-dev --optimize-autoloader在构建时可能因为平台约束报错- 别依赖
pcntl、sockets或sysvshm这些扩展——京东云函数默认没启用,想用得提工单,而且多数场景下不被允许
函数入口文件必须叫 index.php 且暴露 handler 函数
京东云要求 PHP 函数的入口文件必须是项目根目录下的 index.php,而且必须定义一个全局函数 handler(不能是类方法、匿名函数或命名空间内的函数)。这个函数接收两个参数:$event(触发事件数据)和 $context(运行时上下文),返回值会被序列化为响应体。
常见翻车现场:上传 ZIP 后控制台显示“函数状态异常”,或者调用返回空响应,但日志里没有任何报错——十有八九是入口函数名或签名没对上。
正确写法示例:
200,
'headers' => ['Content-Type' => 'application/json'],
'body' => json_encode(['msg' => 'hello', 'len' => strlen($body)])
];
}
几个需要留意的细节:
$event已经由平台自动json_decode($rawBody, true)了,你不需要再调一次json_decode- HTTP 触发器下,
$event的结构与 AWS API Gateway v2 兼容,包含rawQueryString、headers、requestContext等字段,但isBase64Encoded始终为false - 函数里绝对不能写
exit()或die(),否则上下文回收会出异常,影响后续并发请求
依赖打包必须用 --no-dev --optimize-autoloader
京东云函数对部署包体积比较敏感,ZIP 解压后代码目录总大小不能超过 250MB(含 vendor)。而且冷启动时会扫描全部 PHP 文件做 opcode 缓存预热。如果 vendor/ 里混入了 .git、tests/、docs/ 或大量 dev-only 包(比如 phpunit、symfony/var-dumper),上传就会失败或超时。
推荐构建流程:
- 在干净目录里执行:
composer install --no-dev --optimize-autoloader --ignore-platform-reqs - 用
zip -r function.zip index.php vendor/ src/打包,注意把.env、node_modules、composer.lock排除掉(后者虽然不执行但占体积) - 检查 ZIP 内部结构:
unzip -l function.zip | head -20,确认没有意外嵌套目录(比如project/src/而不是src/)
性能方面:如果没有启用 --optimize-autoloader,每次请求都会遍历 vendor/autoload.php 中的 classmap,冷启动延迟能增加 300–800ms,这差别还是挺明显的。
环境变量和 Secret 配置要通过控制台或 CLI 设置,不能硬编码
京东云不支持在函数 ZIP 包里读取 .env 文件,getenv('DB_HOST') 默认返回 false,除非这个变量已经在函数配置页里显式添加了。Secret(比如数据库密码、API Key)必须用京东云 KMS 或 Secret Manager 创建,然后在函数配置里以“引用密钥”方式挂载——此时变量值是解密后的内容,不是密钥 ID。
容易踩的坑:
- 在
index.php顶部写if (file_exists('.env')) { ... }——这个文件不会随 ZIP 上传生效,写了白写 - 把 Secret ID(如
ak-xxxxx)当实际值用,结果连接数据库失败,错误日志里只显示PDOException: SQLSTATE[HY000] [2002],完全没提示是密钥问题 - 环境变量名如果含下划线(如
REDIS_URL)可以正常读取,但含短横线(如redis-url)会被转成REDIS_URL,PHP 里必须用getenv('REDIS_URL'),不能用$_ENV['redis-url']
比较棘手的一点:Secret 挂载后,变量值是运行时注入的,无法在 composer install 阶段用于配置生成。如果你的项目里有类似 config/database.php 依赖环境变量初始化,必须改造为运行时 lazy-load,而不是在文件顶层直接执行 new PDO(...)。