I have this helper class in Magento 2:

class Data extends \Magento\Framework\App\Helper\AbstractHelper
    protected $_countryFactory;

    public function __construct(
         \Magento\Directory\Model\CountryFactory $countryFactory
         $this->_countryFactory = $countryFactory;

    public function getCountryIsoCode($country = 'US')
          $country = $this->_countryFactory->create()->getCollection();
          $country->addFieldToFilter('country_id', array('eq' => country));

          $countryCode = $country->getFirstItem()->getIso3Code());
          $countryCode2 = $country->getFirstItem()->getData('iso3_code'));

          // $countryCode => null
          // $countryCode2 => 'USA'

          return $countryCode;

The function getCountryIsoCode() has an example as parameter ('US').
I don't why the getIso3Code() doesn't work. Instead the getData() works perfectly.

In Magento2 there aren't "php magic function to get database table field" anymore?
Is there something wrong in my code?


The problem is the 3 in the name.
I just tested and the magic getter does not play well with digits in the name.
The method getIso3Code does not exist, so, instead the method __call is called that is defined in Magento\Framework\DataObject.
The get part looks like this.

$key = $this->_underscore(substr($method, 3));
$index = isset($args[0]) ? $args[0] : null;
return $this->getData($key, $index);

the _underscore transforms the method name into the data key needed.
Here is the line that matters.

$result = strtolower(trim(preg_replace('/([A-Z]|[0-9]+)/', "_$1", $name), '_'));

I just ran this code on http://phpfiddle.org/ :

$name = 'iso3_code';
echo strtolower(trim(preg_replace('/([A-Z]|[0-9]+)/', "_$1", $name), '_'));

and to my surprise it showed iso_3_code but you expected iso3_code.

  • This time I beat you :-) Feb 3 '17 at 16:50
  • 3
    Yep. Nice work. I already +1'd your answer.
    – Marius
    Feb 3 '17 at 16:50

No Magento 2 also uses get/set magic methods. If you want to see those magic. Please try this:

$countryId = $country->getFirstItem()->getCountryId();
echo $countryId;

This will output the country_id value of first object as per your code.

So now the question is what happends with the call getIso3Code(). Well, here is the twist. Magento's magic getter will interpret this call as iso_3_code which is obviously undefined, hence you get null as result.

Why Magento treats this call in this way because, it uses preg_replace() method internally to retrieve the real code from the magic getter we are using. This means, when you call getCountryId(), Magento has an internal logic that will trace out the real code which you are looking for is country_id. This same internal logic will fail in case of getIso3Code() due to the occurrence of that number 3.

So in this particular case, it is better to use getData('iso3_code') call.

Hope that will give you a clear picture.

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.