September 30th, 2024 • 6 minutes read time

Dealing with monetary values in any application is something you have to get right the first time. Without the correct approach, you risk displaying prices incorrectly or worse, making miscalculations.

Here's how to work with money properly in Laravel.

The golden rule when storing prices is *never use a float or a double*. This might seem strange at first because we typically think of money represented as a float value (like 5.67 for $5.67).

When dealing with money, we need precision. Floating point numbers have rounding errors. For basic outputting of prices, you *could* use a float, but any kind of comparison or calculation with these values could result in weird behaviour.

Aside from this, it's just plain awkward to calculate with floats. Let's see an example.

Here's what defining a column on a `Product`

model would look like with the wrong approach:

```
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->float('price');
$table->timestamps();
});
```

Now imagine we have a 25% sale and want to calculate the discount a customer would receive on an item priced `$8.99`

. Here's a rough example of calculating this:

```
$product = Product::find(1);
$couponPercentage = 25;
$discount = ($product->price * $couponPercentage) / 100; // 2.2475
```

So the end result is `2.2475`

. The actual amount we'd want to take off is `2.25`

. And now we're left figuring out how to properly round this number with 4 decimal places. Imagine if things got more complex than this? (let's not).

The solution to all this is to use an `integer`

to store money in cents (or whatever monetary unit you use).

Let's change up our migration:

```
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->unsignedInteger('price');
$table->timestamps();
});
```

This is a premium article

Members get access to all articles, plus hundreds of screencasts.

Check it out Already a member? Sign in to continue

We use an `unsignedInteger`

here, which can hold a larger positive value and no negative value, since we don't need negative prices.

To populate prices, you'll now need to multiply the price by 100. Therefore, `8.99`

is stored as `899`

.

Let's look at the same example from earlier, where we want to calculate a 25% discount on this, and see how much easier it is.

```
$product = Product::find(1);
$couponPercentage = 25;
```Look again at that dot. That's here. That's home. That's us. On it everyone you love, everyone you know, everyone you ever heard of, every human being who ever was, lived out their lives.

` Comments `

` No comments, yet. Be the first! `

` Table of contents `

` Tagged under `

```
```