save an attribute value without saving its parent entity in Magento
I'd like to be able to save the value of an a开发者_如何学JAVAttribute 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.
JDThe 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);
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...
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"
);
精彩评论