Calculator phone app

WooCommerce Function of the Week: wc_price

The wc_price function solves your WooCommerce price formatting problems. Using it means you can ignore the WooCommerce price settings.

When you work on WooCommerce customization in your plugin/code snippet, you often need to format a price in order to display it correctly on the front-end.

Unfortunately, this can get tricky: you need to get (from the store settings) the WooCommerce currency symbol, the number of decimals, the decimal separator, the suffix, and so on. “Rebuilding” the price format each time can be really time-consuming.

Developers; please meet wc_price.

This neat WooCommerce function can finally solve your price formatting nightmares and make you completely forget about the WooCommerce price settings: it'll do the job for you.

As usual, we'll take a look at practical examples; but first, let's analyze the function code.

Function Code

By doing a quick search of the WooCommerce plugin's files for the “function wc_price” term, we get a single result under \woocommerce\includes\wc-formatting-functions.php:

/**
 * Format the price with a currency symbol.
 *
 * @param  float $price Raw price.
 * @param  array $args  Arguments to format a price {
 *     Array of arguments.
 *     Defaults to empty array.
 *
 *     @type bool   $ex_tax_label       Adds exclude tax label.
 *                                      Defaults to false.
 *     @type string $currency           Currency code.
 *                                      Defaults to empty string (Use the result from get_woocommerce_currency()).
 *     @type string $decimal_separator  Decimal separator.
 *                                      Defaults the result of wc_get_price_decimal_separator().
 *     @type string $thousand_separator Thousand separator.
 *                                      Defaults the result of wc_get_price_thousand_separator().
 *     @type string $decimals           Number of decimals.
 *                                      Defaults the result of wc_get_price_decimals().
 *     @type string $price_format       Price format depending on the currency position.
 *                                      Defaults the result of get_woocommerce_price_format().
 * }
 * @return string
 */
function wc_price( $price, $args = array() ) {
	$args = apply_filters(
		'wc_price_args',
		wp_parse_args(
			$args,
			array(
				'ex_tax_label'       => false,
				'currency'           => '',
				'decimal_separator'  => wc_get_price_decimal_separator(),
				'thousand_separator' => wc_get_price_thousand_separator(),
				'decimals'           => wc_get_price_decimals(),
				'price_format'       => get_woocommerce_price_format(),
			)
		)
	);

	$original_price = $price;

	// Convert to float to avoid issues on PHP 8.
	$price = (float) $price;

	$unformatted_price = $price;
	$negative          = $price < 0;

	/**
	 * Filter raw price.
	 *
	 * @param float        $raw_price      Raw price.
	 * @param float|string $original_price Original price as float, or empty string. Since 5.0.0.
	 */
	$price = apply_filters( 'raw_woocommerce_price', $negative ? $price * -1 : $price, $original_price );

	/**
	 * Filter formatted price.
	 *
	 * @param float        $formatted_price    Formatted price.
	 * @param float        $price              Unformatted price.
	 * @param int          $decimals           Number of decimals.
	 * @param string       $decimal_separator  Decimal separator.
	 * @param string       $thousand_separator Thousand separator.
	 * @param float|string $original_price     Original price as float, or empty string. Since 5.0.0.
	 */
	$price = apply_filters( 'formatted_woocommerce_price', number_format( $price, $args['decimals'], $args['decimal_separator'], $args['thousand_separator'] ), $price, $args['decimals'], $args['decimal_separator'], $args['thousand_separator'], $original_price );

	if ( apply_filters( 'woocommerce_price_trim_zeros', false ) && $args['decimals'] > 0 ) {
		$price = wc_trim_zeros( $price );
	}

	$formatted_price = ( $negative ? '-' : '' ) . sprintf( $args['price_format'], '<span class="woocommerce-Price-currencySymbol">' . get_woocommerce_currency_symbol( $args['currency'] ) . '</span>', $price );
	$return          = '<span class="woocommerce-Price-amount amount"><bdi>' . $formatted_price . '</bdi></span>';

	if ( $args['ex_tax_label'] && wc_tax_enabled() ) {
		$return .= ' <small class="woocommerce-Price-taxLabel tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>';
	}

	/**
	 * Filters the string of price markup.
	 *
	 * @param string       $return            Price HTML markup.
	 * @param string       $price             Formatted price.
	 * @param array        $args              Pass on the args.
	 * @param float        $unformatted_price Price as float to allow plugins custom formatting. Since 3.2.0.
	 * @param float|string $original_price    Original price as float, or empty string. Since 5.0.0.
	 */
	return apply_filters( 'wc_price', $return, $price, $args, $unformatted_price, $original_price );
}

There are quite a few PHP statements inside that function!

Let's break down each section:

  1. The function starts by getting the $args, which are basically what we said in the introduction: separators, currency, number of decimals, and suffix. These will be used later to formatting a number as a WooCommerce price.
  2. Next, the function converts the raw price to a float in case it's not a float: $price = (float) $price. This is for PHP 8 compatibility.
  3. Then, should the price be negative for whatever reason, $price * -1 does its magic and makes it a positive number.
  4. Now to the cool part. The number_format PHP function converts the original floating point number into a price by using the $args we previously gathered.
  5. Optionally, wc_trim_zeros( $price ) trims trailing zeros. (Yep, wc_trim_zeros is now a candidate for one of the next WooCommerce function of the week posts!)
  6. We then move to HTML; our “number” is formatted thanks to a series of spans, tags, classes and wrappers. It's stored inside the $return variable.
  7. A filter, wc_price, finally allows us to change the price format if necessary. (A different name might have been better to avoid confusion, but that's how it is.)

And that's it!

Function Usage

We know the code now, so let's look at how it's used.

Let's pick a number:

5.6

Let's call wc_price and print its result:

echo wc_price( 5.6 );

And finally, let's take a look at the generated HTML:

<span class="woocommerce-Price-amount amount">
   <bdi>
      <span class="woocommerce-Price-currencySymbol">$</span>
      5.60
   </bdi>
</span>

Magic! (Please note the currency symbol, the currency position, the price with two decimals… that's all from the settings.)

Function Example

Now to the case study.

It may happen that you need to display the total discount the customer has totaled based on the items in the cart.

You'd calculate this total as a float, and with wc_price you can nicely format it based on the store settings without concerning yourself with them!

Let's trigger a notice on the Cart page:

/**
 * @snippet       Display formatted discount | WooCommerce Cart
 * @how-to        Get CustomizeWoo.com FREE
 * @author        Rodolfo Melogli
 * @testedwith    WooCommerce 6
 * @donate $9     https://businessbloomer.com/bloomer-armada/
 */

add_action( 'woocommerce_before_cart', 'bbloomer_show_total_discount' );

function bbloomer_show_total_discount() {

   if ( WC()->cart->is_empty() ) return;
   
   $discount_total = 0;
    
   foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {         
      $product = $values['data'];
      if ( $product->is_on_sale() ) {
         $regular_price = $product->get_regular_price();
         $sale_price = $product->get_sale_price();
         $discount = ( $regular_price - $sale_price ) * $values['quantity'];
         $discount_total += $discount;
      }
   }
             
   if ( $discount_total > 0 ) {
      wc_print_notice( 'Your total discount is: ' . wc_price( $discount ), 'notice' );
   }

}

Right there at the end, I've used wc_price to format the total discount inside the notice: wc_price( $discount ).

Here's a screenshot of the output:

(Regular price was $997, sale price is $897, and quantity = 1, therefore the total discount is $100.)

I hope you enjoyed yet another WooCommerce shortcut.

Just my wc_price( 0.02 )!

Similar Posts