제품 속성을 결합하는 모범 사례


11

제품 참조가있는 사용자 정의 테이블이 product_id있습니다. 이제 백엔드 그리드 에 제품 정보 (sku, 이름)를 표시 하고 싶지만이를 수행하는 가장 좋은 방법은 무엇입니까?

가장 좋은 추측 SKU은 다음과 같습니다.

$collection->join(
    'catalog/product',
    'product_id=`catalog/product`.entity_id',
    array('product_sku' => 'sku')
)

( 내 그리드 블록 클래스 메소드 코드 _prepareCollection() )

그러나 제품 이름은 어떻습니까? catalog_product_entity_varchar에서 찾을 수 있습니다. 내 이해는 자신의 리소스 모델과 컬렉션이 기반 Mage_Eav_Model_Entity_Collection_Abstract이기 때문에 쉽게 얻을 수 있다는 것 joinAttribute입니다. 하지만 내 모델은 간단한 테이블을 기반으로하고로부터 연장되어 Mage_Core_Model_Resource_Db_Collection_Abstract더이 없습니다 joinAttribute가능한 방법.

이 경우 제품 이름을 얻는 가장 좋은 방법은 무엇입니까?

시간과 도움을 주셔서 감사합니다 :-)

업데이트 : 더 정확하게하기 위해 리소스 모델과 컬렉션에 대해 이야기했습니다. 다음과 같은 몇 가지 속성으로 간단한 플랫 테이블과 일치합니다

entity_id    product_id    created_at    user_id

내 의도는 통계를 보여주는 백엔드에 그리드를 배치하는 것입니다.

ProductSku    Count(ProductSku)    MAX(created_at)

내가 아는 한이를 수행하는 가장 좋은 방법은 그리드 블록 클래스를 사용하는 것입니다 _prepareCollection().

내 방법은 다음과 같습니다

protected function _prepareCollection()
{
    // Get and set our collection for the grid
    $collection = Mage::getResourceModel($this->_getCollectionClass());
    $collection
        ->join(
            'catalog/product',
            'product_id=`catalog/product`.entity_id',
            array('product_sku' => 'sku')
            )
        ->addExpressionFieldToSelect('product_count', 'COUNT({{product_id}})', 'product_id')
        ->addExpressionFieldToSelect('newest', 'MAX({{created_at}})', array('created_at'=>'main_table.created_at'))
        ->getSelect()->group('product_id');
    $this->setCollection($collection);

    return parent::_prepareCollection();
}

이것은 sku ( _prepareColums()메소드 에서 product_sku라고 함)에 잘 작동 하지만 join이름 (예 : 제조업체)을 얻으려면 여기에 무엇 을 삽입해야합니까?

사용할 수 없기 때문에 뭔가 잘못하고 joinLeft()있습니까?

답변:


13

컬렉션 클래스 ( /Some/Module/Model/Mysql4 (or Resource)/YourModel/Collection.php)에서이 메소드를 추가하십시오.

public function addProductData()
    {
        /** add particular attribute code to this array */
        $productAttributes = array('name', 'price', 'url_key');
        foreach ($productAttributes as $attributeCode) {
            $alias     = $attributeCode . '_table';
            $attribute = Mage::getSingleton('eav/config')
                ->getAttribute(Mage_Catalog_Model_Product::ENTITY, $attributeCode);

            /** Adding eav attribute value */
            $this->getSelect()->join(
                array($alias => $attribute->getBackendTable()),
                "main_table.product_id = $alias.entity_id AND $alias.attribute_id={$attribute->getId()}",
                array($attributeCode => 'value')
            );
            $this->_map['fields'][$attributeCode] = 'value';
        }
        /** adding catalog_product_entity table fields */
        $this->join(
            'catalog/product',
            'product_id=`catalog/product`.entity_id',
            array('sku' => 'sku', 'type_id' => 'type_id')
        );
        $this->_map['fields']['sku']     = 'sku';
        $this->_map['fields']['type_id'] = 'type_id';
        return $this;
    }

그리드 블록에서이 기능을 사용하십시오.

 protected function _prepareCollection()
    {
        $collection = Mage::getModel('some/yourmodel')
            ->getCollection()->addProductData();
        $this->setCollection($collection);
        return parent::_prepareCollection();
    }

이것은 유망 해 보이지만 불행히도 작동하지 않습니다. 내 컬렉션이 확장되어 Mage_Core_Model_Resource_Db_Collection_Abstract오류가 발생 Call to undefined method Mycompany_Module_Model_Resource_Mymodel_Collection::joinLeft()합니다. EAV 리소스 모델을 사용하지 않기 때문인 것 같습니다.
Celldweller

joinLeft 대신 join을 사용하여 답을 편집했습니다.
mageUz

도! 나는 지금 바보 느낌! ;-) 그리고 나는 그것을 시도한 이유를 모른다. 대단히 감사합니다!
Celldweller

@Celldweller,이 경우 절대적으로 사용할 필요가 없습니다 $this->_map['fields']['sku'] = 'sku'. 동일한 필드 이름이 여러 개 있고 충돌을 방지하기 위해 번역을 수행해야하는 경우에만 필요합니다. 이 사용 사례에 대한 오버 헤드 만 추가합니다. 다른 유스 케이스에서 사용할 수 있습니다 $this->_map['fields']['my_sku'] = 'sku'당신이 컬렉션에서 사용할 수 있습니다 다음 _prepareColumns: $this->addColumn('my_sku', array(…))당신은 필드가있는 경우, 당신이 필터링 또는 정렬 컬럼의 충돌을 방지하는 데 도움이 될 것입니다 sku컬렉션에 다른 DB 테이블 공통적으로 사용
실뱅 Rayé

좋은 대답입니다! 그래도 "같은 ID를 가진 항목이 이미 존재합니다"문제가 발생할 수 있습니다. 간단하게 $this->getSelect()->group('main_table.product_id');문제를 해결하지만 코드를 최적화하여 복제본이 처음에 생성되지 않도록 할 수 있습니까?
Simon

4

안녕하세요 Celldweller 나는 당신이 잘하고 있기를 바랍니다 :-)

클래스에 대한 설명이 잘못되었을 Mage_Core_Model_Resource_Db_Collection_Abstract수 있습니다. Magento 구조를 존중하려면 컬렉션 클래스로 모델을 확장해서는 안되므로 모델이 아닌 리소스 컬렉션을 확장해야합니다. 내가 맞아?

내 수정에 따라 제품 이름 속성을 얻는 빈도에 따라 다른 종류의 접근 방식이 보입니다. 어쨌든 Magento Framework를 통해 SQL 쿼리를 수행하는 것이 가장 좋은 방법이며 효율적이라고 생각합니다. Mage::getModel('catalog/product')->load(1234)->getName()로드 된 각 항목에 대해 수행하는 것보다 빠릅니다 . 사실 그것은 당신이 사용하는 코드와 매우 유사합니다sku

테스트되지 않은 코드

컬렉션이로드 될 때마다 해당 정보를 원합니다

컬렉션 클래스에서 다음 _beforeLoad과 같은 메소드 로 설정할 수 있습니다 .

protected function _beforeLoad()
{
    $productName = Mage::getSingleton('eav/config')->getAttribute('catalog_product','name');

    $this->getSelect()
        ->join( array('product_attribute' => $productName->getBackendTable()),
            'main_table.product_id = product_attribute.entity_id',
            array())
        ->where("product_attribute.attribute_id = ?", $productName->getId());
    }

    return parent::_beforeLoad();
}

그리드에 대한 정보 만 원합니다

에서 위와 _prepareCollection동일한 코드를 사용하여 컬렉션에 메서드를 추가 한 _beforeLoad다음이 메서드를 사용하여 컬렉션을 준비 할 수 있습니다. 둘 다 사용하지 마십시오. 동일한 코드 _beforeLoadaddProductName메소드를 함께 사용하지 말고 둘 중 하나만 사용하십시오. 다음은 샘플입니다.

당신의 grid.php:

protected function _prepareCollection()
{
    ...
    $collection->addProductName();
    $this->setCollection($collection);
    return parent::_prepareCollection();
}

Collection.php에 :

public function addProductName()
{
    $productName = Mage::getSingleton('eav/config')->getAttribute('catalog_product','name');

    $this->getSelect()
        -> join( array('product_attribute' => $productName->getBackendTable()),
            'main_table.product_id = product_attribute.entity_id',
            array())
        ->where("product_attribute.attribute_id = ?", $productName->getId());

    return $this;
}

다시 읽어 주셔서 감사합니다 :-) 대단히 감사하지만 joinLeft () 메서드를 사용할 수 없습니다. EAV 리소스 모델 전용 방법 인 것 같습니다. 네 말이 맞아, 나는 내 첫 질문에 정확하지 않았다. 나는 그것을 편집 할 것이다 :)
Celldweller

오, btw : 물론 그런 상황에서 product-> load ()을 원하지 않습니다. 내가 감히 나를 쏴! ;-) 내 목표는 그리드에서 정렬 및 필터링을 수행 할 수 있도록 모든 것을 하나의 컬렉션에 포함시키는 것입니다. 자세한 내용은 초기 게시물의 업데이트를 참조하십시오.
Celldweller

그래서 참여에 의해 joinLeft을 대체하지만 당신은 이미 내가 제대로 대답하지만 다른 대답을 받아 들여 :-( 대답에 처음이었다
실뱅 Rayé에게

그래 네가 맞아. 나는 그것이 마침내 효과가있어서 그것에 대해 생각하지 않았기 때문에 너무 기뻤습니다. 두 분 모두에게 매우 감사합니다. 당신이 나를 용서할 수 있기를 바랍니다! 나는 당신에게 맥주를 빚지고 있습니다.
Celldweller

걱정 하지마 우리는 기쁨으로 베를린에서 당신을 만납니다 :-)
Sylvain Rayé

4

나는 거의 같은 문제가 있었지만 50 평판이 없기 때문에 의견을 추가 할 수 없습니다. 나는 무엇이 잘못되었는지 알아 내려고 많은 시간을 보냈습니다 (실베인 레이의 코드를 사용했습니다). 어떤 이유로 내 제품 컬렉션이 필터링되었습니다. 그래서 이유를 찾았습니다.

가져 오기 도구 (magmi 등)를 사용하는 경우 종종 빈 속성을 한 번에 만들지 않습니다. 따라서이 ->where("product_attribute.attribute_id = ?", $productName->getId())속성이없는 제품을 사용 하면 선택에서 사라집니다.

올바른 방법은 다음 joinLeft과 같습니다.

$productName = Mage::getSingleton('eav/config')->getAttribute('catalog_product','name');

$this->getSelect()
     ->joinLeft(array('product_attribute' => $productName->getBackendTable()),
        "main_table.product_id = product_attribute.entity_id AND
         product_attribute.attribute_id = {$productName->getId()}",
        array());

이것이 누군가를 돕기를 바랍니다.


-2

제품 표에 사용자 정의 속성을 표시하십시오.

확장 프로그램에서이 블록 Mage_Adminhtml_Block_Catalog_Product_Grid를 덮어 쓰고 _prepareCollection 및 _prepareColumns 함수를 확장 프로그램의 블록 파일로 복사하십시오.

$ this-> setCollection ($ collection) 행 전에 제품 그리드 Mage_Adminhtml_Block_Catalog_Product_Grid의 _prepareCollection 함수에서 속성을 선택하려면 아래 코드를 추가하십시오.

$attributeCode = 'qc_status';//here your attribute code
        $collection->joinAttribute($attributeCode, 'catalog_product/'.$attributeCode, 'entity_id', null, 'left');
        $collection->addAttributeToSelect($attributeCode);

그런 다음 그리드의 _prepareColumns 함수의 열 코드가 아래에 있습니다.

$attributeCodeConfig ='qc_status';//Your attribute code...

        $attributeId = Mage::getResourceModel('eav/entity_attribute')->getIdByCode('catalog_product', $attributeCodeConfig);

        $attribute = Mage::getModel('catalog/resource_eav_attribute')->load($attributeId);
        $attributeData = $attribute->getData();
        $frontEndLabel = $attributeData['frontend_label'];

        $attributeOptions = $attribute->getSource()->getAllOptions();
        $b = new Mage_Catalog_Model_Resource_Eav_Attribute();
        $attributeOptions2 = array();
        foreach ($attributeOptions as $value) {
            if(!empty($value['value'])) {
                $attributeOptions2[$value['value']] = $value['label'];
            }

        }


        if(count($attributeOptions2) > 0) {
            $this->addColumn($attributeCodeConfig,
                array(
                    'header'=> Mage::helper('catalog')->__($frontEndLabel),
                    'width' => '80px',
                    'index' => $attributeCodeConfig,
                    'type'  => 'options',
                    'options' => $attributeOptions2,

            ));
        } else {
            $this->addColumn($attributeCodeConfig,
                array(
                    'header'=> Mage::helper('catalog')->__($frontEndLabel),
                    'width' => '80px',
                    'index' => $attributeCodeConfig,

            ));
        }

핵심 파일을 변경하는 것은 좋은 습관이 아닙니다. 동일new SomeModel()
sv3n

우리는 핵심 파일을 변경할 필요가 없습니다. 기능을 수행하기 위해 해당 블록 (Mage_Adminhtml_Block_Catalog_Product_Grid)을 덮어 쓸 수 있습니다
Savoo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.