Installation
composer require boonkuaeboonsutta/fx-rate-bundle
Configure Routes
Create config/routes/bk_fx_rate.yml:
_bk_fx_rate:
resource: '@BKFxRateBundle/Resources/config/routes.xml'
prefix: /api/fxrate/
Configure API Endpoint
Create config/packages/bk_fx_rate.yml:
bk_fx_rate:
endpoints: https://forex.1forge.com/1.0.3/convert
api_key: 'your_api_key_here'
First Use Case Inject the service in a controller or service:
use BK\FxRateBundle\Service\FxRateService;
class CurrencyController extends Controller
{
public function __construct(private FxRateService $fxRateService) {}
public function convert(Request $request)
{
$amount = $request->input('amount');
$from = $request->input('from');
$to = $request->input('to');
$result = $this->fxRateService->convert($amount, $from, $to);
return response()->json($result);
}
}
Currency Conversion
Use the convert() method to fetch real-time exchange rates:
$rate = $this->fxRateService->convert(100, 'USD', 'EUR');
Dependency Injection
Autowire FxRateService in any class where currency conversion is needed:
public function __construct(private FxRateService $fxRateService) {}
API Integration Extend the service to handle additional endpoints or custom logic:
$this->fxRateService->setEndpoint('https://custom-api.com/convert');
Caching (Manual) Cache responses to avoid repeated API calls (not built-in; implement via Laravel Cache):
$cacheKey = "fxrate_{$from}_{$to}";
$rate = Cache::remember($cacheKey, now()->addHours(1), function () use ($fxRateService, $amount, $from, $to) {
return $fxRateService->convert($amount, $from, $to);
});
success flag or error fields).try {
$rate = $this->fxRateService->convert($amount, $from, $to);
} catch (\Exception $e) {
Log::error("FX Rate API Error: " . $e->getMessage());
return response()->json(['error' => 'Service unavailable'], 503);
}
FxRateService in unit tests:
$this->mock(FxRateService::class)->shouldReceive('convert')->andReturn(['rate' => 0.85]);
Deprecated API
The underlying forex.1forge.com API may be outdated or discontinued. Verify endpoint availability before production use.
No Built-in Caching The bundle does not cache responses by default. Implement caching manually (e.g., Laravel Cache, Redis) to avoid hitting API rate limits.
Hardcoded Endpoint
The endpoints config key is singular, implying only one API can be configured. For multi-provider support, extend the service or use a facade pattern.
No Type Safety
API responses are likely returned as raw arrays. Validate and cast responses to typed objects (e.g., FxRateResponse) for safer usage:
class FxRateResponse {
public function __construct(
public float $rate,
public string $from,
public string $to,
public float $amount
) {}
}
Rate Limiting
The API may throttle requests. Monitor HTTP status codes (e.g., 429) and implement retries with exponential backoff.
$this->fxRateService->setLogger(function ($response) {
Log::debug('FX Rate API Response', ['response' => $response]);
});
api_key is correctly passed in headers (if required by the API). The bundle may not handle this automatically.Custom Providers
Extend FxRateService to support multiple APIs:
class MultiFxRateService extends FxRateService {
public function convertWithProvider(string $provider, float $amount, string $from, string $to) {
$this->setEndpoint($this->getProviderEndpoint($provider));
return parent::convert($amount, $from, $to);
}
}
Webhook Support Add a listener to update exchange rates via webhooks (e.g., from a financial provider):
Event::listen('fxrate.updated', function ($rate) {
Cache::put("fxrate_{$rate->from}_{$rate->to}", $rate->rate, now()->addHours(1));
});
Fallback Mechanism Implement a fallback to a secondary API if the primary fails:
try {
return $this->fxRateService->convert($amount, $from, $to);
} catch (\Exception $e) {
$this->fxRateService->setEndpoint('https://fallback-api.com/convert');
return $this->fxRateService->convert($amount, $from, $to);
}
bk_fx_rate in config/packages/bk_fx_rate.yml matches the bundle’s namespace (BK\FxRateBundle).api_key in .env and reference it in the config:
bk_fx_rate:
api_key: '%env(FX_RATE_API_KEY)%'
How can I help you explore Laravel packages today?