Search code examples
phppostgresqlmoney-php

Money PHP - Loseless way to Persist Money Object in Database


Am refering to moneyphp/money library which I plan to use it in one of our projects for dealing with currencies. The Documentation is great except it does not touch how to persist in the database. It speaks about encoding money object to JSON but storing strings makes it difficult to make queries as simple as comparing the amount or currencies.

Going through issues, I have found few discussion about Doctrine and it is so specific to doctrine that I could not benefit anything.

Asking my question, in concise words: How do I store money object without loosing details? I'm interested in Postgresql but any relational database is OK.

Note: I have read many different way to persist monetary in database and they differ in how they do. Am interested in specific way that works with this specific library.


Solution

  • After tiresome reading of many different threads, posts et al, I have come to the conclusion that only two way are acceptable (see great comments in this question):

    1. Convert all money to smallest unit (eg. Cents) each time you save to the database and reconvert when retrieving it.

    2. Use DECIMAL/NUMERIC data type with needed accuracy (Many recommend NUMERIC(15,4) when doing normal operations or NUMERIC(15, 6) if you do currency exchange operations)

    Of course whatever the choice, it must be coupled with Currency column.

    I have ended up with the first method because of this library (which is not the original when I asked the question), which makes that super easy. Here are explanations from author after I created an issue:

    I can only tell you that I personally store my monies in the database as an integer representing the amount in minor units (cents), and optionally a CHAR(3) for the currency if the application uses multiple currencies (otherwise the currency is hardcoded in the app).

    You can get the amount in minor units this way, as an integer:

    $money->getMinorAmount()->toInt();

    And you can retrieve a Money from an integer stored in the database using:

    Money::ofMinor($integerAmount, 'USD');