Woocommerce - How to get Cart item details from Functions.php - woocommerce

I am adding a condition based surcharge on the cart page but can't work out how to retrieve the meta details for the cart items.
If I do the following I get the item name, quantity & cost.. but how do I get the extra meta info?
$items = $woocommerce->cart->get_cart();
foreach($items as $item => $values) {
$_product = $values['data']->post;
echo "<b>".$_product->post_title.'</b> <br> Quantity: '.$values['quantity'].'<br>';
$price = get_post_meta($values['product_id'] , '_price', true);
echo " Price: ".$price."<br>";
}
Is there some code like
$items = $woocommerce->cart->get_cart_items_details();
or maybe the answer lies deeper in the array.. ?
Any help much appreciated.

Related

How to change add-to-cart form?

Is there a way to change the WooCommerce add-to-cart form through functions.php?
The goal is to add a checkbox for an additional product. When the checkbox is checked this product will also be added to the cart after a click on the add to cart button.
I am looking for a solution which doesn't rely on javascript.
A better title would be "WooCommerce up-sells as checkboxes".
A lot of research and several strategies to tackle this problem lead me to a solution which I thought was not even possible in the beginning.
The solution is now exactly what I wanted. A non-JavaScript, no-template-override, but a simple and pure addition to functions.php. It works for simple and variable products (and probably with grouped and external products too).
It misses some nice features still. It won't work yet if an up-sell is a variable product. Quantity selection and limiting up-sells per item or order would be nice additions too. Based on the code below adding those features should not be a big deal anymore.
// create the checkbox form fields and add them before the cart button
add_action( 'woocommerce_before_add_to_cart_button', 'action_woocommerce_before_add_to_cart_form', 10, 0 );
function action_woocommerce_before_add_to_cart_form(){
global $woocommerce, $product;
// get the product up-sells
$upsells = $product->get_upsells();
// store the number of up-sells and pass it on to the add-to-cart hook
?>
<input type="hidden" name="upsells_size" value="<?php echo(sizeof($upsells)); ?>">
<div id="wb-upsell-div">
<?php
// iterate through all upsells and add an input field for each
$i = 1;
foreach( $upsells as $value ){
$product_id = $value;
?>
<input id="wb-upsell-checkboxes" type="checkbox" name="upsell_<?php echo($i) ?>" value="<?php echo($product_id); ?>"><?php echo( '' . get_the_title( $product_id ) . "". " ($" . get_post_meta( $product_id, '_regular_price', true) . ")"); ?><br>
<?php
$i++;
}
?>
</div>
<?php
}
// function to add all up-sells, where the checkbox have been checked, to the cart
add_action('woocommerce_add_to_cart', 'custom_add_to_cart', 10, 3);
function custom_add_to_cart() {
global $woocommerce;
// get the number of up-sells to iterate through
$upsell_size = $_POST['upsells_size'];
// iterate through up-sell fields
for ($i=1; $i<=$upsell_size; $i++){
// get the product id of the up-sell
$product_id = $_POST['upsell_' . $i];
$found = false;
//check if product already in cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
WC()->cart->add_to_cart( $product_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $product_id );
}
}
}
And here is the CSS for formatting the <div>and the checkboxes. It goes into the style.css file:
#wb-upsell-div {
margin-top: 10px;
margin-bottom: 20px;
}
#wb-upsell-checkboxes{
}
So there's an actual answer to this question, you can add whatever you want inside the add to cart <form> using hooks. For example:
add_action( 'woocommerce_before_add_to_cart_button', 'so_34115452_add_input' );
function so_34115452_add_input(){
echo '<input type="checkbox" name="something"/>' . __( 'Some Checkbox', 'text-domain' );
}

Woocommerce: How do I get the product slug from the id?

I currently have the product id available in the cart and I need to retrieve the slug. How can I do this?
You can use get_post
$product = get_post( 27 );
$slug = $product->post_name;
echo $slug;
Alternatively to get_post, you can use get_product if you already have a product or need it for other purpose
$_pf = new WC_Product_Factory();
$product = $_pf->get_product($product_id);
$slug = $product->get_slug();
A product is a post. To retrieve the post slug, that correspond to post_name post field, from the post ID, the get_post_field() function can be used.
$product_slug = get_post_field('post_name', $product_id);
`Hi, in my case I did it as below: I needed to customize add to cart button entirely on shop page and category page. so I used $product object for this purpose. I needed product id, slug and name, so it did it. hope this will help you as well on cart page.`
add_filter( 'woocommerce_loop_add_to_cart_link', 'ij_replace_add_to_cart_button', 10, 2 );
function ij_replace_add_to_cart_button( $button, $product ) {
$productid = $product->id;
$productslug = $product->slug;
$productname = $product->name;
if (is_product_category() || is_shop()) {
$button_text = __("More Info", "woocommerce");
$button_link = $product->get_permalink();
$button = '<a href="'. $button_link .'" data-quantity="1" class="button product_type_simple add_to_cart_button ajax_add_to_cart" data-product_id="'. $productid.'" data-product_sku="" aria-label="Add “'.$productname.'” to your cart" rel="nofollow" data-productslug="'. $productslug.'" >' . $button_text . ' </a>';
return $button;
}
}

woocommerce coupons description in order email

I've got a problem to show coupon description in thank you order mail.
I have name of coupon by using:
$order->get_used_coupons()
But above function returns only namen. Any one know how to get description for specific coupon name?
Try this code:
$coupons = $order->get_items( 'coupon' );
foreach ( $coupons as $item_id => $item ) {
echo "<span class='coupon-name'><b>".$item['name']."</b></span>";
$post = get_post( $item_id );
echo "<p class='coupon-description'>".$post->post_excerpt."</p>";
}
}

woocommerce - programmatically update cart item quantity

I am trying to programmatically update the quantity of a specific product in the cart if certain criteria is met.
I can easily update the price of the cart items with the following:
add_action( 'woocommerce_before_calculate_totals', 'wwpa_simple_add_cart_price' );
function wwpa_simple_add_cart_price( $cart_object ) {
foreach ( $cart_object->cart_contents as $key => $value ) {
$value['data']->price = '1';
}}
In the function above I tried to add:
$value['data']->quantity= '10';
This doesn't work but not quite sure how or if I can edit the quantity?
I also tried a these combinations that I found while digging around WooCommerce:
$value['data']->quantity= '10';
$value['data']->qty= '10';
$value['quantity'] = '10';
Again none of these worked.
There has been some changes to the WC_Cart class since this post originally got posted, so i updated it with the new changes.
To update the quantity:
WC()->cart->set_quantity($cart_item_key, 100);
How to get the $cart_item_key example:
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
echo $cart_item_key;
}
And another example with a known cart_item_key:
WC()->cart->set_quantity('8d317bdcf4aafcfc22149d77babee96d', 100);
Hope this helps:)

WooCommerce: Add input field to every item in cart

I've been trying to add a single text input field to every item in the cart and submit that user input to product's meta info. It's been 2 days and I haven't succeeded yet.
My objective is to:
Take input from user for every item added to the cart.
Display that input in the order's meta info.
Display that input in confirmation email sent to the customer.
So far, I have copied the template file to my theme and added an input field inside a cell. I'm having trouble with the hooks, learned about hooks I will need from WooCommerce Product Gift Wrap plugin as indicated in this woocommerce issue.
Code I added to the cart.php template copied in my theme directory :
$input_url_data = '<div class="input-url"><input type="text" name="cart-url" value="" title="" class="input-text cart-url text" /></div>';
echo apply_filters( 'woocommerce_add_cart_item_data', $input_url_data, $cart_item_key );
Code I added to my theme's functions.php :
add_filter( 'woocommerce_add_cart_item_data','add_cart_item_data', 10, 2 );
add_filter( 'woocommerce_get_cart_item_from_session','get_cart_item_from_session', 10, 2 );
add_filter( 'woocommerce_get_item_data','get_item_data', 10, 2 );
add_filter( 'woocommerce_add_cart_item','add_cart_item', 10, 1 );
add_action( 'woocommerce_add_order_item_meta','add_order_item_meta', 10, 2 );
function add_cart_item_data( $cart_item_meta, $product_id ) {
$input_url_key = "";
$input_url_data['inputurl'] = $input_url_key;
return $input_url_data;
}
function get_cart_item_from_session( $cart_item, $values ) {
if ( ! empty( $values['inputurl'] ) ) {
$cart_item['inputurl'] = true;
}
return $cart_item;
}
function get_item_data( $item_data, $cart_item ) {
if ( ! empty( $cart_item['inputurl'] ) )
$item_data[] = array(
);
return $item_data;
}
function add_cart_item( $cart_item ) {
if ( ! empty( $cart_item['inputurl'] ) ) {
}
return $cart_item;
}
function add_order_item_meta( $item_id, $cart_item ) {
if ( ! empty( $cart_item['inputurl'] ) )
woocommerce_add_order_item_meta( $item_id, __( 'URL by buyer', 'custom_input_url' ), __( 'Yes', 'custom_input_url' ) );
}
Documentation about hook woocommerce_add_cart_item_data isn't very helpful and I'm stuck at this. How do I proceed?
There is a wordpress plugin called WC Fields Factory for the exact purpose.
You can also achieve this by using the following woocommerce hooks woocommerce_before_add_to_cart_button, woocommerce_add_to_cart, woocommerce_cart_item_name,and 'woocommerce_add_order_item_meta'
like for adding text field to product page
function add_name_on_tshirt_field() {
echo '<table class="variations" cellspacing="0">
<tbody>
<tr>
<td class="label"><label for="color">Name On T-Shirt</label></td>
<td class="value">
<input type="text" name="name-on-tshirt" value="" />
</td>
</tr>
</tbody>
</table>';
}
add_action( 'woocommerce_before_add_to_cart_button', 'add_name_on_tshirt_field' );
For displaying custom field on cart item table use the below
function render_meta_on_cart_item( $title = null, $cart_item = null, $cart_item_key = null ) {
if( $cart_item_key && is_cart() ) {
echo $title. '<dl class="">
<dt class="">Name On T-Shirt : </dt>
<dd class=""><p>'. WC()->session->get( $cart_item_key.'_name_on_tshirt') .'</p></dd>
</dl>';
}else {
echo $title;
}
}
add_filter( 'woocommerce_cart_item_name', 'render_meta_on_cart_item', 1, 3 );
to make your custom meta data on you order details, do some thing like this
function tshirt_order_meta_handler( $item_id, $values, $cart_item_key ) {
wc_add_order_item_meta( $item_id, "name_on_tshirt", WC()->session->get( $cart_item_key.'_name_on_tshirt') );
}
add_action( 'woocommerce_add_order_item_meta', 'tshirt_order_meta_handler', 1, 3 );
for detailed implementation, i have an article about how to do this without using any plugins. http://sarkware.com/how-to-pass-custom-data-to-cart-line-item-in-woocommerce-without-using-plugins/
It's easy. Try searching and reading code of Woocommerce.
This much of code got me to point where I can add Url # Cart. And I can see it in Order review as customer and as admin.
I can't test email because I'm lazy. I'm sorry.
Something like this goes in templates\cart\cart.php (there is need for some more code as it's seperate column)
<td class="product-url">
<?php
$html = sprintf( '<div class="url"><input type="text" name="cart[%s][url]" value="%s" size="4" title="Url" class="input-text url text" /></div>', $cart_item_key, esc_attr( $values['url'] ) );
echo $html;
?>
</td>
Functions.php
// get from session your URL variable and add it to item
add_filter('woocommerce_get_cart_item_from_session', 'cart_item_from_session', 99, 3);
function cart_item_from_session( $data, $values, $key ) {
$data['url'] = isset( $values['url'] ) ? $values['url'] : '';
return $data;
}
// this one does the same as woocommerce_update_cart_action() in plugins\woocommerce\woocommerce-functions.php
// but with your URL variable
// this might not be the best way but it works
add_action( 'init', 'update_cart_action', 9);
function update_cart_action() {
global $woocommerce;
if ( ( ! empty( $_POST['update_cart'] ) || ! empty( $_POST['proceed'] ) ) && $woocommerce->verify_nonce('cart')) {
$cart_totals = isset( $_POST['cart'] ) ? $_POST['cart'] : '';
if ( sizeof( $woocommerce->cart->get_cart() ) > 0 ) {
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
if ( isset( $cart_totals[ $cart_item_key ]['url'] ) ) {
$woocommerce->cart->cart_contents[ $cart_item_key ]['url'] = $cart_totals[ $cart_item_key ]['url'];
}
}
}
}
}
// this is in Order summary. It show Url variable under product name. Same place where Variations are shown.
add_filter( 'woocommerce_get_item_data', 'item_data', 10, 2 );
function item_data( $data, $cart_item ) {
if ( isset( $cart_item['url'] ) ) {
$data['url'] = array('name' => 'Url', 'value' => $cart_item['url']);
}
return $data;
}
// this adds Url as meta in Order for item
add_action ('woocommerce_add_order_item_meta', 'add_item_meta', 10, 2);
function add_item_meta( $item_id, $values ) {
woocommerce_add_order_item_meta( $item_id, 'Url', $values['url'] );
}
400$ is nice price.
You can do this fairly easily with the Woocommerce Product Add-ons plugin
From the WooThemes website:
Allow your customers to customise your products by adding new options
such as input boxes, dropdowns or checkboxes. With the Product Add-ons
extension, gift messages, donations, laser engraving and any other
product which may require user input in some way is now an option for
your customers!
Product add-ons supports required fields, textareas, checkboxes,
radios, select boxes, custom price inputs and file upload boxes.
I've used it before to add an additional donation field to a product purchase and display that on the thank you page/receipt email.
It's about $50 US and will get you up and running in no time to add the text input and display the field on thank you page/email like you want. $50 is definitely worth the amount of time you'd save drying to develop this feature yourself.
Here's the flow from the end-users perspective:
End user enters in field data and adds product to cart
When User views cart the data they entered into the custom field displays along with the product
After purchase, end user lands on thank you page and receives receipt email with field data included with the product item.
On the backend:
Create custom field for each product. The option is located on the Add-Ons menu tab.
Create a new Addon Group
Enter a group name (for easier organization)
Add a new option and enter the label (this is what the end user sees and is tied to the product)
Update/Publish product.
For completed orders, this is what you will see in the Order Details admin:
Hope this helps and saves you a ton of time in development!

Resources