24

I have installed woocommerce to handle product input & checkout process of a wordpress shop.

The shop page is custom built which allows the user to pick a product from a list and customise it which outputs a price in javascript based on information stored in the database.

The products stored in the db are valued at 0.00 because they're different prices depending on the variables chosen.

The output data I'm ready to pass to woocommerce is as follows:

  • WC Product ID (This matches a product in the db)
  • Custom Price
  • Custom Image
  • Custom Description (e.g. 100mm x 100mm)
  • Build Data (to be stored against the item but not seen in checkout)

I'm trying to find a way to add a product to the cart using the product ID (to make it valid) and then overriding the price with the custom price and attaching meta data which most will be seen at checkout and one will be hidden until seen in the wordpress admin.

Adding the product to the cart is achieved by using:

$woocommerce->cart->add_to_cart($_POST['custom_product_id']);

After which point I'm finding it impossible to override the price and add additional information.

Kevin S
  • 1,067
  • 1
  • 10
  • 19
  • It's important the override price isn't static, it's calculated per product and ready to pass across when you add it to the cart, i'm assuming if i save it as additional meta data then that could be used in a function later on to pull out and override the 0.00 price. – Kevin S Jul 17 '15 at 18:52
  • Sounds like the case for [Product Addons](http://www.woothemes.com/products/product-add-ons). – helgatheviking Jul 18 '15 at 00:07
  • The issue with using such a plugin is that it relies upon the pre-made woocommerce templates. The are no product pages, it's an onscreen tool that has information ready to pass to the cart. This information needs to be programatically added to the cart without a reliance on an "add to cart" button, it needs to be completed all within PHP. – Kevin S Jul 18 '15 at 11:30
  • For anyone reading this i've come accross an example here: http://www.xatik.com/2013/02/06/add-custom-form-woocommerce-product/2/ which lays out the basics of what needs to be achieved. I'm following it as we speak and i'll be posting an answer if successful! – Kevin S Jul 18 '15 at 12:09

2 Answers2

42

All of this code goes into functions.php

  1. This captures additional posted information (all sent in one array)

    add_filter('woocommerce_add_cart_item_data','wdm_add_item_data',1,10);
    function wdm_add_item_data($cart_item_data, $product_id) {
    
        global $woocommerce;
        $new_value = array();
        $new_value['_custom_options'] = $_POST['custom_options'];
    
        if(empty($cart_item_data)) {
            return $new_value;
        } else {
            return array_merge($cart_item_data, $new_value);
        }
    }
    
  2. This captures the information from the previous function and attaches it to the item.

    add_filter('woocommerce_get_cart_item_from_session', 'wdm_get_cart_items_from_session', 1, 3 );
    function wdm_get_cart_items_from_session($item,$values,$key) {
    
        if (array_key_exists( '_custom_options', $values ) ) {
            $item['_custom_options'] = $values['_custom_options'];
        }
    
        return $item;
    }
    
  3. This displays extra information on basket & checkout from within the added info that was attached to the item.

    add_filter('woocommerce_cart_item_name','add_usr_custom_session',1,3);
    function add_usr_custom_session($product_name, $values, $cart_item_key ) {
    
        $return_string = $product_name . "<br />" . $values['_custom_options']['description'];// . "<br />" . print_r($values['_custom_options']);
        return $return_string;
    
    }
    
  4. This adds the information as meta data so that it can be seen as part of the order (to hide any meta data from the customer just start it with an underscore)

    add_action('woocommerce_add_order_item_meta','wdm_add_values_to_order_item_meta',1,2);
    function wdm_add_values_to_order_item_meta($item_id, $values) {
        global $woocommerce,$wpdb;
    
        wc_add_order_item_meta($item_id,'item_details',$values['_custom_options']['description']);
        wc_add_order_item_meta($item_id,'customer_image',$values['_custom_options']['another_example_field']);
        wc_add_order_item_meta($item_id,'_hidden_field',$values['_custom_options']['hidden_info']);
    
    }
    
  5. If you want to override the price you can use information saved against the product to do so

    add_action( 'woocommerce_before_calculate_totals', 'update_custom_price', 1, 1 );
    function update_custom_price( $cart_object ) {
        foreach ( $cart_object->cart_contents as $cart_item_key => $value ) {       
            // Version 2.x
            //$value['data']->price = $value['_custom_options']['custom_price'];
            // Version 3.x / 4.x
            $value['data']->set_price($value['_custom_options']['custom_price']);
        }
    }
    

All your custom information will appear in the customer email and order from within wordpress providing you added it as meta data (4.)

Kevin S
  • 1,067
  • 1
  • 10
  • 19
  • 3
    You probably want to do some validation/sanitization on the `$_POST` data. Additionally this is definitely plugin-territory and doesn't belong in `functions.php`. But otherwise, very complete answer. – helgatheviking Jul 18 '15 at 16:43
  • Thanks Kathy, that's given me a bit of confidence to read that from you! I will be sanitizing the post information and i'll look into how to turn this into a plugin at a later date. – Kevin S Jul 19 '15 at 10:20
  • 1
    You're welcome. To make it a plugin, you just put all the functions into a file and add a [plugin header](https://developer.wordpress.org/plugins/the-basics/header-requirements/). – helgatheviking Jul 19 '15 at 16:43
  • 1
    This looks like exactly what I need, but I'm having a bit of trouble understanding it. How do I actually trigger this to add a product to my cart? – JacobTheDev Jul 28 '15 at 18:31
  • 1
    Figured out the issue, I think, but I'm still having trouble fixing it. My custom_options aren't POSTing so the functions.php can read it. Hmm. – JacobTheDev Jul 28 '15 at 19:48
  • Figured it out, it was an issue with serializing my data. – JacobTheDev Jul 28 '15 at 21:29
  • I'm having trouble with this and apostrophes. Trying to figure out how to sanitize it, but having no luck. Any chance you can point me in the right direction? – JacobTheDev Nov 02 '15 at 16:36
  • A recent update to woocommerce in the latest version 3.x has meant step 5 has now been tweaked, uncomment the line of code relevant to your version of woocommerce (currently defaults to version 3) – Kevin S Apr 05 '17 at 09:56
  • Great Stuff! I had to use it like this in order to print value without decimal: $value['data']->set_price($value['_custom_options'] – mysticalghoul Aug 09 '17 at 09:28
  • Very old post but this is excellent. But I can't understand how is the data being POSTed? If it's form that would use `template_redirect` hook then how is `$_POST['custom_options']` available in the `woocommerce_add_cart_item_data` hook? – burf Jul 20 '23 at 10:35
7

Step 1:- You need to create some custom hidden fields to send custom data that will show on single product page. for example :-

add_action('woocommerce_before_add_to_cart_button', 'custom_data_hidden_fields');
function custom_data_hidden_fields() {
    echo '<div class="imput_fields custom-imput-fields">
        <label class="price_prod">price: <br><input type="text" id="price_prod" name="price_prod" value="" /></label>
        <label class="quantity_prod">quantity: <br>
            <select name="quantity_prod" id="quantity_prod">
                <option value="1" selected="selected">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
                <option value="4">4</option>
                <option value="5">5</option>
            </select>
        </label>
    </div><br>';
}

Step 2:- Now after done that you need to write the main logic for Save all Products custom fields to your cart item data, follow the below codes.

// Logic to Save products custom fields values into the cart item data
add_action( 'woocommerce_add_cart_item_data', 'save_custom_data_hidden_fields', 10, 2 );
function save_custom_data_hidden_fields( $cart_item_data, $product_id ) {

    $data = array();

    if( isset( $_REQUEST['price_prod'] ) ) {
        $cart_item_data['custom_data']['price_pro'] = $_REQUEST['price_prod'];
        $data['price_pro'] = $_REQUEST['price_prod'];
    }

    if( isset( $_REQUEST['quantity_prod'] ) ) {
        $cart_item_data['custom_data']['quantity'] = $_REQUEST['quantity_prod'];
        $data['quantity'] = $_REQUEST['quantity_prod'];
    }

    // below statement make sure every add to cart action as unique line item
    $cart_item_data['custom_data']['unique_key'] = md5( microtime().rand() );
    WC()->session->set( 'price_calculation', $data );

    return $cart_item_data;
}

Step 3: you need to override the item price with your custom calculation. It will work with your every scenario of your single product sessions.

add_action( 'woocommerce_before_calculate_totals', 'add_custom_item_price', 10 );
function add_custom_item_price( $cart_object ) {

    foreach ( $cart_object->get_cart() as $item_values ) {

        ##  Get cart item data
        $item_id = $item_values['data']->id; // Product ID
        $original_price = $item_values['data']->price; // Product original price

        ## Get your custom fields values
        $price1 = $item_values['custom_data']['price1'];
        $quantity = $item_values['custom_data']['quantity'];

        // CALCULATION FOR EACH ITEM:
        ## Make HERE your own calculation 
        $new_price = $price1 ;

        ## Set the new item price in cart
        $item_values['data']->set_price($new_price);
    }
}

Everything will be done inside the functions.php

Reference Site

Krishna Gupta
  • 179
  • 3
  • 15