8

I'd like to be able to save the value of an attribute without saving it's parent entity. I have created a new customer attribute via my module's sql/setup file (ref), and now I want to populate that attribute for each of the existing customers. I've created a Backend model for the attribute that detects null values during the entity load (afterLoad) and generates the content, but I am hesitant to save the entity at that point in the process.

class Aligent_Referral_Model_Customer_Attribute_Backend_Referralcode extends Mage_Eav_Model_Entity_Attribute_Backend_Abstract
{
public function afterLoad($oCustomer)
{
    $vAttrCode = $this->getAttribute()->getAttributeCode();
    $vValue = $oCustomer->getData($vAttrCode);
    if (empty($vValue)){
        $oCustomer->setData($vAttrCode, Mage::helper('referral')->generateRafCode($oCustomer));
    }
    return $this;
}
}

Ideally, I'd like to call something like $this->getAttribute()->setValue('blah')->save() in that afterLoad method so that it doesn't rely on the user clicking save.

I could write a script that loads a collection of all customers and walks them to set the value, but there's over 50,000 customers and I'm concerned about the performance impact of running that on a production server...

Any thoughts appreciated.
JD

Community
  • 1
  • 1
Jonathan Day
  • 18,519
  • 10
  • 84
  • 137

3 Answers3

19

The EAV resource model offers the ability to save single attributes without saving the entity.

$value = Mage::helper('referral')->generateRafCode($oCustomer);
$oCustomer->setData($vAttrCode, $value)->getResource()->saveAttribute($oCustomer, $vAttrCode);
Vinai
  • 14,162
  • 2
  • 49
  • 69
  • nice!! I love that, putting it in my notes now. – dan.codes Nov 17 '11 at 14:06
  • @dan.codes you keep notes? I thought that was the whole point of StackOverflow... you'll notice that the reason I'm back at this question is cos I need to use it again and don't have notes! :) – Jonathan Day Feb 06 '12 at 06:01
  • @JonathanDay Ha, yeah its a collection of notes and stack overflow favorites, as well as past projects code snippets. – dan.codes Feb 23 '12 at 15:18
  • 2
    I would like to add that this is not possible for attributes with a "static" backend type! You will get an error "Unknown column 'customer_entity.value_id' in 'field list'" – Michael Leiss Jun 11 '14 at 12:18
  • @vinai can I save an eav Attribute to a specific store scope using this approach? – zainengineer May 25 '15 at 07:15
  • For store scoped variables Mage::getSingleton('catalog/product_action')->updateAttributes(...) seem to work in a similar manner – zainengineer May 25 '15 at 07:37
2

So one option that works it to write directly to the database. This isn't particularly elegant but quite effective in achieving the "lazy-load" approach to populating a new attribute for existing customers (or other entities). Here is the additional code in the Attribute_Backend_Referralcode to what I posted in the question:

$vAttrValue = 'some string';
$oCustomer->setData($vAttrCode, $vAttrValue);
$iAttrId = $this->getAttribute()->getAttributeId();
$data = array(
            'entity_type_id' => $oCustomer->getEntityTypeId(),
            'attribute_id' => $iAttrId,
            'entity_id' => $oCustomer->getId(),
            'value' => $vAttrValue,
        );
$vTableName = $this->getAttribute()->getBackend()->getTable();
Mage::getResourceModel('table/alias')->getWriteAdapter()->insert($vTableName, $data);

It requires exposing a public method to get the Write Adapter on the Mysql4 model, but no big deal there.

Still interested to know if there is an approach that uses the EAV model layer better...

Jonathan Day
  • 18,519
  • 10
  • 84
  • 137
0

The solution Vinai provided is not working for attributes with backend type static. In case of static you can only do something like this:

        $adapter = Mage::getSingleton('core/resource')->getConnection('core_write');
        $adapter->update(
            "customer_entity",
            array("group_id" => $customerGroupId),
            "entity_id=$customerId"
        );
Michael Leiss
  • 5,395
  • 3
  • 21
  • 27