AJAX添加商品时,基于店铺归档页验证WooCommerce购物车遇问题
解决WooCommerce AJAX添加商品时页面判断导致验证钩子失效的问题
首先得明确你遇到的核心问题:AJAX请求的上下文不是用户当前浏览的店铺页面,而是admin-ajax.php,所以你用is_page()做判断时,这个函数会返回false,导致你的验证逻辑根本没执行,看起来就像钩子完全没触发一样。
下面给你两种靠谱的解决方案,选哪种看你的需求:
方案一:在添加商品的AJAX请求里传递当前页面标识
这个方案的思路是,把用户当前所在的店铺页信息(slug或ID)通过AJAX请求传递到后端,后端拿到这个参数后再做判断。
步骤1:给添加到购物车的请求加页面参数
如果你用的是WooCommerce默认的AJAX添加按钮,不用自己写JS,直接在添加到购物车的表单里加个隐藏字段就行:
add_action('woocommerce_before_add_to_cart_button', 'add_current_shop_page_hidden_field'); function add_current_shop_page_hidden_field() { // 只在目标店铺页添加这个字段 if (is_page(array('strongshop', 'smallshop'))) { $current_page_slug = get_post_field('post_name', get_queried_object()); echo '<input type="hidden" name="current_page" value="' . esc_attr($current_page_slug) . '">'; } }
步骤2:修改验证钩子的逻辑
现在后端可以通过$_POST拿到传递的页面参数,然后根据不同页面设置数量限制:
add_filter('woocommerce_add_to_cart_validation', 'custom_shop_cart_item_limit_validation', 10, 3); function custom_shop_cart_item_limit_validation($passed, $product_id, $quantity) { // 检查是否有传递的页面参数,并且是目标店铺页 if (isset($_POST['current_page']) && in_array($_POST['current_page'], array('strongshop', 'smallshop'))) { $current_page = sanitize_text_field($_POST['current_page']); // 设置对应页面的最大商品数 $max_items = $current_page === 'strongshop' ? 20 : 10; // 计算添加后的购物车总商品数 $current_cart_count = WC()->cart->get_cart_contents_count(); $new_total = $current_cart_count + $quantity; // 验证数量是否超限 if ($new_total > $max_items) { wc_add_notice(sprintf('您在%s页面最多只能添加%s件商品到购物车', ucfirst($current_page), $max_items), 'error'); $passed = false; } } return $passed; }
方案二:用Session存储用户当前所在的店铺页
如果不想修改前端请求,也可以在用户访问店铺页时,把页面信息存入Session,后端验证时读取Session的值。
步骤1:存储页面信息到Session
add_action('template_redirect', 'store_user_current_shop_page'); function store_user_current_shop_page() { // 只在目标店铺页存储Session if (is_page(array('strongshop', 'smallshop'))) { // 确保Session已开启 if (!session_id()) { session_start(); } $_SESSION['current_shop_page'] = get_post_field('post_name', get_queried_object()); } }
步骤2:基于Session做验证
add_filter('woocommerce_add_to_cart_validation', 'session_based_cart_item_limit_validation', 10, 3); function session_based_cart_item_limit_validation($passed, $product_id, $quantity) { // 检查Session里的页面信息 if (isset($_SESSION['current_shop_page']) && in_array($_SESSION['current_shop_page'], array('strongshop', 'smallshop'))) { $current_page = sanitize_text_field($_SESSION['current_shop_page']); $max_items = $current_page === 'strongshop' ? 20 : 10; $current_cart_count = WC()->cart->get_cart_contents_count(); $new_total = $current_cart_count + $quantity; if ($new_total > $max_items) { wc_add_notice(sprintf('您当前所在店铺最多只能添加%s件商品', $max_items), 'error'); $passed = false; } } return $passed; }
注意事项
- 测试前记得清除浏览器缓存和网站缓存,避免旧的AJAX请求缓存影响结果;
- 如果你用了缓存插件(比如WP Rocket、W3 Total Cache),要确保Session相关的内容不会被缓存,或者给目标店铺页设置不缓存;
- 两种方案都做了参数安全处理(
sanitize_text_field、esc_attr),避免安全问题。
内容的提问来源于stack exchange,提问作者Giuls
相关产品推荐
相关产品推荐

