---
title: "Country codes & resolvers — Addresses for Laravel | Roundly"
description: "ISO country normalisation on every write, plus an optional CountryResolver for names and geocoding — no bundled data, no network calls."
url: https://roundly-consulting.com/open-source/docs/addresses-for-laravel/countries
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Addresses for Laravel](https://roundly-consulting.com/open-source/docs/addresses-for-laravel.md)

# Country codes & resolvers

Country codes are normalised on the way in: trimmed, upper-cased and checked to be two or three letters — the shape of an ISO 3166-1 alpha-2 or alpha-3 code. Anything else throws InvalidCountryException:

```php
use RoundlyConsulting\Addresses\Support\CountryNormaliser;

CountryNormaliser::normalise(' sk ');   // 'SK'
CountryNormaliser::normalise('usa');    // 'USA'
CountryNormaliser::normalise('XX1');    // throws InvalidCountryException
```

The check is shape-only — the package bundles no country list, so a well-formed but unassigned code such as XX passes. Normalisation runs inside AddressData::make(), which covers every package write path: the builder, addAddress(), createAddress() and UpdateAddressAction with a make()-built DTO.

To store country codes exactly as given (trimmed only, never shape-checked), switch it off — false, or a string such as 'false', '0' or 'off'. inCountry() then matches them case-insensitively:

```php
// config/addresses.php — store country codes as given (trimmed only, never shape-checked)
'normalise_country' => false,
```

## Country names

The package ships no country-name list and no geocoder. To resolve names — or coordinates — implement the CountryResolver contract in your app:

```php
namespace App\Support;

use RoundlyConsulting\Addresses\Contracts\CountryResolver;
use RoundlyConsulting\Addresses\DataTransferObjects\AddressData;
use RoundlyConsulting\Addresses\DataTransferObjects\Coordinates;

final class AppCountryResolver implements CountryResolver
{
    public function name(string $iso): ?string
    {
        return ['SK' => 'Slovakia', 'CZ' => 'Czechia', 'AT' => 'Austria'][$iso] ?? null;
    }

    public function coordinates(AddressData $data): ?Coordinates
    {
        // call your own geocoder here; return null when the address cannot be resolved
        return null;
    }
}
```

Register it in config. The service provider binds it as a singleton on CountryResolver when it registers; with null or a blank value, nothing is bound. Any other value is checked when the resolver is first resolved — it must name a CountryResolver class, or that throws InvalidConfigurationException naming the key, so a typo never silently leaves country names unresolved:

```php
// config/addresses.php
'country_resolver' => \App\Support\AppCountryResolver::class,
```

With a resolver bound, country\_name returns the resolved name; without one it is null. The same value appears in AddressResource. Addresses::countryName() resolves any code and falls back to the normalised ISO code when no resolver is bound or it does not know the code:

```php
use RoundlyConsulting\Addresses\Contracts\CountryResolver;
use RoundlyConsulting\Addresses\Facades\Addresses;

$address->country_name;      // 'Slovakia' with a resolver bound, otherwise null
$address->countryName();     // the same value as a method

Addresses::countryName('sk');   // 'Slovakia' — or the normalised 'SK' without a resolver

if (app()->bound(CountryResolver::class)) {
    $name = app(CountryResolver::class)->name('SK');
}
```

## Geocoding

The package never calls coordinates() itself — it is there for your code, and returns a Coordinates value object (latitude, longitude) or null. For example, geocode an address before you store it:

```php
use RoundlyConsulting\Addresses\Contracts\CountryResolver;
use RoundlyConsulting\Addresses\DataTransferObjects\AddressData;

$data = AddressData::make(
    city: 'Bratislava',
    street: 'Somewhere 1',
    postalCode: '81101',
    countryIso: 'SK',
);

if (app()->bound(CountryResolver::class)) {
    $point = app(CountryResolver::class)->coordinates($data);   // ?Coordinates
    $point?->latitude;
    $point?->longitude;
}

$customer->addAddress($data);
```

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/addresses-for-laravel.md)
