0

This is driving me crazy! The general/region/state_required data from system->configuration cannot be retrieved by Mage::getStoreConfig() function. In the database, this value is presented, and data persistence works OK as well, i.e. changing the value in the CMS will take the change the database. The following is a abstraction from system.xml of Magento default Directory module.

<general>
        <groups>
            <country>
                <fields>
                    <optional_zip_countries translate="label">
                        <label>Postal Code is Optional for the following countries</label>
                        <frontend_type>multiselect</frontend_type>
                        <sort_order>3</sort_order>
                        <source_model>adminhtml/system_config_source_country</source_model>
                        <show_in_default>1</show_in_default>
                        <show_in_website>0</show_in_website>
                        <show_in_store>0</show_in_store>
                        <can_be_empty>1</can_be_empty>
                    </optional_zip_countries>
                </fields>
            </country>
            <region translate="label">
                <label>States Options</label>
                <frontend_type>text</frontend_type>
                <sort_order>4</sort_order>
                <show_in_default>1</show_in_default>
                <show_in_website>0</show_in_website>
                <show_in_store>0</show_in_store>
                <fields>
                    <state_required translate="label">
                        <label>State is required for</label>
                        <frontend_type>multiselect</frontend_type>
                        <source_model>adminhtml/system_config_source_country</source_model>
                        <sort_order>1</sort_order>
                        <show_in_default>1</show_in_default>
                        <show_in_website>0</show_in_website>
                        <show_in_store>0</show_in_store>
                    </state_required>
                    <display_all translate="label">
                        <label>Display not required State</label>
                        <frontend_type>select</frontend_type>
                        <source_model>adminhtml/system_config_source_yesno</source_model>
                        <sort_order>8</sort_order>
                        <show_in_default>1</show_in_default>
                        <show_in_website>0</show_in_website>
                        <show_in_store>0</show_in_store>
                    </display_all>
                </fields>
            </region>
        </groups>
    </general>

In fact, general/region/display_all returns null as well while it has a non-empty value. This is really weird, I have no idea about it now, can anyone please help?!

--Update--

Is it possible that this value is being overridden somewhere? Like some code hardcode this value to be null, it overrides the value in the db.

I tried a couple of methods suggested below, unfortunately they don't solve the problem here. Any more input from people?

  • did you clear the cache? – Marius Oct 27 '14 at 7:49
  • You say 'changing the value in the cms' - can we assume you are talking about editing settings under system -> config and not cms pages? – Jonathan Hussey Oct 27 '14 at 8:29
  • @Marius Yes I did, I even tried rm -rf var/cache/* – Michael Oct 27 '14 at 9:08
  • @JonathanHussey Yes, I mean in the admin, under system > configuration, the point is that the value is getting persisted to the database. – Michael Oct 27 '14 at 9:09
  • Make sure you don't have different values for your config settings at website or store view level. Change the config scope from the top left dropdown. – Marius Oct 27 '14 at 9:14
1

There is an article series by Alan Storm that covers the internals of Mage::getStoreConfig() extensively:

  1. http://alanstorm.com/magento_config_tutorial
  2. http://alanstorm.com/magento_config_declared_modules_tutorial
  3. http://alanstorm.com/magento_loading_config_variables

In short, the value can come from:

  1. default, config/websites and config/stores nodes in any XML file in app/etc (might even be in app/etc/modules, but it's highly unlikely)
  2. default, config/websites and config/stores nodes in any module's config.xml
  3. core_config_data table
  4. default, config/websites and config/stores nodes in app/etc/local.xml

Configuration is loaded in this order, overriding existing values in each step (i.e. local.xml has highest priority)

It is also possible to set configuration values at runtime in the Config model without having them saved anywhere. Searching for Mage::getConfig() in your local code pool might help you finding it.

  • Yeah I did check out that series of tutorials, but they are helpful to me. I searched Mage::getConfig() and didn't find anywhere that these values are being overridden. – Michael Nov 7 '14 at 5:05
  • Did you search in all XML files? If everything fails, I would start debugging the code where the configuration gets loaded. – Fabian Schmengler Nov 7 '14 at 17:37
  • fschmengler, yeah I searched in all XML files, I think it's core functionality that shouldn't have any faults in it, unless plugins override it, but I didn't really find anything conflicting in the plugins. – Michael Nov 9 '14 at 22:53
1

I've came across this exact issue and have figured out how to solve it.

When core config data is loaded from the database inside app/code/core/Mage/Core/Model/Resource/Config.php on line 90

    // load all configuration records from database, which are not inherited
    $select = $read->select()
        ->from($this->getMainTable(), array('scope', 'scope_id', 'path', 'value'));
    if (!is_null($condition)) {
        $select->where($condition);
    }
    $rowset = $read->fetchAll($select);


    // set default config values from database
    foreach ($rowset as $r) {
        if ($r['scope'] !== 'default') {
            continue;
        }
        $value = str_replace($substFrom, $substTo, $r['value']);
        $xmlConfig->setNode('default/' . $r['path'], $value);
    }

all data is fetched from core_config_data and is saved in the xml structure. The data is loaded in same order as the config_id, so what happened was, there was an empty default value set and somewhere toward end of the table like this: enter image description here

notice id 2203. The path is set to general and the value is NULL!

When Magento processes id 2203 inside lib/Varien/Simplexml/Config.php on line 548:

public function setNode($path, $value, $overwrite=true)
{
    $xml = $this->_xml->setNode($path, $value, $overwrite);
    return $this;
}

The NULL default path value wipes the values inside its xml object.

How did this happen?

Well, if we look deeper inside Magento and check how the core_config_data table was created we see that

CREATE TABLE `{$installer->getTable('core_config_data')}` (
  `config_id` int(10) unsigned NOT NULL auto_increment,
  `scope` enum('default','websites','stores','config') NOT NULL default 'default',
  `scope_id` int(11) NOT NULL default '0',
  `path` varchar(255) NOT NULL default 'general',
  `value` text NOT NULL,
  PRIMARY KEY  (`config_id`),
  UNIQUE KEY `config_scope` (`scope`,`scope_id`,`path`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

so by default Magento sets the default path to default, default scope_id to 0, but notice the value is not supposed to be NULL. So how did Magento save a NULL value?

Simple, someone/something did something like this Mage::getConfig()->saveConfig('general'); Try it and see for yourself; it'll work and Magento will save a NULL value in the table. If you're interested in understanding why it works, take a look inside app/code/core/Mage/Core/Model/Config.php line 1535:

public function saveConfig($path, $value, $scope = 'default', $scopeId = 0)
{
    $resource = $this->getResourceModel();
    $resource->saveConfig(rtrim($path, '/'), $value, $scope, $scopeId);

    return $this;
}

and inside app/code/core/Mage/Core/Model/Resource/Config.php on line 184:

    public function saveConfig($path, $value, $scope, $scopeId)
{
    $writeAdapter = $this->_getWriteAdapter();
    $select = $writeAdapter->select()
        ->from($this->getMainTable())
        ->where('path = ?', $path)
        ->where('scope = ?', $scope)
        ->where('scope_id = ?', $scopeId);
    $row = $writeAdapter->fetchRow($select);

    $newData = array(
        'scope'     => $scope,
        'scope_id'  => $scopeId,
        'path'      => $path,
        'value'     => $value
    );

    if ($row) {
        $whereCondition = array($this->getIdFieldName() . '=?' => $row[$this->getIdFieldName()]);
        $writeAdapter->update($this->getMainTable(), $newData, $whereCondition);
    } else {
        $writeAdapter->insert($this->getMainTable(), $newData);
    }
    return $this;
}

Also see https://stackoverflow.com/questions/18908309/mysql-column-set-to-not-null-but-still-allowing-null-values

TL;DR; Solution Run this sql query:

SELECT * FROM magento.core_config_data WHERE value IS NULL;

and delete the row where path === default and value IS NULL(see my screenshot for reference).

DELETE FROM core_config_data WHERE scope = 'default' AND scope_id = 0 AND path = 'general' AND value IS NULL;

0

You can query the config after explicitly setting the store using either of the following:

$config = Mage::getStoreConfig('inchoo/inchoo_group/inchoo_input', Mage::app()->getStore());

or

Mage::app()->setCurrentStore(0);

$config = Mage::getStoreConfig('general/region/state_required');

You could also explicitly reload the configuration and then load the values using

Mage::app()->getConfig()->reinit();

Mage::getStoreConfig('inchoo/inchoo_group/inchoo_input', Mage::app()->getStore());

  • Not working unfortunately. – Michael Nov 3 '14 at 3:39
  • @Michael, see my solution. – Oleg Mar 13 '16 at 19:22

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.