composer require yuwuhsien/laravel-bcmath-cast
AsDecimal cast to your Eloquent model's casts() method:
use YuWuHsien\Decimal\Casts\AsDecimal;
class Product extends Model
{
protected $casts = [
'price' => AsDecimal::class,
];
}
$product = Product::find(1);
$product->price = $product->price * 1.1; // Applies 10% tax
$product->save();
AsFloat, AsInteger).Arithmetic Operations:
Use native operators (+, -, *, /, %) on model attributes for arbitrary-precision calculations:
$order->subtotal = $order->subtotal + $item->price * $item->quantity;
$order->tax = $order->subtotal * 0.08;
Comparison Logic: Leverage BCMath’s precision for financial comparisons:
if ($product->price > $budget) {
// Handle out-of-budget case
}
Database Storage:
The cast automatically serializes/deserializes BCMath\Number to/from the database (default: string type). Customize via:
protected $casts = [
'price' => [AsDecimal::class, 'precision' => 4], // Stores as DECIMAL(10,4)
];
Query Filtering:
Use where clauses with BCMath-compatible syntax:
// Finds products priced between $10 and $20
Product::where('price', '>=', new BCMath\Number('10'))
->where('price', '<=', new BCMath\Number('20'))
->get();
Order, Product, Invoice, or Payment models where precision matters.$products->each(fn ($p) => $p->update(['price' => $p->price * 0.95])); // 5% discount
numeric rule for input validation:
$request->validate(['price' => 'required|numeric']);
public function getDiscountedPriceAttribute()
{
return $this->price * new BCMath\Number('0.9');
}
BCMath\Number in unit tests:
$this->partialMock(BCMath\Number::class, ['__toString']);
PHP Version Requirement:
Class 'BCMath\Number' not found if PHP < 8.4.Database Precision:
string may cause performance overhead or truncation in DECIMAL columns.'price' => [AsDecimal::class, 'precision' => 10, 'scale' => 4]
Operator Precedence:
// Correct: ($price * $quantity) + $tax
// Incorrect: $price * $quantity + $tax (may evaluate as $price * ($quantity + $tax))
Serialization:
"123.45"). Parse back to BCMath\Number if reusing in calculations:
$number = new BCMath\Number($jsonString);
Type Mismatches:
BCMath\Number or compatible types (e.g., string/float will auto-convert).(string) $model->price; // Check raw value
Database Errors:
DECIMAL(10,4) for 4 decimal places).Schema::table('products', function (Blueprint $table) {
$table->decimal('price', 10, 4)->change();
});
Performance:
$products->each(fn ($p) => $p->update(['price' => $p->price * $rate]));
Custom Operators:
bcmod):
// In a custom cast class
public function get($model, string $key, $value, array $attributes)
{
$number = new BCMath\Number($value);
return bcmod($number, new BCMath\Number('100'), 0); // Modulo operation
}
Testing Edge Cases:
bcadd('1e20', '1')).$total = new BCMath\Number('1.23456');
$rounded = bcscale(2, $total); // Returns "1.23"
Fallback for Older PHP:
bcmath() functions if BCMath\Number is unavailable:
if (class_exists(BCMath\Number::class)) {
$result = $a * $b; // BCMath\Number
} else {
$result = bcadd(bcmul($a, $b), 0, 2); // Legacy bcmath
}
Laravel Mixins:
// app/Models/Concerns/UsesBCMath.php
trait UsesBCMath {
public function bcAdd($value) {
return $this->{$this->getKeyName()} = $this->{$this->getKeyName()} + $value;
}
}
How can I help you explore Laravel packages today?