Magento-カスタム(EAV以外)モデル、複数のフィールドによるロード
-
16-10-2019 - |
質問
カスタムモデルとリソースモデルがあります。 1つ以上のフィールドを使用して、モデルの単一インスタンスをロードしたいと思います。
モデルには次のフィールドがあります。
id
tag_name
custom_name
group_name
IDの代わりにTAG_NAME、custom_name、およびgroup_nameに基づいてこのモデルをロードしたい。
現在、各フィールドにコレクションとaddFilterを使用しています。これはうまくいきますが、Magentoにこのタイプのことに標準的な戦略があるのではないかと思いましたか?
編集
Core Magentoは、このシナリオにコレクションを使用していないようですが、代わりにリソースモデルで直接SQLクエリを使用しています。
この例は次のとおりです。
loadByAccountAndDate()
の Mage_Paypal_Model_Resource_Report_Settlement
コレクションがより簡潔な方法であると思われる場合、書かれるコードの量の観点から
マゼントがこのようにすることを選ぶ理由がわからない
解決
これは良いアプローチだと思います。モデルクラスでラッパーを作成する必要があるかもしれないので、同じことを何度も書くことを避ける必要があります。
何かのようなもの:
public function loadByMultiple($tag, $customName, $group){
$collection = $this->getCollection()
->addFieldToFilter('tag_name', $tag)
->addFieldToFilter('custom_name', $customName)
->addFieldToFilter('group_name', $group);
return $collection->getFirstItem();
}
また、このようなアイテムを他の場所にロードできます。
$model = Mage::getModel('model/class_here')->loadByMultiple($tag, $customName, $group);
if ($model->getId()){
//the instance exists
}
else{
//not found
}
他のヒント
モジュール/モデル/somemodel.php
public function loadByAttributes($attributes)
{
$this->setData($this->getResource()->loadByAttributes($attributes));
return $this;
}
モジュール/モデル/リソース/somemodel.php:
public function loadByAttributes($attributes)
{
$adapter = $this->_getReadAdapter();
$where = array();
foreach ($attributes as $attributeCode=> $value) {
$where[] = sprintf('%s=:%s', $attributeCode, $attributeCode);
}
$select = $adapter->select()
->from($this->getMainTable())
->where(implode(' AND ', $where));
$binds = $attributes;
return $adapter->fetchRow($select, $binds);
}
そして最後に、次のモデルをロードできます。
$attributes = array('tag_name'=> 'any', 'custome_name'=> 'some','group_name'=>'some');
$model = Mage::getModel('module/somemodel')->loadByAttributes($attributes);
更新しました
ちなみに、この(loadbyattributes)メソッドをコレクションではなく簡単に使用でき、より理解しやすいです。 Magentoはまた、コレクションまたはエンティティを読み込んでいる間にいくつかのイベントを派遣し、サードパーティの拡張機能はオブザーバーによるコレクションまたはエンティティを更新できます。リソースを介してエンティティをロードすると(私の例とあなたの例で与えられます)、イベント/オブザーバーの火災はなく、コレクションよりも「クリーン」エンティティをより速く取得できます。また、Magentoはこのようにキャッシュコレクションを使用していないため、DBテーブルから直接ロードします。
たぶんそれがMagento Coreモジュールによってこの方法を使用する理由です。
あなたはそれを正しくやっています addFilter
. 。 Magentoでは、任意の属性でロードできますが、一度に複数の属性ではありません。フィルターを追加することで、オーバーヘッドを追加せずに同じ効果を達成します。
まず、コレクションをフィルタリングする戦略が正しいです。 Magento Lazy-Loadのコレクションは、リソースモデルにメソッドを作成して、カスタム負荷の要件をより厳密に定義する機能を備えています。
サンプリングするコードの一部がなければ、リソースモデルで次の擬似メソッドを検討してください。
<?php
class Marty_Wallace_Model_Resource_Method extends Mage_Core_Model_Resource_Db_Abstract{
protected function _construct()
{
$this->_init('yourmodel/table', 'entity_id');
}
public function loadByCriteria(array $filter)
{
//$filter should be array('columnname'=>'value','columname'=>'value')
$collection = Mage::getModel('yourmodel/class')->getCollection();
foreach($filter as $column=>$value){
$collection->addFieldToFilter($column,$value);
}
return $collection;
}
}