WordPress使用AJAX更新post_meta关联数组时数据库字段清空问题
问题核心原因
本次字段被清空最直接的原因是PHP端json_decode默认返回对象,而_wc_booking_pricing字段要求存储数组格式,格式不匹配导致更新失败直接写入空值。同时还存在其他潜在逻辑漏洞,完整问题如下:
- 后端未校验传入的JSON有效性,空值/无效JSON解码后为
null,直接存储就会清空字段 - 前端输出JSON的div可能存在多余空白字符,导致JSON解析失败拿到空数组
- 用循环计数器作为删除索引,删除一次后数组索引重排、页面索引未同步,后续删除会操作错误元素
- 两层重复的
ready事件包裹逻辑,可能导致初始化异常
修复步骤
1. 修改前端标记,改用原始数组键作为删除标识
避免计数器索引不匹配问题:
<?php $response_cost = get_post_meta( 379, '_wc_booking_pricing', true ); ?> <!-- 输出JSON时去掉多余换行空白,加trim避免解析错误 --> <div id="response-cost" class="hidden"><?php echo trim(json_encode( $response_cost, JSON_UNESCAPED_UNICODE )); ?></div> <?php // 直接用原始数组的键作为标识,不用计数器 foreach ($response_cost as $key => $response) { ?> <tr id="array-<?php echo esc_attr($key); ?>"> <!-- 其他表格列代码 --> <td><button class="remove-array" data-key="<?php echo esc_attr($key); ?>"><i class="fa fa-times"></i></button></td> </tr> <?php }; ?>
2. 优化JS逻辑,加容错处理
去掉重复的ready事件,添加JSON解析容错,用键删除而不是splice适配关联数组:
(function($) { $(document).ready(function () { // 取文本后先trim去掉首尾空白 const arrString = $('#response-cost').text().trim(); let arr = []; // 加解析容错,避免无效JSON导致后续逻辑崩溃 try { arr = JSON.parse(arrString); } catch (e) { console.error('定价数据解析失败', e); return; } $('.remove-array').click(function(){ const targetKey = $(this).data("key"); if (!arr.hasOwnProperty(targetKey)) return; // 删除对应键的元素 delete arr[targetKey]; const arr_stringify = JSON.stringify(arr); $.ajax({ url: ajax_object.ajaxurl, type: 'POST', data:{ action: 'update_cost_rule_table_action', stringified_arr: arr_stringify, }, success: function( data ){ console.log( data ); // 删除成功后直接移除对应行,避免重复点击 $(this).closest('tr').remove(); }.bind(this) }); }); }); })(jQuery);
3. 修复后端处理逻辑,加校验+返回数组
add_action( 'wp_ajax_update_cost_rule_table_action', 'update_cost_rule_table' ); add_action( 'wp_ajax_nopriv_update_cost_rule_table_action', 'update_cost_rule_table' ); function update_cost_rule_table(){ // 先校验参数是否存在 if (empty($_POST['stringified_arr'])) { wp_send_json_error('缺少提交数据'); } // 第二个参数设为true,强制返回关联数组而不是对象 $response_cost = json_decode(sanitize_text_field($_POST['stringified_arr']), true); // 校验解码是否成功 if (json_last_error() !== JSON_ERROR_NONE || !is_array($response_cost)) { wp_send_json_error('数据格式错误'); } // WC原生字段用update_post_meta更稳妥,不需要调用ACF的update_field update_post_meta(379, '_wc_booking_pricing', $response_cost); wp_send_json_success('更新成功'); }
4. 脚本入队优化(可选)
加版本号避免缓存导致修改不生效:
function gt21_scripts() { // 最后一个参数设为true,把脚本放到页脚加载,避免DOM未加载就执行 wp_register_script( 'cost-rule', get_template_directory_uri() . '/js/cost-rule.js', array( 'jquery' ), '1.0', true ); wp_enqueue_script( 'cost-rule' ); wp_localize_script( 'cost-rule', 'ajax_object', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) ); }; add_action( 'wp_enqueue_scripts', 'gt21_scripts' );
内容的提问来源于stack exchange,提问作者Eric Brockman
相关产品推荐
相关产品推荐

