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

WordPress Ajax筛选返回400错误,请求代码排查解决

WordPress Ajax筛选文章返回400错误排查

我在WordPress中开发了一个简易的Ajax筛选文章功能,折腾3天了,Ajax仍持续返回400错误,以下是相关代码及错误信息,恳请帮忙排查:


一、相关代码

1. HTML/PHP结构代码

<?php $categories = get_categories(); ?>
<ul class="cat-list">
  <li><a class="cat-list_item active" href="#" data-slug="">All projects</a></li>

  <?php foreach($categories as $category) : ?>
   <li>
  <a class="cat-list_item" href="#" data-slug="<?= $category->slug; ?>" data-type="projecten">
    <?= $category->name; ?>
  </a>
</li>
  <?php endforeach; ?>
</ul>


<?php 
 $projects = new WP_Query([
   'post_type' => 'customer_stories',
   'posts_per_page' => -1,
   'tax_query' => [
      [
         'taxonomy' => 'category',
         'field'    => 'term_id',
         'terms'    => $termIds, // 示例 $termIds = [4,5]
         'operator' => 'IN'
      ],
   ]
]);
?>

<?php
// 查询
$the_query = new WP_Query( $args );
// 循环输出
if ( $the_query->have_posts() ) {
    echo '<ul>';
    while ( $the_query->have_posts() ) {
        $the_query->the_post();
        echo '<li>' . esc_html( get_the_title() ) . '</li>';
    }
    echo '</ul>';
} else {
    esc_html_e( 'Sorry, no posts matched your criteria.' );
}

// 恢复原始文章数据
wp_reset_postdata(); ?>

2. Ajax处理函数

function filter_projects() {
  // 验证nonce
  if ( !isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'theme_ajax_nonce') ) {
    wp_send_json_error('Invalid nonce');
    exit;
  }

  // 安全获取POST参数
  $postType = isset($_POST['type']) ? sanitize_text_field($_POST['type']) : '';
  $catSlug = isset($_POST['category']) ? sanitize_text_field($_POST['category']) : '';

  $args = [
    'post_type' => 'customer_stories',
    'posts_per_page' => -1,
    'orderby' => 'menu_order', 
    'order' => 'desc',
  ];

  // 如果分类slug不为空,添加分类查询
  if ( !empty($catSlug) ) {
    $args['category_name'] = $catSlug;
  }

  $ajaxposts = new WP_Query($args);
  $response = '';

  if($ajaxposts->have_posts()) {
    while($ajaxposts->have_posts()) : $ajaxposts->the_post();
      $response .= get_template_part( 'src/page-modules/project-list-item.php' );
    endwhile;
  } else {
    $response = 'empty';
  }

  wp_reset_postdata(); // 恢复原始文章数据
  echo $response;
  exit;
}
add_action('wp_ajax_filter_projects', 'filter_projects');
add_action('wp_ajax_nopriv_filter_projects', 'filter_projects');

3. 原始JavaScript代码

(function($){
$.ajax({
  type: 'POST',
  url : wpajax.url,
  dataType: 'html',
  data: {
    action: 'filter_projects',
    category: $(this).data('slug'),
    type: $(this).data('type'),
  },
  success: function(res) {
    $('.project-tiles').html(res);
  }
});

WP_enqueue

})(jQuery);

4. 脚本注册代码

<?php
// 主题CSS & JS

function base_scripts_styles() {
    $in_footer = true;
    $ver = 1;

    // 加载功能脚本
    wp_enqueue_script( 'base-script', get_template_directory_uri() . '/dist/js/main.js', array( 'jquery' ), $ver, $in_footer );
    wp_enqueue_script( 'theme-script', get_template_directory_uri() . '/theme.js', array( 'jquery' ), $ver, $in_footer );
    wp_enqueue_script( 'ajax', get_template_directory_uri() . '/inc/ajax_script.js', array( 'jquery' ), $ver, $in_footer );

    // 加载样式
    wp_enqueue_style( 'base-main', get_template_directory_uri() . '/dist/css/main.css', array(), $ver );
    wp_enqueue_style( 'base-style', get_stylesheet_uri(), array(), $ver );

    // 本地化脚本,传递Ajax参数
    wp_localize_script(
        'ajax',
        'wpajax',
        array(
            'url' => admin_url( 'admin-ajax.php'),
            'nonce' => wp_create_nonce( 'theme_ajax_nonce' ),
            'searchButton' => esc_attr( __( 'Search', 'base' ) ),
        )
    );

    wp_register_script( 'lottie-player', 'https://unpkg.com/@lottiefiles/lottie-player@latest/dist/lottie-player.js', array(), $ver );
}
add_action( 'wp_enqueue_scripts', 'base_scripts_styles' );

function theme_add_admin_styles() {
    wp_enqueue_style( 'admin_css', get_template_directory_uri() . '/admin-style.css', false, '' );
}
add_action( 'admin_enqueue_scripts', 'theme_add_admin_styles' );

二、错误信息

JavaScript控制台错误

jquery-3.6.0.min.js:2 Uncaught Error: Syntax error, unrecognized expression: #!
at se.error (jquery-3.6.0.min.js:2:13639)
at se.tokenize (jquery-3.6.0.min.js:2:21650)
at se.select (jquery-3.6.0.min.js:2:22477)
at Function.se [as find] (jquery-3.6.0.min.js:2:7116)
at S.fn.init.find (jquery-3.6.0.min.js:2:25047)
at new S.fn.init (jquery-3.6.0.min.js:2:25536)
at S (jquery-3.6.0.min.js:2:1051)
at l.t [as getAnchorTarget] (main.js?ver=1:3:153334)
at HTMLAnchorElement.<anonymous> (main.js?ver=1:3:153137)
at jquery-3.6.0.min.js:2:24485

三、问题排查与修复方案

1. 修复wp_localize_script参数错误

原脚本注册代码中wp_localize_script多传了两个无效参数'base-script'和'themeAjax',该函数仅接受3个参数:脚本handle名、全局变量名、数据数组,删除多余参数后即可正确传递wpajax变量。

2. 添加Nonce验证(解决400错误核心)

WordPress的admin-ajax.php默认需要Nonce验证,未提交或验证失败会直接返回400错误:

  • PHP端:在Ajax处理函数开头添加Nonce验证逻辑
  • JS端:在Ajax请求的data中加入nonce: wpajax.nonce

3. 修正JS中$(this)的指向问题

原JS代码直接执行Ajax,$(this)并非点击的分类标签,需要绑定a标签的点击事件,将Ajax逻辑放入回调函数中,同时阻止默认跳转行为:

(function($){
    $('.cat-list_item').on('click', function(e){
        e.preventDefault(); // 阻止a标签默认跳转
        $.ajax({
            type: 'POST',
            url : wpajax.url,
            dataType: 'html',
            data: {
                action: 'filter_projects',
                nonce: wpajax.nonce, // 添加nonce验证
                category: $(this).data('slug'),
                type: $(this).data('type'),
            },
            success: function(res) {
                $('.project-tiles').html(res);
                // 可选:切换active类
                $('.cat-list_item').removeClass('active');
                $(this).addClass('active');
            }.bind(this), // 绑定this指向,让success里的this指向当前点击的a标签
            error: function(xhr){
                console.log(xhr.responseText); // 打印错误信息便于排查
            }
        });
    });
})(jQuery);

4. 修复a标签href="#!"的jQuery选择器错误

jQuery无法解析#!作为锚点选择器,将href="#!"改为href="#"或href="javascript:void(0)",同时配合e.preventDefault()阻止默认跳转,避免页面滚动到顶部。

5. 增强Ajax处理函数的安全性与健壮性

  • 使用isset()检查POST参数是否存在,避免未定义索引警告
  • 使用sanitize_text_field()过滤用户输入,防止XSS等安全问题
  • 添加wp_reset_postdata()恢复原始文章数据,避免后续查询出错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 01:10:54