propelorm / Propel2

Propel2 is an open-source high-performance Object-Relational Mapping (ORM) for modern PHP
http://propelorm.org/
MIT License
1.26k stars 399 forks source link

Suggestion/discussion: complex serialisers/deserialisers #1774

Open nederdirk opened 3 years ago

nederdirk commented 3 years ago

Hi, we have a table with a structure like this:

    <table name="invoiceline">
        ⋮
        <column name="currency_code" type="VARCHAR" required="true"/>
        ⋮
        <column name="amount_items" type="INTEGER" required="true" description="Items amount in smallest currency unit (e.g. cents for EUR)"/>
        <column name="amount_shipping" type="INTEGER" required="true" description="Shipping amount in smallest currency unit (e.g. cents for EUR)"/>
        ⋮

With several amount columns. For money amounts and calculations we use the excellent https://github.com/moneyphp/money library, which holds to the (correct!) view that a money value consists of an amount and a currency. Although the currency in our model is the same for each invoice, we record it also on the invoice lines (mostly for historic reasons, but it often helps to have the currency in the local line-context).

We would like our generated base-classes to do the serialisation/deserialisation of the Money object instances. The phpType attribute would help us in the case of the Money\Currency type, as that's constructed with a currency code in the constructor parameter (e.g. 'EUR' for Euro; recorded in the currency_code field) and its __toString method returns the currency code again. For the Money\Money objects it's a bit more complicated, as those are constructed with an amount value (i.e. an int or a int-like string representing the base unit of the currency, like cents) and a Money\Currency value. The amount_items, amount_shipping, etc columns are, for their PHP values depend on two columns in the database.

We can't save the amount_* columns as string-values like € 123.45, as we often require in-database arithmetic (take the sum of all amounts for invoices from a specified period etc).

In the end, I would like to be able to do something like

<column name="amount_items" type="INTEGER" required="true"
    phpType="\Money\Money" serializer="\Mynamespace\MoneySerializer"/>

with MoneySerializer implementing a (yet to be defined) interface providing deserialising (something like ::deserializeDatabaseValue($databaseValue, array $otherFields) and ::serialiseDatabaseValue(Money $phpValue, InvoiceLine $recordContext), but I'm very open to other ideas to approach this)

Would something like this be a good extension to Propel2?