52

Every time I try to run this code there is a message saying:

Fatal error: Call to undefined function money_format()

The lines that have that problem are:

$pricetotal = money_format("%10.2n", $pricetotal);

and

$cartTotal = money_format("%10.2n", $cartTotal);

Can you please explain me the reason why this happens ?

$cartOutput = "";
$cartTotal = "";
$pp_checkout_btn = '';
$product_id_array = '';
if (!isset($_SESSION["cart_array"]) || count($_SESSION["cart_array"]) < 1) {
    $cartOutput = "<h2 align='center'>Your shopping cart is empty</h2>";
} else {
    // Start PayPal Checkout Button
$pp_checkout_btn .= '<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
    <input type="hidden" name="cmd" value="_cart">
    <input type="hidden" name="upload" value="1">
    <input type="hidden" name="business" value="you@youremail.com">';
    // Start the For Each loop
    $i = 0; 
    foreach ($_SESSION["cart_array"] as $each_item) { 
        $item_id = $each_item['item_id'];
        $sql = mysql_query("SELECT * FROM products WHERE id='$item_id' LIMIT 1");
        while ($row = mysql_fetch_array($sql)) {
            $product_name = $row["product_name"];
            $price = $row["price"];
            $details = $row["details"];
        }
        $pricetotal = $price * $each_item['quantity'];
        $cartTotal = $pricetotal + $cartTotal;
        setlocale(LC_MONETARY, "en_US");
        $pricetotal = money_format("%10.2n", $pricetotal);
        // Dynamic Checkout Btn Assembly
        $x = $i + 1;
        $pp_checkout_btn .= '<input type="hidden" name="item_name_' . $x . '" value="' . $product_name . '">
        <input type="hidden" name="amount_' . $x . '" value="' . $price . '">
        <input type="hidden" name="quantity_' . $x . '" value="' . $each_item['quantity'] . '">  ';
        // Create the product array variable
        $product_id_array .= "$item_id-".$each_item['quantity'].","; 
        // Dynamic table row assembly
        $cartOutput .= "<tr>";
        $cartOutput .= '<td><a href="product.php?id=' . $item_id . '">' .     $product_name . '</a><br /><img src="inventory_images/' . $item_id . '.jpg" alt="' . $product_name. '" width="40" height="52" border="1" /></td>';
    $cartOutput .= '<td>' . $details . '</td>';
    $cartOutput .= '<td>$' . $price . '</td>';
    $cartOutput .= '<td><form action="cart.php" method="post">
    <input name="quantity" type="text" value="' . $each_item['quantity'] . '" size="1" maxlength="2" />
    <input name="adjustBtn' . $item_id . '" type="submit" value="change" />
    <input name="item_to_adjust" type="hidden" value="' . $item_id . '" />
    </form></td>';
    //$cartOutput .= '<td>' . $each_item['quantity'] . '</td>';
    $cartOutput .= '<td>' . $pricetotal . '</td>';
    $cartOutput .= '<td><form action="cart.php" method="post"><input name="deleteBtn' . $item_id . '" type="submit" value="X" /><input name="index_to_remove" type="hidden" value="' . $i . '" /></form></td>';
    $cartOutput .= '</tr>';
    $i++; 
} 
setlocale(LC_MONETARY, "en_US");
$cartTotal = money_format("%10.2n", $cartTotal);
$cartTotal = "<div style='font-size:18px; margin-top:12px;' align='right'>Cart Total : ".$cartTotal." USD</div>";
// Finish the Paypal Checkout Btn
$pp_checkout_btn .= '<input type="hidden" name="custom" value="' . $product_id_array . '">
<input type="hidden" name="notify_url" value="https://www.yoursite.com/storescripts/my_ipn.php">
<input type="hidden" name="return" value="https://www.yoursite.com/checkout_complete.php">
<input type="hidden" name="rm" value="2">
<input type="hidden" name="cbt" value="Return to The Store">
<input type="hidden" name="cancel_return" value="https://www.yoursite.com/paypal_cancel.php">
<input type="hidden" name="lc" value="US">
<input type="hidden" name="currency_code" value="USD">
<input type="image" src="http://www.paypal.com/en_US/i/btn/x-click-but01.gif" name="submit" alt="Make payments with PayPal - its fast, free and secure!">
</form>';
}
?>
Machavity
  • 30,841
  • 27
  • 92
  • 100
user3201312
  • 521
  • 1
  • 4
  • 3
  • 10
    From the [PHP Reference manual](http://www.php.net/manual/en/function.money-format.php): The function money_format() is only defined if the system has strfmon capabilities. For example, Windows does not, so money_format() is undefined in Windows. –  Feb 02 '14 at 07:04
  • I have closed this as a duplicate of how to replace the use of this function. **This function is not available in PHP 8.0 and later**. – Machavity Jul 29 '22 at 18:40

4 Answers4

64

if you are using windows based system then you will not have this function available.

The function money_format() is only defined if the system has strfmon capabilities. For example, Windows does not, so money_format() is undefined in Windows.

(this has been pointed out by Mike W in comments as well)

http://www.php.net/manual/en/function.money-format.php

Maz I
  • 3,664
  • 2
  • 23
  • 38
  • Looks like the link above also provides a separate implementation of money_format that works on Windows. I tried it out and it seems to work fine. – Landon Poch Nov 15 '15 at 06:52
  • 2
    I ended up adding a `!function_exists('money_format')` conditional around the polyfill provided by Rafael M. Salvioni on the PHP man page above. Works fine. Surprised that the PHP core team hasn't accounted for this. – HartleySan Aug 19 '19 at 14:38
51

It has been pointed out that you may not have this function because it does not exist on all operating systems (see Mike W's comment or Learner Student's answer).

Since the function appears absent on your system, you can write your own function based on the number_format function. You appear to want to format the number as US dollars, so the default (decimal = . and thousands = , should work for you).

function asDollars($value) {
  if ($value<0) return "-".asDollars(-$value);
  return '$' . number_format($value, 2);
}

Then you can replace

$pricetotal = money_format("%10.2n", $pricetotal);

with

$pricetotal = asDollars($pricetotal);

The updated code puts the negative sign in front of the currency sign even for negative numbers (per the comment by @kunal).

Floris
  • 45,857
  • 6
  • 70
  • 122
  • 1
    Or: "$" . number_format($row[1], 0) //0 decimals, no function Thanks Floris! Side note: No clue why they didn't just implement this for Windows. Wouldve been a simple thing to add, and very common as well... – Kevin Aug 11 '18 at 18:24
  • '$' . number_format(-1254, 2); it will return output $-1,254 but i want -$1,254 how it possible?? – kunal Oct 29 '19 at 10:10
  • @kunal you could test for the sign of the input, and choose the appropriate format string – Floris Oct 29 '19 at 14:29
  • @Floris but i have checked online money_format automatically does this is there any another alternative function available? – kunal Oct 30 '19 at 04:28
  • @kunal please see the updated code. It now works (more) like `money_format`... – Floris Oct 30 '19 at 12:17
4

For Windows WAMP User and > PHP v7.4.2 please you might use this function which implements the same function for all platforms from here money_format()

Please use that function as fallback.. so use if ( ! function_exists( 'money_format' ) ) {} to avoid function can not redeclare fatal error.

Below for quick copying...

if ( ! function_exists( 'money_format' ) ) {

function money_format($format, $number)
{
    $regex  = '/%((?:[\^!\-]|\+|\(|\=.)*)([0-9]+)?'.
              '(?:#([0-9]+))?(?:\.([0-9]+))?([in%])/';
    if (setlocale(LC_MONETARY, 0) == 'C') {
        setlocale(LC_MONETARY, '');
    }
    $locale = localeconv();
    preg_match_all($regex, $format, $matches, PREG_SET_ORDER);
    foreach ($matches as $fmatch) {
        $value = floatval($number);
        $flags = array(
            'fillchar'  => preg_match('/\=(.)/', $fmatch[1], $match) ?
                           $match[1] : ' ',
            'nogroup'   => preg_match('/\^/', $fmatch[1]) > 0,
            'usesignal' => preg_match('/\+|\(/', $fmatch[1], $match) ?
                           $match[0] : '+',
            'nosimbol'  => preg_match('/\!/', $fmatch[1]) > 0,
            'isleft'    => preg_match('/\-/', $fmatch[1]) > 0
        );
        $width      = trim($fmatch[2]) ? (int)$fmatch[2] : 0;
        $left       = trim($fmatch[3]) ? (int)$fmatch[3] : 0;
        $right      = trim($fmatch[4]) ? (int)$fmatch[4] : $locale['int_frac_digits'];
        $conversion = $fmatch[5];

        $positive = true;
        if ($value < 0) {
            $positive = false;
            $value  *= -1;
        }
        $letter = $positive ? 'p' : 'n';

        $prefix = $suffix = $cprefix = $csuffix = $signal = '';

        $signal = $positive ? $locale['positive_sign'] : $locale['negative_sign'];
        switch (true) {
            case $locale["{$letter}_sign_posn"] == 1 && $flags['usesignal'] == '+':
                $prefix = $signal;
                break;
            case $locale["{$letter}_sign_posn"] == 2 && $flags['usesignal'] == '+':
                $suffix = $signal;
                break;
            case $locale["{$letter}_sign_posn"] == 3 && $flags['usesignal'] == '+':
                $cprefix = $signal;
                break;
            case $locale["{$letter}_sign_posn"] == 4 && $flags['usesignal'] == '+':
                $csuffix = $signal;
                break;
            case $flags['usesignal'] == '(':
            case $locale["{$letter}_sign_posn"] == 0:
                $prefix = '(';
                $suffix = ')';
                break;
        }
        if (!$flags['nosimbol']) {
            $currency = $cprefix .
                        ($conversion == 'i' ? $locale['int_curr_symbol'] : $locale['currency_symbol']) .
                        $csuffix;
        } else {
            $currency = '';
        }
        $space  = $locale["{$letter}_sep_by_space"] ? ' ' : '';

        $value = number_format($value, $right, $locale['mon_decimal_point'],
                 $flags['nogroup'] ? '' : $locale['mon_thousands_sep']);
        $value = @explode($locale['mon_decimal_point'], $value);

        $n = strlen($prefix) + strlen($currency) + strlen($value[0]);
        if ($left > 0 && $left > $n) {
            $value[0] = str_repeat($flags['fillchar'], $left - $n) . $value[0];
        }
        $value = implode($locale['mon_decimal_point'], $value);
        if ($locale["{$letter}_cs_precedes"]) {
            $value = $prefix . $currency . $space . $value . $suffix;
        } else {
            $value = $prefix . $value . $space . $currency . $suffix;
        }
        if ($width > 0) {
            $value = str_pad($value, $width, $flags['fillchar'], $flags['isleft'] ?
                     STR_PAD_RIGHT : STR_PAD_LEFT);
        }

        $format = str_replace($fmatch[0], $value, $format);
    }
    return $format;
  }
}
2

I had the same issue while developing a site on Laravel. For me, I replaced older code :

return money_format('$%i', $this->price / 100);

with the following:

return '$' . number_format(($this->price) / 100);

Prem Sagar
  • 147
  • 2
  • 8