Количество товара (quantity) — один важнейших элементов функционала интернет-магазина (woocommerce в частности). Есть множество нюансов связанных с количеством товара, рассмотрим их.
Вывод количества в категориях товаров
По-умолчанию в шаблоне вывода товаров параметр количество товара не выводится. Включить его можно функцией:
add_filter( 'woocommerce_loop_add_to_cart_link', 'quantity_inputs_for_woocommerce_loop_add_to_cart_link', 10, 2 ); function quantity_inputs_for_woocommerce_loop_add_to_cart_link( $html, $product ) { if ( $product && $product->is_type( 'simple' ) && $product->is_purchasable() && $product->is_in_stock() && ! $product->is_sold_individually() ) { $html = '<form action="' . esc_url( $product->add_to_cart_url() ) . '" class="cart" method="post" enctype="multipart/form-data">'; $html .= woocommerce_quantity_input( array(), $product, false ); $html .= '<button type="submit" class="button alt">' . esc_html( $product->add_to_cart_text() ) . '</button>'; $html .= '</form>'; } return $html; }
Поле Количество в шаблоне архива (Ajax)
Отличное решение на Ajax, работает с мини-корзиной.
function custom_quantity_field_archive() { $product = wc_get_product( get_the_ID() ); if ( ! $product->is_sold_individually() && 'variable' != $product->product_type && $product->is_purchasable() && $product->is_in_stock() ) { woocommerce_quantity_input( array( 'min_value' => 1, 'max_value' => $product->backorders_allowed() ? '' : $product->get_stock_quantity() ) ); } } add_action( 'woocommerce_after_shop_loop_item', 'custom_quantity_field_archive', 9 ); function custom_add_to_cart_quantity_handler() { wc_enqueue_js( ' jQuery( ".product-type-simple" ).on( "click", ".quantity input", function() { return false; }); jQuery( ".product-type-simple" ).on( "change input", ".quantity .qty", function() { var add_to_cart_button = jQuery( this ).parents( ".product" ).find( ".add_to_cart_button" ); // For AJAX add-to-cart actions add_to_cart_button.data( "quantity", jQuery( this ).val() ); // For non-AJAX add-to-cart actions add_to_cart_button.attr( "href", "?add-to-cart=" + add_to_cart_button.attr( "data-product_id" ) + "&quantity=" + jQuery( this ).val() ); }); ' ); } add_action( 'init', 'custom_add_to_cart_quantity_handler' );
Устанавливаем минимум и максимум
//Min and Max quantity // Simple products add_filter( 'woocommerce_quantity_input_args', 'jk_woocommerce_quantity_input_args', 10, 2 ); function jk_woocommerce_quantity_input_args( $args, $product ) { if ( is_singular( 'product' ) ) { $args['input_value'] = 1; // Starting value (we only want to affect product pages, not cart) } $args['max_value'] = 100; // Maximum value $args['min_value'] = 1; // Minimum value $args['step'] = 1; // Quantity steps return $args; } // Variations add_filter( 'woocommerce_available_variation', 'jk_woocommerce_available_variation' ); function jk_woocommerce_available_variation( $args ) { $args['max_qty'] = 100; // Maximum value (variations) $args['min_qty'] = 1; // Minimum value (variations) return $args; }
Изменение товара в мини-корзине
Если необходимо корректировать количество (+ -) товара в мини-корзине, то нужно сделать следующее:
1. Вставляем в шаблоне мини-корзины (cart/mini-cart.php) кнопки + и —
<a rel="nofollow" href="/?wc-ajax=add_to_cart&add-to-cart=<?php echo $cart_item['product_id'];?>" data-quantity="1" data-product_id="<?php echo $cart_item['product_id'];?>" data-product_sku="" class="button product_type_simple add_to_cart_button ajax_add_to_cart btnPlus">+</a> <?php echo '<a class="button btnMinus" onClick="updateQty(\''.$cart_item_key.'\','.($cart_item['quantity']-1).')">–</a>'; ?>
2. Создаем шаблон php c названием template-setquantity.php и содержимым:
<?php // Template Name: Request template for Set Quantity ?> <?php //the cart key stores information about cart $cartKeySanitized = filter_var($_POST['cart_item_key'], FILTER_SANITIZE_STRING); //the new qty you want for the product in cart $cartQtySanitized = filter_var($_POST['cart_item_qty'], FILTER_SANITIZE_STRING); //update the quantity global $woocommerce; ob_start(); $woocommerce->cart->set_quantity($cartKeySanitized,$cartQtySanitized); ob_get_clean(); ?>
3. Создаем новую страницу с названием Updatecart и выбираем шаблон Request template for Set Quantity
4. Добавляем скрипт (в файл с другими скриптами сайта)
function updateQty(key,qty){ url = 'https://bazabirs.ru/updatecart/'; data = "cart_item_key="+key+"&cart_item_qty="+qty; jQuery.post( url, data ) .done(function( data ) { //function updateCartFragment updateCartFragment(); }); } function updateCartFragment() { $fragment_refresh = { url: woocommerce_params.ajax_url, type: 'POST', data: { action: 'woocommerce_get_refreshed_fragments' }, success: function( data ) { if ( data && data.fragments ) { jQuery.each( data.fragments, function( key, value ) { jQuery(key).replaceWith(value); }); if ( $supports_html5_storage ) { sessionStorage.setItem( "wc_fragments", JSON.stringify( data.fragments ) ); sessionStorage.setItem( "wc_cart_hash", data.cart_hash ); } jQuery('body').trigger( 'wc_fragments_refreshed' ); } } }; //Always perform fragment refresh jQuery.ajax( $fragment_refresh ); }
CSS стили кнопок + и —
.btnPlus { background-color: #01a7e5; padding: 7px; width: 10px; color: #fff; } .btnMinus { background-color: #ff5722; padding: 7px; width: 10px; color: #fff; cursor: pointer; }
Изменить вид quantity
Стандартный вид количества woocmmerce не очень удобен, доработаем его.
Изменим шаблон woocommerce global/quantity-input.php:
if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } ?> <div class="quantity"> <input class="minus" type="button" value="-"> <input type="number" step="<?php echo esc_attr( $step ); ?>" min="<?php echo esc_attr( $min_value ); ?>" max="<?php echo esc_attr( $max_value ); ?>" name="<?php echo esc_attr( $input_name ); ?>" value="<?php echo esc_attr( $input_value ); ?>" title="<?php echo esc_attr_x( 'Qty', 'Product quantity input tooltip', 'woocommerce' ) ?>" class="input-text qty text" size="4" /> <input class="plus" type="button" value="+"> </div>
CSS
/* Количество */ input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { /* display: none; <- Crashes Chrome on hover */ -webkit-appearance: none; margin: 0; /* <-- Apparently some margin are still there even though it's hidden */ } input[type="number"] { -moz-appearance: textfield;} .quantity {margin: 0 auto; display: table;} .minus { border: none; color: #fff; background-color: rgba(140,215,32,0.7); height: 30px; width: 30px; /*display: table-cell;*/ cursor: pointer; } .plus { border: none; color: #fff; background-color: rgba(140,215,32,0.7); height: 30px; width: 30px; /*display: table-cell;*/ cursor: pointer; } .minus:hover, .plus:hover {background-color: rgba(140,215,32,1);} .qty { border: none; color: #111; /* font-weight: bold; */ height: 30px; display: table-cell; box-sizing: border-box; width: 20% !important; }
И добавляем скрипт
// Скрипт для кнопок + и - $(document).ready(function(){ $('.quantity').on('click', '.plus', function(e) { $input = $(this).prev('input.qty'); var val = parseInt($input.val()); $input.val( val+1 ).change(); }); $('.quantity').on('click', '.minus', function(e) { $input = $(this).next('input.qty'); var val = parseInt($input.val()); if (val > 1) { $input.val( val-1 ).change(); } }); });
В шаблоне архивов товаров, в карточке товаров, сопутствующих — метод работает отлично. В корзине не работает из-за обновления ajax.
Чтобы работал в корзине надо изменить .quantity на body. Но с body не работает в шаблоне архивов товаров.
// Скрипт для кнопок + и - $(document).ready(function(){ $('body').on('click', '.plus', function(e) { $input = $(this).prev('input.qty'); var val = parseInt($input.val()); $input.val( val+1 ).change(); }); $('body').on('click', '.minus', function(e) { $input = $(this).next('input.qty'); var val = parseInt($input.val()); if (val > 1) { $input.val( val-1 ).change(); } }); });
if (val > 1) { — если это сравнение снизить до ноля, то можно в корзине, с помощью кнопки минус, фактически удалять товары.
Еще один важный момент! Если корзина обновляется автоматически, то при нажатии + или - минус в первый раз обновление срабатывает, а кнопка update_cart только становится активной (изначально у этого input стоит атрибут disabled), и только после второго нажатия срабатывает обновление. Исправляем это так — изначально "взводим" кнопку обновления, при этом изначально и при последующих обновлениях ajax.
$(document).bind('ready ajaxComplete', function(){ $('[name="update_cart"]').attr("disabled",false); });
Надо разделить вывод скрипта в корзине от скрипта в архивах.
При нажатии + или - происходит перезагрузка ajax, но пользователь, который хочет изменить количество на десятки единиц может этого не понять. Чтобы этот момент сгладить, надо в скрипте автоматического обновления корзины (при обновлении количества) добавить небольшую задержку:
setTimeout(function () { jQuery("[name='update_cart']").trigger("click"); }, 1000);
При нажатии на кнопку «добавить в корзину» все-равно добавляется в кол-ве 1 штука, а не столько, сколько было введено на карточке товара.
Кнопка «-» не работает в мини корзине
Когда вставляешь сами кнопки в шаблон WC миникорзины нужно кнопку «—» поставить перед полем количество, а кнопку «+» после.
У меня сделано так:
<td style="width: 20px;">
<?php echo '<a class="minus" onClick="updateQty(\''.$cart_item_key.'\','.($cart_item['quantity']-1).')">–</a>'; ?>
</td>
<td class="product-quantity">
<?php echo apply_filters( 'woocommerce_checkout_cart_item_quantity', ' <strong class="product-quantity">' . sprintf( '× %s', $cart_item['quantity'] ) . '</strong>', $cart_item, $cart_item_key ); ?>
</td>
<td style="width: 20px;">
<a rel="nofollow" href="/?wc-ajax=add_to_cart&add-to-cart=<?php echo $cart_item['product_id'];?>" data-quantity="1" data-product_id="<?php echo $cart_item['product_id'];?>" data-product_sku="" class="product_type_simple add_to_cart_button ajax_add_to_cart plus">+</a>
</td>
Какой то костыль получился по мини-корзине. Вот более наверное правильное решение https://gist.github.com/ashokmhrj/fda5a23f7bdfc55749bd2bd53c64a8ca