Set a specific product price conditionally on Woocommerce single product page & cart
Asked Answered
W

2

3

In Woocommerce I would like to alter the price of a specific product (in this case with an ID of 87) on both the single product page and for related cart items.

The product price needs to be increased by $10 but only on the single product page and only externally (so that the internal price or price set in Woocommerce is not altered).

Additionally, this price should also be altered in the cart but only if products from a certain category are NOT also in the cart.

Context: If someone buys this product on its own, they should be charged $10 above the regular price. If someone buys this item in conjunction with products from a certain category, they should be charged the regular price. This is essentially an inverted discount (I don't want to use coupon functionality to charge extra).

For the cart functionality, so far I have this but it's not working - the cart price is coming out at $75 when the current regular/base price is $45. I have no idea where 75 is coming from when it should be 55.

function wc_cart_custom_price( $cart_object ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

        // set our flag to be false until we find a product in that category
        $cat_check = false;

        // check each cart item for our category
        foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {

            $product = $cart_item['data'];

            // replace 'your-category' with your category's slug
            if ( has_term( 'your-category', 'product_cat', $product->id ) ) {
                $cat_check = true;
                // break because we only need one "true" to matter here
                break;
            }
        }

        // if a product in the cart is in our category, stop there and don't change price
        if ( $cat_check ) {
            return;
        }
        // else continue and alter the product price
        else if ( $cart_item['product_id'] == 87 ) {
            // we have the right product, do what we want
            $price = $cart_item['data']->get_price(); // Get the product price
            $new_price = $price + 10; // the calculation
            $cart_item['data']->set_price( $new_price ); // Set the new price
            }
}
add_action( 'woocommerce_before_calculate_totals', 'wc_cart_custom_price' );

My code for changing the product page price is, at the moment:

function wc_change_product_price($price, $product) {
    if ( is_single('87') ) {
        $post_id = $product->id;

        $regular_price = get_post_meta( $post_id, '_regular_price', true);
        $custom_value = ( $regular_price + 10 );
        $price = $custom_value;

    return $price;
    }
}
add_filter('woocommerce_get_price', 'wc_change_product_price', 99);

It is a disaster and causing a 500 server error. What I am doing wrong? Any help is welcome.

References:

Change cart item prices in WooCommerce version 3.0

https://rudrastyh.com/woocommerce/change-product-prices-in-cart.html

https://www.skyverge.com/blog/checking-woocommerce-cart-contains-product-category/

Wines answered 29/5, 2018 at 0:8 Comment(0)
V
2

Update 3 (Only for a defined product ID)

To make it work as you want to change the simple products prices only on single product pages (without altering archives product prices, related product prices, upsells and cross-sells) if any cart item doesn't belong to a specific product category.

Then you will need all this following code:

// Change displayed price on single product pages
add_action( 'woocommerce_single_product_summary', 'change_simple_product_price_html', 9 );
function change_simple_product_price_html() {
    global $product;

    // Only for product ID 87
    if( $product->get_id() != 87 ) return;

    // HERE set your product category term ID, slug or name
    $product_category = 't-shirts';

    // Checking for the product category in cart items loop
    foreach ( WC()->cart->get_cart() as $cart_item ) {
        if ( has_term( $product_category, 'product_cat', $cart_item['product_id'] ) )
            return; // Product category found ==> We EXIT from this function
    }

    remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
    add_action( 'woocommerce_single_product_summary', 'custom_simple_product_price_html', 10 );
}

function custom_simple_product_price_html(){
    global $product;

    $addp = 10; // Here the price additional amount

    if ( '' !== $product->get_price() && ! $product->is_on_sale() ) {
        $price = wc_price( wc_get_price_to_display( $product ) + $addp ) . $product->get_price_suffix();
    }
    echo '<p class="price">' . apply_filters( 'woocommerce_get_price_html', $price, $product ) . '</p>';
}

// Add custom calculated price to cart item data
add_filter( 'woocommerce_add_cart_item_data', 'add_cart_simple_product_custom_price', 20, 2 );
function add_cart_simple_product_custom_price( $cart_item_data, $product_id ){
    // Only for product ID 87
    if( $product_id != 87 ) 
        return $cart_item_data;

    $product = wc_get_product($product_id); // The WC_Product Object

    // Only if product is not on sale
    if( $product->is_on_sale() ) 
        return $cart_item_data;

    $price = (float) $product->get_price();

    // Set the custom amount in cart object
    $cart_item_data['new_price'] = $price + 10;

    return $cart_item_data;
}

// Set custom calculated price to cart
add_action( 'woocommerce_before_calculate_totals', 'set_cart_simple_product_custom_price', 20, 1 );
function set_cart_simple_product_custom_price( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // HERE set your product category term ID, slug or name
    $product_category = 't-shirts';

    // 1st cart items Loop: checking for the product category
    foreach ( $cart->get_cart() as $cart_item ) {
        if ( has_term( $product_category, 'product_cat', $cart_item['product_id'] ) )
            return; // Product category found ==> We EXIT from this function
    }

    // 2nd Loop: Changing cart item prices (Product category not found)
    foreach ( $cart->get_cart() as $cart_item ) {
        if( isset($cart_item['new_price']))
            $cart_item['data']->set_price( $cart_item['new_price'] );
    }
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

Vassal answered 29/5, 2018 at 2:19 Comment(9)
This will alter the price of all simple products though, correct? I am just wanting to alter the price of one specific product (with the id of 87). And when product id 87 is added to the cart, if there is any other products in category X, the regular price will be added. But if category X is NOT also in the cart, the additional $10 price is shown.Wines
Sorry, I have a disability which causes aphasia (I get similar words mixed up). "alter the price of a single product" should have been "alter the price of a specific product" which is why in my code there is $targeted_product_id = 87;Wines
The problem is that I don't understand why I need to completely change my question because I used a word wrong which meant my question was misinterpreted. I really appreciate your time but it doesn't at all help with what I am actually needing and asking the same question again just seems redundant.Wines
Thank you so much! Works perfect.Wines
I stupidly didn't think about changing the price of the product (with id 87) on the archive pages (aka store page and category page). Is this easy to alter to include those too or should I create a new question to tweak the above to do that? Thanks again! :)Wines
If you want to display that specific product price without restrictions, meaning to be displayed everywhere, that is very different and much more compact (different code). So yes it will be better to ask a new question, and notify me here and I will answer it. ThanksVassal
Here it is thank you @Vassal :) #50595420Wines
@Vassal Can you explain a bit for what is the if( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return; part, please?Hassler
Downvote. You should filter the price rather than use remove add action.Crewelwork
S
0

If you want to make it work to change the products price on single produt page. Please follow this code there I have added my product ID "99":

add_action( 'woocommerce_single_product_summary', 'e_coding_change_simple_product_price_html', 9 );
function e_coding_change_simple_product_price_html() {
    global $product;

// Only for product ID 99
if( $product->get_id() != 99 ) return;

// HERE set your product category term ID, slug or name
$product_category = 'my-book';

// Checking for the product category in cart items loop
foreach ( WC()->cart->get_cart() as $cart_item ) {
    if ( has_term( $product_category, 'product_cat', $cart_item['product_id'] ) )
        return; // Product category found ==> We EXIT from this function
}

remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
add_action( 'woocommerce_single_product_summary', 'custom_simple_product_price_html', 10 );
}

function custom_simple_product_price_html(){
global $product;

$addp = 10; // Here the price additional amount

if ( '' !== $product->get_price() && ! $product->is_on_sale() ) {
    $price = wc_price( wc_get_price_to_display( $product ) + $addp ) . $product->get_price_suffix();
}
echo '<p class="price">' . apply_filters( 'woocommerce_get_price_html', $price, $product ) .'</p>';
}

// Add custom calculated price to cart item data

add_filter( 'woocommerce_add_cart_item_data', 'add_cart_simple_product_custom_price', 20, 2 );

function add_cart_simple_product_custom_price( $cart_item_data, $product_id ){

// Only for product ID 87
if( $product_id != 99 )
    return $cart_item_data;

$product = wc_get_product($product_id); // The WC_Product Object

// Only if product is not on sale
if( $product->is_on_sale() )
    return $cart_item_data;

$price = (float) $product->get_price();

// Set the custom amount in cart object
$cart_item_data['new_price'] = $price + 10;

return $cart_item_data;
}


function cw_change_product_price_display( $price ) {

    $price .= ' At Each Item Product';
    return $price;

}

add_filter( 'woocommerce_get_price_html', 'cw_change_product_price_display' );
add_filter( 'woocommerce_cart_item_price', 'cw_change_product_price_display' );
Standford answered 14/9, 2018 at 14:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.