andriichuk / laracash
PHP Laravel Money 包
v2.2.0
2024-05-16 03:07 UTC
Requires
- php: ^8.0
- ext-json: *
- illuminate/config: ^7.2|^8.0|^9.0|^10.0|^11.0
- illuminate/contracts: ^7.2|^8.0|^9.0|^10.0|^11.0
- illuminate/database: ^7.30|^8.40|^9.0|^10.0|^11.0
- illuminate/support: ^7.2|^8.0|^9.0|^10.0|^11.0
- moneyphp/money: ^4.0
Requires (Dev)
- ext-bcmath: *
- ext-gmp: *
- ext-intl: *
- orchestra/testbench: ^6.20|^8.0|^9.0
- phpunit/phpunit: ^9.0|^10.5
- vimeo/psalm: ^4.9|^5.6
This package is auto-updated.
Last update: 2024-09-16 03:51:41 UTC
README
- Laravel 对 MoneyPHP 库的封装
- 提供了一种方便的方式处理货币列作为值对象
- 使用 Laravel 7.x 的自定义转换功能
目录
- 功能
- 要求
- 安装
- 支持的概念
- 在表单输入字段中显示货币数据
- 从请求字段解析货币
- 在 API 资源中使用
- 创建模型
- 创建比特币
- 检索数据
- 操作
- 库 API
功能
- 方便地使用原生的 MoneyPHP 库和 Laravel Eloquent ORM
- 货币列转换
- 货币列转换
- 支持的概念
- 具有默认货币(无特定列)的货币列
- 无货币的货币列
- 许多货币列引用一个货币列
- 货币到货币列的映射
要求
- PHP ^8.0
- Laravel v7.x|v8.x
建议
- BCMath(`ext-bcmath`)和 GMP(`ext-gmp`)PHP 扩展用于大整数的计算
- Intl PHP 扩展(`ext-intl`)用于格式化
安装
需要包
composer require andriichuk/laracash
发布供应商设置
php artisan vendor:publish --provider="Andriichuk\Laracash\ServiceProviders\LaracashServiceProvider" --tag="config"
默认设置
[ 'currency' => 'USD', 'locale' => 'en_US', ]
使用概念
具有默认货币的货币列
<?php namespace App; use Andriichuk\Laracash\Casts\MoneyCast; use Illuminate\Database\Eloquent\Model; use Money\Money; /** * Class OrderItem * * @property Money $price * @property Money $discount */ class OrderItem extends Model { protected $fillable = ['name', 'price', 'discount']; protected $casts = [ 'price' => MoneyCast::class, 'discount' => MoneyCast::class, ]; }
OrderItem::create([ 'name' => 'Order Item', 'price' => makeMoney(1000), 'discount' => makeMoney(15), ]);
无货币的货币列
<?php namespace App; use Andriichuk\Laracash\Casts\CurrencyCast; use Andriichuk\Laracash\Model\HasCurrency; use Andriichuk\Laracash\Model\HasCurrencyInterface; use Illuminate\Database\Eloquent\Model; use Money\Currency; /** * Class Rate * * @property Currency $currency */ class Rate extends Model implements HasCurrencyInterface { use HasCurrency; protected $fillable = ['name', 'price', 'currency', 'native_currency']; protected $casts = [ 'currency' => CurrencyCast::class, 'native_currency' => CurrencyCast::class, ]; }
Rate::create([ 'name' => 'Rate #1', 'price' => 99, 'currency' => new Currency('USD'), 'native_currency' => 'UAH', ]);
多个货币列引用一个货币列
use Andriichuk\Laracash\Casts\CurrencyCast; use Andriichuk\Laracash\Casts\MoneyCast; use Andriichuk\Laracash\Model\HasCurrency; use Andriichuk\Laracash\Model\HasMoneyWithCurrency; use Andriichuk\Laracash\Model\HasMoneyWithCurrencyInterface; use Illuminate\Database\Eloquent\Model; use Money\Currency; use Money\Money; /** * Class Transaction * * @property Money $payment_amount * @property Money $discount * @property Currency $currency */ class Transaction extends Model implements HasMoneyWithCurrencyInterface { use HasMoneyWithCurrency; use HasCurrency; protected $fillable = ['name', 'payment_amount', 'discount', 'currency']; protected $casts = [ 'payment_amount' => MoneyCast::class, 'discount' => MoneyCast::class, 'currency' => CurrencyCast::class, ]; public function getCurrencyColumnFor(string $field): string { return 'currency'; } }
如果货币在相关模型中,只需在 `getCurrencyColumnFor()` 中返回一个空字符串(`''`)。
货币到货币列的映射
use Andriichuk\Laracash\Casts\CurrencyCast; use Andriichuk\Laracash\Casts\MoneyCast; use Andriichuk\Laracash\Model\HasCurrency;use Andriichuk\Laracash\Model\HasMoneyWithCurrency; use Andriichuk\Laracash\Model\HasMoneyWithCurrencyInterface; use Illuminate\Database\Eloquent\Model; use Money\Currency; use Money\Money; /** * Class Product * * @property Money $payment_amount * @property Money $discount * @property Currency $currency */ class Product extends Model implements HasMoneyWithCurrencyInterface { use HasMoneyWithCurrency; use HasCurrency; protected $fillable = ['name', 'price', 'currency', 'book_price', 'native_currency']; protected $casts = [ 'price' => MoneyCast::class, 'currency' => CurrencyCast::class, 'book_price' => MoneyCast::class, 'native_currency' => CurrencyCast::class ]; public function getCurrencyColumnFor(string $field): string { return [ 'price' => 'currency', 'book_price' => 'native_currency', ][$field] ?? ''; } }
Product::create([ 'price' => \Money\Money::USD(1000), 'book_price' => Money::UAH(25000), ]);
如果您想使用魔法访问器(`*_as_currency`、`*_as_decimal`)对货币字段进行操作,则应将 `HasMoney` 特性添加到您的 Eloquent 模型中(访问器将自动添加)
<?php namespace App; use Andriichuk\Laracash\Casts\MoneyCast; use Andriichuk\Laracash\Model\HasMoney; use Illuminate\Database\Eloquent\Model; use Money\Money; /** * Class Product * * @property Money $price * @property-read string $price_as_currency * @property-read string $price_as_decimal */ class Product extends Model { use HasMoney; protected $fillable = ['name', 'price']; protected $casts = [ 'price' => MoneyCast::class, ]; }
现在您可以调用魔法字段
use App\Product; $product = Product::find(1); $product->price_as_decimal; // "10.00" $product->price_as_currency; // "$10.00" $product->price = 5000; $product->price_as_decimal; // "50.00" $product->price_as_currency; // "$50.00"
在表单输入字段中显示货币数据
分配模型
use App\Product; use Illuminate\Support\Facades\Route; Route::view('/', 'productForm', ['product' => Product::find(1)]);
将货币对象表示为十进制值
<input type="number" name="price" value="{{ formatMoneyAsDecimal($product->price) }}"> {{-- or with magic syntax --}} <input type="number" name="price" value="{{ $product->price_as_decimal }}">
从请求字段解析货币
use App\Product; use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; Route::post('products/{product}', function (Product $product, Request $request) { $product->price = parseMoneyDecimal($request->get('price')); // 55.99 => Money::USD(5599) });
在 API 资源中使用
定义模型资源
use App\Product; use Illuminate\Http\Resources\Json\JsonResource; /** * Class ProductResource * * @mixin Product */ final class ProductResource extends JsonResource { public function toArray($request): array { return [ 'id' => $this->id, 'name' => $this->name, 'price' => $this->price, 'price_as_currency' => $this->price_as_currency, // or formatMoneyAsCurrency($this->price) ]; } }
将资源应用于模型
use App\Product; use App\Http\Resources\ProductResource; Route::get('products/{product}', function (Product $product) { return new ProductResource($product); });
输出
{ "data": { "id": 1, "name": "Product name", "price": { "amount": "1000", "currency": "USD" }, "price_as_currency": "$10.00" } }
模型创建
使用标量值(int|string)
use App\Product; Product::create([ 'name' => 'The First Product', 'price' => 100, ]);
使用 `Money\Money` 对象
use App\Product; use Money\Money; Product::create([ 'name' => 'The Second Product', 'price' => Money::USD(100), ]);
使用外观
use Andriichuk\Laracash\Facades\Laracash; use App\Product; Product::create([ 'name' => 'The Third Product', 'price' => Laracash::factory()->make(100) ]);
使用辅助函数
use App\Product; Product::create([ 'name' => 'The Fourth Product', 'price' => makeMoney(100) ]);
创建比特币
use Andriichuk\Laracash\Facades\Laracash; use Money\Money; // Using Facade Laracash::factory()->makeBitcoin(1000000000); // Using helper makeBitcoin(1000000000); // Using native library factory call Money::XBT(1000000000);
检索数据
use App\Product; $product = Product::find(1); dd($product->price);
Money\Money {#403 ▼
-amount: "1000"
-currency: Money\Currency {#404 ▼
-code: "USD"
}
}
操作
查看原始库 文档 获取更多信息
use Andriichuk\Laracash\Facades\Laracash; use App\Product; $product = Product::find(1); $product->price = $product->price->add(Laracash::factory()->make(2000)); $product->save();
API
创建
使用 `Laracash` 外观创建货币实例。
*如果您不传递第二个参数 `currency`,则它将从 `config` 文件中获取
use \Andriichuk\Laracash\Facades\Laracash; Laracash::factory()->make(1000); Laracash::factory()->make('10000000000000');
指定货币
use \Andriichuk\Laracash\Facades\Laracash; use \Money\Currency; Laracash::factory()->make(1000, 'USD'); Laracash::factory()->make(1000, new Currency('USD')); // Or use native method Money::USD(100)
Money\Money {#403 ▼
-amount: "1000"
-currency: Money\Currency {#404 ▼
-code: "USD"
}
}
格式化
货币实例格式化。 更多信息
十进制
use \Andriichuk\Laracash\Facades\Laracash; use Money\Money; Laracash::formatter()->formatAsDecimal(Money::USD(100)); // "1.00" formatMoneyAsDecimal(Money::USD(100)); // "1.00"
使用 `Intl` 扩展
use \Andriichuk\Laracash\Facades\Laracash; use Money\Money; Laracash::formatter()->formatAsIntlDecimal(Money::USD(100)); // "1" Laracash::formatter()->formatAsIntlDecimal(Money::USD(100), 'uk_UA'); // "1"
`Intl` 货币
use \Andriichuk\Laracash\Facades\Laracash; use Money\Money; Laracash::formatter()->formatAsIntlCurrency(Money::USD(100)); // "$1.00" Laracash::formatter()->formatAsIntlCurrency(Money::USD(100), 'uk_UA'); // "1,00 USD" formatMoneyAsCurrency(Money::USD(100)); // "$1.00" formatMoneyAsCurrency(Money::XBT(1000000000)); // "Ƀ10.00"
指定自定义 `Intl` 格式化样式
use \Andriichuk\Laracash\Facades\Laracash; use Money\Money; use NumberFormatter; Laracash::formatter()->formatIntlWithStyle(Money::USD(100), 'en_US', NumberFormatter::SPELLOUT); // "one" Laracash::formatter()->formatIntlWithStyle(Money::USD(100), 'en_US', NumberFormatter::SCIENTIFIC); // "1E0"
比特币
use \Andriichuk\Laracash\Facades\Laracash; use Money\Money; Laracash::formatter()->formatBitcoin(Money::XBT(1000000000)); // "Ƀ10.00" // or use helper function formatMoneyAsCurrency(makeBitcoin(1000000000)); // "Ƀ10.00"
比特币作为十进制
use \Andriichuk\Laracash\Facades\Laracash; use Money\Money; Laracash::formatter()->formatBitcoinAsDecimal(Money::XBT(1000000000)); // "10.00000000" // or use helper function formatMoneyAsDecimal(makeBitcoin(1000000000)); // "10.00000000"
解析
使用 `Intl` 解析带货币的货币字符串
use Andriichuk\Laracash\Facades\Laracash; Laracash::parser()->parseIntlCurrency('$1.00');
结果
Money\Money {#369 ▼
-amount: "100"
-currency: Money\Currency {#368 ▼
-code: "USD"
}
}
解析十进制
use Andriichuk\Laracash\Facades\Laracash; Laracash::parser()->parseDecimal('1.30'); parseMoneyDecimal('1.30');
结果
Money\Money {#368 ▼
-amount: "130"
-currency: Money\Currency {#367 ▼
-code: "USD"
}
}
测试
运行特性和单元测试
./vendor/bin/phpunit
致谢
许可证
Laracash 是一个开源软件,根据 MIT 许可证授权。