
本文详解在 nginx + php(如 raspberry pi 上的 php-fpm)环境中,通过表单提交动态更新 json 文件的完整实现方案,涵盖语法修正、文件权限配置、安全防护要点及错误处理技巧。
本文详解在 nginx + php(如 raspberry pi 上的 php-fpm)环境中,通过表单提交动态更新 json 文件的完整实现方案,涵盖语法修正、文件权限配置、安全防护要点及错误处理技巧。
在 Nginx 服务器上使用 PHP 写入 json 文件是一个常见但易出错的操作——尤其当页面提交后跳转至空白页、JSON 文件未更新或出现 500 internal Server Error 时,问题往往源于语法错误、路径权限不足、PHP 配置限制或逻辑缺陷。以下是一套经过验证的、生产就绪的实现方案。
✅ 核心修复与最佳实践
首先,原始代码中存在一个致命语法错误:
'name'=>>$_POST['username'] // ❌ 多了一个 >
应修正为:
'name' => $_POST['username'] // ✅ 正确的数组键值语法
其次,避免将 HTML 表单与处理逻辑分离在 index.html 和 index.php 中——这不仅导致路由混乱(如 action=”index.php” 提交后覆盖首页),还容易引发 Nginx 的静态文件优先匹配问题(.html 不经 PHP 解析)。推荐采用「单文件混合模式」:HTML 前端与 PHP 后端逻辑统一置于 index.php 中,由同一入口响应 GET(展示表单)和 POST(处理数据)请求。
立即学习“PHP免费学习笔记(深入)”;
✅ 完整可运行示例(index.php)
<?php $output = null; $filepath = 'whitelist.json'; // 仅在表单提交且字段非空时执行写入 if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit']) && !empty(trim($_POST['uuid'])) && !empty(trim($_POST['username']))) { // 1. 初始化数据:若 JSON 文件不存在,则创建空数组 if (file_exists($filepath)) { $json_content = file_get_contents($filepath); $json_arr = json_decode($json_content, true); if (json_last_error() !== JSON_ERROR_NONE) { $output = "⚠️ JSON 文件格式损坏,请手动检查或删除后重试。"; } } else { $json_arr = []; } // 2. 安全过滤输入(防止 XSS 或恶意字符注入) $safe_uuid = filter_var($_POST['uuid'], FILTER_SANITIZE_STRING); $safe_name = filter_var($_POST['username'], FILTER_SANITIZE_STRING); // 3. 追加新条目(注意:此处不校验 UUID 重复性,如需请自行扩展) $json_arr[] = [ 'uuid' => $safe_uuid, 'name' => $safe_name, 'timestamp' => date('c') // 可选:记录写入时间 ]; // 4. 原子化写入:先写入临时文件,再原子替换,避免并发写入损坏 $temp_file = $filepath . '.tmp'; $json_encoded = json_encode($json_arr, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); if (file_put_contents($temp_file, $json_encoded) !== false) { if (rename($temp_file, $filepath)) { $output = "✅ 成功写入!共 " . count($json_arr) . " 条记录,已保存至 <code>{$filepath}</code>。"; } else { $output = "❌ 无法重命名临时文件,请检查目录写入权限。"; } } else { $output = "❌ JSON 编码失败或磁盘空间不足。"; } } ?> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>白名单管理</title> <style> body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; margin: 4rem auto; max-width: 600px; padding: 0 1rem; } .group { margin: 1rem 0; } input[type="text"] { width: 100%; padding: 0.5rem; border: 1px solid #ccc; border-radius: 4px; } button { background: #007bff; color: white; border: none; padding: 0.75rem 1.5rem; border-radius: 4px; cursor: pointer; } .message { margin-top: 1rem; padding: 0.5rem; border-radius: 4px; } .success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; } .error { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; } </style> </head> <body> <h1>? 白名单添加</h1> <form method="POST" autocomplete="off"> <div class="group"> <input type="text" name="uuid" placeholder="请输入 UUID(如:123e4567-e89b-12d3-a456-426614174000)" required> </div> <div class="group"> <input type="text" name="username" placeholder="请输入用户名" required> </div> <button type="submit" name="submit">提交</button> </form> <?php if ($output): ?> <div class="message <?= strpos($output, '✅') !== false ? 'success' : 'error' ?>"> <?= htmlspecialchars($output) ?> </div> <?php endif; ?> <!-- 可选:显示当前 JSON 内容摘要 --> <?php if (file_exists($filepath)): ?> <details style="margin-top: 1.5rem;"> <summary>? 当前白名单(仅显示前 5 条)</summary> <pre class="brush:php;toolbar:false;" style="max-height: 200px; overflow: auto; background: #f5f5f5; padding: 0.5rem; border-radius: 4px; font-size: 0.9em;"> <?php $json_preview = json_decode(file_get_contents($filepath), true); $preview = array_slice($json_preview ?? [], 0, 5); echo json_encode($preview, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); ?>