yuwuhsien / eloquent-bcmath-cast
Laravel Eloquent casts for PHP 8.4's BCMath\Number object API
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/yuwuhsien/eloquent-bcmath-cast
Requires
- php: ^8.4
- ext-bcmath: *
- illuminate/contracts: ^11.0
- illuminate/database: ^11.0
Requires (Dev)
- laravel/pint: ^1.25
- orchestra/testbench: ^9.15
- pestphp/pest: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
- phpstan/extension-installer: ^1.3
- phpstan/phpstan: ^1.10
- phpstan/phpstan-phpunit: ^1.3
README
Laravel BCMath Cast
Laravel Eloquent casts for PHP 8.4's BCMath\Number object API, enabling natural operator-based arithmetic on model attributes while maintaining arbitrary precision decimal accuracy.
Why This Package?
PHP 8.4 introduced the BCMath\Number class with operator overloading, transforming cumbersome decimal calculations:
// Old way with BCMath functions $total = bcadd(bcmul($price, $quantity), $tax, 2); // New way with BCMath\Number $total = ($price * $quantity) + $tax;
This package bridges Laravel's Eloquent ORM with PHP 8.4's BCMath\Number, letting you write clean, precise arithmetic directly on model attributes.
Read more: BCMath Object API in PHP 8.4
Requirements
- PHP 8.4+ (for
BCMath\Numberclass) - Laravel 11.x
Installation
composer require yuwuhsien/laravel-bcmath-cast
Usage
Basic Usage
Add the AsDecimal cast to your Eloquent model:
use YuWuHsien\Decimal\Casts\AsDecimal; class Product extends Model { protected function casts(): array { return [ 'price' => AsDecimal::class, 'cost' => AsDecimal::class, 'tax_rate' => AsDecimal::class, ]; } }
Now your model attributes are automatically converted to BCMath\Number objects:
$product = Product::create([ 'price' => '19.99', 'cost' => '12.50', 'tax_rate' => '0.0825', ]); // Attributes are BCMath\Number instances $product->price instanceof Number; // true // Perform precise calculations with natural operators $margin = $product->price - $product->cost; // Number('7.49') $marginPercent = ($margin / $product->cost) * new Number('100'); // Number('59.92') // Calculate total with tax $total = $product->price * (new Number('1') + $product->tax_rate); // Number('21.639175')
Setting Values
The cast accepts multiple input types:
// BCMath\Number objects $product->price = new Number('29.99'); // Numeric strings (recommended for precision) $product->price = '29.99'; // Integers $product->price = 30; // Floats (works but may lose precision - triggers warning) $product->price = 29.99; // ⚠️ Warning: precision loss possible
Database Column Types
Use DECIMAL columns, NOT FLOAT:
Schema::create('products', function (Blueprint $table) { $table->decimal('price', 10, 2); // ✅ Correct $table->decimal('cost', 10, 4); // ✅ Correct $table->float('amount'); // ❌ Wrong - loses precision });
The DECIMAL type preserves exact decimal values. Floats introduce rounding errors that defeat the purpose of BCMath.
Testing
# Run tests composer test # Run tests with coverage composer test-coverage # Run static analysis composer analyse
License
The MIT License (MIT). Please see License File for more information.