5

Here is my Magento code:

private function getAllCountry() {

    require_once("../app/Mage.php");
    umask(0);
    Mage::app("default");

    $countryName = Mage::getModel('directory/country')->load('FR')->getName(); //get country name

    echo 'Country Name ->'.$countryName.'<br/>';

    $states = Mage::getModel('directory/country')->load('FR')->getRegions();//state names

    foreach ($states as $state)
    {
        echo 'ID->'.$state->getId().'<br/>';
        echo 'Name->'.$state->getName().'<br/>';

    }
}

I want to get the list of all country names with their states and region id in an array.

9

Note that although these answers might work, they're not the proper Magento Way™ to do this. The right path to choose is to use Service Contract.

The Directory module comes with a very handy Service Contract called the "CountryInformationAcquirerInterface". You can find it at Magento\Directory\Api\CountryInformationAcquirerInterface. This has a very handy function called getCountriesInfo(), which returns an array of CountryInformation data models, which - in their turn - have a method called getAvailableRegions(). So the full example would look something like this:

/**
 * @var \Magento\Directory\Api\CountryInformationAcquirerInterface
 */
protected $countryInformationAcquirer;

/**
 * Constructor call.
 * @param \Magento\Directory\Api\CountryInformationAcquirerInterface $countryInformationAcquirer
 */
public function __construct(
    \Magento\Directory\Api\CountryInformationAcquirerInterface $countryInformationAcquirer
) {
    $this->countryInformationAcquirer = $countryInformationAcquirer;
}

/**
 * Just a simple example
 * @return array
 */
public function example()
{
    $data = [];

    $countries = $this->countryInformationAcquirer->getCountriesInfo();

    foreach ($countries as $country) {
        // Get regions for this country:
        $regions = [];

        if ($availableRegions = $country->getAvailableRegions()) {
            foreach ($availableRegions as $region) {
                $regions[] = [
                    'id'   => $region->getId(),
                    'code' => $region->getCode(),
                    'name' => $region->getName()
                ];
            }
        }

        // Add to data:
        $data[] = [
            'value'   => $country->getTwoLetterAbbreviation(),
            'label'   => __($country->getFullNameLocale()),
            'regions' => $regions
        ];
    }

    return $data;
}

With most tasks in Magento 2, the best approach is to check first if there's a Service Contract that might fit your needs. Because most of the time, there is.

  • Are there any "restriction" not to use API/Service Contracts? – sv3n Oct 11 '18 at 23:15
  • 1
    Not as far as I'm aware of. It's even more reliable: if the service contract has an @api-annotation, it's guaranteed to be backward compatible (see devdocs.magento.com/guides/v2.2/extension-dev-guide/… and devdocs.magento.com/guides/v2.2/contributor-guide/…). The only "restriction" I can think of is DI: since you depend on abstractions you don't know the explicit implementation. But then again: the whole idea of interfaces is that you should not need to care about this. If you do care about this, you probably have a code smell. – Giel Berkers Oct 15 '18 at 8:38
6

Try this for Magento2. It will return an multi array with country's and there regions if available.

$countryHelper = $this->_objectManager->get('Magento\Directory\Model\Config\Source\Country'); 
$countryFactory = $this->_objectManager->get('Magento\Directory\Model\CountryFactory');

$countries = $countryHelper->toOptionArray(); //Load an array of countries

    foreach ( $countries as $countryKey => $country ) {

        if ( $country['value'] != '' ) { //Ignore the first (empty) value

            $stateArray = $countryFactory->create()->setId(
                $country['value']
            )->getLoadedRegionCollection()->toOptionArray(); //Get all regions for the given ISO country code

            if ( count($stateArray) > 0 ) { //Again ignore empty values
                $countries[$countryKey]['states'] = $stateArray;
            }

        }
    }

var_dump($countries);

STAND ALONE VERSION

Add the code below to a file 'test.php' in your magento root directory and navigate to it from a web browser. By no means should you attempt to use objectmanager directly inside of a controller, but outside of magento, this is the 'approved' way of getting to it.

<?php


use Magento\Framework\AppInterface;

try {
    require __DIR__ . '/app/bootstrap.php';

} catch (\Exception $e) {
    echo 'Autoload error: ' . $e->getMessage();
    exit(1);
}
try {
    $bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);
    $objectManager = $bootstrap->getObjectManager();

    $countryHelper = $objectManager->get('Magento\Directory\Model\Config\Source\Country');
    $countryFactory = $objectManager->get('Magento\Directory\Model\CountryFactory');
    $countryCollection = $objectManager->get('Magento\Directory\Model\ResourceModel\Country\Collection');

$items = $countryCollection->loadByStore(null);

foreach ($items as $item) {
    var_dump($item->getData());
}

$countries = $countryHelper->toOptionArray(); //Load an array of countries
foreach ( $countries as $countryKey => $country ) {


if ( $country['value'] != '' ) { //Ignore the first (empty) value

            $stateArray = $countryFactory->create()->setId(
                $country['value']
            )->getLoadedRegionCollection()->toOptionArray(); //Get all regions for the given ISO country code

            if ( count($stateArray) > 0 ) { //Again ignore empty values
                $countries[$countryKey]['states'] = $stateArray;
            }

        }
    }
  • Please update your answer with an explanation of what the code does and how it will solve the OP's problem. – 7ochem Mar 18 '16 at 11:04
  • This code works perfectly. I suppose its a prerequisite you need to understand magento dependency injection in order to get it to work. It returns an array of the countries, and regions. – CarComp Jun 3 '16 at 18:01
  • +1 for Good work...! Keep it up..! – Sanjay Gohil May 21 at 18:46
3

Done in two files:

Template File:

<select name="countries">
    <option class="placeholder" value="" disabled selected>Country</option>
    <?php 
        $countries = $block->getAvailableCountries();
        foreach ($countries as $country) { ?>
            <option value="<?php echo $country->getCountryId(); ?>"><?php echo $country->getName(); ?></option>
        }
    ?>
</select>

Block File:

use Magento\Directory\Model\ResourceModel\Country\CollectionFactory as CountryCollectionFactory;
use Magento\Framework\View\Element\Template;

class Catalogue extends Template
{

    protected $_countryCollectionFactory;

    public function __construct(
        CountryCollectionFactory $countryCollectionFactory,
        Template\Context $context,
        array $data = []
    )
    {
        $this->_countryCollectionFactory = $countryCollectionFactory;
        parent::__construct($context, $data);
    }

    public function getAvailableCountries()
    {
        $collection = $this->_countryCollectionFactory->create();
        $collection->addFieldToSelect('*');

        return $collection;
    }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.