5

In my resource model I have defined a field as serializable (see property $_serializableFields in Mage_Core_Model_Resource_Db_Abstract): Magento handles automatically serialization/unserialization of the contents when loading data from the database and before saving the object.

This works perfectly, but when I iterate over a collection of those objects, the field contents are not unserialized automatically. I tried with $collection->walk('afterLoad') but soon realized that unserializeFields() is triggered in the resource model load(), and not in afterLoad() like I first thought. What is the best practice in this case? How do I get this field unserialized automatically? I can of course reload the object in my loop, doing something like $object = $object->load($object->getId()), but I was wondering if there is a smarter way to achieve this.

7

I can of course reload the object in my loop, doing something like $object = $object->load($object->getId())

This is not a reload - this is a load. Items (model instances) in collections are not loaded. They merely have had an associative array of result row data applied to them. It's an important and slightly confusing difference between these collection-owned model instances and those which are self-load data through their resource model.

In your collection's _afterLoad(), iterate over the _items and unserialize() the appropriate field:

protected function _afterLoad()
{
    parent::_afterLoad();
    foreach ($this->getItems() as $item) {
        $item->setData('field',unserialize($item->getData('field')));
        $item->setDataChanges(false);
        //The above sets items as not dirty.
        //Value will be serialized on save via resource model.
    }
    return $this;
}
  • I know they are not loaded, wrong wording, but thanks for pointing that out! Neat solution indeed, thought there might be an easier way, but this looks just right. – fmrng Jun 28 '13 at 12:24
  • It would be nice if Mage_Core_Model_Resource_Db_Abstract defined a getter for _serializableFields that the collection abstract would use to perform the same logic. That said, it would be easy enough for you to create one in your resource model. – benmarks Jun 28 '13 at 12:28
  • Also a good idea, to keep the logic inside the resource model. Like that, the collection doesn't need to know which fields need to be unserialized. Even if I only have one field and I'm not planning to add more, it is definitely more consistent. – fmrng Jun 28 '13 at 12:37
0

To do this for product collections I added an event listener to catalog_product_collection_load_after and to iterate over all products.

/**
 * Apply backend manipulations of attributes to collection items.
 * Listens to catalog_product_collection_load_after.
 *
 * @param Varien_Event_Observer $observer
 * @return Mage_Catalog_Model_Observer
 */
public function loadCollectionAttributes(Varien_Event_Observer $observer)
{
    $collection = $observer->getCollection();
    /* @var $collection Mage_Catalog_Model_Resource_Product_Collection */
    foreach ($collection as $product) {
        /* @var $product Limora_Catalog_Model_Product */
        foreach ($product->getAttributes() as $attribute) {
            /* @var $attribute Mage_Eav_Model_Attribute */
            $attribute->getBackend()->afterLoad($product);
        }
    }
}
0

Or more simply, in your resource model collection:-

class Collection 
extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
    protected function _afterLoad()
    {
        parent::_afterLoad();
        foreach ($this->getItems() as $item) {
            $this->getResource()->unserializeFields($item);
            $item->setDataChanges(false);
        }
        return $this;
   }
}
  • Not working in M2 (2.2.6) – Priyank Feb 15 at 9:02

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.