Я добавил настраиваемое поле ввода номера на страницы отдельных продуктов. Обычная цена умножается на введенное целое значение. Например, если базовая цена составляет 10 долларов США, а пользователь вводит значение 2 в поле настраиваемого ввода, новая цена станет 20 долларов США.
Обновление цены работает нормально, но когда пользователь попадает в корзину и обновляет количество товара в корзине, цена пересчитывается. например Новая рассчитанная цена составила 20 долларов (пример выше), и пользователь меняет количество в корзине с 1 на 5, цена снова пересчитывается с помощью пользовательского целочисленного поля, поэтому 20 долларов снова умножаются на 2 и теперь составляют 40 долларов. .
Но я не понимаю, почему это происходит...
Это мой текущий код:
add_action( 'woocommerce_after_add_to_cart_quantity', 'add_custom_input_number_field', 0 );
function add_custom_input_number_field() {
echo '<div class = "custom-input-number-field">';
echo '<label>' . __( 'Custom Input Number', 'woocommerce' ) . '</label>';
echo '<input type = "number" required = "true" placeholder = "max. 30.500" class = "custom-input-number" name = "custom_input_number" min = "1" step = "0.001" />';
echo '</div>';
}
add_filter( 'woocommerce_get_price_html', 'update_product_price_based_on_custom_input_on_product_page', 9999, 2 );
function update_product_price_based_on_custom_input_on_product_page( $price, $product ) {
if ( is_product() && isset( $_POST['custom_input_number'] ) ) {
$custom_input_value = (float) $_POST['custom_input_number'];
$product_price = $product->get_price();
$new_price = $product_price * $custom_input_value;
$price = wc_price( $new_price ) . $product->get_price_suffix();
}
return $price;
}
add_filter( 'woocommerce_add_cart_item_data', 'save_custom_input_number_field_data', 10, 2 );
function save_custom_input_number_field_data( $cart_item_data, $product_id ) {
if ( isset( $_POST['custom_input_number'] ) ) {
$cart_item_data['custom_input_number'] = wc_clean( $_POST['custom_input_number'] );
$cart_item_data['custom_input_number'] = (float) $cart_item_data['custom_input_number'];
}
return $cart_item_data;
}
add_action( 'woocommerce_before_calculate_totals', 'update_product_price_based_on_custom_input_in_cart', 10, 1 );
function update_product_price_based_on_custom_input_in_cart( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
return;
}
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
if ( isset( $cart_item['custom_input_number'] ) ) {
$custom_input_value = $cart_item['custom_input_number'];
$product = $cart_item['data'];
$product_price = $product->get_price();
$new_price = $product_price * $custom_input_value;
$product->set_price( $new_price );
}
}
}
Я пробовал разные подходы. Лучшим вариантом было просто заблокировать Woo от повторного обновления цены после того, как она была добавлена один раз, но я также хочу работать с многоуровневым ценообразованием для некоторых продуктов, поэтому это не вариант.
Я также пробовал разные хуки (add_to_cart, woocommerce_before_calculate_totals и т. д.).
В вашем коде есть некоторые ошибки и неправильное использование хуков.
Вместо этого попробуйте следующее, это решит проблему, с которой вы столкнулись:
// Additional custom input field in single product
add_action( 'woocommerce_after_add_to_cart_quantity', 'add_custom_input_number_field', 0 );
function add_custom_input_number_field() {
echo '<div class = "custom-input-number-field">
<label>' . __( 'Custom Input Number', 'woocommerce' ) . '</label>
<input type = "number" required = "true" placeholder = "max. 30.500" class = "custom-input-number" name = "custom_number" min = "1" step = "0.001" />
</div>';
}
// Save custom input field value as custom cart item data
add_filter( 'woocommerce_add_cart_item_data', 'save_custom_input_number_field_data', 10, 2 );
function save_custom_input_number_field_data( $item_data, $product_id ) {
if (isset( $_POST['custom_number']) ) {
$item_data['custom_number'] = floatval($_POST['custom_number']);
}
return $item_data;
}
// Change and set cart item custom calculated price
add_action( 'woocommerce_before_calculate_totals', 'update_product_price_based_on_custom_input_in_cart', 10, 1 );
function update_product_price_based_on_custom_input_in_cart( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
foreach ( $cart->get_cart() as $item ) {
if ( isset($item['custom_number']) && $item['custom_number'] ) {
$item['data']->set_price( $item['data']->get_price() * $item['custom_number'] );
}
}
}
// Cart and mini cart displayed calculated price
add_filter( 'woocommerce_cart_item_price', 'filter_cart_item_price', 10, 2 );
function filter_cart_item_price( $price_html, $cart_item ) {
if ( isset($cart_item['custom_number']) && $cart_item['custom_number'] ) {
$product = wc_get_product( $cart_item['variation_id'] > 0 ? $cart_item['variation_id'] : $cart_item['product_id'] );
$args = array('price' => ($product->get_price() * $cart_item['custom_number']));
if ( WC()->cart->display_prices_including_tax() ) {
$product_price = wc_get_price_including_tax( $cart_item['data'], $args );
} else {
$product_price = wc_get_price_excluding_tax( $cart_item['data'], $args );
}
return wc_price( $product_price );
}
return $price_html;
}
Код находится в файле function.php вашей дочерней темы (или в плагине). Протестировано и работает.
Причина в том, что блоки корзины и оформления заказа на самом деле не допускают настройки за пределами доступных настроек блока.
Хорошо, тогда я буду использовать традиционную корзину и оформление заказа, спасибо :)
Спасибо, это сработало (по крайней мере частично). Он работает с традиционными Woo Cart и Checkout, но с новыми блоками Cart и Checkout проблема остается (действительно интересно). У вас есть идеи, почему это так?