Magentoコレクションのシリアル化可能なフィールド
-
16-10-2019 - |
質問
私のリソースモデルでは、フィールドをシリアル化可能として定義しました(プロパティを参照してください $_serializableFields
の Mage_Core_Model_Resource_Db_Abstract
):Magentoは、データベースからデータを読み込んだときおよびオブジェクトを保存する前に、コンテンツのシリアル化/非正規化を自動的に処理します。
これは完全に機能しますが、これらのオブジェクトのコレクションを反復すると、フィールドの内容は自動的に非正規化されません。一緒に試しました $collection->walk('afterLoad')
しかし、すぐにそれを実現しました unserializeFields()
リソースモデルでトリガーされています load()
, 、ではありません afterLoad()
私が最初に思ったように。この場合のベストプラクティスは何ですか?このフィールドを自動的に非選択化するにはどうすればよいですか?もちろん、ループ内のオブジェクトをリロードして、ようなことをすることができます $object = $object->load($object->getId())
, 、しかし、私はこれを達成するためのより賢い方法があるかどうか疑問に思っていました。
解決
もちろん、ループ内のオブジェクトをリロードして、ようなことをすることができます
$object = $object->load($object->getId())
これは いいえ リロード - これは負荷です. 。コレクションのアイテム(モデルインスタンス) そうではありません ロード。彼らは単にそれらに適用される結果行データの連想配列を持っていただけです。これは、これらのコレクション所有のモデルインスタンスと、リソースモデルを介してデータを自己ロードしているモデルインスタンスとの間の重要でわずかに混乱する違いです。
あなたのコレクションで _afterLoad()
, 、繰り返します _items
と unserialize()
適切なフィールド:
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;
}
他のヒント
製品コレクションのためにこれを行うには、イベントリスナーを追加しました catalog_product_collection_load_after
そして、すべての製品を反復します。
/**
* 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);
}
}
}
より簡単に言えば、リソースモデルのコレクションで: -
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; } }