-
-
Notifications
You must be signed in to change notification settings - Fork 102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom currencies #5
Comments
Seems good to me. 👍 It prevents anybody to break 3rd party code. It is still very simple to extend (create new currency). If someone wants to introduce to create money in his own currency from string, he can always introduce his own global factory, this way he can't break anything. function money($amount, $currencyString) {
// 1) look up currency and assign into $currency
return Money::of($amount, $currency);
}
// usage of custom global factory
$moneyInMyCurrency = money(16, 'PRG'); |
I just realized that if we follow this route, we won't be able to use
or we have to accept an optional CurrencyProvider instance as a second parameter. |
That sounds like a serious issue if someone use this for serialization. (I do not) Do we want to support that at all? Does not seems that useful to me and there is a serious complexity involved in getting this right. (e.g. providing factory with currency list, which can create and reconstruct monies) |
Serialization (using As for TBH I've only used it in unit tests so far. It's not a big deal to drop it, or at least restrict it to ISO currencies for now. |
FWIW, I guess I'd be fine even with Restricting code resolution to ISO currencies sounds like a good way to go 👍 Ad side question: they do, for example Bitcoin is divisible to 8 places; Ethereum has a scale of 18, apparently |
Personally I store my currencies as 3-letter strings in the DB, so the convenience of accepting a string for ISO currencies is nice. We'll do this then, strings for ISO only, and force objects for non-ISO currencies.
Interesting, thanks! |
I tend to agree with @jiripudil here, I think As for the |
Honestly I would miss Your reasoning is correct and I do use DBAL types as well, but more sparsely since a few years ago, when I profiled a slow app and realized that the CPU time was mostly spent on hydrating properties that were only rarely used. Now I'm mostly using a "proxy" approach, where the property contains the raw value (amount =
I may remove |
This is interesting, maybe have a look at consistence/consistence-doctrine#7? I was actually solving this last week and testing on a lot of data. This is using an PostLoadListener, because I need to have per field additional parameter (the resulting instance's class), so using only a DBAL type is unfortunately not possible. But when you look at the timings, it seems that the overhead in the implementation after optimization is nearly negligible (as seen from the last test where I "skipped" the execution). But in any way as noted in the referenced issue, I think that in most cases, when this comes into focus as being a problem, a lot of time its the case that Doctrine is used in a way, that is not suited for. Anyway the particular implementation does not matter from my point of view, because even if it was lazy-evaluated I would want it to be abstracted away from the other code, so that again everywhere only |
This was several years ago and the culprit was Zend_Date (ZF1). I had a Doctrine type for this class, and realized after a while that initialization of this class was very heavy. It's definitely cheaper to instantiate your enums inconditionally, because they do not require a lot of code to be run. Money would be only slightly more expensive, but still, parsing a BigDecimal, parsing a Currency, doing some consistency checks and all, for a type that might not be used for sure, is a waste of resources IMHO. Mapping Doctrine types to proxy classes generated specially for your objects is another solution. But we're digressing :) |
Summary: methods accepting |
Part of the list of things I want to work on before tagging a release, as mentioned in #2. Comments welcome.
The library ships with ISO currencies, but allows you to add custom currencies (bitcoins, etc.). This is done through a class called
DefaultCurrencyProvider
; Money uses it to resolve a currency code such asUSD
to aCurrency
instance, to get its default scale among other things.My issue with the current implementation is that it's a singleton: if your code adds a custom currency, it affects third-party code using Money as well, and vice versa. ISO currencies can't be overridden, but conflicts between custom currencies are possible.
The only way I can see around this, would be to not allow currency codes in Money factory methods, and force a
Currency
instance to be provided.This used to be this way, but this was very unfriendly to use. You want to be able to write:
and not:
So at some point, you have to resolve the currency code from somewhere, and I could not find a better idea than making this a global, singleton configuration.
Now that I'm thinking about it, another option could be to allow a currency code string to be provided for ISO currencies only; custom currencies would need to be provided as a Currency object. This would remove the currency provider bloat entirely. Thoughts?
Side question: the Currency object has this thing called the default fraction digits (default scale, for example 2 for USD/EUR/etc.); do cryptocurrencies have a somewhat official, default scale like traditional currencies?
The text was updated successfully, but these errors were encountered: