마 젠토-사용자 정의 (비 eav) 모델, 여러 필드에 의해로드


15

사용자 지정 모델과 리소스 모델이 있습니다. 둘 이상의 필드를 사용하여 모델의 단일 인스턴스를로드하고 싶습니다.

이 모델에는 다음과 같은 필드가 있습니다.

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

작성해야 할 코드의 양 측면에서 컬렉션이 더 간결한 방식 인 것처럼 보이는 이유가 있습니까?

나는 왜 magento가 이런 식으로 그것을 선택했는지 모르겠다.

답변:


22

나는 이것이 좋은 접근 방법이라고 생각합니다. 모델 클래스에서 랩퍼를 작성해야하므로 동일한 내용을 반복해서 작성하지 않아도됩니다.
다음과 같은 것 :

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
}

컬렉션 사용에 대한 우려로 내 질문을 업데이트했습니다
Marty Wallace

로직에서 컬렉션을 제외하려면 @mageUz가 자신의 답변에 쓴 내용을 확인하십시오. 나는 그것을 테스트하지 않았지만 좋은 아이디어처럼 솔기가 있습니다. 참고 : 컬렉션 사용에 여전히 문제가 없습니다.
Marius

그것들을 제외하고 싶지는 않지만 magento 모범 사례를 사용하고 싶습니다. 핵심 코드가 특정 방식으로 무언가를 수행하는 경우 일반적으로 따라야 할 징후입니다. 난 정말 최선의 방법 모르는이 경우 그러나 나는 guidence이 포럼에 질문입니다
마티 월러스

1
이 경우 컬렉션 사용에 대한 우려도 있습니다. 아마도 해당 컬렉션에는 _itemObjectClass실제로 호출하는 모델과 동일한 컬렉션이 loadByMultiple있습니다. 결과적 $x = Mage::getModel('some/model')으로 모델의 한 인스턴스 가 아니며 $x->loadByMultiple($tag, $customName, $group)실제로 다른 / 새 인스턴스가 되겠습니까?
kojiro

@kojiro. 예, 다른 인스턴스가 될 것입니다 loadByAttribute. 참조를 위해이 질문을 참조하십시오 : magento.stackexchange.com/q/5926/146
Marius

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 2016 년

컬렉션 대신 select를 사용하므로 Mage_Paypal_Model_Resource_Report_Settlement에서 loadByAccountAndDate ()를 볼 수 있습니까
Marty Wallace

그리고 실제로 핵심 코드 에서이 상황은 거의 독점적으로 이와 같으며 컬렉션을 사용하는 것을 볼 수 없습니다.
Marty Wallace

1
컬렉션 사용에 대한 우려로 내 질문을 업데이트했습니다
Marty Wallace

1

먼저 컬렉션을 필터링하는 전략이 정확합니다. 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;

    }
}

이 특정 유스 케이스에 컬렉션을 사용하는 것에 대한 우려로 내 질문을 업데이트했지만 magento가 왜 이런 식으로 작동하는지 알 수있는 지식이 충분하지 않습니다.
Marty Wallace
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.