背景
系統(tǒng)中涉及到金額的字段,View 層表現(xiàn)的時候一般都是以元為單位使用小數(shù)形式展示炭臭,不過 Domain 層存儲時從空間、性能、容錯角度出發(fā)黄选,經(jīng)常以分為單位,用整型來存儲吼野。
在 Lavarel 中聘鳞,可以在 Model 中添加屬性方法進(jìn)行轉(zhuǎn)換
public function getAmountAttribute($value)
{
return $value / 100;
}
public function setAmountAttribute($value)
{
$this->attributes['amount'] = (int)($value * 100);
}
不過涉及金額的字段比較多時就需要定義很多相同邏輯的函數(shù),本項目即將該邏輯抽出為 Trait锹雏,簡化金額字段相關(guān)的處理巴比。
原理
將轉(zhuǎn)換邏輯封裝在 AmountTrait 中,覆寫 Model 類的 getMutatedAttributes, mutateAttributeForArray, getAttributeValue 及 setAttribute 方法礁遵,當(dāng)訪問相關(guān)字段時自動進(jìn)行轉(zhuǎn)換處理轻绞。
public static $amountTimes = 100;
public function getMutatedAttributes()
{
$attributes = parent::getMutatedAttributes();
return array_merge($attributes, $this->getAmountFields());
}
protected function mutateAttributeForArray($key, $value)
{
return (in_array($key, $this->getAmountFields()))
? $value / self::$amountTimes
: parent::mutateAttributeForArray($key, $value);
}
public function getAttributeValue($key)
{
$value = parent::getAttributeValue($key);
if (in_array($key, $this->getAmountFields())) {
$value = $value / self::$amountTimes;
}
return $value;
}
public function setAttribute($key, $value)
{
if (in_array($key, $this->getAmountFields())) {
$value = (int)($value * self::$amountTimes);
}
parent::setAttribute($key, $value);
}
public function getAmountFields()
{
return (property_exists($this, 'amountFields')) ? $this->amountFields : [];
}
依賴
Laravel >= 5.2
安裝
composer require "hao-li/laravel-amount:dev-master"
使用
- 在 Model 中引用 AmountTrait
use HaoLi\LaravelAmount\Traits\AmountTrait;
- 使用 AmountTrait
use AmountTrait;
- 定義金額字段(本例中為 amount)
protected $amountFields = ['amount'];
- 完成
之后讀取 amount 字段時,該字段的內(nèi)容會自動從數(shù)據(jù)庫的分轉(zhuǎn)換為元佣耐,向其賦值時反之從元轉(zhuǎn)換為分政勃。
FAQ
和別的 trait 中方法沖突
以 setRawAttributes 為例(此為之前方案,目前并未覆寫此方法兼砖,僅為舉例奸远,其他方法原理相同)
- 將沖突的方法分別重命名
use AmountTrait, BTrait {
AmountTrait::setRawAttributes as amountTraitSetRawAttributes;
BTrait::setRawAttributes as BTraitSetRawAttributes;
}
- 在 Model 中定義該沖突的方法既棺,根據(jù)情況分別調(diào)用別名方法
public function setRawAttributes(array $attributes, $sync = false)
{
$this->BTraitSetRawAttributes($attributes, $sync);
$attributes = $this->getAttributes();
$this->amountTraitSetRawAttributes($attributes, $sync);
}
注意這里 $attributes 可能已被改變,所以再次使用時要重新取得最新值