Magento-カスタム(非eav)モデル、複数フィールドによるロード


15

カスタムモデルとリソースモデルがあります。複数のフィールドを使用してモデルの単一インスタンスをロードしたい。

モデルには次のフィールドがあります。

id
tag_name
custom_name
group_name

idではなくtag_name、custom_name、およびgroup_nameに基づいてこのモデルをロードします。

現在、各フィールドにコレクションとaddFilterを使用しています。これは機能しますが、Magentoにこのタイプのことに対する標準的な戦略があるのではないかと思いましたか?

編集

コアmagentoはこのシナリオではコレクションを使用しないようですが、代わりにリソースモデルで直接SQLクエリを使用します。

この例は次のとおりです。

loadByAccountAndDate()Mage_Paypal_Model_Resource_Report_Settlement

コレクションがより簡潔な方法であると思われるときに、書かれるコードの量の点で、これには理由があります

magentoがこのように選択する理由がわかりません

回答:


21

これは良いアプローチだと思います。モデルクラスにラッパーを作成して、同じことを何度も繰り返さないようにする必要があるかもしれません。
何かのようなもの:

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
}

コレクションの使用に関する懸念で質問を更新しました
マーティウォレス

本当にコレクションをロジックから除外したい場合は、@ mageUzが彼の答えに書いたことを確認してください。私はそれをテストしませんでしたが、縫い目は良いアイデアのようです。注:コレクションの使用に関する問題はまだありません。
マリウス

それらを除外したいわけではありませんが、Magentoのベストプラクティスを使用したいと思います。コアコードが特定の方法で何かを実行している場合、通常、それは従うべき何かの兆候であるはずです。しかし、この場合、私は本当に最善の方法を知らないので、このフォーラムで指導を求めています
マーティウォレス

1
この場合、コレクションの使用にも懸念があります。おそらく、問題のコレクションに_itemObjectClassは、実際に呼び出すモデルと同じがありloadByMultipleます。結果として、$x = Mage::getModel('some/model')モデルの1つのインスタンスではなく、$x->loadByMultiple($tag, $customName, $group)実際には異なる/新しいインスタンスになりますか?
小次郎14

@kojiro。はい、それは別のインスタンスになりますが、そうloadByAttributeです。この質問を参照してください:magento.stackexchange.com/q/5926/146
マリウス

7

モジュール/モデル/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コアモジュールでこのメソッドを使用する理由です。


:私はあなたがこのライン上のgetData()を欠けていると思う $this->setData($this->getResource()->loadByAttributes($attributes));であるべき、: $this->setData($this->getResource()->loadByAttributes($attributes)->getData()); 右の?
Mihai MATEI

2

あなたはそれを正しくやっていますaddFilter。Magentoでは、任意の属性で読み込むことができますが、複数の属性を一度に読み込むことはできません。フィルタを追加することで、追加のオーバーヘッドなしで同じ効果を達成できます。


db selectを使用することは、コレクションを使用することよりも良くないでしょうか?
マーティウォレス

何をしていると思いますaddFilterか?:-)
user487772

これは、コレクションの代わりに選択し使用しているとして、あなたはMage_Paypal_Model_Resource_Report_Settlement中)(loadByAccountAndDateで見ることができます
マーティ・ウォレス

そして、実際にコアコードでこのような状況は、次のようにほぼ独占的であると私は、任意の使用してコレクションを見ることができない
マーティ・ウォレス

1
コレクションの使用に関する懸念で質問を更新しました
マーティウォレス

1

まず、コレクションをフィルタリングする戦略は正しいです。Magentoの遅延ロードのコレクションでは、リソースモデルでメソッドを作成して、カスタムロードの要件をより厳密に定義することができます。

サンプリングするコードの一部がない場合、リソースモデルで次の擬似メソッドを検討してください。

<?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;

    }
}

私は、この特定のユースケースのためのコレクションを使用して上で、私の懸念に私の質問を更新しましたが、私はMagentoのは、このようにそれを行う理由を知るための十分な知識を持っていない
マーティ・ウォレス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.