Đa số các product trong Woocommerce sẽ set cứng giá hoặc thêm variable để tùy chỉnh giá của sản phẩm. Nhưng trong trường hợp mình có một sản phẩm giá sẽ được tính theo chu vi hoặc diện tích. Với các field cho phép người dùng nhập chiều dài , chiều rộng vào thì sao.
Trong bài viết này sẽ hướng dẫn các bạn Custom Form tính giá cho sản phẩm trong Woocommerce WordPress.
Để demo cho bài viết này, mình có tham khảo giá của Sàn gỗ Savi bên site này, Sàn gỗ Savi 160.000 đ/m2.
Trong demo này mình dùng theme Storefront của woo luôn nhé.
Bây giờ tiến hành custom thôi nào:
B1: Add Woo Advanced custom field
Chỗ này mình muốn add 1 option để có thể enable/disable custom form hiển thị ở front-end.
//Add woo custom field
add_action( 'woocommerce_product_options_advanced', 'ntc_add_custom_field_product_dashboard_advanced_tab' );
function ntc_add_custom_field_product_dashboard_advanced_tab() {
global $post;
$custom_price_form_product_option = get_post_meta( $post->ID, '_custom_price_form_of_product', true );
echo '<div class="options_group ">';
// Checkbox Field
woocommerce_wp_checkbox( array(
'id' => '_custom_price_form_of_product',
'description' => __( 'Show custom price form of product', 'woocommerce' ),
'label' => __( 'Show custom price form of product', 'woocommerce' ),
'value' => $custom_price_form_product_option,
) );
echo '</div>';
}
B2: Save data của custom field vừa tạo ở B1 nhé
//Save data
add_action( 'woocommerce_process_product_meta', 'ntc_save_custom_product_fields' );
function ntc_save_custom_product_fields( $post_id ) {
$_custom_price_form_of_product = isset( $_POST['_custom_price_form_of_product'] ) ? 'yes' : 'no';
//=========
update_post_meta( $post_id, '_custom_price_form_of_product', esc_attr( $_custom_price_form_of_product ) );
}
B3: Giờ thì show form ra Front-End nào
Ở bước này, mình có kiểm tra điều kiện là nếu là single product và form được cho phép hiển thị thì nó sẽ xuất hiện ở front-end, trước button add to cart.
//show to frontend
add_action( 'woocommerce_before_add_to_cart_button', 'ntc_show_custom_input_field_to_single_product', 0 );
function ntc_show_custom_input_field_to_single_product() {
global $post;
$custom_price_form_product_option = get_post_meta( $post->ID, '_custom_price_form_of_product', true );
$product = wc_get_product( $post->ID );
//Check is product and form is enable -> show on single product
if ( is_product() && $custom_price_form_product_option == 'yes' ) { ?>
<table id="ntc_price_calculator">
<tbody>
<tr class="price-table-row length-input">
<td>
<label for="length_value">Chiều dài</label>
</td>
<td style="text-align:right;">
<div class="input-wrap">
<input type="number" name="length_value" id="length_value" class="amount_needed" autocomplete="off" required>
</div>
</td>
</tr>
<tr class="price-table-row width-input">
<td>
<label for="width_value">Chiều rộng</label>
</td>
<td style="text-align:right;">
<div class="input-wrap">
<input type="number" name="width_value" id="width_value" class="amount_needed" autocomplete="off" required>
</div>
</td>
</tr>
<tr class="price-table-row total-row">
<td>Thành tiền</td>
<td style="text-align:right;"><span class="standard-total" data-product-price="<?php echo $product->get_price(); ?>">0</span></td>
</tr>
</tbody>
</table>
<?php
// custom js form
echo "<script>
jQuery(document).ready(function() {
jQuery('#length_value, #width_value').on('change', function (e) {
let length = jQuery('#length_value').val(),
width = jQuery('#width_value').val(),
product_price = jQuery('.standard-total[data-product-price]').data('product-price');
length =length? parseFloat(length):0;
width =width? parseFloat(width):0;
product_price = parseFloat(product_price);
let total = length*width*product_price;
jQuery('.standard-total[data-product-price]').html((length*width)+'m<sup>2</sup> -- '+total.toLocaleString('vi-VN') +'₫');
console.log(length, width,product_price,total.toLocaleString('vi-VN'));
})
});
</script>";
}
}
Ngoài ra trong đoạn code trên, mình có add thêm đoạn js để tính toán và hiển thị giá ở trên form đó luôn. Bạn có thể add đoạn js này vào 1 file riêng và enqueue vào nhé.
B4: Ở bước này thì chúng ta tính toán một chút và add data vào cart nhé.
// Set custom field and calculated price as custom cart data in the cart item
add_filter( 'woocommerce_add_cart_item_data', 'ntc_save_custom_data_in_cart_object', 30, 3 );
function ntc_save_custom_data_in_cart_object( $cart_item_data, $product_id, $variation_id ) {
if ( ! isset( $_POST['length_value'] ) || ! isset( $_POST['width_value'] ) ) {
return $cart_item_data;
}
$length_value = isset( $_POST['length_value'] ) ? floatval( $_POST['length_value'] ) : 0;
$width_value = isset( $_POST['width_value'] ) ? floatval( $_POST['width_value'] ) : 0;
$lVal = floatval( $length_value < 0 ? $length_value * - 1 : $length_value );
$wVal = floatval( $width_value < 0 ? $width_value * - 1 : $width_value );
$product = wc_get_product( $product_id );
$product_price = floatval( $product->get_price() );
$price_total = $lVal * $wVal * $product_price;
$cart_item_data['custom_data']['price'] = $price_total;
$cart_item_data['custom_data']['length'] = $length_value . ' (m)';
$cart_item_data['custom_data']['width'] = $width_value . ' (m)';
return $cart_item_data;
}
B5: Set new price cho product -> hiển thị ở page cart và page checkout
// Set the new calculated price of the cart item -- https://prnt.sc/rfpz1w
add_action( 'woocommerce_before_calculate_totals', 'ntc_calculate_product_fee', 99, 1 );
function ntc_calculate_product_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
return;
}
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) {
return;
}
foreach ( $cart->get_cart() as $cart_item ) {
if ( isset( $cart_item['custom_data']['price'] ) ) {
// Get the new calculated price
$new_price = (float) $cart_item['custom_data']['price'];
// Set the new calculated price
$cart_item['data']->set_price( $new_price );
}
}
}
//Show price in cart item - https://prnt.sc/rfpumh
add_filter( 'woocommerce_cart_item_product', 'ntc_woo_filter_cart_item_product', 20, 3 );
function ntc_woo_filter_cart_item_product( $cart_data, $cart_item, $cart_item_key ) {
if ( isset( $cart_item['custom_data']['price'] ) ) {
// Get the new calculated price
$new_price = (float) $cart_item['custom_data']['price'];
// Set the new calculated price
$cart_data->set_price( $new_price );
}
return $cart_data;
}
B6: Hiển thị custom text ở page cart và page checkout
Custom text ở đây là chiều dài và chiều rộng của sản phẩm được add vào form ở trên.
// Display Custom text in cart and checkout pages
add_filter( 'woocommerce_get_item_data', 'ntc_render_meta_on_cart_and_checkout', 99, 2 );
function ntc_render_meta_on_cart_and_checkout( $cart_data, $cart_item = null ) {
if ( isset( $cart_item['custom_data']['length'] ) ) {
$cart_data[] = array( "name" => "Length", "value" => $cart_item["custom_data"]["length"] );
}
if ( isset( $cart_item['custom_data']['width'] ) ) {
$cart_data[] = array( "name" => "Width", "value" => $cart_item["custom_data"]["width"] );
}
return $cart_data;
}
B7: Add custom text vào phần order để hiển thị trong backend và email các thứ nhé.
// Save the custom text as order item data (displaying it in order and notifications)
add_action( 'woocommerce_add_order_item_meta', 'ntc_order_meta_handler', 99, 3 );
function ntc_order_meta_handler( $item_id, $values, $cart_item_key ) {
if ( isset( $values['custom_data']['length'] ) ) {
wc_add_order_item_meta( $item_id, "Length", $values["custom_data"]["length"] );
}
if ( isset( $values['custom_data']['width'] ) ) {
wc_add_order_item_meta( $item_id, "Width", $values["custom_data"]["width"] );
}
}
Các bạn có thể test sản phẩm demo ở đây nhé https://ccgr.tk/product/san-go-savi-sv6034-thuong-hieu-san-go-viet-nam-cao-cap/
Code on Gist https://gist.github.com/trongcong/c3ce527ffe691288e3c28d5117dd17e7
Vậy là xong các bước để thêm form tính giá sản phẩm trong Woocommerce WordPress rồi đấy.
Bạn ơi. Code này thì chèn vào file nào đấy bạn?