PHP表单POST更新数据库后刷新页面未同步显示最新数据
问题根因
核心问题是代码执行顺序错误:你先执行了组织数据的查询、把旧结果赋值给了$user_org变量,之后才处理POST请求执行数据库更新。本次请求渲染表单时用的是更新前就查好的旧数据,哪怕数据库已经写入成功,当前页面渲染用的变量还是旧值。
如果刷新后依然显示旧值,额外排查两个点:
- 你混用了WordPress自带
$wpdb和原生mysqli两套数据库连接,要确认两者连接的是同一个数据库实例,不要一个连测试库一个连生产库 - 站点开了页面/对象缓存(比如WordPress缓存插件、服务器Redis缓存),更新数据后没有自动清缓存,导致查询一直返回旧结果
另外原代码还有几个必须修复的问题: - 直接把POST参数拼接进SQL语句,存在严重SQL注入风险
- 多写了一个多余的右花括号,存在语法错误隐患
- 没有做CSRF校验、权限校验、输入输出转义,存在Web安全漏洞
- 全表遍历查询匹配组织,性能很差
排查思路
- 先梳理代码执行流:必须把「数据库更新逻辑」放在「数据查询逻辑」前面,确保查询到的是更新完成后的最新值
- 打印渲染表单时用到的
$user_org变量,确认变量内存的是不是最新值,排除变量赋值错误 - 临时关闭站点缓存插件、服务器缓存,排除缓存导致的旧数据问题
- 提交更新后直接去数据库里核对对应记录的值,确认更新语句确实命中了正确的行
修复后代码
直接替换原有代码即可,适配WordPress环境,修复了上述所有问题:
<?php global $wpdb; $user_id = get_current_user_id(); // 未登录用户直接跳转登录页 if (!$user_id) { wp_redirect(wp_login_url()); exit; } $org_id = get_user_meta($user_id, '_org_id', true); $update_success = false; // 1. 优先处理POST更新请求 if(isset($_POST['update']) && wp_verify_nonce($_POST['org_nonce'], 'update_org')) { // 用WP自带的update方法,自带预处理防注入,不需要手动拼SQL $update_res = $wpdb->update( 'wp_organization', [ 'name' => sanitize_text_field($_POST['org_name']), 'shortname' => sanitize_text_field($_POST['shortname']), 'industry' => sanitize_text_field($_POST['industry']), 'description' => sanitize_textarea_field($_POST['description']) ], ['id' => $org_id], ['%s', '%s', '%s', '%s'], ['%d'] ); if ($update_res !== false) { $update_success = true; // 若开了缓存,手动清理当前组织数据的缓存 clean_post_cache($org_id, 'organization'); } } // 2. 更新完成后再查询最新数据,此时查到的一定是更新后的值 $user_org = $wpdb->get_row($wpdb->prepare("SELECT * FROM wp_organization WHERE id = %d", $org_id)); ?> <!-- 组织信息表单 --> <form class="py-4 col-md-6 mx-auto" method="post" action=""> <!-- 加CSRF校验字段 --> <input type="hidden" name="org_nonce" value="<?php echo wp_create_nonce('update_org'); ?>"> <h2 class="mb-3 text-center">组织信息</h2> <?php if ($update_success): ?> <div class="alert alert-success text-center">信息更新成功</div> <?php endif; ?> <label class="form-label">名称</label> <input type="text" required name="org_name" value="<?php echo esc_attr($user_org->name); ?>" class="form-control mb-3" /> <label class="form-label">所属行业</label> <input type="text" name="industry" value="<?php echo esc_attr($user_org->industry); ?>" class="form-control mb-3" /> <label class="form-label">简称(4字符以内)</label> <input type="text" name="shortname" required maxlength="4" value="<?php echo esc_attr($user_org->shortname); ?>" class="form-control mb-3" /> <label class="form-label">简介</label> <textarea class="form-control mb-3" name="description" rows="5" cols="50"><?php echo esc_textarea(trim(stripslashes($user_org->description))); ?></textarea> <div class="d-flex justify-content-center"> <input type="submit" name="update" value='更新' class='btn btn-primary'> </div> </form>
额外优化点
如果要避免用户刷新页面触发重复提交表单,可以在更新成功后加一行302跳转代码,实现POST-Redirect-GET模式:
if ($update_res !== false) { // 更新成功后跳转到当前页,清空POST请求状态 wp_redirect($_SERVER['REQUEST_URI']); exit; }
加完这段跳转后,用户提交表单后会自动跳转到GET请求的页面,无论怎么刷新都不会重复提交,也能100%保证显示最新数据。
内容的提问来源于stack exchange,提问作者jbomb
相关产品推荐
相关产品推荐

