I checked the woocommerce source, and it took time ;-) It boils down how your theme handles the price - on an archive or as single product. Dig into your theme and you find out.
With my theme I use on https://golfball.pro the archive and the single product call the get_price_html() method of the WC_Product Class:
public function get_price_html( $deprecated = '' ) {
if ( '' === $this->get_price() ) {
$price = apply_filters( 'woocommerce_empty_price_html', '', $this );
} elseif ( $this->is_on_sale() ) {
$price = wc_format_sale_price( wc_get_price_to_display( $this, array( 'price' => $this->get_regular_price() ) ), wc_get_price_to_display( $this ) ) . $this->get_price_suffix();
} else {
$price = wc_price( wc_get_price_to_display( $this ) ) . $this->get_price_suffix();
}
return apply_filters( 'woocommerce_get_price_html', $price, $this );
}
What happens is the following - the code checks the prices, which are stored in the table wp_postmeta:
- _price gets retrieved from wp_postmeta
- if the value does not exist, no price is shown but a filter is called, where you could add your own price logic. If you dont do it the price remains empty.
- If the key _price exists for the product, it checks if the product is on sale, and if yes use two prices - the _regular_price and surprise _price (for the sale price)
- if the product is not on sale the _price field is used.
So... the logic does not happen here at retrieval of the values, it happens at save the updates in the WC_Product_Data_Store_CPT class, the handle_updated_props method starting from line 650:
if ( in_array( 'date_on_sale_from', $this->updated_props, true ) || in_array( 'date_on_sale_to', $this->updated_props, true ) || in_array( 'regular_price', $this->updated_props, true ) || in_array( 'sale_price', $this->updated_props, true ) || in_array( 'product_type', $this->updated_props, true ) ) {
if ( $product->is_on_sale( 'edit' ) ) {
update_post_meta( $product->get_id(), '_price', $product->get_sale_price( 'edit' ) );
$product->set_price( $product->get_sale_price( 'edit' ) );
} else {
update_post_meta( $product->get_id(), '_price', $product->get_regular_price( 'edit' ) );
$product->set_price( $product->get_regular_price( 'edit' ) );
}
}
This is the code in WC_Product_Data_Store_CPT that handles the save and has the logic for _price, _regular_price and _sale_price; this snippet gets executed before a save. So if the _regular_price is updated or the _sale_price is updated, this will trigger an update:
- If there is an update in SaleTo or SaleFrom Date, regular or sale price or pruduct_type
- Update the _price
Long story short, _price is always updated. In your case I would check where your theme is getting the price from, maybe not from get_price_html and therefore the behavior is different.