WordPress AJAX调用中如何获取当前产品页的产品ID
问题原因
WordPress的AJAX请求全部走/wp-admin/admin-ajax.php统一入口,这个请求和你当前浏览的产品详情页是完全独立的PHP执行流程,产品页里初始化的global $product、$post这类全局变量根本不会自动传到AJAX回调里,直接在回调函数里调全局变量当然拿不到值。另外你原来的代码里WP_Query循环也用$product当循环变量,就算真拿到了全局产品对象也会被覆盖,本身写法就有坑。
实现步骤
1. 前端发请求时把当前页的产品ID一起传过去
AJAX本身不会自动带当前页面的上下文数据,你得在页面渲染阶段就把产品ID准备好,跟着请求参数传给后端。
首先改JS代码,加个参数接收当前产品ID:
jQuery(document).ready(function($) { var data = { 'action': 'get_product_list', 'current_product_id': typeof window.currentProductId !== 'undefined' ? window.currentProductId : 0 }; jQuery.post("/wp-admin/admin-ajax.php", data, function(response) { console.log(response); }); });
然后在主题functions.php里加个钩子,只在产品详情页把当前产品ID输出到页面JS里,非产品页不会输出这个变量,JS会默认传0:
add_action('wp_footer', 'output_current_product_id_for_js'); function output_current_product_id_for_js() { if (function_exists('is_product') && is_product()) { global $product; echo '<script>window.currentProductId = ' . esc_js($product->get_id()) . ';</script>'; } }
如果你是用wp_enqueue_script加载的JS,不想用全局变量,也可以用wp_localize_script把产品ID绑到你的JS对象上,逻辑完全一样,本质都是在页面生成的时候把ID打在前端,跟着请求走。
2. 后端AJAX回调接收参数使用
修改你原来的回调函数,先从请求里取前端传的ID,做安全校验之后就能正常用了:
add_action('wp_ajax_get_product_list', 'get_product_list'); add_action('wp_ajax_nopriv_get_product_list', 'get_product_list'); function get_product_list() { // 接参数,强制转整数做安全校验,避免非法输入 $current_product_id = isset($_POST['current_product_id']) ? intval($_POST['current_product_id']) : 0; $args = array( 'post_type' => 'product', 'post_status' => 'publish', 'posts_per_page' => -1, 'orderby' => 'name', 'order' => 'ASC' ); $loop = new WP_Query($args); $allProducts = ''; // ID大于0就说明请求来自产品详情页 if ($current_product_id > 0) { // 在这里写你需要的当前产品逻辑就行,要拿产品对象就用wc_get_product($current_product_id) $current_product = wc_get_product($current_product_id); } // 这里循环变量别用$product,避免和全局对象冲突 foreach ($loop->posts as $product_item) { $selected_attr = ($product_item->ID == $current_product_id) ? 'selected' : ''; $allProducts .= '<option value="' . $product_item->ID . '" ' . $selected_attr . '>' . esc_html($product_item->post_title) . '</option>'; } wp_reset_query(); echo $allProducts; wp_die(); }
避坑提醒
- 别尝试靠解析请求的referer头、匹配页面url的方式拿产品ID,固定链接结构改了、装个缓存插件就容易失效,稳定性极差
- 所有前端传过来的参数一定要做格式校验,这里直接转int就行,避免安全问题
- 不要在WP_Query循环里用
$product当临时变量,很容易覆盖全局的产品对象导致其他逻辑出问题
内容的提问来源于stack exchange,提问作者stemon
相关产品推荐
相关产品推荐

