cult3

Create a PHP Money Class

Dec 26, 2012

Table of contents:

  1. Create the Class
  2. Declarations
  3. Methods
  4. Using the Class
  5. Conclusion

Handling money values within an application is something that you do not want to go wrong. If it’s an ecommerce application, displaying or charging the wrong amount to a customer is a big mistake. Calculating the various amounts of a transaction can also be time consuming if you don’t already have a pre-written solution.

Whilst a fully blown ecommerce website is fantastic for handling these kinds of problems, it will often be overkill if you only want a really simple solution. You don’t want the bloat of a full ecommerce platform, if all you want to do is put payments for a couple of products through Paypal and create automatic invoices.

Dealing with amounts of money is a problem you should solve once, and then all you need to do is call upon that solution whenever you need it. With this in mind, here is a reusable PHP class for handling money and creating invoices.

Note: This Class has been created for English currency and tax laws. Hopefully it is self explanatory enough so you can customise it for your local currency and laws.

Create the Class

If you are new to the concept of Classes, or Object Oriented PHP, then hopefully this example will give you a good overview of exactly how the theory works in a real life situation.

So the first thing we need to do is to create a new Class.

class Money
{
}

Declarations

Next we need to declare the properties we are going to be using in the Class. I’ll go through them one-by-one and explain what each is for. Don’t worry if this seems overwhelming, most of these declarations are simply variables to hold running totals.

/**
 * Rate of VAT
 * @var float
 */
private $vat;

vat

First we need to store the rate of VAT. We store this as a variable so when the rate changes, we only need to update the class in one place. It is also useful to have the rate stored so we can quickly and easily print the value whenever we need it.

/**
 * Currency symbol
 * @var string
 */
private $symbol;

symbol

When we print out a formatted amount of money, we need to include the symbol of the currency we are using. If you would like to extend this class to use you own local currency, you will just need to update this string within the constructor.

/**
 * Total
 * @var float
 */
private $total;

total

When we are looping through an array of products, it will be useful to keep a running total of the costs.

/**
 * Total VAT
 * @var float
 */
private $totalVat;

totalVat

One of the requirements of an invoice is to supply VAT as a separate amount. This variable will store that running total.

/**
 * Total of products with VAT
 * @var float
 */
private $totalProductsWithVat;

totalProductsWithVat

Another requirement of an invoice is to display the total amount of the products with VAT.

/**
 * Total VAT from products with VAT
 * @var float
 */
private $totalProductsWithVatVat;

totalProductWithVatVat

Again, another requirement is to display the total of VAT from products with VAT.

/**
 * Total products without VAT
 * @var float
 */
private $totalProductsWithoutVat;

totalProductsWithoutVat

And finally, we need to record the total amount of the products without VAT.

Methods

Next we need to write the Methods of the Class. Methods are simply functions that are grouped together within a Class.

Constructor

First we need to write the constructor. A PHP constructor method is a magic method that is automatically called when the Class is instantiated. A constructor method is usually used to set the environment for the Class. In this case, I’m simply setting the variables with initial values.

/**
 * Constructor
 *
 * Sets the rate of VAT
 * Sets the currency symbol
 */
public function __construct() {
    // Set VAT
    $this->vat = 0.2;
    // Set the currency symbol
    $this->symbol = '&pound';
    // Set totals
    $this->total = 0.00;
    $this->totalVat = 0.00;
    $this->totalProductsWithVat = 0.00;
    $this->totalProductsWithVatVat = 0.00;
    $this->totalProductsWithoutVat = 0.00;
}

Format()

When dealing with money, we want to ensure that the money is always formatted correctly. When doing certain calculations with money, you can often end up with values that have more than two decimal places. To stop this problem, we can simply round the number and ensure that it is formatted to two decimal places.

/**
 * Format to currency
 *
 * Rounds a number to 2 decimal places
 * Formats the number to 2 decimal places
 *
 * @param float Number to be formatted
 * @return float Formatted number
 */
public function format($input) {
    // Round number and format to 2 decimal places
    return number_format(round($input, 2), 2);
}

vat()

An important job of this class is going to be calculating the amount of VAT from a given amount. This simple method will calculate the VAT and return the formatted amount.

/**
 * VAT
 *
 * Calculates and returns the formatted VAT
 *
 * @param float Price to calc VAT from
 * @return float VAT amount
 */
public function vat($input) {
    // Return formatted Vat from input amount
    return $this->format($input * $this->vat);
}

add()

One of the most important jobs of this Class is to keep a running total of each of the various amounts that we need to create an invoice. The add method manages these running totals whenever we add an additional amount.

/**
 * Add
 *
 * Add to running total
 * If VAT is set, get VAT and add to total
 * Else, just add to total
 * Return the amount of VAT
 *
 * @param float The price of the item
 * @param bool If VAT is set
 * @return float The amount of VAT
 */
public function add($input, $vat = NULL) {
    // If VAT is set
    if ($vat == true) {
        // Get the VAT
        $vat = $this->vat($input);
        // Add to running total
        $this->total += ($input + $vat);
        // Add to running VAT total
        $this->totalVat += $vat;
        // Add to products with VAT total
        $this->totalProductsWithVat += $input;
        // Add VAT to products with VAT total
        $this->totalProductsWithVatVat += $vat;
        // Return the amount of Vat
        return $vat;
    }else{
        // Add to running total
        $this->total += $input;
        // Add to products without VAT total
        $this->totalProductsWithoutVat += $input;
        // Return 0.00 Vat
        return $this->format(0.00);
    }
}

display()

Whenever we want to take a raw amount from our products database and display that amount on the product page, we need to format the price correctly. By separating the cost of the product and the VAT, we can maintain the database prices independently with the fluctuation of VAT. Also, by formatting the amount at this stage, we can maintain a clean separation of the integer value and the required formatted string.

/**
 * Display
 *
 * Display the amount
 * Add VAT if applicable
 * Add currency symbol
 * Return formatted
 *
 * @param float The price of the item
 * @param bool If VAT is set
 * @return float The formatted price
 */
public function display($input, $vat = NULL) {
    // If VAT is set
    if ($vat == true) {
        // Get VAT
        $vat = $this->vat($input);
        // Add VAT to input
        $input += $vat;
        // Return the formatted total
        return $this->symbol . $this->format($input);
    }else{
        // Return formatted
        return $this->symbol . $this->format($input);
    }
}

displayVAT()

You will usually want to display the amount of VAT you are charging at some point on your website. Instead of hardcoding that amount into pages dotted all over your website, you can instead use this method. Now whenever the rate of VAT changes, you only have to change it once to see it reflected across your entire website.

/**
 * Display VAT
 *
 * Display the rate of VAT
 * as a percentage
 *
 * @return string e.g "20%";
 */
public function displayVat() {
    return ($this->vat * 100). "%";
}

total()

To display the total, we need a method that that will return the value. We will probably also need this value as an integer or as a formatted string. To return it as a string, we can pass an optional argument so it displays correctly.

/*
* Total
*
* Return the running total
* as either a float or a formatted string
*
* @param string Type of formatting
* @return float
*/
public function total($type = NULL) {
    // Return running total
    if ($type == "string") {
        // Return formated as a string
        return $this->symbol . $this->format($this->total);
    }else{
        // Return as float
        return $this->format($this->total);
    }
}

The following methods for displaying the other various totals are pretty self explanatory as they all follow the same pattern.

totalVat()

/*
* Total VAT
*
* Return the running VAT total
* as either a float or a formatted string
*
* @param string Type of formatting
* @return float
*/
public function totalVat($type = NULL) {
    // Return running VAT total
    if ($type == "string") {
        // Return formatted as a string
        return $this->symbol . $this->format($this->totalVat);
    }else{
        // Return as float
        return $this->format($this->totalVat);
    }
}

totalMinusVat()

/*
* Total minus VAT
*
* Return the total minus VAT
*
* @param string Type of formatting
* @return float
*/
public function totalMinusVat($type = NULL) {
    // Return Total minus VAT
    if ($type == "string") {
        // Return formatted as a string
        return $this->symbol . $this->format($this->total - $this->totalVat);
    }else{
        // Return as float
        return $this->format($this->total - $this->totalVat);
    }
}

totalProductsWithVat()

/*
* Total of products with VAT
*
* Returns a running total of
* the value of products with VAT
*
* @param string Type of formatting
* @return string As string
* @return float As float
*/
public function totalProductsWithVat($type = NULL) {
    if ($type == "string") {
        return $this->symbol . $this->format($this->totalProductsWithVat);
    }else{
        $this->format($this->totalProductsWithVat);
    }
}

totalProductsWithoutVat()

/*
* Total of products without VAT
*
* Returns a running total of
* the value of products without VAT
*
* @param string Type of formatting
* @return string As string
* @return float As float
*/
public function totalProductsWithoutVat($type = NULL) {
    if ($type == "string") {
        return $this->symbol . $this->format($this->totalProductsWithoutVat);
    }else{
        return $this->format($this->totalProductsWithoutVat);
    }
}

Using the Class

Using the Class to handle amounts of money is really easy.

To get started we need to instantiate a new instance of the class:

$money = new Money();

First, we will display the current rate of VAT.

echo $money->displayVat();

Next, we will display some raw product amount formatted and with VAT added.

echo $money->display(9.99, true);
echo $money->display(19.99, true);
echo $money->display(100.0, true);

Next we will add five product amounts, three with VAT and two without.

$money->add(9.99, true);
$money->add(32.67, true);
$money->add(19.99);
$money->add(42.65, true);
$money->add(12.99);

First, we will print the total of the products:

echo $money->total("string");

Next, we will print the total amount of VAT:

echo $money->totalVat("string");

Next, the total minus VAT:

echo $money->totalMinusVat("string");

Next, the total products with VAT:

echo $money->totalProductsWithVat("string");

And finally, the total products without VAT:

echo $money->totalProductsWithoutVat("string");

Conclusion

And there you have it, a simple PHP Class for displaying and formatting currency and making invoice calculations. Hopefully this should just slot into any project you are working on that requires any kind of currency calculations as it has no dependancies.

If you would like to extend this Class to use your local currency, or you would like to include it within your project, feel free to copy it and change what you need. No attribution is needed, but if you would like to show how you are using the code, please leave a comment so I can take a look.

Philip Brown

@philipbrown

© Yellow Flag Ltd 2024.