【发布时间】:2016-05-24 14:40:06
【问题描述】:
我使用整数将钱存储在我的数据库中。这意味着 0.50 美元是 50。我扩展了 Integer db 字段,使其现在可以在前端正常工作。它很好地转换为整数。
在后端,但是我遇到了问题。 silverstripe CMS 似乎进行了自己的转换(例如添加千位分隔符),结果很有趣:)。
你们会如何解决这个问题?我尝试使用 onbeforewrite 和自定义 getter。
这是我的代码,从整数 db-field 的扩展开始
/**
* Format a number to currency
* @param int $number_of_decimals When larger than 0 it will return this number of decimals, AND divide the amount by 10^number of the amount of decimals
* @param bool $round Round the resulting number to the closest whole number
* @param string $thousands_char Character used as thousands separator
* @param string $decimal_char Character used as decimal separator
* @return string
*/
public function toCurrency($number_of_decimals=2, $round=false, $thousands_char=".", $decimal_char=",") {
$divide_by = pow(10,$number_of_decimals);
$value = $this->owner->value/$divide_by;
if($round) {
//no decimals when rounding :)
$number_of_decimals=0;
}
return number_format($value, $number_of_decimals, $decimal_char,$thousands_char);
}
public function fromCurrency($number_of_decimals=2, $thousands_char=".", $decimal_char=",") {
$multiply_by = pow(10,$number_of_decimals);
//get rid of the thousand separator
$value = str_replace($thousands_char,"",$this->owner->value);
//replace the decimal char with a point
$value = str_replace($decimal_char,".",$value);
$value = $value*$multiply_by;
return number_format($value, 0, ".","");
}
我还将它添加到 SiteConfig 的扩展中(从而创建了一种全局可用的功能
/**
* Creates a DBField equivalent of the value, based on the type. In such a way, we can make use of the dame functions that are in an extension of a dbfield.
* @param $type The type of the DBfield to create (e.g. Varchar, Int etc.).
* @param $value The value, a string or number
* @return mixed
*/
public function ToDBField($type,$value) {
$field = $type::create();
$field->setValue($value);
return $field;
}
这些函数做实际的工作,它们在一个数据对象中:
public function GetAmount() {
$amount = parent::getField("Amount");
if (is_subclass_of(Controller::curr(), "LeftAndMain")) {
$int_amount = SiteConfig::current_site_config()->ToDBField("Int", $amount);
return $int_amount->toCurrency($number_of_decimals=2, $round=false, $thousands_char="", $decimal_char=".");
}
return $amount;
}
public function onBeforeWrite() {
$int_amount = SiteConfig::current_site_config()->ToDBField("Int", $this->Amount);
$this->Amount = $int_amount->fromCurrency(2,",",".");
parent::onBeforeWrite();
}
【问题讨论】:
-
我们能看看你的 DataObject 长什么样吗?我很好奇您为什么使用整数 DB 字段,而您可以使用 Currency 字段。这加上其他一些对您的代码的调整,应该可以帮助您获得想要的工作。
-
嗯,主要是因为精确度以及某些货币没有小数点的事实,而其他货币则有。顺便说一句,我不知道货币字段。
-
那么对于您的场景,扩展一个 DBField(整数或货币)怎么样?扩展它应该可以让您更好地处理多种货币(因为否则这两个字段都不会非常适合)并可能扩展其中一个 FormField 以最好地在 CMS 中呈现您的自定义 DBField。话虽如此,您没有提到 CMS 当前使用的 FormField 元素是 NumericField 还是 CurrencyField?我们可以看到一些与您当前如何进行此设置相关的代码吗?
-
我添加了一些代码。在 CMS 中,我只使用了可用于整数字段的脚手架。也许我应该将其转换为 varchar 字段。
-
首先我想提的是你的 SiteConfig 扩展,听起来你很成熟/非常想使用
DbField::create_field。对于您的应用程序,您希望在 CMS 中有一个数字字段来更改整数值还是转换为整数的货币格式字符串?
标签: silverstripe