PHP解析n8n原始请求数据需先判断Content-Type,JSON格式用file_get_contents('php://input')读取并json_decode解析,表单格式回退$_POST+$_GET;返回时须设header('Content-Type: application/json')并确保json_encode合法。

PHP里怎么解析n8n传来的原始请求数据
n8n的“HTTP Request”或“Webhook”节点发来的数据,默认是 application/json 或 application/x-www-form-urlencoded,但 PHP 的 $_POST 和 $_GET 在非表单场景下可能为空——尤其当 n8n 用 raw 方式 POST JSON 时。
必须手动读取原始输入流:
if (isset($_SERVER['CONTENT_TYPE']) && strpos($_SERVER['CONTENT_TYPE'], 'application/json') !== false) {
$raw = file_get_contents('php://input');
$data = json_decode($raw, true);
if (json_last_error() !== JSON_ERROR_NONE) {
http_response_code(400);
exit('Invalid JSON');
}
} else {
$data = $_POST + $_GET; // fallback for form-encoded
}
- n8n 的 “Data Transformer” 节点若输出为 “JSON”,且被下游 HTTP Request 节点以
RAW方式发送,php://input是唯一可靠入口 -
$_REQUEST不可靠:它不自动解析 JSON,也不包含 raw body - 别直接用
json_decode($HTTP_RAW_POST_DATA)——该超全局变量默认关闭且已废弃
如何在PHP中复现n8n的“Set”节点逻辑
n8n 的 “Set” 节点本质是对象字段赋值/重命名/类型转换。PHP 没有内置等价物,但可封装一个轻量函数模拟其核心行为:
function applyN8nSetRules(array $input, array $rules): array {
$output = $input;
foreach ($rules as $rule) {
$value = $rule['value'] ?? null;
$key = $rule['name'] ?? null;
if (!$key || !is_string($key)) continue;
// 支持简单路径如 'user.name' → 递归设置
$keys = explode('.', $key);
$ref = &$output;
foreach (array_slice($keys, 0, -1) as $k) {
if (!isset($ref[$k]) || !is_array($ref[$k])) $ref[$k] = [];
$ref = &$ref[$k];
}
$ref[end($keys)] = $value;
}
return $output;
}
- 规则格式需对齐 n8n 导出的 JSON 配置:
{"name": "result.code", "value": "={{ $input[0].json.status }}"}→ 这里 PHP 端只处理静态值或简单映射,动态表达式(如=开头)需额外解析器,不建议在 PHP 层硬解 - 若 n8n 已在上游完成表达式计算(推荐做法),PHP 只需接收最终值,避免重复解析
- 注意键名含数字索引(如
items.0.json.id)时,PHP 数组不支持点号访问,需转为$input['items'][0]['json']['id']—— 所以最好让 n8n 把结构扁平化再传
PHP返回值怎么让n8n的“HTTP Request”节点正常解析
n8n 的 “HTTP Request” 节点默认把响应体当作 JSON 解析,但 PHP 默认不设 header,容易触发 Unexpected token 错误。
立即学习“PHP免费学习笔记(深入)”;
必须显式声明 Content-Type 并确保输出是合法 JSON:
header('Content-Type: application/json; charset=utf-8');
http_response_code(200);
echo json_encode([
'success' => true,
'data' => $processed,
'timestamp' => date('c')
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
- 漏掉
header()会导致 n8n 尝试按 text/plain 解析,遇到中文或特殊字符就报错 -
json_encode()返回false时不会报错,务必检查:if ($json === false) { error_log(json_last_error_msg()); die('JSON encode failed'); } - n8n 对响应状态码敏感:返回 5xx 会进 “Error Output”,4xx 视为业务失败但不一定中断流程——根据你的错误处理策略决定用 400 还是 500
调试时怎么快速确认n8n和PHP之间的数据是否对得上
最有效的方式不是看日志,而是让 PHP 输出原始请求快照,再跟 n8n 的 “Debug” 面板比对:
$debug = [
'method' => $_SERVER['REQUEST_METHOD'],
'headers' => getallheaders(),
'content_type' => $_SERVER['CONTENT_TYPE'] ?? '',
'raw_input' => substr(file_get_contents('php://input'), 0, 512),
'post' => $_POST,
'get' => $_GET,
];
file_put_contents('/tmp/n8n-debug.log', json_encode($debug, JSON_PRETTY_PRINT) . "\n", FILE_APPEND | LOCK_EX);
- 别依赖
var_dump输出到页面——n8n 不会渲染 HTML,只会截断或报错 -
getallheaders()在 CLI 或某些 FastCGI 模式下不可用,可改用apache_request_headers()或从$_SERVER提取(如HTTP_CONTENT_TYPE) - 记录 raw input 前做
substr限制长度,避免日志爆炸;真实调试时可临时去掉限制
n8n 和 PHP 之间没有魔法,只有明确的协议边界。最容易忽略的是:n8n 的表达式在发送前就已完成求值,PHP 看到的永远是最终数据——别试图在 PHP 里重新实现 ={{ $input[0].json.user?.name }} 这类逻辑,那属于上游职责。



















