Reputation: 79
I am trying to create a WooCommerce plugin for single product pages. I need to add up regular pricing with custom pricing. I was able to get the sum up of regular price with custom price, but when I click on "Add to Cart" I am not able to set up the new calculated price, in cart.
Any help is appreciated.
// WooCommerce activation
function custom_product_page()
{
global $wpdb;
global $product;
wp_enqueue_style('my-plugin-styles', plugins_url('assets/css/diamond_style.css', __FILE__));
if (class_exists('WooCommerce') && is_product()) {
$product = wc_get_product(get_the_ID());
$product_categories = wp_get_post_terms(get_the_ID(), 'product_cat');
$is_ring = false;
foreach ($product_categories as $product_category) {
if ($product_category->slug === 'rings' || $product_category->slug === 'ring') {
$is_ring = true;
break;
}
}
$table_name = $wpdb->prefix . 'diamond_purity';
$ring_size_table = $wpdb->prefix . 'ring_size';
// Show Metal Color only if the product category is "ring"
if ($is_ring) {
// Retrieve the latest gold rate
$gold_rate_table = $wpdb->prefix . 'gold_rate';
$gold_rate = $wpdb->get_var("SELECT final_price FROM $gold_rate_table ORDER BY id DESC LIMIT 1");
// Get the net weight attribute
$net_weight = $product->get_attribute('net-weight-g');
// Get the regular price
$regular_price = $product->get_regular_price();
// Calculate the updated price
$updated_price = ($gold_rate * $net_weight) + $regular_price;
// Display the updated price
echo '<p class="productprice">₹' . $updated_price . '</p>';
$gross_weight = $product->get_attribute('gross-weight');
echo 'Weight: ' . $gross_weight . ' g';
// Update cart item price with the custom price
add_filter('woocommerce_add_cart_item', function ($cart_item) use ($updated_price) {
$cart_item['data']->set_price($updated_price);
return $cart_item;
});
}
}
}
add_action('woocommerce_single_product_summary', 'custom_product_page', 25);
I tried using add_filter but didn't work me.
Upvotes: 2
Views: 573
Reputation: 254362
I have revisited your code, as there are some mistakes, errors and missing things. Here, what is missing is a hidden input field in product add to cart form, to post your custom price on add to cart action. Then you will be able to use that custom price.
As it seems that you are using your code in a plugin, you should start adding the following to the main plugin file, to check that WooCommerce is active:
defined( 'ABSPATH' ) or exit;
// Make sure WooCommerce is active
if ( ! in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
return;
}
Enqueuing a CSS styles file requires a separated function (you may need to make some CSS changes in your style rules):
add_action( 'wp_enqueue_scripts', 'custom_product_pricing_css' );
function custom_product_pricing_css() {
// Only on product single pages
if( ! is_product() ) return;
wp_enqueue_style('my-plugin-styles', plugins_url('assets/css/diamond_style.css', __FILE__));
}
For your custom database queries, is better to set each in a separated function (reason: code modularity):
function get_the_gold_rate() {
global $wpdb;
return $wpdb->get_var( "SELECT final_price FROM {$wpdb->prefix}gold_rate ORDER BY id DESC LIMIT 1");
}
Here is your revisited code function, hooked in a different hook (where I include a mandatory hidden input field inside the product form):
add_action('woocommerce_before_add_to_cart_button', 'add_to_cart_product_pricing', );
function add_to_cart_product_pricing() {
global $woocommerce, $product;
if ( is_a($woocommerce, 'WooCommerce') && is_product() ) {
// Targeting "ring" or "rings" product category
if ( has_term( array('ring', 'rings'), 'product_cat' ) ) {
// Load the latest gold rate
$gold_rate = (float) get_the_gold_rate();
// Get net weight product attribute
$net_weight = $product->get_attribute('net-weight-g');
// Get product regular price
$regular_price = $product->get_regular_price();
// Calculate product updated price
$updated_price = ($gold_rate * $net_weight) + $regular_price;
// Get the displayed price
$args = array( 'price' => floatval( $updated_price ) );
if ( 'incl' === get_option('woocommerce_tax_display_shop') ) {
$displayed_price = wc_get_price_including_tax( $product, $args );
} else {
$displayed_price = wc_get_price_excluding_tax( $product, $args );
}
// Display product updated price
printf( '<p class="productprice">%s</p>', wc_price( $displayed_price ) );
// Display a hidden input field with the "updated_price" as value
printf( '<input type="hidden" name="updated_price" value="%s" />', $updated_price );
// Get gross weight product attribute
$gross_weight = $product->get_attribute('gross-weight');
// Display the Gross Weight
printf( '<p class="grossweight">' . __('Weight: %s g') . '</p>', $gross_weight );
}
}
}
Now to include the updated price as custom cart item data, we use the following:
add_filter( 'woocommerce_add_cart_item_data', 'save_custom_cart_item_data', 10, 2 );
function save_custom_cart_item_data( $cart_item_data, $product_id ) {
if( isset($_POST['updated_price']) && ! empty($_POST['updated_price']) ) {
// Set the custom data in the cart item
$cart_item_data['updated_price'] = (float) wc_clean($_POST['updated_price']);
// Make each item as a unique separated cart item
$cart_item_data['unique_key'] = md5( microtime().rand() );
}
return $cart_item_data;
}
So we can now show in Minicart, items with this custom updated price:
add_action( 'woocommerce_cart_item_price', 'filter_cart_displayed_price', 10, 2 );
function filter_cart_displayed_price( $price, $cart_item ) {
if ( isset($cart_item['updated_price']) ) {
$args = array( 'price' => floatval( $cart_item['updated_price'] ) );
if ( 'incl' === get_option('woocommerce_tax_display_cart') ) {
$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;
}
And finally, we set the cart item price with the custom updated price:
add_action( 'woocommerce_before_calculate_totals', 'set_new_cart_item_updated_price' );
function set_new_cart_item_updated_price( $cart ) {
if ( ( is_admin() && ! defined( 'DOING_AJAX' ) ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop through cart items and set the updated price
foreach ( $cart->get_cart() as $cart_item ) {
// Set the new price
if( isset($cart_item['updated_price']) ){
$cart_item['data']->set_price($cart_item['updated_price']);
}
}
}
Code goes in functions.php file of your active child theme (or active theme) or in a plugin too. Tested and works.
Related: Custom cart item price set from product hidden input field in Woocommerce 3
Upvotes: 5