猿问

如何更新 WooCommerce 购物车并在单个请求中返回新的 HTML?

我有一个自定义的“迷你购物车”,它具有购物车主页面的所有功能,即更改数量、删除项目、输入优惠券、删除优惠券。我目前正在监听change购物车form元素并通过 Ajax 提交(简化如下):


ajaxTask = $.post(

        $form.action, // this is a non-Ajax (front-end) URL, ie "/cart"

        $form.serialize()

    )

    .done(function(data,status,jqXHR){

        $cart.html(data);

    });

这会触发普通的 WC 表单处理程序,就好像update_cart单击了按钮一样(我添加<input type="hidden" name="update_cart" id="update_cart" value="1">到表单中是为了实现这一点)。


问题是,“更新购物车”操作有一个内置的重定向,它应该重新加载页面。所以上面的函数返回整个页面。


据我所知,没有其他函数可以简单地处理表单(无论是更改数量、删除项目、添加项目还是应用优惠券)并退出。将大部分表单处理程序复制/粘贴到我自己的代码中只是为了避免重定向,这似乎是一种笨拙/愚蠢/不好的做法。


我希望服务器做的是:


static function ajax_update_cart() {

    // ( an action that updates the cart and outputs nothing )

    echo cart_html(); // output the custom cart HTML

    exit;

}

但我没有看到明显的方式。我确实了解购物车碎片,但这些碎片至少需要服务器往返两次。有没有办法提交购物车数据,更新购物车,然后返回我自己的 HTML?


弑天下
浏览 220回答 1
1回答

宝慕林4294392

考虑到这一点后,我相信以下应该有效。对 wp_safe_redirect() 的调用将应用几个过滤器:'wp_safe_redirect_fallback'、'wp_redirect'、'wp_redirect_status',......任何这些都可以被滥用以防止发生 HTTP 重定向并返回您自己的 HTML。add_filter('wp_safe_redirect_fallback', function($url) {&nbsp; &nbsp; if (/* wp_safe_redirect() is called from your cart update AJAX request */) {&nbsp; &nbsp; &nbsp; &nbsp; # Render your new cart HTML&nbsp; &nbsp; &nbsp; &nbsp; echo cart_html();&nbsp; &nbsp; &nbsp; &nbsp; # This filter cannot return otherwise wp_redirect() will be called!&nbsp; &nbsp; &nbsp; &nbsp; exit();&nbsp; &nbsp; }&nbsp; &nbsp; return $url;}注意,过滤器不是用作过滤器,而是用作更改 wp_safe_redirect() 执行的钩子,以不执行 HTTP 重定向并返回生成的 HTML。即调用 exit() 是必要的!附录我想到了另一种方法来实现这一目标。它再次涉及滥用过滤器。在这种情况下,过滤器“woocommerce_update_cart_action_cart_updated”将谎称正在更新购物车,从而阻止调用 wp_safe_redirect()。然后较低优先级的操作将生成更新的购物车 HTML。add_filter( 'woocommerce_update_cart_action_cart_updated', function($cart_updated) {&nbsp; &nbsp; if (/* filter 'woocommerce_update_cart_action_cart_updated' is called from your cart update AJAX request */) {&nbsp; &nbsp; &nbsp; &nbsp; # returning false prevents the call to wp_safe_redirect()&nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; }&nbsp; &nbsp; return $cart_updated;} );add_action( 'wp_loaded', function() {&nbsp; &nbsp; if (/* filter 'woocommerce_update_cart_action_cart_updated' is called from your cart update AJAX request */) {&nbsp; &nbsp; &nbsp; &nbsp; # need to calculate totals as this step was bypassed.&nbsp; &nbsp; &nbsp; &nbsp; WC()->cart->calculate_totals();&nbsp; &nbsp; &nbsp; &nbsp; # Render your new cart HTML&nbsp; &nbsp; &nbsp; &nbsp; echo cart_html();&nbsp; &nbsp; &nbsp; &nbsp; wp_die();&nbsp; &nbsp; }}, 21 );&nbsp; &nbsp;# priority 21 so this action runs after WC_Form_Handler::update_cart_action() which runs at priority 20
随时随地看视频慕课网APP
我要回答