Dealing With Money in Laravel/PHP: Best Practices

When working with money in your Laravel projects, whether it's product prices or invoice total order amounts, we need to be extremely careful not to miscalculate something. Luckily, there are best practices and tools to help us with that, let's explore them in this article.

What we'll cover:

  • Typical (and wrong) Money Behavior: Floats
  • One Step Better: Integers
  • Special PHP Packages For Money
  • Laravel Way: Custom Casts
  • Currency Conversion
  • Specific Laravel Packages/Wrappers

Let's get into it!


Typical (and wrong) Money Behavior: Floats

How do you save data in the database when you need to work with things like product price, or order total?

Since the amount of money is a float - like $3.45, the logical way would be to store it the same way in the database.

1$table->decimal('price', 8, 2);
2// 8 is total digits, 2 is decimal digits

And then, whenever you need to show the price in Blade, you do something like:

1Total price: ${{ number_format($product->price, 2) }}

In the code above, we need number_format() so that 9.1 would be shown as 9.10, with two digits.

In most cases, this approach should work fine, as long as you have one currency in your project and you're not doing a lot of calculations with those fields.

But the way how programming languages and database engines work with calculating floats, you may encounter a rounding problem. Meaning, you may have incorrect calculations by 0.01 if the wrong roundings add up.

Here are a few articles to read more about this problem:

If you are not in the mood to read those articles, and if you want to just trust me, I will simplify it for you:

NEVER STORE MONEY VALUES AS FLOATS IN THE DATABASE.

There, I said it.

Here's another quote for you:

Money rounding

Yes, the possibility of that rounding error happening is very low, but still, it's better to be on the safe side, right? So here are the solutions below...

The full tutorial [11 mins, 2077 words] is only for Premium Members

Become a Premium Member for $129/year or $29/month

Written by

You might also like