I use woocommerce on wordpress. This is my code
<?php
global $woocommerce;
$items = $woocommerce->cart->get_cart();
foreach($items as $item => $values) {
$_product = $values['data']->post;
echo $_product->ID.',';
}
?>
And this is the result of teh code:
1297,1694,1297,3911,4999,
How can I get just last id '4999' ?
Storing the ids in an array and using the end() function would be a solution:
<?php
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$ids = array();
foreach($items as $item => $values) {
$_product = $values['data']->post;
$ids[] = $_product->ID;
}
echo 'Last item = ' . end($ids);
?>
You can do it even simpler that what Akhilesh proposed - instead of iterating through $items array go to the last item there:
end($items)['data']->post->ID;
I am not sure, but probably you would need PHP 5.3+ for that.
Related
On the Woocommerce order page, I have of items in the order, through which I want to loop and exclude a specific item by product id.
$order->get_order_number();
$items = $order->get_items();
foreach( $items as $key => $value) :
$exclude = $value->get_product_id();
if( in_array($exclude, array('3404') ) {
unset($items[$key]);
}
}
endforeach;
$new_items = array_values($items);
I thought this would loop through the original array, remove the $item whose $product_id == 3404 and then reindex.
I'm having no luck here. Any thoughts?
Solved ->
//Filter out colon cleanse duo
$items = array_filter($order->get_items(), function($item) {
return $item->get_product_id() != 3404;
});
//Randomize ids and grab one
shuffle($items);
foreach( $items as $item) :
$product_id = $item->get_product_id();
$product_name = $item->get_name();
break;
endforeach;
You should be able to do this:
$items = array_filter($order->get_items(), function($item) {
return $item->get_product_id() != 3404;
});
This iterates over $items and passes like a foreach each value to $item. If the callback of array_filter returns a true, the value will be kept else dropped.
You even can pass $order->get_items() directly in without fetching the items to an array.
Additionally if you require to exclude more than one, as asked in your comment, you can do like so:
$items = array_filter($order->get_items(), function($item) {
return !in_array($item->get_product_id(), [3404, 6890]);
});
I'm trying to get the SKU of all the products in my cart.
In the past i tried something similar with the product names. I did it like this:
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$product_names=array();
foreach($items as $item => $values) {
$_product = $values['data']->post;
$product_names[]=$_product->post_title;
}
Is there a way like this but instead of the title get the SKU of a product?
EDIT:
I tried Thoby's way like this :
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$product_names=array();
$productsku=array();
foreach($items as $item => $values) {
$_product = $values['data']->post;
$product_names[]=$_product->post_title;
$productsku[]= $_woo_product->get_sku();
}
But i get an error :
Fatal error: Call to undefined method WP_Post::get_sku()
Try :
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$product_names = array();
foreach($items as $item => $values) {
// Retrieve WC_Product object from the product-id:
$_woo_product = wc_get_product( $values['product_id'] );
// Get SKU from the WC_Product object:
$product_names[] = $_woo_product->get_sku();
}
The official WooCommerce API docs: wc_get_product()
I believe this might help you-
$_product->get_sku();
It works with product loops and you can use it inside your cart/checkout/etc..
I assume you already have access to $cart
$cart_items = $cart->get_cart_contents();
$skus = array();
foreach($cart_items as $cart_item) {
// Get WC_Product by Variation ID, if not avaiable use Product ID
$product = wc_get_product($cart_item["variation_id"] ? $cart_item["variation_id"] :
$cart_item["product_id"]);
// Add new SKU to array
array_push($skus, $product->get_sku());
}
The easiest way to get the SKU of a product when you have access to the cart items:
$cart = WC()->cart->get_cart();
foreach( $cart as $cart_item_key => $cart_item ){
$product = $cart_item['data'];
$product->get_sku();
}
I'm trying to extract item meta value from Woocommerce's orders by using:
$data = wc_get_order_item_meta( $item, '_tmcartepo_data', true );
However, I can't find a way to get order_item_id as the first parameter (using get_items)
global $woocommerce, $post, $wpdb;
$order = new WC_Order($post->ID);
$items = $order->get_items();
foreach ( $items as $item ) {
$item_id = $item['order_item_id']; //???
$data = wc_get_order_item_meta( $item_id, '_tmcartepo_data', true );
$a = $data[0]['value'];
$b = $data[1]['value'];
echo $a;
echo $b;
}
And I mean this order item_id (1 and 2)
Order_item_id in database - Image
How can I don that?
Thanks.
2018 Update:
Clarifying the answer with 2 possible cases
Added compatibility for woocommerce 3+
So There can be 2 cases:
1) Get product meta data (not set in order item meta data):
You will need to get the product ID in the foreach loop for a WC_Order and to get some metadata for this product you wil use get_post_meta() function ( but NOT wc_get_order_item_meta() ).
So here is your code:
global $post;
$order = wc_get_order( $post->ID );
$items = $order->get_items();
foreach ( $order->get_items() => $item ) {
// Compatibility for woocommerce 3+
$product_id = version_compare( WC_VERSION, '3.0', '<' ) ? $item['product_id'] : $item->get_product_id();
// Here you get your data
$custom_field = get_post_meta( $product_id, '_tmcartepo_data', true);
// To test data output (uncomment the line below)
// print_r($custom_field);
// If it is an array of values
if( is_array( $custom_field ) ){
echo implode( '<br>', $custom_field ); // one value displayed by line
}
// just one value (a string)
else {
echo $custom_field;
}
}
2) Get order item meta data (custom field value):
global $post;
$order = wc_get_order( $post->ID );
$items = $order->get_items();
foreach ( $order->get_items() as $item_id => $item ) {
// Here you get your data
$custom_field = wc_get_order_item_meta( $item_id, '_tmcartepo_data', true );
// To test data output (uncomment the line below)
// print_r($custom_field);
// If it is an array of values
if( is_array( $custom_field ) ){
echo implode( '<br>', $custom_field ); // one value displayed by line
}
// just one value (a string)
else {
echo $custom_field;
}
}
If the custom field data is an array, you can access the data in a foreach loop:
// Iterating in an array of keys/values
foreach( $custom_field as $key => $value ){
echo '<p>key: '.$key.' | value: '.$value.'</p>';
}
All code is tested and works.
Reference related to data in orders:
How to get WooCommerce order details (also for woocommerce 3)
Get Order items and WC_Order_Item_Product in Woocommerce 3
When doing the foreach on $order->get_items(), their key is actually the orderline ID. So:
foreach ( $order->get_items() as $key => $item ) {
$data = wc_get_order_item_meta( $key, '_tmcartepo_data' );
...
}
Late to the party, but being working with the same point with TM Extra Product Options plugin, I think this is what answers your question:
$order = wc_get_order( $post->ID );
$items = $order->get_items();
foreach( $items as $item ){
$data = unserialize($item['item_meta']['_tmcartepo_data'][0]);
$a = $data[0]['value'];
$b = $data[1]['value'];
echo $a;
echo $b;
}
Tested and works in my case.
Use this <pre><?php print_r($items); ?></pre> to check all the contents of the $items array/object.
foreach ( $order->get_items() as $key => $item ) {
$data = wc_get_order_item_meta( $key, '_tmcartepo_data' );
...
This solution was worth to me, change "_tmcartepo_data" for your meta_key.
A simple way to get order items from database;
/**
* #param $order_id
*
* #return array|null|object
*/
function get_order_items( $order_id ) {
global $wpdb, $table_prefix;
$items = $wpdb->get_results( "SELECT * FROM `{$table_prefix}woocommerce_order_items` WHERE `order_id` = {$order_id}" );
$item_name = array();
foreach ( $items as $item ) {
$item_name[] = $item->order_item_name;
}
return $item_name;
}
I am want to get the category of the items in the cart at the checkout in WooCommerce. I want to extract it and then place it in a field in my custom checkout.
I'm using WooCommerce MultiStep Checkout Wizard premium plugin and a specific hook:
add_action('woocommerce_multistep_checkout_before_order_info', 'destinationStep');
I'm a little lost and can't find much documentation for what I need to use to get it.
I'm trying to just get items to appear but I just get an empty array.
$order = new WC_Order( $order_id );
$items = $order->get_items();
var_dump($items);
You could try first with your approach "new WC_Order( $order_id );", this way:
function destinationStep( $order_id )
global $woocommerce;
$order = new WC_Order( $order_id );
$items = $order->get_items();
// echo var_dump($items);
//----
foreach ($items as $key => $item) {
$product_name = $item['name'];
$product_id = $item['product_id'];
$terms = get_the_terms( $product_id, 'product_cat' );
// echo var_dump($terms);
foreach ( $terms as $term ) {
// Categories by slug
$product_cat_slug= $term->slug;
}
}
add_action('woocommerce_multistep_checkout_before_order_info', 'destinationStep', 10, 1);
If it still doesn't work try with "new WC_Order($post->ID)" approach:
function destinationStep()
global $woocommerce, $post;
$order = new WC_Order($post->ID);
$items = $order->get_items();
// echo var_dump($items);
//----
foreach ($items as $key => $item) {
$product_name = $item['name'];
$product_id = $item['product_id'];
$terms = get_the_terms( $product_id, 'product_cat' );
// echo var_dump($terms);
foreach ( $terms as $term ) {
// Categories by slug
$product_cat_slug= $term->slug;
}
}
add_action('woocommerce_multistep_checkout_before_order_info', 'destinationStep');
Update - After some thought:
You can't get the order Id for `'post_type' => 'shop_order', because it doesn't exist yet. This order ID is generated when customer submit the order, but not before on checkout page.
So in this case, it's normal to get an empty array.
I am trying to get the results from my Foreach in another echo way later then the foreach but I am stuck, any help would be much appericated.
$items = $order->get_items();
// Output the loop
foreach ($order->get_items() as $item) {
// Getting some information
$product_qty = $item['qty'];
$product_variation_id = $item['variation_id'];
$product = new WC_Product($item['product_id']);
// SKU
$SKU = $product->get_sku();
print_r($SKU);
print_r($product_qty);
print_r(' ');
}
// this gives all 3 quantities and all 3 sku, added a space at the end for easier reading
// this only gives the 1st entry of both variables but i need all 3 of both variables
echo '<a href="https://www.domainname.someurl'.$product_quantity .$SKU . '" target=_blank>';
echo "<p>TEXT</p></a>";
I hope it is clear like this, thanks
Well, you're overwriting the value of $SKU and product_qty on each iteration, maybe try storing them in an array? Like create an array outsite the loop and use array_push(created_array, array($SKU, $product_qty)). Hope it helps.
$items = $order->get_items();
$push = array();
// Output the loop
foreach ($order->get_items() as $item) {
// Getting some information
$product_qty = $item['qty'];
$product_variation_id = $item['variation_id'];
$product = new WC_Product($item['product_id']);
// SKU
$SKU = $product->get_sku();
array_push($push, array('sku'=>$SKU, 'qty'=>$product_qty));
print_r($SKU);
print_r($product_qty);
print_r(' ');
}
// this gives all 3 quantities and all 3 sku, added a space at the end for easier reading
// this only gives the 1st entry of both variables but i need all 3 of both variables
$link = '<a href="https://www.domainname.someurl';
for ($i=0;$i<count($push);$i++){
$link .= $push[$i]['qty'];
$link .= $push[$i]['sku'];
}
$link .= '" target=_blank>';
echo $link;
Try the below code
$items = $order->get_items();
// Output the loop
$product_qty_string = '';
$sku_string = '';
foreach ($order->get_items() as $item) {
// Getting some information
$product_qty_string .= $item['qty']."-";
// SKU
$SKU = $product->get_sku();
$sku_string .=$SKU."-";
}
$product_quantity = rtrim($product_qty_string,'-');
$SKU = rtrim($sku_string,'-');
echo '<a href="https://www.domainname.someurl'.$product_quantity.''.$SKU.''" target=_blank>';
echo "<p>TEXT</p></a>";
Why don't you add your values in a array and then implode them.
$items = $order->get_items();
// Output the loop
$SKU = $product_qty = [];
foreach ($order->get_items() as $item) {
// Getting some information
$product_qty[] = $item['qty'];
$product_variation_id = $item['variation_id'];
$product = new WC_Product($item['product_id']);
// SKU
$SKU[] = $product->get_sku();
print_r($SKU);
print_r($product_qty);
print_r(' ');
}
$sku_string = implode('-', $SKU);
$product_qty_string = implode('-', $product_qty);
echo '<a href="https://www.domainname.someurl'.$product_qty_string .$sku_string . '" target=_blank>';
echo "<p>TEXT</p></a>";
You can implode your data with any separator you want, i use "-" for my example but its depending on your needs.