How to store prices efficiently in Laravel Eloquent ?
We can store prices efficiently in Laravel Eloquent by focusing on avoiding floating-point issues and optimizing storage. The appraoch is storing price as integer. Here is how.
How to store prices as integer ? ๐
- Define an integer column in your database table to store the price in the smallest denomination of your currency. For example, for USD, store the price in cents (e.g., $10.50 becomes 1050).
- Use a mutator in your Eloquent model to handle price setting. The mutator multiplies the user-provided decimal value by the conversion factor (e.g., 100 for cents).
- Define an accessor in your model to format the price for display. The accessor divides the stored integer value by the conversion factor and formats it as a decimal string (e.g., with currency symbol and commas).
Benefits of storing price as integer ๐
- Storage efficiency: Integers use less space compared to decimals.
- Accuracy: Avoids rounding errors inherent in floating-point numbers.
- Speed: Calculations with integers are faster.
Implementation of storing prices as integers ๐
In your model, add the price
column to the $fillable
s.
class Product extends Model
{
protected $fillable = ['price'];
}
Add a mutator (a function) that convert decimal into integer before storing it into the database.
class Product extends Model
{
// store 'int' instead of 'double' in db for performance
public function setPriceAttribute($value)
{
// 5.50 USD (UI) -> 550 Cents (db)
$this->attributes['price'] = $value * 100;
}
}
Add an accessor (a function) that converts integer into decimal before accessing the price value.
class Product extends Model
{
public function getPriceAttribute()
{
// 550 cents (db) -> 5.50 USD (UI)
return number_format($this->attributes["price"] / 100, 2);
}
}
But if you will use the price in further calculation, use this accessor (get function) instead.
class Product extends Model
{
public function getPriceAttribute()
{
// 550 cents (db) -> 5.50 USD (UI)
return floatval(number_format($this->attributes["price"] / 100, 2));
}
}
because floatval()
ensures that the returned value is a floating-point number.
I hope this post helps you. If you know a person who can benefit from this information, send them a link of this post. If you want to get notified about new posts, follow me on YouTube , Twitter (x) , LinkedIn , and GitHub .