dotdev/currency
PHP currency conversion component for objects, originally from the Sylius ecosystem. Provides a lightweight engine for converting between currencies in your applications. See Sylius docs for usage, contributions, and issue tracking.
## Technical Evaluation
### Architecture Fit
- **Modular Design**: The package is a **standalone currency conversion component**, making it ideal for **Laravel applications requiring multi-currency support** without coupling to Sylius. It aligns with Laravel’s **service container** and **dependency injection** patterns, allowing seamless integration into existing architectures.
- **Domain-Specific Features**: Provides **currency-aware objects**, **exchange rate management**, and **localized formatting**, which are critical for eCommerce, fintech, or localization-heavy applications. However, it lacks **real-time API integrations** or **advanced financial features** (e.g., tax calculations), which may require additional layers.
- **Laravel Synergy**: While not Laravel-specific, its **PSR-compliant** nature ensures compatibility with Laravel’s ecosystem. For example, it can integrate with **Laravel’s config system**, **Eloquent models**, or **Blade directives** for UI rendering.
### Integration Feasibility
- **Core Functionality**:
- **Currency Conversion**: Supports static/dynamic rate conversions (e.g., `USD → EUR`).
- **Monetary Formatting**: Localized number formatting (e.g., `1,000.00` vs. `1.000,00`).
- **Rate Management**: Manual or external API-driven rate updates (though API integration is not built-in).
- **Laravel-Specific Implementation**:
- **Service Provider**: Requires binding the package’s `CurrencyConverterInterface` to its implementation in Laravel’s container.
- **Configuration**: Exchange rates and default currency can be managed via Laravel’s `config/currency.php`.
- **Database**: If using dynamic rates, a migration for an `exchange_rates` table may be needed.
- **Caching**: Recommended to cache rates (e.g., Redis) for performance, though the package does not enforce this.
- **Dependencies**:
- Minimal (PHP standard library + optional HTTP client for API rates).
- **No Laravel-specific dependencies**, reducing conflict risk with existing packages.
### Technical Risk
- **Archived Status**:
- Last release in **2022**, with **no active maintenance**. Risks include:
- **Stale documentation** (Sylius docs may no longer align).
- **Unpatched vulnerabilities** (though MIT license mitigates legal risk).
- **Limited community support** (fallback to Sylius issue tracker).
- **Feature Gaps**:
- **No built-in API integrations** (e.g., Open Exchange Rates, ECB). Requires manual setup.
- **No Laravel-specific helpers** (e.g., Eloquent macros, Blade directives).
- **No testing framework** for Laravel-specific edge cases (e.g., caching, queue jobs).
- **Precision and Edge Cases**:
- Financial calculations require **high precision** (e.g., `decimal(19,6)`). The package must handle rounding errors correctly, which may need validation.
### Key Questions
1. **Why Not Alternatives?**
- Does this package offer **unique eCommerce-specific features** (e.g., Sylius optimizations) that `moneyphp/money` or `league/currency` lack?
- Is **domain modeling** (e.g., `Money` objects with metadata) critical for the product?
2. **Exchange Rate Strategy**:
- Will rates be **hardcoded, API-fetched, or database-driven**? How will this be configured in Laravel?
- What’s the **fallback mechanism** if the API fails (e.g., cached rates)?
3. **Performance**:
- For high-volume apps, will **rate caching** (Redis) be required? Is this supported out-of-the-box?
- How will **concurrent conversions** scale (e.g., during Black Friday sales)?
4. **Localization**:
- Does the package handle **pluralization, decimal separators, or currency symbols** per locale? If not, how will Laravel’s `locale` config or `laravel-localization` integrate?
5. **Fallback Plan**:
- If the package is abandoned, what’s the **migration path** to alternatives like `spatie/money` or `moneyphp/money`?
- How will **backward compatibility** be maintained during potential migrations?
---
## Integration Approach
### Stack Fit
- **PHP/Laravel**: The package is **PSR-compliant** and framework-agnostic, making it a **natural fit** for Laravel. It avoids Laravel-specific dependencies, reducing integration friction.
- **Alternatives Considered**:
- **`moneyphp/money`**: More mature, but lacks eCommerce-specific features.
- **`league/currency`**: Simpler, but less feature-rich for complex use cases.
- **Laravel’s `money` facade**: Basic, but requires customization for advanced scenarios.
- **Decision Drivers**:
- Need for **Sylius compatibility** (if migrating from Sylius).
- Requirement for **domain-specific currency logic** (e.g., tax-inclusive pricing).
- Preference for **MIT-licensed** (vs. proprietary) solutions.
### Migration Path
1. **Evaluation Phase**:
- Spin up a **Laravel sandbox** to test:
- Currency conversion accuracy (e.g., `100 USD = 92.50 EUR`).
- Integration with existing `Money` models or pricing logic.
- Performance under load (e.g., 1,000 concurrent conversions).
2. **Dependency Setup**:
- Add to `composer.json`:
```bash
composer require dotdev/currency
```
- Publish config (if needed):
```bash
php artisan vendor:publish --tag="currency-config" --provider="Dotdev\Currency\CurrencyServiceProvider"
```
3. **Service Binding**:
- Register the package’s service provider in `config/app.php`:
```php
Dotdev\Currency\CurrencyServiceProvider::class,
```
- Bind interfaces to implementations in a **custom service provider** (e.g., `app/Providers/CurrencyServiceProvider.php`):
```php
$this->app->bind(
Dotdev\Currency\CurrencyConverterInterface::class,
Dotdev\Currency\CurrencyConverter::class
);
```
4. **Database Schema** (if applicable):
- Create a migration for `exchange_rates`:
```php
Schema::create('exchange_rates', function (Blueprint $table) {
$table->string('base_currency');
$table->string('target_currency');
$table->decimal('rate', 19, 6);
$table->timestamps();
});
```
5. **Testing**:
- Write **Pest/PHPUnit tests** for:
- Conversion accuracy (e.g., `assertEquals(92.50, $converter->convert(100, 'USD', 'EUR'))`).
- Edge cases (e.g., zero rates, unsupported currencies).
- Integration with payment gateways or invoicing logic.
### Compatibility
- **Laravel Versions**:
- Likely compatible with **Laravel 8+** (PHP 8.0+). Test with the target Laravel version.
- **PHP Extensions**:
- No special requirements (unlike `intl` for some localization packages).
- **Conflict Risk**:
- Low risk of dependency conflicts (minimal dependencies).
- Potential naming collisions with existing `Money` classes (use **fully qualified namespaces**).
### Sequencing
1. **Phase 1: Core Integration**
- Implement basic conversion and formatting.
- Replace hardcoded currency logic (e.g., in controllers or models) with package calls.
- Example:
```php
$amount = $converter->convert(100, 'USD', 'EUR'); // Returns 92.50
```
2. **Phase 2: Advanced Features**
- Add API-based rate fetching (e.g., ECB or ExchangeRate-API).
- Implement caching (Redis) for rate lookups:
```php
$rate = Cache::remember("exchange_rate_{$base}_{$target}", now()->addHours(1), function () use ($base, $target) {
return $this->fetchRateFromApi($base, $target);
});
```
3. **Phase 3: Optimization**
- Benchmark and optimize for high-traffic endpoints (e.g., checkout pages).
- Add monitoring for failed conversions (e.g., Sentry alerts).
---
## Operational Impact
### Maintenance
- **Pros**:
- **MIT license** allows forking/modifications.
- **Simple codebase** (likely <1k LOC) = easier to maintain internally.
- **Cons**:
- **No active maintenance** → bugs or security issues may go unpatched.
- **Documentation reliance on Sylius** (may be outdated).
- **Mitigation Strategies**:
- **Fork the repo** on GitHub to apply critical fixes.
- **Add to `composer.json` as a "private" package** to control updates:
```json
"repositories": [
{
"type": "vcs",
"url": "https://github.com/your-team/currency.git"
}
],
"require": {
"your-team/currency": "dev-main"
}
```
- **Add unit tests** to prevent regressions.
### Support
How can I help you explore Laravel packages today?