数日探していましたが、まだ答えがありません。基本的に、woocommerceの標準の「カートの更新」ボタンをajax呼び出しに置き換えようとしています。これは、数量が変更されたときに注文の合計価格を自動的に更新します。これは私のhtmlです
<div class="cart_item">
<div class="product-thumbnail">
<a href="http://example.com"><img width="90" height="90" src="path to thumbnail"/></a>
</div>
<div class="product-name">
<a class="cart-page-product__title" href="http://example.com">Product1 name</a>
</div>
<div class="product-quantity">
<div class="quantity">
<input type="number" step="1" name="cart[some_security_key][qty]" value="1" class="input-text qty text" size="4"/>
</div>
</div>
<div class="product-subtotal"><span class="amount">2 000</span></div>
<div class="product-remove">
<a class="product-remove_link" href="http://example.com/?remove_item">×</a>
</div>
</div>
<div class="cart_item">
<div class="product-thumbnail">
<a href="http://example.com"><img width="90" height="90" src="path to thumbnail"/></a>
</div>
<div class="product-name">
<a class="cart-page-product__title" href="http://example.com">Product2 name</a>
</div>
<div class="product-quantity">
<div class="quantity">
<input type="number" step="1" name="cart[some_security_key][qty]" value="1" class="input-text qty text" size="4"/>
</div>
</div>
<div class="product-subtotal"><span class="amount">2 000</span></div>
<div class="product-remove">
<a class="product-remove_link" href="http://example.com/?remove_item">×</a>
</div>
</div>
Functions.phpには、合計を更新するための関数があります。
public function update_total_price() {
check_ajax_referer( 'update_total_price', 'security' );
if ( ! defined('WOOCOMMERCE_CART') ) {
define( 'WOOCOMMERCE_CART', true );
}
$cart_updated = false;
$cart_totals = isset( $_POST['cart'] ) ? $_POST['cart'] : '';
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
// Skip product if no updated quantity was posted
if ( ! isset( $_POST['quantity'] ) ) {
// if ( ! isset( $cart_totals[ $cart_item_key ]['qty'] ) ) {
continue;
}
// Sanitize
$quantity = apply_filters( 'woocommerce_stock_amount_cart_item', apply_filters( 'woocommerce_stock_amount', preg_replace( "/[^0-9\.]/", '', filter_var($_POST['quantity'], FILTER_SANITIZE_NUMBER_INT)) ), $cart_item_key );
// $quantity = apply_filters( 'woocommerce_stock_amount_cart_item', apply_filters( 'woocommerce_stock_amount', preg_replace( "/[^0-9\.]/", '', $cart_totals[ $cart_item_key ]['qty'] ) ), $cart_item_key );
if ( '' === $quantity || $quantity == $values['quantity'] )
continue;
// Update cart validation
$passed_validation = apply_filters( 'woocommerce_update_cart_validation', true, $cart_item_key, $values, $quantity );
// is_sold_individually
if ( $_product->is_sold_individually() && $quantity > 1 ) {
wc_add_notice( sprintf( __( 'You can only have 1 %s in your cart.', 'woocommerce' ), $_product->get_title() ), 'error' );
$passed_validation = false;
}
if ( $passed_validation ) {
WC()->cart->set_quantity( $cart_item_key, $quantity, false );
}
$cart_updated = true;
}
}
// Trigger action - let 3rd parties update the cart if they need to and update the $cart_updated variable
$cart_updated = apply_filters( 'woocommerce_update_cart_action_cart_updated', $cart_updated );
if ( $cart_updated ) {
// Recalc our totals
WC()->cart->calculate_totals();
woocommerce_cart_totals();
exit;
}
}
そして、Jqueryコードは次のとおりです。
jQuery( function( $ ) {
// wc_cart_params is required to continue, ensure the object exists
if ( typeof wc_cart_params === 'undefined' ) {
return false;
}
// Cart price update depends on quantity
//$( document ).on( 'click', '.quantity', function() {
$( document ).on( 'change', '.quantity, input[type=number]', function() {
var qty = $( this ).val();
var currentVal = parseFloat( qty);
$( 'div.cart_totals' ).block({ message: null, overlayCSS: { background: '#fff url(' + wc_cart_params.ajax_loader_url + ') no-repeat center', backgroundSize: '16px 16px', opacity: 0.6 } });
var data = {
action: 'rf_update_total_price',
security: rf_cart_params.rf_update_total_price_nonce,
quantity: currentVal
};
$.post( rf_cart_params.ajax_url, data, function( response ) {
$( 'div.cart_totals' ).replaceWith( response );
$( 'body' ).trigger( 'rf_update_total_price' );
});
return false;
});
});
上記のコードは、カートに商品が1つしかない場合にうまく機能します。
しかし、他の製品を追加してそのうちの1つの数量を変更すると、関数はすべての製品の数量の最後の値を使用します。
たとえば、2番目の画像の合計価格は7000(2000 * 1 + 2500 * 2)である必要がありますが、9000(2000 * 2 + 2500 * 2)です。私はajaxとjqueryを初めて使用するので、助けていただければ幸いです。
これは、商品だけでなく、すべてのカートを更新しているためです。
まず、JavaScriptスクリプトでアイテムカートハッシュ(セキュリティハッシュではなく、すべての製品バリエーションを含む製品ハッシュ)を送信する必要があります。
var item_hash = $( this ).attr( 'name' ).replace(/cart\[([\w]+)\]\[qty\]/g, "$1");
var data = {
action: 'rf_update_total_price',
security: rf_cart_params.rf_update_total_price_nonce,
quantity: currentVal,
hash : item_hash
};
次に、function update_total_price
を編集できます。簡略化しました;)
function update_total_price() {
// Skip product if no updated quantity was posted or no hash on WC_Cart
if( !isset( $_POST['hash'] ) || !isset( $_POST['quantity'] ) ){
exit;
}
$cart_item_key = $_POST['hash'];
if( !isset( WC()->cart->get_cart()[ $cart_item_key ] ) ){
exit;
}
$values = WC()->cart->get_cart()[ $cart_item_key ];
$_product = $values['data'];
// Sanitize
$quantity = apply_filters( 'woocommerce_stock_amount_cart_item', apply_filters( 'woocommerce_stock_amount', preg_replace( "/[^0-9\.]/", '', filter_var($_POST['quantity'], FILTER_SANITIZE_NUMBER_INT)) ), $cart_item_key );
if ( '' === $quantity || $quantity == $values['quantity'] )
exit;
// Update cart validation
$passed_validation = apply_filters( 'woocommerce_update_cart_validation', true, $cart_item_key, $values, $quantity );
// is_sold_individually
if ( $_product->is_sold_individually() && $quantity > 1 ) {
wc_add_notice( sprintf( __( 'You can only have 1 %s in your cart.', 'woocommerce' ), $_product->get_title() ), 'error' );
$passed_validation = false;
}
if ( $passed_validation ) {
WC()->cart->set_quantity( $cart_item_key, $quantity, false );
}
// Recalc our totals
WC()->cart->calculate_totals();
woocommerce_cart_totals();
exit;
}
これを実現する簡単な方法は次のとおりです。すべてのクレジットは Reigel Gallarde に送られます。
// we are going to hook this on priority 31, so that it would display below add to cart button.
add_action( 'woocommerce_single_product_summary', 'woocommerce_total_product_price', 31 );
function woocommerce_total_product_price() {
global $woocommerce, $product;
// let's setup our divs
echo sprintf('<div id="product_total_price" style="margin-bottom:20px;display:none">%s %s</div>',__('Product Total:','woocommerce'),'<span class="price">'.$product->get_price().'</span>');
echo sprintf('<div id="cart_total_price" style="margin-bottom:20px;display:none">%s %s</div>',__('Cart Total:','woocommerce'),'<span class="price">'.$product->get_price().'</span>');
?>
<script>
jQuery(function($){
var price = <?php echo $product->get_price(); ?>,
current_cart_total = <?php echo $woocommerce->cart->cart_contents_total; ?>,
currency = '<?php echo get_woocommerce_currency_symbol(); ?>';
$('[name=quantity]').change(function(){
if (!(this.value < 1)) {
var product_total = parseFloat(price * this.value),
cart_total = parseFloat(product_total + current_cart_total);
$('#product_total_price .price').html( currency + product_total.toFixed(2));
$('#cart_total_price .price').html( currency + cart_total.toFixed(2));
}
$('#product_total_price,#cart_total_price').toggle(!(this.value <= 1));
});
});
</script>
<?php
}
2016年6月にリリースされたWooCommerce2.6.0以降、WooCommerceカートページはAjaxを使用して、[カートの更新]ボタンをクリックした後にカートの合計を更新します。 WooCommerce2.6.0にはWP 4.4以降が必要です。
バックエンドや独自のAjax呼び出しの作成について心配する必要はなく、[カートの更新]ボタンに割り当てられているものを使用できます。
この機能をすぐに使用できるようにするには、無料のプラグインを使用できます。このプラグインには、いくつかの便利な追加オプションもあります。
または、子テーマを使用して次のことを行います。 [カートの更新]ボタンを非表示にしてから、カートページの数量変更時にデフォルトのカート更新イベントをトリガーするスクリプトをエンキューします(カートウィジェットとミニカートウィジェットの両方で機能します)。テンプレートリダイレクトフック、jQueryとの依存関係を使用し、このスクリプトがカートページにのみ読み込まれるようにします。
CSSでボタンを非表示にするには、タグの代わりにクラス.buttonを使用して、すべてのWooCommerceバージョンとの互換性を維持します。
.button[name='update_cart'] {
display: none!important;
}
または、PHPヘッドスタイル:
add_action('wp_head', 'hide_update_cart_button', 20);
function hide_update_cart_button() {
echo "<style>.button[name='update_cart']{ display: none!important;}</style>";
}
JQueryに依存するスクリプトをエンキューします。
add_action( 'template_redirect', 'auto_update_cart_totals' );
function auto_update_cart_totals() {
if (! is_cart() ) return; // Only if it's cart page.
// Enqueue js file.
add_action( 'wp_enqueue_scripts', 'my_cart_autoupdate' );
}
function my_cart_autoupdate( ) {
// Here goes code to hide CSS button if you decide to use PHP solution for styling.
wp_enqueue_script( 'my-cart-autoupdate', 'path-to-js-file-its-name-and-extension', array('jquery'), '', true);
}
JQueryコードで最も重要で、通常見落とされがちなことは、更新遅延を設定することです。この例では1000です。私のプラグインでは、設定でこの値を変更できます。この遅延中にユーザーが数量を再度変更すると、完全な期間にリセットされます。実装されておらず、インクリメントボタンをクリックして数量を1から10に変更すると、1ではなく9つのAjax呼び出しがトリガーされます。これを.jsファイルに配置します。
var timeout;
jQuery('div.woocommerce').on('change keyup mouseup', 'input.qty', function(){ // keyup and mouseup for Firefox support
if (timeout != undefined) clearTimeout(timeout); //cancel previously scheduled event
if (jQuery(this).val() == '') return; //qty empty, instead of removing item from cart, do nothing
timeout = setTimeout(function() {
jQuery('[name="update_cart"]').trigger('click');
}, 1000 );
});