Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Bcmath Cast Laravel Package

yuwuhsien/laravel-bcmath-cast

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation: Require the package via Composer:
    composer require yuwuhsien/laravel-bcmath-cast
    
  2. Model Setup: Add the AsDecimal cast to your Eloquent model's casts() method:
    use YuWuHsien\Decimal\Casts\AsDecimal;
    
    class Product extends Model
    {
        protected $casts = [
            'price' => AsDecimal::class,
        ];
    }
    
  3. First Use Case: Perform arithmetic operations directly on model attributes:
    $product = Product::find(1);
    $product->price = $product->price * 1.1; // Applies 10% tax
    $product->save();
    

Where to Look First

  • Package README: Focus on the "Usage" section for basic syntax.
  • BCMath\Number Docs: Understand PHP 8.4's native operator overloading (PHP Manual).
  • Laravel Eloquent Casts: Review Laravel’s built-in casts for comparison (e.g., AsFloat, AsInteger).

Implementation Patterns

Usage Patterns

  1. 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;
    
  2. Comparison Logic: Leverage BCMath’s precision for financial comparisons:

    if ($product->price > $budget) {
        // Handle out-of-budget case
    }
    
  3. 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)
    ];
    
  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();
    

Workflows

  • Financial Models: Ideal for Order, Product, Invoice, or Payment models where precision matters.
  • Batch Updates: Apply arithmetic to collections:
    $products->each(fn ($p) => $p->update(['price' => $p->price * 0.95])); // 5% discount
    
  • API Responses: Serialize to JSON/arrays automatically (returns string representation).

Integration Tips

  • Validation: Combine with Laravel’s numeric rule for input validation:
    $request->validate(['price' => 'required|numeric']);
    
  • Accessors/Mutators: Override for custom logic while retaining BCMath precision:
    public function getDiscountedPriceAttribute()
    {
        return $this->price * new BCMath\Number('0.9');
    }
    
  • Testing: Mock BCMath\Number in unit tests:
    $this->partialMock(BCMath\Number::class, ['__toString']);
    

Gotchas and Tips

Pitfalls

  1. PHP Version Requirement:

    • Error: Class 'BCMath\Number' not found if PHP < 8.4.
    • Fix: Upgrade PHP or use a polyfill (though this package requires native BCMath\Number).
  2. Database Precision:

    • Issue: Storing high-precision numbers as string may cause performance overhead or truncation in DECIMAL columns.
    • Fix: Explicitly set precision in the cast:
      'price' => [AsDecimal::class, 'precision' => 10, 'scale' => 4]
      
  3. Operator Precedence:

    • Gotcha: Parentheses are required for complex expressions:
      // Correct: ($price * $quantity) + $tax
      // Incorrect: $price * $quantity + $tax (may evaluate as $price * ($quantity + $tax))
      
  4. Serialization:

    • Warning: JSON/API responses return strings (e.g., "123.45"). Parse back to BCMath\Number if reusing in calculations:
      $number = new BCMath\Number($jsonString);
      

Debugging

  • Type Mismatches:

    • Ensure all operations use BCMath\Number or compatible types (e.g., string/float will auto-convert).
    • Debug: Cast to string to inspect:
      (string) $model->price; // Check raw value
      
  • Database Errors:

    • Verify your database column type supports the precision (e.g., DECIMAL(10,4) for 4 decimal places).
    • Fix: Migrate columns if needed:
      Schema::table('products', function (Blueprint $table) {
          $table->decimal('price', 10, 4)->change();
      });
      

Tips

  1. Performance:

    • For bulk operations, minimize database writes by batching updates:
      $products->each(fn ($p) => $p->update(['price' => $p->price * $rate]));
      
  2. Custom Operators:

    • Extend the cast to support additional BCMath functions (e.g., 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
      }
      
  3. Testing Edge Cases:

    • Test with very large/small numbers (e.g., bcadd('1e20', '1')).
    • Verify rounding behavior:
      $total = new BCMath\Number('1.23456');
      $rounded = bcscale(2, $total); // Returns "1.23"
      
  4. Fallback for Older PHP:

    • Use a feature flag or conditional logic to fall back to 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
      }
      
  5. Laravel Mixins:

    • Add a global trait to all models for convenience:
      // app/Models/Concerns/UsesBCMath.php
      trait UsesBCMath {
          public function bcAdd($value) {
              return $this->{$this->getKeyName()} = $this->{$this->getKeyName()} + $value;
          }
      }
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium