Is it possible to add a unique name to a specific product when it's added to the shopping cart using the woocommerce API?
For example suppose I sell pets. The user decides he wants a dog named spot. He then clicks on a particular dog breed (the product) say border collie and that product should appear in the shopping cart as a border collie named spot.
To answer your question, yes. You can change things in your own code by adding filters. So for example, say you want to change the name of the product in the cart. In wp-content/plugins/woocommerce/templates/cart/cart.php there is a filter called 'woocommerce_cart_item_name' where the title is outputted. You can modify this in your own code like so:
function your_function( $title, $cart_item, $cart_item_key ){
/*code to modify title*/
return $title;
}
add_filter('woocommerce_cart_item_name','your_function',10,3);
You could add this to the functions.php of your theme.
How you get the name spot in this function depends on your situation.
Read more about filters at https://codex.wordpress.org/Function_Reference/add_filter
Related
I am using both WooCommerce (WC) and Modern Events Calendar (MEC). I am trying to display a list view of the MEC events on a corresponding WC product page. As there is no connecting between these two instances it will need some creativity to get to work.
The WC product pages won't be changing a lot in the future so I figured I'd use the product ID. Then every event I make in MEC, I tag with the WC product ID. Then on the frontend I have the MEC shortcode (the list view widget) filter it's output on the WC product ID. Sounds simple enough but I have not been able to figure out how I can get it to work.
In my quest to archive this I have created a shortcode in MEC and changed the filter setting to filter by tag with the following variable [prod_id] after I created this shortcode in the functions file:
function product_id_shortcode() {
global $product;
$id = $product->get_id();
return $id;
}
add_shortcode( 'prod_id', 'product_id_shortcode' );
Unfortunately this did not give the expected result, so I assume filtering by [prod_id] is not being accepted. Any help would be greatly appreciated!
First of all, thank you for your support all those years.
I am building a role-based pricing plugin for a client and I am having an existential crisis over filters WooCommerce uses for prices. I made this post in hope someone can explain this so someone in the future can find this post.
I managed to understand how filters for simple products work but I don't have an idea how equivalent filters for variable products work
Simple products
As from what I understood, you can override price, regular price, and sale price for simple products returning some value inside filters woocommerce_product_get_price, woocommerce_product_get_regular_price, and woocommerce_product_get_sale_price. Those filters will save provided data into $product object and you can easily access them later in woocommerce_get_price_html filter by using $product->get_regular_price
Variable products
Looks like variable products work differently. For example, they dont save overriden price to $product or $variation object and you cannot fetch overriden prices by calling $variation->get_regular_price.
As I understood, following filters change price of the product on add-to-cart variation select, and in the cart and do not save them in $variation object.
woocommerce_product_variation_get_price
woocommerce_product_variation_get_regular_price
woocommerce_product_variation_get_sale_price
I didnt manage to fully understand what following filters do. But when I turn them on loop price changes and product price changes but prices are removed from add-to-cart select and cart prices are not changed.
woocommerce_variation_prices_price
woocommerce_variation_prices_regular_price
woocommerce_variation_prices_sale_price
In WooCommerce variable product, there are attributes and attribute values, which create variations.
E.g. :
Attribute: 1 (Size) | Values: XS/S/M/L/XL
Attribute: 2 (Style/Color) | Values: Red/Green/Blue/Black/...
Attribute: 3 (Fabric) | Cotton/Polyester/Some other stuff...
Let's assume you have 1 picture per style value.
Let's also assume you have 500 total variations (due to triple attributes, which stacks).
Is there a simple way to associate a single picture per "ATTRIB2 VALUE" so you don't have to manually edit every single picture from variations?
100 products with 500 single variations seems like a lot of monkey work, there has to be a better way.
Edit:
1 picture for ALL blue variations;
1 picture for all red variations...
etc...
Side-question: Is there a way to use the bulk "Set Regular Price" to apply to ALL variations instead of only the ones on active "page"?
The following works for me in my test installation:
/**
* Replace Woocommerce Product Variation Images
* based on variation slug
*/
add_filter( 'woocommerce_product_variation_get_image_id', 'so_filter_wooc_product_variation_images', 10, 2 ) ;
function so_filter_wooc_product_variation_images( $image_id, $data ) {
//the variation product slug includes "-black"...
if ( strpos( $data->slug, '-black') ) {
//replace with new image by id number
return $new_image_id ;
}
//else return the image_id according to default settings
return $image_id ;
}
Now, you don't have search the product slug as I have done here, necessarily: There are other variables that, depending in part on your installation design, may distinguish one set of variable products from another. By default, however, the product slug for a product variation will combine the attribute terms. So, if your product is "Test Product"; you have two sizes, "Big" and "Small," and two colors, "Black" and "White"; they're enabled to produce variations; and the variations are priced (which is required), you'll get product slugs in the format test-product-big-black and test-product-big-white, and so on, so this seems like a sound method for achieve approximately what you want, focused on the attribute.
It's not, however, a foolproof method: if the attribute name occurs in the item title, then there's some chance of occasional overlap - for, say, a product with the title "Test Black Product." How to solve this issue programmatically is, obviously, a more complicated question: The function I've provided here still illustrates the general concept.
As for $new_image_id_number, you could get that in various different ways, so I've left that open. For example, you could just find the attachment ID by hovering over the image you want to use in the Media Library. Alternatively, you could create a site option - the old-fashioned away or maybe with Advanced Custom Fields Pro - and extract the ID from an image upload.
Anyway, this working solution turns out to be fairly simple. The filter hook is based on the protected function in abstract-wc-data.php...
$value = apply_filters( $this->get_hook_prefix() . $prop, $value, $this );
...which is constructed from the "hook prefix," in this case woocommerce_product_variation_, and the property in question, in this case image_id.
(I was initially confused when, viewing the product variation class, I found a filter with a similar structure that essentially duplicates the functionality for certain cases that don't apply here.)
As mentioned above I want to display "product added to cart message" in woocommerce.
I know there is some kind of built in function
wc_add_to_cart_message()
If I paste it in index page together with
wc_print_notices();
Like this:
wc_add_to_cart_message('products');
wc_print_notices();
wc_add_to_cart_message('products');
wc_print_notices();
then my current output is:
“” has been added to your cart.
My desired output is that it would return that particular product name together with a message.
but what would be the proper way of using it?
Or is there some other way?
In that function you actually have to give product id or array of product ids, so your line should look like:
wc_add_to_cart_message($product_id);
I have a digital product which is described by a quantity and a price, but which also needs 3 more numbers to completely specify it (Unix dates, etc). Problem: how do I get these numbers into the cart?
As far as I can see, there are 2 possible ways to handle this:
A product variation
A product custom field
It looks like variations can only handle discrete values with a limited range (ie. red/yellow/green, S/M/L, etc), and can't handle general integers, like dates. That leaves custom fields. I think I'm right in saying that custom fields are ordinary meta data on the product post page, so I can handle them with get_post_meta and update_post_meta.
So, if I go for custom fields, then I would update the product page field during ordering, and then I would read back the field during checkout, when the WC_Order is created, and add the field to the new order. However, this won't work. I can't change metadata on the product page, because the product is global to all customers, and this operation would interfere with other customers. In other words, you can't store order-specific information in a product, so neither of these options would work.
So, how do I store temporary product metadata and pass it between the ordering and checkout phases (ie. between WC_Cart and WC_Order)?
One option would be to store it as user metadata (or as session data?), but there's got to be a better way - any ideas?
It turns out to be easy to do this with session data. When you're adding an item to the cart (see the source for add_to_cart_action) you create a session variable, containing all your additional meta data:
WC()->session->set(
'my_session_var_name',
array(
'members' => $members,
'start' => $start,
'expiry' => $expiry,
'etc' => $etc));
When the user checks out, the cart data disappears, and a new order is created. You can hook into woocommerce_add_order_item_meta to add the session meta data to the order meta data:
add_action(
'woocommerce_add_order_item_meta', 'hook_new_order_item_meta', 10, 3);
function hook_new_order_item_meta($item_id, $values, $cart_item_key) {
$session_var = 'my_session_var_name';
$session_data = WC()->session->get($session_var);
if(!empty($session_data))
wc_add_order_item_meta($item_id, $session_var, $session_data);
else
error_log("no session data", 0);
}
That's it. You do have to figure out how to get the order metadata out and do something useful with it, though. You may also want to clear the session data, from hooks into woocommerce_before_cart_item_quantity_zero, and woocommerce_cart_emptied. There's gist here which has some example code for this.