spatie/tax-calculator
Interfaces and helpers to simplify tax calculations in PHP. Use TaxCalculation with plain numbers or items implementing HasTax to compute base, tax, and total prices, and combine calculations (e.g., cart items + delivery) on the fly.
HasTax contract), making it highly modular and composable. This aligns well with Laravel’s dependency injection and service container patterns, enabling seamless integration into existing tax logic without tight coupling.Order, Cart). This improves separation of concerns and testability.HasTax is implemented). Minimal boilerplate required for basic use cases.taxPrice()) assume standard VAT calculations. Complex scenarios (e.g., tiered rates, exemptions) may require custom logic.HasTax) need optimization? Benchmark against custom implementations.Order models) migrate to the HasTax interface? Requires a phased refactor.HasTax on Product, OrderItem, or Cart models.TaxCalculation into services (e.g., CheckoutService) via constructor.Phase 1: Interface Adoption
HasTax to critical models (e.g., Product, OrderItem).class Product implements HasTax {
public function getTaxRate(): float { return $this->tax_rate; }
public function getTaxablePrice(): float { return $this->price; }
}
HasTax contracts.Phase 2: Core Logic Replacement
Order model) with TaxCalculation calls:
// Before
$order->subtotal * (1 + $order->tax_rate);
// After
TaxCalculation::fromCollection($order->items)->taxedPrice();
Phase 3: Edge Cases
TaxCalculation for custom rules (e.g., shipping tax):
class CustomTaxCalculation extends TaxCalculation {
public function calculateShippingTax(float $price): float {
return $price * config('tax.shipping_rate');
}
}
spatie/laravel-activitylog, laravel/breeze).getTaxRate()/getTaxablePrice() methods return float (not string or int).| Step | Priority | Effort | Dependencies |
|---|---|---|---|
Add HasTax to models |
High | Medium | None |
| Replace core tax logic | High | High | HasTax implementation |
| Extend for custom rules | Low | Medium | Core integration done |
| Write tests | Critical | High | All implementations |
| Deprecate old logic | Low | Low | Test coverage |
dd(TaxCalculation::debug()) to inspect intermediate calculations.event(new TaxCalculated($order, $taxBreakdown))) for audits.bcmath or round() where needed.config('tax.rates')) if they’re static to avoid repeated DB lookups.| Scenario | Impact | Mitigation |
|---|---|---|
| Package update breaks | Tax calculations fail silently | Fork and pin version in composer.json |
HasTax not implemented |
Runtime errors | Use instanceof checks or fallbacks |
| Tax rate data missing | Incorrect calculations | Validate getTaxRate() returns > 0 |
| Floating-point errors | Rounding discrepancies | Use number_format() for display |
HasTax.TaxCalculation methods, and edge cases.HasTax consistency.HasTax on 1 model (e.g., Product).How can I help you explore Laravel packages today?