Format Price
Overview
Format numeric values as portable price strings for templates, builders, or plain PHP usage.
The helper is generic rather than WooCommerce- or SureCart-specific. It accepts integers, floats, and numeric strings, returns an empty string for invalid values, and supports symbol placement, separator changes, decimal precision, and trailing-zero stripping.
Builder examples:
{echo:mac_format_price({acf_price})}
{echo:mac_format_price({acf_price}, 'USD')}
{echo:mac_format_price({acf_price}, 'EUR', {symbol_position: 'after', space_between: true})}
Usage
mac_format_price(
int|float|string $amount,
string $currency = 'USD',
array $args = []
): string
Supported args:
symboldecimalsdecimal_separatorthousands_separatorsymbol_positionspace_betweenstrip_trailing_zeros
Examples:
mac_format_price( 49 );
mac_format_price( 49, 'USD' );
mac_format_price( 49, 'EUR', [ 'symbol_position' => 'after', 'space_between' => true ] );
mac_format_price( '1499.50', 'RON', [ 'symbol' => 'lei', 'space_between' => true ] );
mac_format_price( 24.00, 'USD', [ 'strip_trailing_zeros' => true ] );
Variants
- Procedural
- OOP
<?php
/**
* Format numeric values as portable price strings.
*
* Examples:
* mac_format_price( 49 );
* mac_format_price( 49, 'USD' );
* mac_format_price( 49, 'EUR', [ 'symbol_position' => 'after', 'space_between' => true ] );
*
* Builder usage:
* {echo:mac_format_price({acf_price})}
* {echo:mac_format_price({acf_price}, 'USD')}
* {echo:mac_format_price({acf_price}, 'EUR', {symbol_position: 'after', space_between: true})}
*
* @param int|float|string $amount Raw amount.
* @param string $currency Optional. Defaults to USD.
* @param array<string,mixed> $args Formatting overrides.
* @return string
*/
if ( ! function_exists( 'mac_format_price' ) ) {
function mac_format_price( int|float|string $amount, string $currency = 'USD', array $args = [] ): string {
$normalized_amount = null;
if ( is_int( $amount ) || is_float( $amount ) ) {
$normalized_amount = (float) $amount;
} else {
$amount = trim( $amount );
if ( $amount !== '' ) {
$normalized = str_replace( [ ' ', ',' ], [ '', '' ], $amount );
$normalized_amount = is_numeric( $normalized ) ? (float) $normalized : null;
}
}
if ( null === $normalized_amount ) {
return '';
}
$currency = strtoupper( trim( $currency ) );
$currency = '' !== $currency ? $currency : 'USD';
$symbols = [
'AUD' => '$',
'CAD' => '$',
'CHF' => 'CHF',
'EUR' => 'EUR',
'GBP' => 'GBP',
'JPY' => 'JPY',
'RON' => 'RON',
'USD' => '$',
];
$defaults = [
'symbol' => $symbols[ $currency ] ?? $currency,
'decimals' => 2,
'decimal_separator' => '.',
'thousands_separator' => ',',
'symbol_position' => 'before',
'space_between' => false,
'strip_trailing_zeros' => false,
];
$config = array_merge( $defaults, $args );
$decimals = 2;
if ( is_scalar( $config['decimals'] ) && is_numeric( (string) $config['decimals'] ) ) {
$decimals = max( 0, (int) $config['decimals'] );
}
$decimal_separator = is_scalar( $config['decimal_separator'] ) && '' !== (string) $config['decimal_separator']
? (string) $config['decimal_separator']
: '.';
$thousands_separator = is_scalar( $config['thousands_separator'] ) && '' !== (string) $config['thousands_separator']
? (string) $config['thousands_separator']
: ',';
$symbol = is_scalar( $config['symbol'] ) ? (string) $config['symbol'] : $defaults['symbol'];
$symbol_position = is_scalar( $config['symbol_position'] ) && 'after' === strtolower( trim( (string) $config['symbol_position'] ) )
? 'after'
: 'before';
$space_between = (bool) $config['space_between'];
$strip_trailing_zeros = (bool) $config['strip_trailing_zeros'];
$prefix = $normalized_amount < 0 ? '-' : '';
$formatted_amount = number_format( abs( $normalized_amount ), $decimals, $decimal_separator, $thousands_separator );
if ( $strip_trailing_zeros && $decimals > 0 && str_contains( $formatted_amount, $decimal_separator ) ) {
$formatted_amount = rtrim( rtrim( $formatted_amount, '0' ), $decimal_separator );
$formatted_amount = '' !== $formatted_amount ? $formatted_amount : '0';
}
$glue = $space_between && '' !== $symbol ? ' ' : '';
if ( 'after' === $symbol_position ) {
return $prefix . $formatted_amount . $glue . $symbol;
}
return $prefix . $symbol . $glue . $formatted_amount;
}
}
<?php
/**
* Format numeric values as portable price strings.
*/
declare(strict_types=1);
if ( ! class_exists( 'FormatPrice' ) ) {
/**
* Generic price formatting helper.
*/
final class FormatPrice
{
/**
* Common currency symbols used as defaults.
*
* @var array<string,string>
*/
private const SYMBOLS = [
'AUD' => '$',
'CAD' => '$',
'CHF' => 'CHF',
'EUR' => 'EUR',
'GBP' => 'GBP',
'JPY' => 'JPY',
'RON' => 'RON',
'USD' => '$',
];
/**
* Format a numeric amount as a price string.
*
* @param int|float|string $amount Raw amount.
* @param string $currency Optional. Defaults to USD.
* @param array<string,mixed> $args Formatting overrides.
* @return string
*/
public static function format( int|float|string $amount, string $currency = 'USD', array $args = [] ): string
{
$normalized_amount = self::normalize_amount( $amount );
if ( null === $normalized_amount ) {
return '';
}
$currency = strtoupper( trim( $currency ) );
$currency = '' !== $currency ? $currency : 'USD';
$defaults = [
'symbol' => self::SYMBOLS[ $currency ] ?? $currency,
'decimals' => 2,
'decimal_separator' => '.',
'thousands_separator' => ',',
'symbol_position' => 'before',
'space_between' => false,
'strip_trailing_zeros' => false,
];
$config = array_merge( $defaults, $args );
$decimals = self::normalize_decimals( $config['decimals'] ?? 2 );
$decimal_separator = self::normalize_separator( $config['decimal_separator'] ?? '.', '.' );
$thousands_separator = self::normalize_separator( $config['thousands_separator'] ?? ',', ',' );
$symbol = is_scalar( $config['symbol'] ?? null ) ? (string) $config['symbol'] : $defaults['symbol'];
$symbol_position = self::normalize_symbol_position( $config['symbol_position'] ?? 'before' );
$space_between = (bool) ( $config['space_between'] ?? false );
$strip_trailing_zeros = (bool) ( $config['strip_trailing_zeros'] ?? false );
$prefix = $normalized_amount < 0 ? '-' : '';
$formatted_amount = number_format( abs( $normalized_amount ), $decimals, $decimal_separator, $thousands_separator );
if ( $strip_trailing_zeros && $decimals > 0 ) {
$formatted_amount = self::strip_trailing_zeros( $formatted_amount, $decimal_separator );
}
$glue = $space_between && '' !== $symbol ? ' ' : '';
if ( 'after' === $symbol_position ) {
return $prefix . $formatted_amount . $glue . $symbol;
}
return $prefix . $symbol . $glue . $formatted_amount;
}
/**
* @param int|float|string $amount
* @return float|null
*/
private static function normalize_amount( int|float|string $amount ): ?float
{
if ( is_int( $amount ) || is_float( $amount ) ) {
return (float) $amount;
}
$amount = trim( $amount );
if ( '' === $amount ) {
return null;
}
$normalized = str_replace( [ ' ', ',' ], [ '', '' ], $amount );
return is_numeric( $normalized ) ? (float) $normalized : null;
}
/**
* @param mixed $value
* @return int
*/
private static function normalize_decimals( mixed $value ): int
{
if ( ! is_scalar( $value ) || ! is_numeric( (string) $value ) ) {
return 2;
}
return max( 0, (int) $value );
}
/**
* @param mixed $value
* @param string $fallback
* @return string
*/
private static function normalize_separator( mixed $value, string $fallback ): string
{
if ( ! is_scalar( $value ) ) {
return $fallback;
}
$separator = (string) $value;
return '' !== $separator ? $separator : $fallback;
}
/**
* @param mixed $value
* @return string
*/
private static function normalize_symbol_position( mixed $value ): string
{
if ( ! is_scalar( $value ) ) {
return 'before';
}
return 'after' === strtolower( trim( (string) $value ) ) ? 'after' : 'before';
}
/**
* @param string $formatted_amount
* @param string $decimal_separator
* @return string
*/
private static function strip_trailing_zeros( string $formatted_amount, string $decimal_separator ): string
{
if ( ! str_contains( $formatted_amount, $decimal_separator ) ) {
return $formatted_amount;
}
$trimmed = rtrim( rtrim( $formatted_amount, '0' ), $decimal_separator );
return '' !== $trimmed ? $trimmed : '0';
}
}
}
if ( ! function_exists( 'mac_format_price' ) ) {
/**
* Format numeric values as price strings.
*
* @param int|float|string $amount
* @param string $currency
* @param array<string,mixed> $args
* @return string
*/
function mac_format_price( int|float|string $amount, string $currency = 'USD', array $args = [] ): string
{
return FormatPrice::format( $amount, $currency, $args );
}
}