You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WordPress后台AJAX删除数据报400(Bad Request)错误求助

WordPress后台AJAX删除请求返回400 Bad Request错误排查与解决

问题背景

在WordPress后台(wp-admin)中,我通过表格展示用户表单提交的数据库数据,删除逻辑涉及三个文件:

  • functions.php:渲染表格及带ID的删除按钮
  • /js/delete.js:获取ID并发起AJAX删除请求
  • plugin/form-plugin.php:处理删除逻辑的delete_custom_form_data()函数

但AJAX请求始终返回**400 (Bad Request)**错误,以下是相关代码:

functions.php 代码

function display_custom_form_data() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'custom_form_data';
    $data = $wpdb->get_results("SELECT * FROM $table_name", ARRAY_A);
    ?>
    
    <div class="wrap">
        <h2>Jurnalul programărilor</h2>
         <input type="hidden" id="ajax-url" value="<?php echo admin_url('admin-ajax.php'); ?>">
        <table class="wp-list-table widefat striped">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Nume</th>
                    <th>Email</th>
                    <th>Telefon</th>
                    <th>Specializare</th>
                    <th>Data Programării</th>
                    <th>Ora Programării</th>
                    <th>Data Aplicării</th>
                    <th>Acțiune</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($data as $row): ?>
                
                    <tr>
                        <td><?php echo $row['id']; ?></td>
                        <td><?php echo $row['name']; ?></td>
                        <td><?php echo $row['email']; ?></td>
                        <td><?php echo $row['phone']; ?></td>
                        <td><?php echo $row['spec']; ?></td>
                        <td><?php echo $row['date']; ?></td>
                        <td><?php echo $row['time']; ?></td>
                        <td><?php echo $row['sub_time']; ?></td>
                        
                      <td><button class="delete-button" data-id="<?php echo $row['id']; ?>">Șterge</button></td>
                    
                      
                    </tr>
                <?php endforeach; ?>
                 
            </tbody>
        </table>
    </div>

    <?php
}

add_action('admin_menu', 'custom_form_admin_page');
// 注意:这里重复添加了相同的钩子,建议删除其中一个
add_action('admin_menu', 'custom_form_admin_page');

delete.js 代码

document.addEventListener('DOMContentLoaded', function() {
    const ajaxUrlElement = document.getElementById('ajax-url');
    if (ajaxUrlElement) {
        const ajaxUrl = ajaxUrlElement.value;
        const deleteButtons = document.querySelectorAll('.delete-button');

        deleteButtons.forEach(function(button) {
            button.addEventListener('click', function() {
                const id = encodeURIComponent(this.getAttribute('data-id'));

                if (confirm('Ești sigur că vrei să ștergi acest rând?')) {
                    fetch(ajaxUrl, {
                        method: 'POST',
                        headers: {
                            'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'
                        },
                        body: 'action=delete_custom_form_data&id=' + id
                    })
                    .then(response => {
                        if (!response.ok) {
                            throw new Error('Network response was not ok. Status: ' + response.status + '. Body: ' + response.statusText);
                        }
                        location.reload();
                    })
                    .catch(error => {
                        console.error('There has been a problem with your fetch operation: ', error);
                    });
                }
            });
        });
    }
});

plugin/form-plugin.php 代码

function delete_custom_form_data() {
   
    if (isset($_POST['id'])) {
        
        $id = $_POST['id'];
       
        error_log('ID-ul primit pentru ștergere: ' . $id);

      
        global $wpdb;
       
        $table_name = $wpdb->prefix . 'custom_form_data';
        
        
        $result = $wpdb->delete($table_name, array('id' => $id));

        
        if ($result === false) {
           
            echo 'Eroare la ștergerea rândului cu ID-ul ' . $id;
        } else {
            
            echo 'Rândul cu ID-ul ' . $id . ' a fost șters cu succes!';
        }
    } else {
        
        echo 'ID-ul nu a fost furnizat.';
    }
}


add_action('admin_post_custom_delete_action', 'delete_custom_form_data');
add_action('admin_post_nopriv_custom_delete_action', 'delete_custom_form_data');

问题根源与解决方案

1. AJAX钩子不匹配(核心问题)

你在JS中传递的action参数是delete_custom_form_data,但PHP中绑定的是admin_post_*钩子——这类钩子用于处理直接提交到admin-post.php的请求,而非admin-ajax.php的AJAX请求。

修正:
将form-plugin.php中的钩子替换为WordPress AJAX专用的wp_ajax_*前缀钩子:

// 管理员后台AJAX请求
add_action('wp_ajax_delete_custom_form_data', 'delete_custom_form_data');
// 如果需要允许前台未登录用户执行(这里是后台操作,可省略)
add_action('wp_ajax_nopriv_delete_custom_form_data', 'delete_custom_form_data');

2. 缺失权限验证

没有验证当前用户是否有权执行删除操作,存在安全风险,同时可能触发WordPress的安全拦截导致400错误。

修正:
在delete_custom_form_data函数开头添加权限校验:

function delete_custom_form_data() {
    // 验证用户权限(仅管理员可执行)
    if (!current_user_can('manage_options')) {
        wp_die('无权执行此操作');
    }

    // 原有逻辑...
}

3. 未正确结束AJAX请求

WordPress要求AJAX请求必须用wp_die()、wp_send_json()等函数结束,直接echo可能导致响应格式错误。

修正:
替换函数中的echo为WordPress标准AJAX响应函数:

if ($result === false) {
    wp_send_json_error('Eroare la ștergerea rândului cu ID-ul ' . $id);
} else {
    wp_send_json_success('Rândul cu ID-ul ' . $id . ' a fost șters cu succes!');
}
// 替换else分支的echo
wp_send_json_error('ID-ul nu a fost furnizat.');

同时更新JS中的响应处理逻辑,适配JSON格式:

.then(response => response.json())
.then(data => {
    if (data.success) {
        alert(data.data); // 可选:显示成功提示
        location.reload();
    } else {
        alert(data.data); // 显示错误信息
    }
})

4. 清理冗余代码

functions.php中重复添加了add_action('admin_menu', 'custom_form_admin_page');,删除其中一个即可。

内容的提问来源于stack exchange,提问作者Octavian Racu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 15:53:16