How to Get Currency Exchange Rates in Laravel
Tags: laravel, php, webdev, tutorial
Published: 2021-10-21 13:58:52

## Introduction

Sometimes when you're building web applications, you might need some functionality that deals with different currencies from around the world. To be able to work with different currencies, you need to find the exchange rates.

In this article, we're going to look at how to use the [Laravel Exchange Rates](https://github.com/ash-jc-allen/laravel-exchange-rates) package to interact with the [exchangeratesapi.io](http://exchangeratesapi.io) API. We'll also take a look at how to use it to get the latest or historical exchange rates and convert monetary values between different currencies.

<p align="center">
<img src="https://ashallendesign.co.uk/images/custom/laravel-exchange-rates-logo.png" alt="Laravel Exchange Rates" width="600">
</p>

## Installation

To get started with using the Laravel Exchange Rates package, we'll first need to run the following command to install it using Composer:

```
composer require ashallendesign/laravel-exchange-rates
```

### Getting Your API Key

Now that we have the package installed, we'll need to get an API key from from [https://exchangeratesapi.io/pricing](https://exchangeratesapi.io/pricing). You can sign up for free or use the paid tiers, depending on which of the features you need to access.

### Configuration

You can now publish the package's config file by using the following command:

```
php artisan vendor:publish --provider="AshAllenDesign\LaravelExchangeRates\Providers\ExchangeRatesProvider"
```

You should now have a new `config/laravel-exchange-rates.php` file. By default, the package's config is set up to make requests via HTTP. But, if you're in a production environment and are using one of the paid tiers of the API, I'd highly recommend using HTTPS instead. To do this, you can simply update the config file to and change the `api_url` field to start with `https://` rather than `http://`:

```php
return [
  
    // ...

    'api_url' => env('EXCHANGE_RATES_API_URL', 'http://api.exchangeratesapi.io/v1/'),

    // ...
  
];
```

You'll also need to make sure that you add your API key to your `.env`:

```
EXCHANGE_RATES_API_KEY={Your-API-Key-Here}
```

## Getting Exchange Rates For a Single Date

To get the exchange for one currency to another, we can use the package's `->exchangeRate()` method. 

If we wanted to get the exchange rate for today from 'GBP' to 'EUR', we could write something like this:

```php
$exchangeRates = new ExchangeRate();
$result = $exchangeRates->exchangeRate('GBP', 'EUR');

// $result: '1.10086'
```

However, if we wanted to get the exchange for a specific date, we could pass a `Carbon` date object of the day we wanted. As an example, if we wanted to get the exchange rate from 'GBP' to 'EUR' on the 1st January 2021, we could use the following:

```php
$exchangeRates = new ExchangeRate();
$result = $exchangeRates->exchangeRate('GBP', 'EUR', Carbon::create('2021-01-01'));

// $result: '1.10086'
```

## Getting the Exchange Rate Between Two Dates

If we want to get exchange rates between two currencies between a given date range, we can use the package's `->exchangeRateBetweenDateRange()` method.

Let's imagine that we want to get the exchange rates from 'GBP' to 'EUR' for the past 3 days. We could write our code like so:

```php
$exchangeRates = new ExchangeRate();
$result = $exchangeRates->exchangeRateBetweenDateRange(
    'GBP',
    'EUR',
    Carbon::now()->subDays(3),
    Carbon::now(),
);

// $result: [
//     '2021-07-07' => 1.1092623405
//     '2021-07-08' => 1.1120625424
//     '2021-07-09' => 1.1153867604
// ];
```

## Converting Currencies For a Single Date

Not only does the package allow us to grab the exchange rates between currencies, it also allows us to convert monetary value from one currency to another. To do this we can use the `->convert()` method.

For example, we could convert £1 'GBP' to 'EUR' at today's exchange rate:

```php
$exchangeRates = new ExchangeRate();
$result = $exchangeRates->convert(100, 'GBP', 'EUR', Carbon::now());

// $result: 110.15884906
```

You might have noticed that we passed `100` as the first parameter. This is because the package requires us to pass monetary values in the currencies lowest denomination. For example, in this case, we wanted to convert £1, so we passed 100 because £1 is equal to 100 pence.

## Converting Currencies Between Two Dates

Similar to getting the exchange rates between a date range, you can also convert monetary values from one currency to another using the package. To do this we can use the `->convertBetweenDateRange()` method.

Let's imagine that we want to convert £1 'GBP' to 'EUR' using the exchange rates for the past 3 days. We could write our code like so:

```php
$exchangeRates = new ExchangeRate();
$exchangeRates->convertBetweenDateRange(
    100,
    'GBP',
    'EUR',
    Carbon::now()->subDays(3),
    Carbon::now()
);

// $result: [
//     '2020-07-07' => 110.92623405,
//     '2020-07-08' => 111.20625424,
//     '2020-07-09' => 111.53867604,
// ];
```

## Improving Performance by Using the Package's Caching

By default, all of the API responses from the [exchangeratesapi.io](http://exchangeratesapi.io) API are cached by the package. This allows for significant performance improvements and reduced bandwidth from your server. It is also beneficial because it prevents you from using some of your monthly API requests if you've already fetched the exchange rate in the past.

However, if for any reason you require a fresh result from the API and not a cached result, the pacakge provides a `->shouldBustCache()` method that we can use. 

Let's take a look at how we could grab a fresh exchange rate from the API and ignore any cached rates:

```php
$exchangeRates = new ExchangeRate();
$exchangeRates->shouldBustCache()->convert(100, 'GBP', 'EUR', Carbon::now());
```

## Using the Package's Validation Rule

There may be times that you allow your users to choose currencies that are going to be converted. In this case, it's important to ensure that your users can only input a currency that is supported by the Exchange Rates API.

To help with this, Laravel Exchange Rates comes with its own `ValidCurrency` rule for validating currencies.

Let's imagine that we have a form request that is being used to validate a currency that is sent in a request. Our form request might look a bit like this:

```php
<?php

namespace App\Http\Requests;

use AshAllenDesign\LaravelExchangeRates\Rules\ValidCurrency;
use Illuminate\Foundation\Http\FormRequest;

class MyAwesomeRequest extends FormRequest
{
    // ...
  
    public function rules(): array
    {
        return [
            'currency' => ['required', new ValidCurrency()],
        ];
    }
  
    // ...
}

```

## Tests

If you're writing tests for code that deals with the Laravel Exchange Rates package, you'll likely want to prevent any API requests actually being made. For this reason, you'll probably want to instantiate the `ExchangeRate` class using dependency injection or using the package's provided facade. In fact, if you're interested in reading more about this type of thing, I'd recommend giving my [How to Make Your Laravel App More Testable](https://ashallendesign.co.uk/blog/how-to-make-your-laravel-app-more-testable) article a read.

Let's take a quick look at how we could write a basic test for a controller method that is fetching the exchange rate from 'GBP' to 'EUR' for today. Our controller might look like this:

```php
use AshAllenDesign\LaravelExchangeRates\Classes\ExchangeRate;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class MyAwesomeController extends Controller
{
    public function __invoke(Request $request, ExchangeRate $exchangeRate): JsonResponse
    {
        $rate = $exchangeRates->exchangeRate('GBP', 'EUR');

        return response()->json(['rate' => $rate]);
    }
}
```

Now, let's write a test for this controller method. We'll make the assumption that the route name for the method is `awesome.route`. Our test could look something like this:

```php
use AshAllenDesign\LaravelExchangeRates\Classes\ExchangeRate;
use Mockery\MockInterface;
use Tests\TestCase;

class MyAwesomeControllerTest extends TestCase
{
    /** @test */
    public function success_response_is_returned(): void
    {
        // Create the mock of the service class.
        $this->mock(ExchangeRate::class, function (MockInterface $mock): void {
            $mock->shouldReceive('exchangeRate')
                ->once()
                ->withArgs(['GBP', 'EUR'])
                ->andReturn(123.456);
        });
	
        $this->postJson(route('awesome.route'))
            ->assertExactJson([
                'rate' => 123.456
            ]);
    }
}
```

## Conclusion

Hopefully, this article should have shown you how to use the Laravel Exchange Rates package to interact with the Exchange Rates API to get exchange rates and currency conversions. It should have also given you a brief insight into how to write tests for code that use the package.

If this post helped you out, I'd love to hear about it. Likewise, if you have any feedback to improve this post, I'd also love to hear that too.

If you're interested in getting updated each time I publish a new post, feel free to [sign up for my newsletter](https://ashallendesign.co.uk/blog).

Keep on building awesome stuff! 🚀