I am working on a plugin for woocommerce and came across the hook "woocommerce_variation_price_html" which allows you to hook into the variation prices drop down on single products. So created a quick function to test and have a play:
add_action( 'woocommerce_variation_price_html' , 'wholesale_variation_price' );
function wholesale_variation_price($term){
return '';
}
The above works nicely and removes all data. However i am trying to add custom meta_data to replace the default values.
So i then did the following:
add_action( 'woocommerce_variation_price_html' , 'wholesale_variation_price' );
function wholesale_variation_price($term){
$var_price = get_post_meta( get_the_id(), '_my_price', true );
return $var_price;
}
This for some reason does not work? Has anyone had any experience working with this hook in woocommerce? There is not much documentation on that hook anywhere.
Any help would be greatly appreciated!
As already indicated that you can read here about filters for html.
Maybe you have Sale price set for variation? Then in link you can see that there are total of 4 filters. For: price, sale price, free and no price.
This code works
add_filter( 'woocommerce_variation_sale_price_html', 'my_html', 10, 2);
add_filter( 'woocommerce_variation_price_html', 'my_html', 10, 2);
function my_html( $price, $variation ) {
return woocommerce_price(5);
}
Also this one works too. This allows you to modify whole variation. Read in code here
add_filter( 'woocommerce_available_variation', 'my_variation', 10, 3);
function my_variation( $data, $product, $variation ) {
$data['price_html'] = woocommerce_price(6);
return $data;
}
Screenshots:
First example
Second example
Works like magic!
P.S. you can see prices like this in screenshots because I have design that show them like that.
EDIT 2016-09-10
Version 2.6+
As woocommerce_price is deprecated in 2.6 then use wc_price for newer versions.
// Display Price For Variable Product With Same Variations Prices
add_filter('woocommerce_available_variation', function ($value, $object = null, $variation = null) {
if ($value['price_html'] == '') {
$value['price_html'] = '<span class="price">' . $variation->get_price_html() . '</span>';
}
return $value;}, 10, 3);
By looking at WooCommerce source code, I see that woocommerce_variation_price_html is a filter, not an action. I don't know how you managed to get your sample code to work like that... weird.
Try this:
function wholesale_variation_price( $price, $product ) {
$var_price = get_post_meta( $product->variation_id, '_my_price', true );
return $var_price;
}
add_filter( 'woocommerce_variation_price_html', 'wholesale_variation_price', 10, 2 )
I used this to modify the variation prices to show the price for each variation product excluding tax before and including tax after :)
add_filter( 'woocommerce_available_variation', 'my_variation', 10, 3);
function my_variation( $data, $product, $variation ) {
$data['price_html'] = "<span class='ex-vat-price'>ex. " . woocommerce_price($variation->get_price_excluding_tax()) . "</span><br>";
$data['price_html'] .= "<span class='inc-vat-price'>inc. " . woocommerce_price($variation->get_price_including_tax()) . "</span>";
return $data;
}
Related
I’m trying to modify the word “reservado” or “backordered” in the order details page.
I use the following code, unfortunately without the desired result. The "backordered" text does not change, any advice?
function custom_backorder_message( $text, $product ){
if ($product->is_on_backorder( 0 ) ) {
$text = __( 'This item may take 3-4 weeks to deliver' );
}
return $text;
}
add_filter( 'woocommerce_get_availability_text', 'custom_backorder_message', 10, 2 );
If you want to change it via code you can use the woocommerce_backordered_item_meta_name filter hook.
So you get:
function filter_woocommerce_backordered_item_meta_name( $string, $item ) {
// Replace with new text
$string = 'My new text';
return $string;
}
add_filter( 'woocommerce_backordered_item_meta_name', 'filter_woocommerce_backordered_item_meta_name', 10, 2 );
But you could also change it in the language file.
I am working in Wordpress Multisite and trying to ensure that all the stock info is fetched from the base site tables. I am trying to overwrite get_stock_quantity() woocomerce function in my theme's functions.php. What i found was
public function get_stock_quantity( $context = 'view' ) {
return $this->get_prop( 'stock_quantity', $context );
}
Now this is neither a filter nor an action. I overwrote one filter that is
add_filter( 'woocommerce_product_get_stock_quantity', 'wcs_custom_get_stock_quantity', 1, 2);
function wcs_custom_get_stock_quantity( $availability, $_product ) {
global $wpdb;
$productQuantity = $wpdb->get_results( 'SELECT * FROM '.$wpdb->base_prefix.'postmeta WHERE post_id = '.$_product->get_id() ." AND meta_key = '_stock'", OBJECT );
return $productQuantity[0]->meta_value;
}
But woocommerce_product_get_stock_quantity only works on the Products List page. The individual product-edit page uses get_stock_quantity.
How can I overwrite it without changing Core files?
Thanks
The correct way to alter get_stock_quantity() method depends on the product. AS you have already notice looking at the source code you see that:
return $this->get_prop( 'stock_quantity', $context );
Now get_prop() method is a part of WC_Data class and has a generic filter hook:
$value = apply_filters( $this->get_hook_prefix() . $prop, $value, $this );
And if you look to get_hook_prefix() method you have this:
return 'woocommerce_' . $this->object_type . '_get_';
For product variations the object_type is: product_variation
For other products the object_type is: product
The $prop argument is stock_quantity
So know you can built the related filter hooks. Try this:
add_filter( 'woocommerce_product_get_stock_quantity' ,'custom_get_stock_quantity', 10, 2 );
add_filter( 'woocommerce_product_variation_get_stock_quantity' ,'custom_get_stock_quantity', 10, 2 );
function custom_get_stock_quantity( $value, $product ) {
$value = 15; // <== Just for testing
return $value;
}
So for product variations you use woocommerce_product_variation_get_stock_quantity filter hook.
And for the other cases woocommerce_product_get_stock_quantity filter hook
You can update the database, but remember this code is executed one time each time you list your products, and when you update your product
add_filter( 'woocommerce_product_get_stock_quantity' ,'custom_get_stock_quantity', 10, 2 );
add_filter( 'woocommerce_product_variation_get_stock_quantity' ,'custom_get_stock_quantity', 10, 2 );
function custom_get_stock_quantity( $value, $product ) {
$value = 15; // <== Just for testing
//update dabatabase:
update_post_meta( $product->get_id(), '_stock', $value );
return $value;
}
From what I understand you can use $product->set_stock($value); as well to set the value in database
add_filter( 'woocommerce_product_get_stock_quantity' ,'custom_get_stock_quantity', 10, 2 );
add_filter( 'woocommerce_product_variation_get_stock_quantity' ,'custom_get_stock_quantity', 10, 2 );
function custom_get_stock_quantity( $value, $product ) {
$value = 15; // <== Just for testing
//update dabatabase:
$product->set_stock($value);
return $value;
}
I found this 2 filters for WooCommerce to extend the membership plan list:
add_filter( 'manage_edit-wc_user_membership_columns', array( $this, 'customize_columns' ) );
add_filter( 'manage_edit-wc_user_membership_sortable_columns', array( $this, 'customize_sortable_columns' ) );
I want to add a new column with the memberships plan id to show.
any suggestion on how to use that in the functions.php
You found the correct filter manage_edit-wc_user_membership_columns – it allows to add a column in membership plans, example:
add_filter( 'manage_edit-wc_user_membership_columns', 'my_add' );
function my_add( $columns ) {
$columns['id_of_the_plan'] = 'Memberships plan id';
return $columns;
}
Once you insert this code in your current theme functions.php file or in a custom plugin, the column will appear. Now it is time to add the data to it. manage_posts_custom_column will help with it.
add_action( 'manage_posts_custom_column', 'my_id' );
function my_id( $column ) {
if( $column == 'id_of_the_plan' ) {
$m = wc_memberships_get_user_membership( get_the_ID() );
echo $m->plan_id;
}
}
The original code is taken from this example.
I have a change_flat_rates_cost() function, but it works only when loading the page. but it is necessary for me that function worked at each change of the field "city", (in checkout fields).
I have tried to use ajax function and to call there add_filter() function, but it doesn't help.
I do it to change delivery cost without reset of the page depending on the chosen city
change_flat_rates_cost function (changes the shipping price)
function change_flat_rates_cost($rates, $package) {
$userid = get_current_user_id();
$meta_city = get_user_meta( $userid, 'billing_city', true );
if ( isset( $rates['shipping_method_1'] ) ) {
if ($meta_city == 'City1'){
$rates['shipping_method_1']->cost = 100;
}
if ($meta_city == 'City2'){
$rates['shipping_method_1']->cost = 200;
}
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'change_flat_rates_cost', 10, 2 );
ajax function:
add_action( 'wp_ajax_change_shipping', 'change_shipping' );
add_action( 'wp_ajax_nopriv_change_shipping', 'change_shipping' );
function change_shipping() {
global $woocommerce;
add_filter( 'woocommerce_package_rates', 'change_flat_rates_cost', 10, 2 );
die();
}
You can add filter as normal "add_filter". No need to put it there in ajax, because anyways there are conditions mentioned in your function.
So, do add_filter normally and instead of using add_filter in ajax function, you should use "apply_filters". This will call your custom shipping function.
I hope I've made it clear.
Does anybody know how to disable the Postcode validation on the checkout page in WooCommerce?
My country is set up as Switzerland, but I want also people from Austria and Germany allow to order.
So when I enter a German Postcode with 5 digits (in Switzerland there are only 4), the shop says it's an invalid postcode. (but in the settings I allowed every country).
Any idea how to fix that?
Adding this code to the functions.php file should work:
function custom_override_default_address_fields( $address_fields )
{
unset( $address_fields['postcode'] );
return $address_fields;
}
EDIT:
// Hook into the checkout fields (shipping & billing)
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
// Hook into the default fields
add_filter( 'woocommerce_default_address_fields' , 'custom_override_default_address_fields' );
function custom_override_checkout_fields( $fields )
{
unset( $fields['billing']['billing_postcode'] );
unset( $fields['shipping']['shipping_postcode'] );
return $fields;
}
function custom_override_default_address_fields( $address_fields )
{
unset( $address_fields['postcode'] );
return $address_fields;
}
ANOTHER EDIT:
add_filter( 'woocommerce_default_address_fields' , 'custom_override_default_address_fields' );
function custom_override_default_address_fields( $address_fields )
{
$address_fields['postcode']['required'] = false;
return $address_fields;
}
So I didn't actually find a simple code solution for this one but I noticed that if I set
WooCommerce > Preferences > General > Geolocate address
it will work (if settings are set to "Sell to all countries", in my case)
This code only removes validation of address fields in my-account page, what you need:
add_filter( 'woocommerce_default_address_fields',
'custom_override_default_address_fields' );
function custom_override_default_address_fields($address_fields)
{
$address_fields['postcode']['validate'] = false;
return $address_fields;
}
for billing and shipping:
add_filter( 'woocommerce_checkout_fields' , 'remove_postcode_validation', 99 );
function remove_postcode_validation( $fields ) {
unset($fields['billing']['billing_postcode']['validate']);
unset($fields['shipping']['shipping_postcode']['validate']);
return $fields;
}
Also i think with removing "validate-required" class in wc-template-function.php, this feature will be deactivated (no test).
Sorry for bad English and hope this solutions solve your problem.
The previous answers don't seem to address the question! The postcode is still a required field, it's matter of whether other postcodes can be allowed that WooCommerce is saying is wrong.
For a checkout I'm building I've used this filter to allow any postcode to be considered valid regardless of country/postcode given.
add_filter( 'woocommerce_validate_postcode' , 'mycode_override_postcode_check', 99, 3 );
function mycode_override_postcode_check( $valid, $postcode, $country ) {
return true;
}
You can change that return true; for more complex code logic that reviews the postcode and country, this can help if your version of WooCommerce doesn't cover new postcode/zip code rules and you need them to be accepted.
Source: https://github.com/EloxZ/wordpresscrm/blob/main/wp-content/plugins/woocommerce/includes/class-wc-validation.php#L123