DEV Community

Cover image for How to Get Currency Exchange Rates in Laravel
Ash Allen
Ash Allen

Posted on • Originally published at ashallendesign.co.uk

How to Get Currency Exchange Rates in Laravel

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 package to interact with the 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.

Laravel Exchange Rates

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
Enter fullscreen mode Exit fullscreen mode

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. 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"
Enter fullscreen mode Exit fullscreen mode

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://:

return [

    // ...

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

    // ...

];
Enter fullscreen mode Exit fullscreen mode

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

EXCHANGE_RATES_API_KEY={Your-API-Key-Here}
Enter fullscreen mode Exit fullscreen mode

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:

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

// $result: '1.10086'
Enter fullscreen mode Exit fullscreen mode

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:

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

// $result: '1.10086'
Enter fullscreen mode Exit fullscreen mode

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:

$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
// ];
Enter fullscreen mode Exit fullscreen mode

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:

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

// $result: 110.15884906
Enter fullscreen mode Exit fullscreen mode

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:

$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,
// ];
Enter fullscreen mode Exit fullscreen mode

Improving Performance by Using the Package's Caching

By default, all of the API responses from the 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:

$exchangeRates = new ExchangeRate();
$exchangeRates->shouldBustCache()->convert(100, 'GBP', 'EUR', Carbon::now());
Enter fullscreen mode Exit fullscreen mode

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

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()],
        ];
    }

    // ...
}

Enter fullscreen mode Exit fullscreen mode

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 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:

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]);
    }
}
Enter fullscreen mode Exit fullscreen mode

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:

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
            ]);
    }
}
Enter fullscreen mode Exit fullscreen mode

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.

Keep on building awesome stuff! 🚀

Discussion (0)