andriichuk/laracash
Composer 安装命令:
composer require andriichuk/laracash
包简介
PHP Laravel Money Package
README 文档
README
- Laravel wrapper over the MoneyPHP library
- Provides a convenient way to work with the money column as a Value Object
- Uses the Custom Casts Laravel 7.x feature
Table of Contents
- Features
- Requirements
- Installation
- Supported concepts
- Display money data in the form input field
- Parse money from request field
- Using in API resources
- Model creation
- Bitcoin creation
- Retrieving data
- Operations
- Library API
Features
- Convenient work with the native the MoneyPHP library and Laravel Eloquent ORM
- Money columns casting
- Currencies columns casting
- Supported concepts
- Money columns with default Currency (without a specific column)
- Currency columns without Money
- Many Money columns reference to one Currency column
- Money to Currencies columns mapping
Requirements
- PHP ^8.0
- Laravel v7.x|v8.x
Suggest
- BCMath (
ext-bcmath) and GMP (ext-gmp) PHP Extensions for calculations with large integers - Intl PHP Extension (
ext-intl) for formatting
Installation
Require package
composer require andriichuk/laracash
Publish vendor settings
php artisan vendor:publish --provider="Andriichuk\Laracash\ServiceProviders\LaracashServiceProvider" --tag="config"
Default settings
[
'currency' => 'USD',
'locale' => 'en_US',
]
Usage Concepts
Money columns with default Currency
<?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), ]);
Currency columns without Money
<?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', ]);
Multiple Money columns refer to one Currency column
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'; } }
If the currency is in a related model, just return an empty string (
'') ingetCurrencyColumnFor().
Money to Currencies columns mapping
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), ]);
If you want to use magic accessors (*_as_currency, *_as_decimal) for money fields then you should add HasMoney trait to your Eloquent Model (accessors will be added automatically)
<?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, ]; }
Now you can call magic fields
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"
Display money data in the form input field
Assign model
use App\Product; use Illuminate\Support\Facades\Route; Route::view('/', 'productForm', ['product' => Product::find(1)]);
Present money object as a decimal value
<input type="number" name="price" value="{{ formatMoneyAsDecimal($product->price) }}"> {{-- or with magic syntax --}} <input type="number" name="price" value="{{ $product->price_as_decimal }}">
Parse money from request field
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) });
Using in API resources
Define model resource
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) ]; } }
Apply resource to the model
use App\Product; use App\Http\Resources\ProductResource; Route::get('products/{product}', function (Product $product) { return new ProductResource($product); });
Output
{
"data": {
"id": 1,
"name": "Product name",
"price": {
"amount": "1000",
"currency": "USD"
},
"price_as_currency": "$10.00"
}
}
Model Creation
Using scalar values (int|string)
use App\Product; Product::create([ 'name' => 'The First Product', 'price' => 100, ]);
Using Money\Money object:
use App\Product; use Money\Money; Product::create([ 'name' => 'The Second Product', 'price' => Money::USD(100), ]);
Using facade:
use Andriichuk\Laracash\Facades\Laracash; use App\Product; Product::create([ 'name' => 'The Third Product', 'price' => Laracash::factory()->make(100) ]);
Using helper function:
use App\Product; Product::create([ 'name' => 'The Fourth Product', 'price' => makeMoney(100) ]);
Bitcoin creation
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);
Retrieving data
use App\Product; $product = Product::find(1); dd($product->price);
Money\Money {#403 ▼
-amount: "1000"
-currency: Money\Currency {#404 ▼
-code: "USD"
}
}
Operations
Check original library docs for more information
use Andriichuk\Laracash\Facades\Laracash; use App\Product; $product = Product::find(1); $product->price = $product->price->add(Laracash::factory()->make(2000)); $product->save();
API
Creation
Money instance creation using Laracash facade.
*If you do not pass the second argument currency, then it will take from config file
use \Andriichuk\Laracash\Facades\Laracash; Laracash::factory()->make(1000); Laracash::factory()->make('10000000000000');
Specify currency
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"
}
}
Formatting
Money instance formatting. More info
Decimal
use \Andriichuk\Laracash\Facades\Laracash; use Money\Money; Laracash::formatter()->formatAsDecimal(Money::USD(100)); // "1.00" formatMoneyAsDecimal(Money::USD(100)); // "1.00"
Using Intl extension
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 currency
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"
Specify custom Intl formatting style
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"
Bitcoin
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"
Bitcoin as decimal
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"
Parsing
Intl parse money string with currency
use Andriichuk\Laracash\Facades\Laracash; Laracash::parser()->parseIntlCurrency('$1.00');
Result
Money\Money {#369 ▼
-amount: "100"
-currency: Money\Currency {#368 ▼
-code: "USD"
}
}
Parse decimal
use Andriichuk\Laracash\Facades\Laracash; Laracash::parser()->parseDecimal('1.30'); parseMoneyDecimal('1.30');
Result
Money\Money {#368 ▼
-amount: "130"
-currency: Money\Currency {#367 ▼
-code: "USD"
}
}
Tests
Run features and unit tests:
./vendor/bin/phpunit
Credits
License
Laracash is an open-sourced software licensed under the MIT license.
andriichuk/laracash 适用场景与选型建议
andriichuk/laracash 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 109.27k 次下载、GitHub Stars 达 75, 最近一次更新时间为 2020 年 03 月 21 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「money」 「laravel」 「ValueObject」 「Laracash」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 andriichuk/laracash 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 andriichuk/laracash 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 andriichuk/laracash 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Beyonic PHP Library
Value objects
This helper can create object from passed classname and value, or return null, if passed value is also null
Helpers to implement the Value Object pattern in Laravel 5
Collection of handy Value Objects
The Payum Yandex Money gateway
统计信息
- 总下载量: 109.27k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 75
- 点击次数: 19
- 依赖项目数: 1
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2020-03-21
