Magento – Product attribute not saving programmatically

attributesfrontendmagento-1.7model

I am running a method to save attribute store view titles prgrammatically, but one attribute store view titles does not save when the method is run inside a loop. I thought it was a caching issue, but had no luck when I added the clear cache code like it says to do in this example code. This method runs properly and saves correctly when not run in a loop or is run manually inside the admin UI.

What am I missing?

I have also tried to put a sleep(1); out of desperation without any luck.

The attribute store title is shown inside $model after addData() method.

$data = array();
$model = Mage::getModel('catalog/resource_eav_attribute');
$model->load($attr_id);

$data['frontend_label'] = $attribute_title; // array of titles for store views
$data['option'] = array('value' => $attribute_arr); // array of option labels for store views

$model->addData($data);
$model->save();

$session = Mage::getSingleton('adminhtml/session');

// Clear translation cache because attribute labels are stored in translation

Mage::app()->cleanCache(array(Mage_Core_Model_Translate::CACHE_TAG));
$session->setAttributeData(false);

e.g. of $data['frontend_label'] on the first loop:

[frontend_label] => Array (
        [1] => Color2
        [2] => Cõôlõôr
        [3] => Còôlòôr
        [0] => Color
    )

On the next loop after the model saved once the attribute model is loaded again and Array[2] was not been saved:

[frontend_label] => Array (
        [1] => Color2
        [2] => Color3
        [3] => Còôlòôr
        [0] => Color
    )

EDIT:

controller action:

public function updateAction() {
  $success = TRUE;
  $end_count = 0;
  $start_count = 0;
  $translation = array();
  $gl_arr = Mage::helper("my_helper")->gl_get_all_completed_targets();
  foreach ($translation_arr as $translation) {
    $result_arr = Mage::helper("my_helper")->get_status_objects(FALSE);
    if ($result_arr[0]['status'] == Mage::helper("my_helper")->_get_submission_status_ready() ||
        $result_arr[0]['status'] == Mage::helper("my_helper")->_get_submission_status_error()) {
      try {
        Mage::helper("my_helper")->update_translated_record_in_magento($translation);
        $start_count++;
        }
      catch (SoapFault $sf) {
        $success = FALSE;
      }
      catch (Exception $ex) {
      $success = FALSE;
    }
  }
}

helper file (e.g. my_help.php):

public function update_translated_record_in_magento($translation) {

    $gl_object = $this->parse_target_xml($translation['translated_content']);
    $mapped_langs = $this->get_mapped_locales();
    $tgt_lang_store_id = $mapped_langs[$translation['target_locale']]['store_id'];

if ($gl_object['object_type'] == $this->_get_object_type_product_attributes()) {
      $attr_model = Mage::getModel('catalog/resource_eav_attribute');
      $attr_model->load($gl_object['object_id']);

      $option_arr = array();
      $attribute = Mage::getModel('eav/config')->getAttribute('catalog_product', $attr_model->attribute_code);
      foreach ($attribute->getSource()->getAllOptions(false) as $option) {
        $option_arr[$option['value']] = $option['label'];
      }

      $product = Mage::getModel('catalog/product')->load();
      $attribute_title = $product->getResource()->getAttribute($attr_model->attribute_code)->getStoreLabels();
      $attribute_title[0] = $attr_model->frontend_label;

      $stores = Mage::app()->getStores();
      $attribute_arr = array();
      foreach ($stores as $store_key => $object) {
        $store_id = Mage::app()->getStore($store_key)->getId();
        $config = Mage::getModel('eav/config');
        $get_attribute = $config->getAttribute(Mage_Catalog_Model_Product::ENTITY, $attr_model->attribute_code);
        $attribute_val = $get_attribute->setStoreId($store_id)->getSource()->getAllOptions();

        unset($attribute_val[0]);

        foreach ($attribute_val as $val) {
          $attribute_arr[$val['value']][$store_id] = $val['label'];
        }

        foreach ($option_arr as $key => $option) {
          $attribute_arr[$key][0] = $option;
        }
     }

     $data = array();
     $data['frontend_label'] = $attribute_title;
     $data['option'] = array('value' => $attribute_arr);

     $attributes = $gl_object['attributes'];
     foreach ($attributes as $key => $attribute) {
       if ($key == 'frontend_label') {
         $data['frontend_label'][$tgt_lang_store_id] = $attribute;
       }
       else {
         if (!empty($option_arr[$key])) {
            $data['option']['value'][$key][$tgt_lang_store_id] = $attribute;
         }
       }
     }

    try {
      $attr_model->addData($this->filterPostData($data));
      $attr_model->save();
      $session = Mage::getSingleton('adminhtml/session');

      Mage::app()->cleanCache(array(Mage_Core_Model_Translate::CACHE_TAG));
      $session->setAttributeData(false);
    }
    catch (Exception $e) {
      $session = Mage::getSingleton('adminhtml/session');
      $session->addError($e->getMessage());
      $session->setAttributeData($data);
    }
  }
}

Best Answer

I'm guessing this is a script that's running outside of the normal Magento structure and you are including app/Mage.php and instantiating it with Mage::app();?

In that case the label might be saved on a different level than your store. Try using the emulate functionality to save the model data in the right store view.

$appEmulation = Mage::getSingleton('core/app_emulation');
//Start environment emulation of the specified store
$initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation($storeId);
/*
 * Any code thrown here will be executed as we are currently running that store
 * with applied locale, design and similar
 */
//Stop environment emulation and restore original store
$appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo);

(source: Inchoo)

Also try and reindex the data in your store. Start the script with setting indexes to manual

$processes = Mage::getSingleton('index/indexer')->getProcessesCollection();
$processes->walk('setMode', array(Mage_Index_Model_Process::MODE_MANUAL));
$processes->walk('save');

And before emptying cache execute

$processes->walk('reindexAll');
$processes->walk('setMode', array(Mage_Index_Model_Process::MODE_REAL_TIME));
$processes->walk('save');

This should rebuild all indexes making sure you're retrieving the latest data from the product flat table.

Related Topic