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.