Woocommerce Get Attribute value in cart page - wordpress

I have a product where it has custom attribute(delivaryDate is attribute name) but no variations are created with it.
On the product page, the attribute is selected.
On the cart page, I am able to retrieve data on all attributes where it has variations. But the attribute where variations are not created cannot be retrieved.
Code used :
foreach ( WC()->cart->get_cart() as $cart_item ) {
$item_data = $cart_item['data'];
echo $item_data;
}
Screenshot of dump for reference.
So is a way to retrieve all attributes values even variation not created with those attributes.
I am looking to get attributeName1_attaributeName2 as a value from each product on cart. Any help would be appericated.
Thanks in advance.

When working with WooCommerce, it is always preferred to use their methods.
For getting attributes this would be, continuing as from $cart_item['data']; that you already have
// Get the product object for the cart item
$product = $cart_item['data'];
// Get the product attributes
$attributes = $product->get_attributes();
// Iterate through each attribute
foreach ( $attributes as $attribute ) {
// Get the attribute name only
$attribute_name = $attribute->get_name();
// If you want to print the attribute name too
echo $attribute_name;
}

Related

Struggling to get product attribute for variable product

I'm currently having an issue with WooCommerce that randomly a product attribute is or is not written to the database. Result is that in the order for some items I can't see the attributes. Hence, I thought about having an intermediate solution by dumping the cart into an email to ourselves as soon as the customer hits the "order now" button.
But doing so, I'm struggling to get the attributes right.
We're selling coffee for which I have 2 attributes: coffee_bag_size and coffee_ground_for. Both attributes are set for variations, but I have created 2 only variations based on coffee_bag_size (for 250 grammes and 500 grammes bag) with different prices whereas the coffee_ground_for can be any value. I just have to know what the customer chooses.
I read in another post that in case an attribute is not used in variations, one has to get it from the parent, so I did:
foreach ( WC()->cart->get_cart() as $cart_item )
{
$product = $cart_item['data'];
$bagsize = $product->get_attribute('pa_coffee_bag_size') ;
// For Product Variation type
if( $product->get_variation_id() > 0 )
{
$parent = wc_get_product($product->get_parent_id());
$ground = $parent->get_attribute('pa_coffee_ground_for') ;
}
// For other Product types
else
{
$ground = $product->get_attribute('pa_coffee_ground_for') ;
}
}
Getting the coffee_bag_size attribute is no problem.
Getting the coffee_ground_for is the problem. If I get it from the product it's empty, if I get it from the parent then I get a comma-separated list of all possible values. But I only need the value that was chosen. How do I do that?
I tried a few things more .... they all give me an empty string back:
$ground = $product->get_meta('pa_coffee_ground_for',true);
$ground = $cart_item['variation']['pa_coffee_ground_for'];
$attributes = $product->get_attributes();
foreach ( $attributes as $attribute => $attribute_term )
{
$term = get_term_by('name','pa_coffee_ground_for', $attribute);
$ground = $term->term;
}
Check out slug of you attribute it may be 'pa_coffee-ground-for'
$product = $cart_item['data'];
if( $product->is_type( 'variation' ) )
{
$product = wc_get_product($product->get_parent_id());
}
$ground = $product->get_attribute( 'pa_coffee-ground-for' );
Tested and working

How to display the last ordered product in WooCommerce via a shortcode

I'm looking for a way to display the last ordered product on another page.
I think it would be possible to maybe create a shortcode in the functions that takes the order details and displays them wherever I add the shortcode.
But I can't seem to figure out how to get it to work. So far I got this information to work with:
add_shortcode( 'displaylast', 'last' );
function last(){
$customer_id = get_current_user_id();
$order = wc_get_customer_last_order( $customer_id );
return $order->get_order();
}
[displaylast] is currently showing me noting. It does work when I change get_order() to get_billing_first_name().
That displays the order name. But I can't seem to get the item that was bought. Maybe there is a get_() that I'm not seeing?
You are close, however you must obtain the last product from the order object.
So you get:
function last() {
// Not available
$na = __( 'N/A', 'woocommerce' );
// For logged in users only
if ( ! is_user_logged_in() ) return $na;
// The current user ID
$user_id = get_current_user_id();
// Get the WC_Customer instance Object for the current user
$customer = new WC_Customer( $user_id );
// Get the last WC_Order Object instance from current customer
$last_order = $customer->get_last_order();
// When empty
if ( empty ( $last_order ) ) return $na;
// Get order items
$order_items = $last_order->get_items();
// Latest WC_Order_Item_Product Object instance
$last_item = end( $order_items );
// Get product ID
$product_id = $last_item->get_variation_id() > 0 ? $last_item->get_variation_id() : $last_item->get_product_id();
// Pass product ID to products shortcode
return do_shortcode("[product id='$product_id']");
}
// Register shortcode
add_shortcode( 'display_last', 'last' );
SHORTCODE USAGE
In an existing page:
[display_last]
Or in PHP:
echo do_shortcode('[display_last]');

How to use an already existing product attribute and not create a new one with WC_Product_Attribute class in WooCommerce?

I am trying to create a Wordpress plugin that creates variable products programmatically, but the problem is, I would like to use attributes I have previously defined manually from the admin dashboard. I need to assign the attribute to the the product I'm creating.
Here is the code that I am using (not mine, I got it from this answer: Create programmatically a variable product and two new attributes in WooCommerce):
function addProduct(){
//Create main product
$product = new WC_Product_Variable();
//Create the attribute object
$attribute = new WC_Product_Attribute();
//pa_size tax id
$attribute->set_id( 0 ); // -> SET to 0
//pa_size slug
$attribute->set_name( 'Couleur' ); // -> removed 'pa_' prefix
//Set terms slugs
$attribute->set_options( array(
'Noir'
) );
$attribute->set_position( 0 );
//If enabled
$attribute->set_visible( 1 );
//If we are going to use attribute in order to generate variations
$attribute->set_variation( 1 );
$product->set_attributes(array($attribute));
//Save main product to get its id
$id = $product->save();
$variation = new WC_Product_Variation();
$variation->set_regular_price(10);
$variation->set_parent_id($id);
//Set attributes requires a key/value containing
// tax and term slug
$variation->set_attributes(array(
'Couleur' => 'Noir' // -> removed 'pa_' prefix
));
//Save variation, returns variation id
echo get_permalink ( $variation->save() );
// echo get_permalink( $id ); // -> returns a link to check the newly created product
}
The product is correctly created, but the code creates a new attribute and calls it "Couleur" instead of using my already defined "Couleur" attribute.
Thanks in advance.
Thanks to Vincenzo Di Gaetano, the problem was solved.
Here's the working code:
function add_product(){
//Create main product
$product = new WC_Product_Variable();
//Create the attribute object
$attribute = new WC_Product_Attribute();
// get a product attribute ID by name.
$attribute_id = wc_attribute_taxonomy_id_by_name( 'Couleur' );
$attribute->set_id( $attribute_id );
//pa_size slug
$attribute->set_name( 'pa_couleur' ); // -> removed 'pa_' prefix
//Set terms slugs
$attribute->set_options( array(
'noir'
) );
$attribute->set_position( 0 );
//If enabled
$attribute->set_visible( 1 );
//If we are going to use attribute in order to generate variations
$attribute->set_variation( 1 );
$product->set_attributes(array($attribute));
//Save main product to get its id
$id = $product->save();
$variation = new WC_Product_Variation();
$variation->set_regular_price(10);
$variation->set_parent_id($id);
//Set attributes requires a key/value containing
// tax and term slug
$variation->set_attributes(array(
'pa_couleur' => 'noir' // -> removed 'pa_' prefix
));
//Save variation, returns variation id
echo get_permalink ( $variation->save() );
// echo get_permalink( $id ); // -> returns a link to check the newly created product
}
WooCommerce allows you to use global attributes and product-level (local or custom) attributes.
Global attributes are available for all products. When you delete a term for that attribute, it will be removed for all products that use that attribute with that term. Conversely, when you add a new term it will be available for all other products.
Global attributes you will find them in Wordpress Dashboard > Products >
Attributes.
While the product-level (local or custom) attribute is only defined for that product and will not be available for others.
The product-level attributes will only be found within the product
edit page in the "Attributes" section.
You can find more detailed information here:
Managing Product Attributes in WooCommerce
Product Variations: Global or local attributes – why use one vs other
SOLUTION
Programmatically you will need to add the prefix pa_ to each attribute slug.
Also you are setting the id to zero: $attribute->set_id( 0 ); but by doing this you are setting a product-level (and not global) attribute. You will need to change this line to:
// get a product attribute ID by name.
$attribute_id = wc_attribute_taxonomy_id_by_name( 'Couleur' );
$attribute->set_id( $attribute_id );
Instead of using this answer you should use this.
USEFUL LINK
Create programmatically a variable product and two new attributes in WooCommerce

Display Woocommerce variable product dimensions

Have Woocommerce setup with a range of variable products. In the variable tab I've setup a unique price, image, description, weight & dimensions for each item.
All variable data displays as expected on the front-end except the dimensions & weight.
Despite hours of searching, I cannot find any documentation, tutorials, hints on how to hook into it.
Have Woocommerce templates setup and know that I will need to hook into the do_action( 'woocommerce_single_variation' ); in variable.php.
Anyone know how to get each variable's dimensions & weight to display beneath the variable description?
If you have the variation ID, you can use it to create a new WC_Product(). This object will then have properties available on it for the $length, $width, and $height. See the docs here (at the bottom under "Magic Properties").
To get the variations for a given product, you can use the global $product and then the get_available_variations() function.
global $product
$variations = $product->get_available_variations();
foreach ( $variations as $variable_array ){
$variation = new WC_Product( $variable_array['variation_id'] );
echo "The length is {$variation->length}.";
}
If you want to display additional information regarding your variable product add this function to your child theme’s function.php (or plugin). You’ll probably want to alter the html tags to fit your theme:
add_filter( 'woocommerce_product_additional_information', 'tim_additional_tab', 9 );
function tim_additional_tab( $product ){
$variations = $product->get_available_variations();
//print the whole array in additional tab and examine it
//echo '<pre>';
//print_r($variations);
//echo '</pre>';
//html and style to your likings
foreach ( $variations as $key ){
echo $key['image']['title'].'<br>';
echo $key['weight_html'].'<br>';
echo $key['dimensions_html'].'<br>';
}
}

Get Item/Product Attribute in WooCommerce Order

I'm trying to get Item or Product Attribute in WooCoomerce Order.
How can I get it?
$order = new WC_Order( $order_id );
$items = $order->get_items();
foreach ( $items as $item ) {
$pid = $item['product_id'];
$patt = $pid->get_attribute( 'pa_myattrname' );
echo $patt;
}
Later, I want to insert autoresponder link on attribute, so that after user complete payment, they will automatically subscribed into my autoresponder.
Thank you
I know that it is old question, but that answer may help someone who is looking for nicer option.
There is much simpler way to get product attributes from order. You just need to go into products (items) and then load meta data
// at first get order object
$order = wc_get_order($orderId);
// iterate through order items/products
foreach ($order->get_items() as $item) {
// load meta data - product attributes
foreach ($item->get_meta_data() as $metaData) {
$attribute = $metaData->get_data();
// attribute value
$value = $attribute['value'];
// attribute slug
$slug = $attribute['key'];
}
}
$item['product_id']; will return the integer product_id, you cannot call get_attribute method on it. Using the integer product_id you need to create a Product object and then call the method
$pid = $item['product_id']; // returns the product id
$p = new WC_Product( $pid ); // create an object of WC_Product class
$patt = $p->get_attribute( 'pa_myattrname' ); // call get_attribute method
echo $patt;

Resources