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

WordPress中使用Ajax批量删除数据失败问题求助

WordPress中使用Ajax批量删除数据失败问题求助

大家好,我在开发WordPress插件的Ajax批量删除功能时遇到了卡壳的情况——点击删除按钮后,数据库里的数据丝毫未动,日志显示删除操作受影响的行数为0。以下是我的代码和调试日志,麻烦各位帮我排查下问题出在哪?

我的调试日志输出

IDs received for deletion: Array ( [0] => 10 [1] => 8 )
check error: %d,%d
Prepared query for deletion: DELETE FROM wp_slf_schedule_post_title_log WHERE id IN (%d,%d)
IDs received for deletion: 0

后端PHP代码

public function otslf_delete_multiple_blog_title() {
    if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'ai-seo-content-nonce' ) ) {
        wp_send_json_error( __( 'Invalid nonce.', 'super-fast-blog-ai' ) );
    }
    error_log( $_POST['nonce'] ); // Debugging line

    global $wpdb;
    $table_name = $wpdb->prefix . 'slf_schedule_post_title_log';
    $ids = isset($_POST['id']) ? array_map('intval', $_POST['id']) : [];
    error_log('IDs received for deletion: ' . print_r($ids, true)); // Debugging line

    $placeholders = implode(',', array_fill(0, count($ids), '%d'));
    $query = "DELETE FROM $table_name WHERE id IN ($placeholders)";
    error_log('check error: ' . $placeholders); // Debugging line
    error_log('Prepared query for deletion: ' . $query); // Debugging line

    $deleted = $wpdb->query($wpdb->prepare($query, $ids)); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
    error_log('IDs received for deletion: ' . $deleted);

    if ($deleted !== false) {
        wp_send_json_success(['message' => 'Selected titles deleted successfully.']);
    } else {
        wp_send_json_error(['message' => 'Failed to delete selected titles.']);
    }
}

前端jQuery代码

jQuery(document).ready(function($) {
    jQuery('#select_title').click(function() {
        let isChecked = jQuery(this).is(':checked');
        jQuery('input[name="select_title[]"]').prop('checked', isChecked);
    });

    jQuery('#delete-selected').click(function(e) {
        e.preventDefault();
        let id = jQuery('input[name="select_title[]"]:checked').map(function() {
            return jQuery(this).val();
        }).get();
        console.log('Selected IDs:', id);

        if (id.length === 0) {
            jQuery.toast({
                text: "Please select at least one title to delete.",
                heading: 'Failed',
                icon: 'error',
                showHideTransition: 'fade',
                allowToastClose: true,
                hideAfter: 3000,
                stack: 5,
                position: 'top-right',
            });
        }

        jQuery.ajax({
            url: ajax_ob.ajax_url,
            type: 'POST',
            data: {
                action: 'otslf_delete_multiple_blog_title',
                id: id,
                nonce: ajax_ob.nonce
            },
            beforeSend: function(xhr) {
                jQuery('#delete-selected').append('<span class="loading-spinner"></span>');
            },
            success: function(response) {
                console.log('Response:', response);
                if (response.success) {
                    jQuery('input[name="select_title[]"]:checked').closest('tr').remove();
                    jQuery.toast({
                        text: "Selected Title Deleted Successfully",
                        heading: 'success',
                        icon: 'success',
                        showHideTransition: 'fade',
                        allowToastClose: true,
                        hideAfter: 4000,
                        stack: 15,
                        position: {
                            left : 'auto',
                            right : 100,
                            top : 153,
                            bottom : 'auto'
                        },
                        textAlign: 'left',
                        loader: true,
                        loaderBg: '#9EC600',
                    });
                } else {
                    jQuery.toast({
                        text: "Please select at least one title to delete.",
                        heading: 'Failed',
                        icon: 'error',
                        showHideTransition: 'fade',
                        allowToastClose: true,
                        hideAfter: 3000,
                        stack: 5,
                        position: 'top-right',
                    });
                }
            },
            complete: function() {
                jQuery('#delete-selected').find('.loading-spinner').remove();
            },
            error: function(xhr, status, error) {
                jQuery.toast({
                    text: 'An error occurred: ' + error,
                    heading: 'NOTE',
                    icon: 'error',
                    showHideTransition: 'fade',
                    allowToastClose: true,
                    hideAfter: 3000,
                    stack: 5,
                    position: 'top-right',
                });
            }
        });
    });
});

我已经确认数据库里存在ID为10和8的记录,查询语句看起来也没问题,但就是删不掉数据,实在摸不着头脑了...


问题分析与解决方案

你遇到的核心问题是$wpdb->prepare的参数传递方式错误,导致SQL查询没有正确匹配到目标ID,所以返回受影响行数0。

问题根源

$wpdb->prepare要求每个占位符对应一个独立的参数,但你直接把整个ID数组作为第二个参数传递,它会把数组转换成字符串(比如"Array"),而不是逐个替换占位符。这就导致实际执行的SQL中,IN子句里的值是无效的,自然删不到数据。

修复方案

在PHP 5.6及以上版本,可以用**展开运算符...**把数组元素拆成独立参数传递:

// 替换原来的$wpdb->query行
$deleted = $wpdb->query($wpdb->prepare($query, ...$ids)); // phpcs:ignore WordPress.DB.DirectDatabaseQuery

如果你的环境PHP版本低于5.6,用call_user_func_array来兼容:

$stmt = call_user_func_array([$wpdb, 'prepare'], array_merge([$query], $ids));
$deleted = $wpdb->query($stmt);

额外优化建议

  1. 添加权限校验:避免未授权用户操作数据,在函数开头增加:
if ( ! current_user_can('manage_options') ) { // 根据插件需求调整权限
    wp_send_json_error( __( 'Insufficient permissions.', 'super-fast-blog-ai' ) );
}
  1. 空ID提前拦截:后端也处理空ID的情况,避免执行无效SQL:
if (empty($ids)) {
    wp_send_json_error( __( 'No IDs selected for deletion.', 'super-fast-blog-ai' ) );
}
  1. 日志补充:添加最终执行的SQL日志,方便后续排查:
error_log('Final executed SQL: ' . $wpdb->last_query);

修改后再测试,批量删除功能应该就能正常工作了。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 08:29:34