Code Monkey home page Code Monkey logo

laravel-iso-countries's Introduction

Laravel ISO Countries

Latest Version on Packagist GitHub Tests Action Status Total Downloads

This package provides ready-to-use application models and seeds the database with ISO data from various sources. This package can be used in multi-language apps and supports Country/Language/Currency names in almost any locale.

Included datasets

Unlike other packages, this one also includes relevant data relationships, such as:

// Official languages spoken in Luxembourg ('LU')
Country::find('LU')->languages;

// Currencies used in Ghana ('GH')
Country::find('GH')->currencies;

// Countries that have Spanish ('es') as one of their official languages 
Language::find('es')->countries;

// Countries that use the Euro ('EUR') as currency
Currency::find('EUR')->countries;

Installation

You can install the package via composer:

composer require io238/laravel-iso-countries

The latest version of this package requires PHP version 8.0 or above. If you need support for PHP 7.4, please install version 2 of this package.

Migrations

There is no need to run any migrations. All country data information is stored in a pre-compiled SQLITE database that is stored within this package.

By default, this database includes all country/language/&currency names translated into English, German, French, and Spanish. If you want to compile your own database with other languages, please see the instructions here.

Rebuilding the database

Country-level ISO data does not change very often. Nevertheless, if at any time you want to update the ISO data to the latest available version, you can manually re-seed the tables:

Config

Optionally, you can publish the config file with:

php artisan vendor:publish --provider="Io238\ISOCountries\ISOCountriesServiceProvider" --tag="config"

In the config you can define, which translations of country/language/currency names you want to store in your DB.

This is the contents of the published config file:

[
    // Supported locales for names (countries, languages, currencies)
    'locales' => [
        'en',
        'de',
        'fr',
        'es',
    ],

    // Path for storing your own SQLITE database
    'database_path' => database_path('iso-countries.sqlite'),
];

After making changes to the config you need to re-build the database with the following command:

php artisan db:seed countries:build

This will create a new SQLITE database and stores it in your project at database/iso-countries.sqlite. Exclude this file from .gitignore to have it available in all environments.

# database/.gitignore

*.sqlite*
!iso-countries.sqlite

Usage

Country model

Country::find('AD');

Io238\ISOCountries\Models\Country {
     id: "AD",
     alpha3: "AND",
     name: "{"en":"Andorra","de":"Andorra","fr":"Andorre","es":"Andorra"}",
     native_name: "Andorra",
     capital: "Andorra la Vella",
     top_level_domain: ".ad",
     calling_code: "376",
     region: "Europe",
     subregion: "Southern Europe",
     population: 78014,
     lat: 42.5,
     lon: 1.5,
     demonym: "Andorran",
     area: 468,
   }

Language model

Country::find('pt');

Io238\ISOCountries\Models\Language {
     id: "pt",
     iso639_2: "por",
     iso639_2b: null,
     name: "{"en":"Portuguese","de":"Portugiesisch","fr":"portugais","es":"portugu\u00e9s"}",
     native_name: "Português",
     family: "Indo-European",
     wiki_url: "https://en.wikipedia.org/wiki/Portuguese_language",
   }

Currency model

Currency::find('COP');

Io238\ISOCountries\Models\Currency {
     id: "COP",
     name: "{"en":"Colombian Peso","de":"Kolumbianischer Peso","fr":"peso colombien","es":"peso colombiano"}",
     name_plural: "Colombian pesos",
     symbol: "CO$",
     symbol_native: "$",
     decimal_digits: 0,
     rounding: 0,
   }

Query relationships

All models have pre-defined many-to-many relationships that can be queried:

// Retrieve languages that are spoken in Luxembourg
Country::find('LU')->languages;

Illuminate\Database\Eloquent\Collection {                                                                  
     all: [                                                                                                        
       Io238\ISOCountries\Models\Language {                                                                   
         id: "de",                                                                                                 
         iso639_2: "deu",                                                                                          
         iso639_2b: "ger",                                                                                         
         name: "{"en":"German","de":"Deutsch","fr":"allemand","es":"alem\u00e1n"}",                                
         native_name: "Deutsch",                                                                                   
         family: "Indo-European",                                                                                  
         wiki_url: "https://en.wikipedia.org/wiki/German_language",                                                
       },                                                                                                          
       Io238\ISOCountries\Models\Language {                                                                   
         id: "fr",                                                                                                 
         iso639_2: "fra",                                                                                          
         iso639_2b: "fre",                                                                                         
         name: "{"en":"French","de":"Franz\u00f6sisch","fr":"fran\u00e7ais","es":"franc\u00e9s"}",                 
         native_name: "français, langue française",                                                                
         family: "Indo-European",                                                                                  
         wiki_url: "https://en.wikipedia.org/wiki/French_language",                                                
       },                                                                                                          
       Io238\ISOCountries\Models\Language {                                                                   
         id: "lb",                                                                                                 
         iso639_2: "ltz",                                                                                          
         iso639_2b: null,                                                                                          
         name: "{"en":"Luxembourgish","de":"Luxemburgisch","fr":"luxembourgeois","es":"luxemburgu\u00e9s"}",       
         native_name: "Lëtzebuergesch",                                                                            
         family: "Indo-European",                                                                                  
         wiki_url: "https://en.wikipedia.org/wiki/Luxembourgish_language",                                         
       },                                                                                                          
     ],                                                                                                            
   }                                                                                                                                                                                                     
// Retrieve all countries that use the Euro (EUR) as currency.
Currency::find('EUR')->countries->pluck('name');

Illuminate\Support\Collection {
     all: [
       "Andorra",
       "Austria",
       "Åland Islands",
       "Belgium",
       "St. Barthélemy",
       "Cyprus",
       "Germany",
       "Estonia",
       "Spain",
       "Finland",
       "France",
       "French Guiana",
       "Guadeloupe",
       "Greece",
       "Ireland",
       "Italy",
       "Lithuania",
       "Luxembourg",
       "Latvia",
       "Monaco",
       "Montenegro",
       "St. Martin",
       "Martinique",
       "Malta",
       "Netherlands",
       "St. Pierre & Miquelon",
       "Portugal",
       "Réunion",
       "Slovenia",
       "Slovakia",
       "San Marino",
       "French Southern Territories",
       "Vatican City",
       "Republic of Kosovo",
       "Mayotte",
       "Zimbabwe",
     ],
   }

Localized names

Each of the package models (Country, Language, Currency) has a ->name attribute, which will be displayed in the app's locale, using the spatie/laravel-translatable package. The default config will migrate localized names for en, de, fr, and es. This can be adjusted in the config. The config app.locale and app.fallback_locale are automatically included.

// Set the app locale
app()->setLocale('fr');

// Retrieve the top 10 countries in Africa (by population):
Io238\ISOCountries\Models\Country::where('region', 'Africa')->orderByDesc('population')->limit(10)->pluck('name');

// Country names will be returned according to the app locale (fr = French)
Illuminate\Support\Collection {
     all: [
       "Nigéria",
       "Éthiopie",
       "Égypte",
       "Congo-Kinshasa",
       "Afrique du Sud",
       "Tanzanie",
       "Kenya",
       "Algérie",
       "Soudan",
       "Ouganda",
     ],
   }

Attribute casting

If you already use ISO codes in your models, you can enrich them by casting them as Country/Language/Currency model:

use Io238\ISOCountries\Casts\Currency;

class MyModel{
    
    // ...

    protected $casts = [
        'currency' => Currency::class,
    ];
    
    // ...
}

// Now you can dynamically retrieve all meta data associated with the currency
MyModel::first()->currency;

Io238\ISOCountries\Models\Currency {
     id: "JPY",
     name: "{"en":"Japanese Yen","de":"Japanischer Yen","fr":"yen japonais","es":"yen"}",
     name_plural: "Japanese yen",
     symbol: "¥",
     symbol_native: "",
     decimal_digits: 0,
     rounding: 0,
   }


// When filling the model, the ISO code (string) or the model can be used 
MyModel::first()->update(['currency' => 'USD']);
MyModel::first()->update(['currency' => Io238\ISOCountries\Models\Currency::find('USD')]);

Testing

composer test

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.

laravel-iso-countries's People

Contributors

io238 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

laravel-iso-countries's Issues

infinite loop when casting

Hello

I'm getting this error when trying to cast in my model

ERROR Xdebug has detected a possible infinite loop, and aborted your script with a stack depth of '256' frames in vendor/laravel/framework/src/Illuminate/Foundation/AliasLoader.php on line 73.

i don't have any classes called Language or Country or Currency
Only thing is the model i'm using has the following fields

`class PeopleSpokenLanguage extends Model
{
use HasFactory;

protected $casts = [
    'language' => Language::class,
    'accent' => Country::class

];

}`

Numeric ISO Codes

I noticed the countries table does not include the numeric codes, I prefer storing countries by their numeric codes because they don't change like the 2 or 3 letter ones can, they very rarely change, but still do sometimes.

Build command does not set translations

From loadNameTranslations() in Build.php

` foreach ($locales as $locale) {

        $file = match ($model) {
            Country::class => __DIR__ . "/../../data/translations/countries/$locale/country.php",
            Language::class => __DIR__ . "/../../data/translations/languages/$locale/language.php",
            Currency::class => __DIR__ . "/../../data/translations/currencies/$locale/currency.php",
        };

        if ( ! file_exists($file)) {
            continue;
        }

        $translations = require $file;

        foreach ($translations as $id => $name) {
            $item = $model::find($id)?->setTranslation('name', $locale, $name)->saveQuietly();
        }

`

The files you look for in the match are non-existent and the translations are never set. This results in only english in the JSON object for a translatable field in the DB. Could you please have a look at this?

Facade issue

Facing an issue when running the following command on laravel 9;

php artisan ide-helper:generate --ansi
Exception: Target class [iso-countries] does not exist.
Skipping \Io238\ISOCountries\ISOCountriesFacade.

In Facade.php line 216:

Illegal offset type in isset or empty

Error could not find driver

So I have run this command composer require io238/laravel-iso-countries and after that I just tried to call

Country::find("pt"), and I got could not find driver (Connection: iso-countries, SQL: select * from \"countries\")

I have a connection to MySQL database on .env, Am I missing something?

Also when I publish the config and I do not change anything and I try to run the command php artisan db:seed countries:build I got

php artisan db:seed countries:build

   INFO  Seeding database.


   Illuminate\Contracts\Container\BindingResolutionException

  Target class [Database\Seeders\countries:build] does not exist.

  at vendor\laravel\framework\src\Illuminate\Container\Container.php:914
    910▕
    911▕         try {
    912▕             $reflector = new ReflectionClass($concrete);
    913▕         } catch (ReflectionException $e) {
  ➜ 914▕             throw new BindingResolutionException("Target class [$concrete] does not exist.", 0, $e);
    915▕         }
    916▕
    917▕         // If the type is not instantiable, the developer is attempting to resolve
    918▕         // an abstract type such as an Interface or Abstract Class and there is

  1   vendor\laravel\framework\src\Illuminate\Container\Container.php:912
      ReflectionException::("Class "Database\Seeders\countries:build" does not exist")

  2   vendor\laravel\framework\src\Illuminate\Container\Container.php:912
      ReflectionClass::__construct("Database\Seeders\countries:build")

PHP version: 8.1.10
Laravel Framework 10.33.0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.