Magento2가 프로그래밍 방식으로 속성 옵션을 추가하는 방법 (설정에 없음)


15

수입 모듈에서 크기 및 색상 속성에 대한 옵션을 추가하려고 시도하지만 방법은 없습니다.

private function addOption($attributeCode, $value)
{
    $ob = $this->_objectManager;      
    /* @var $m \Magento\Eav\Model\Entity\Attribute\OptionManagement */
    $m = $this->optionManagement;
    /* @var $option \Magento\Eav\Model\Entity\Attribute\Option */
    $option = $this->attributeOption;

    $option->setLabel($value);      
    $option->setValue($value);

    $m->add(\Magento\Catalog\Api\Data\ProductAttributeInterface::ENTITY_TYPE_CODE,
            $attributeCode,
            $option);

이 보고서는 오류가 (난에보고 예외 수정 OptionMaganger.php> 메시지 예외 중을 )

속성 크기를 저장할 수 없습니다. 참고 : 정의되지 않은 색인 : 177 행의 /var/www/html/magento2/vendor/magento/module-swatches/Model/Plugin/EavAttribute.php에서 삭제

  • 옵션 관리 및 옵션은 _contstructor
  • OptionManagement를 사용하면 기존 항목을 검색 할 수 있으므로 확인해야합니다.

setLabel()그리고 setValue()기본값이지만 setData를 시도 하고 옵션 인스턴스를로드 OptionManagement->getItems하고 add (...) "again"으로 전달했지만 오류가 여전히 존재합니다 ...

가져 오기 프로세스 중에 EAV 옵션 (견본)을 어떻게 추가 할 수 있습니까? (모듈 설정이 아님)


업데이트 :

다른 방법으로 옵션을 추가 할 수 있습니다.

$attributeCode = 137; /* on size, 90 on color ... */

$languageValues[0]='Admin Label'; 

$languageValues[1]='Default Store Label - XXXXL';
$ob = $this->_objectManager;

private function addOption($attributeCode,$languageValues){
$ob = $this->_objectManager;
/* @var $attr \Magento\Eav\Model\Entity\Attribute */
$attr = $ob->create('\Magento\Eav\Model\Entity\Attribute'); 
$attr->load($attributeCode); 
$option = []; 
$option['value'][$languageValues[0]] = $languageValues; 
$attr->addData(array('option' => $option));
$attr->save();
}

이 방법으로 Magento2는 속성에 옵션을 저장할 수 있지만 "공식적인"방법이 무엇인지 모르겠습니다 :)


옵션은 정수로 지원되지 않는 문자열로 값을 추가했습니다
Ajay Patel

답변:


2
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Store\Model\StoreManagerInterface;

알리다:

protected $_eavSetupFactory;

생성자 :

public function __construct(
    \Magento\Eav\Setup\EavSetupFactory $eavSetupFactory,
    \Magento\Store\Model\StoreManagerInterface $storeManager,
    \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attributeFactory,
    \Magento\Framework\ObjectManagerInterface $objectmanager,
    ModuleDataSetupInterface $setup,
    \Magento\Catalog\Model\ProductFactory $productloader
) {
    $this->_eavSetupFactory = $eavSetupFactory;
    $this->_storeManager = $storeManager;
    $this->_attributeFactory = $attributeFactory;
    $this->_objectManager = $objectmanager;
    $this->setup = $setup;
    $this->_productloader = $productloader;
}

메소드 실행 :

public function execute(EventObserver $observer)
{
    /** @var $brand \Ktpl\Brand\Model\Brand */
    $brand = $observer->getEvent()->getBrand();
    $option_id = "";

    $data = [];
    $attribute_arr = [$brand['brand_id'] => $brand['brand_title']];
    $optionTable = $this->setup->getTable('eav_attribute_option');
    $attributeInfo=$this->_attributeFactory->getCollection()
           ->addFieldToFilter('attribute_code',['eq'=>"shop_by_brand"])
           ->getFirstItem();

    $attribute_id = $attributeInfo->getAttributeId();

    $eavAttribute = $this->_objectManager->create('Magento\Eav\Model\Config');

    $option=array();
    $option['attribute_id'] = $attributeInfo->getAttributeId();
    $option['value'] = array(0=>array()); // 0 means "new option_id", other values like "14" means "update option_id=14" - this array index is casted to integer

    $storeManager = $this->_objectManager->get('Magento\Store\Model\StoreManagerInterface');
    $stores = $storeManager->getStores();
    $storeArray[0] = "All Store Views";       

    foreach ($stores  as $store) {
        $storeArray[$store->getId()] = $store->getName();
    }


    if (empty($brand['optionId'])) {
        foreach($attribute_arr as $key => $value){
            $option['value'][0][0]=$value;
                foreach($storeArray as $storeKey => $store){
                    $option['value'][0][$storeKey] = $value;
                }                
        }
    }
    else
    {
        foreach($attribute_arr as $key => $value){
                foreach($storeArray as $storeKey => $store){
                    $option['value'][$brand['optionId']][$storeKey] = $value;
                }                
        }
    }

    $eavSetup = $this->_eavSetupFactory->create();
    $eavSetup->addAttributeOption($option)

}

코드에 심각한 오류가 있습니다. 따라서 숫자가없는 문자열 (예 : "검은 색")이 있으면 0이됩니다. 그러나 $ value가 "10 Black"과 같은 경우 10으로 캐스팅하고 대신 option_id = 10으로 데이터베이스 엔터티를 업데이트합니다. 상점 데이터베이스에 심각한 혼란이 발생할 수 있습니다.
A.Maksymiuk

알려 형제에게 감사합니다. 당신은 당신이 A.Maksymiuk @ 내 대답 업데이트 할 수있는 것보다 오류 발견하는 경우
Ronak 차우

그것을했다. 동의하면 다운 보트를 되돌릴 것입니다.
A.Maksymiuk

승인되었지만 답변을 다운 투표하는 것은 올바른 방법이 아닙니다. 답변이 요청에 따라 관련이 없거나 그렇지 않다고 생각하는 경우 다른 사람의 답변을 다운 투표 할 수 없습니다. @ A.Maksymiuk
Chauhan

이 코드를 사용하도록 경고하면 데이터 무결성이 심각하게 손상 될 수 있으므로이 경고를 사용하도록 경고했습니다. 예를 들어, "42"(크기)라는 새 옵션을 추가하면 스크립트가 option_id = 42 (완전히 다른 속성의 기존 옵션)를 업데이트했습니다. 다행히 테스트 서버와 새로운 데이터베이스에서 나에게 일어났다.
A.Maksymiuk

2

다른 방법으로 옵션을 추가 할 수 있습니다.

$attributeCode = 137; /* on size, 90 on color ... */

$languageValues[0]='Admin Label'; 

$languageValues[1]='Default Store Label - XXXXL';
$ob = $this->_objectManager;



private function addOption($attributeCode,$languageValues){
$ob = $this->_objectManager;
/* @var $attr \Magento\Eav\Model\Entity\Attribute */
$attr = $ob->create('\Magento\Eav\Model\Entity\Attribute'); 
$attr->load($attributeCode); 
$option = []; 
$option['value'][$languageValues[0]] = $languageValues; 
$attr->addData(array('option' => $option));
$attr->save();
}

이 방법으로 Magento2는 속성에 옵션을 저장할 수 있지만 "공식적인"방법이 무엇인지 모르겠습니다.


내 길을 봐 나는 그것이 '공식적인'것이라고 믿는다
CarComp

솔루션은 작동하지만 옵션이 옵션 인 경우에만 정수에 대해 작동하지 않음
Ajay Patel

정수 값에 왜 작동하지 않습니까?
Vincent Teyssier

0

유효성 검사 문제인 것 같습니다. 데이터의 삭제 키는 백엔드의 양식에서 가져 오므로 다음 방법으로 빈 삭제 키를 추가하십시오.

$option->setData('delete','');

작동 할 수 있습니다.


안타깝게도 OptionManager add (..)는 $ option 매개 변수를 재분석하고 'delete'키를 비워 두십시오. 이유는 없습니다 ... 그러나 다른 방법을 찾았습니다 ....
Interpigeon

문제를 해결하기 위해 답변으로 솔루션을 추가하십시오.
MauroNigrele

내 질문에 대답 할 수 없지만 질문을 업데이트했습니다. 내 해결책은 해결책이라고 생각합니다 ...
Interpigeon

이봐, 당신은 당신의 질문이 꽤 일반적이라고 대답 할 수 있습니다.
MauroNigrele

0

Ryan H가 제안한 ObjectFactory 메소드를 사용 하여이 전체 답변을 다시 작성했습니다.

결국 고객 객체에서 만든 일부 속성을 사용하는 도우미 클래스가되었지만 EAV + ObjectFactories를 사용하여 속성 옵션을 조작하는 방법에 대한 아이디어가 있습니다.

<?php


namespace Stti\Healthday\Helper {
    use Magento\Eav\Model\Entity\AttributeFactory;
    use Magento\Eav\Model\Entity\Attribute\OptionFactory;
    use Magento\Eav\Model\Entity\Attribute\OptionManagementFactory;
    use Magento\Framework\App\Helper\AbstractHelper;
    use Magento\Framework\App\Helper\Context;
    use Magento\Eav\Model\Entity\Attribute;
    use Stti\Healthday\Model\RelationFactory;


    /**
     * Eav data helper
     */
    class Data extends AbstractHelper {

        protected $optionFactory;

        protected $attributeFactory;

        protected $relationFactory;

        protected $optionManagementFactory;

        public function __construct(Context $context, AttributeFactory $attributeFactory, OptionFactory $optionFactory,
            RelationFactory $relationFactory,
            OptionManagementFactory $optionManagementFactory) {
            $this->optionFactory = $optionFactory;
            $this->attributeFactory = $attributeFactory;
            $this->optionFactory = $optionFactory;
            $this->relationFactory = $relationFactory;
            $this->optionManagementFactory = $optionManagementFactory;
            parent::__construct($context);
        }

        public function addRelationsHelper($answerJson, $attributeCode) {
            // IMPORTANT: READ THIS OR THE CODE BELOW WONT MAKE SENSE!!!!
            // Since magento's attribute option model was never meant to
            // hold guids, we'll be saving the guid as the label. An option_id will
            // get created, which can then be saved to the relationship table.  Then
            // the label in the attribute_option table can be changed to the actual 'word'
            // by looking up all of the options, matching on the guid, and doing a replace.
            // At that point, there will be a 1:1 relation between guid, option_id, and the 'word'



            // Get the attribute requested
            $attribute = $this->attributeFactory->create();
            $attribute  = $attribute->loadByCode("customer", $attributeCode);

            $answers = json_decode($answerJson, true);

            // Prepare vars
            //$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
            $prekeys = array();
            $prevalues = array();

            foreach ($answers as $answer) {
                $prekeys[] = $answer['Key'];
                $prevalues[] = $answer['Value'];
            }

            // load up all relations
            // generate an array of matching indexes so we can remove
            // them from the array to process
            $collection = $this->relationFactory->create()->getCollection();

            $removalIds = array();
            foreach ($collection as $relation) {
                // if the item is already in the magento relations,
                // don't attempt to add it to the attribute options
                for($cnt = 0; $cnt < sizeof($answers); $cnt++) {
                    if ($relation['stti_guid'] == $prekeys[$cnt]) {
                        $removalIds[] = $cnt;
                    }
                }
            }

            // Remove the values from the arrays we are going to process
            foreach($removalIds as $removalId) {
                unset($prekeys[$removalId]);
                unset($prevalues[$removalId]);
            }

            // "reindex" the arrays
            $keys = array_values($prekeys);
            $values = array_values($prevalues);

            // prepare the array that will be sent into the attribute model to
            // update its option values
            $updates = array();
            $updates['attribute_id'] = $attribute->getId();

            // This section utilizes the DI generated OptionFactory and OptionManagementFactory
            // to add the options to the customer attribute specified in the parameters.
            for($cnt = 0; $cnt < sizeof($keys); $cnt++) {
                $option = $this->optionFactory->create();
                $option->setLabel($keys[$cnt]);
                $this->optionManagementFactory->create()->add("customer", $attributeCode, $option);
            }

            // After save, pull all attribute options, compare to the 'keys' array
            // and create healthday/relation models if needed
            $relationIds = $attribute->getOptions();
            $updatedAttributeCount = 0;
            $options = array();
            $options['value'] = array();

            for($cnt = 0; $cnt < sizeof($keys); $cnt++) {

                $option_id = 0;
                foreach($relationIds as $relationId) {
                    if ($relationId->getLabel() == $keys[$cnt]) {
                        $option_id = $relationId['value'];
                        break;
                    }
                }
                if ($option_id > 0) {
                    // Create the healthday relation utilizing our custom models DI generated ObjectFactories
                    $relation = $this->relationFactory->create();
                    $relation->setAttributeId($attribute->getId());
                    $relation->setOptionId($option_id);
                    $relation->setSttiGuid($keys[$cnt]);
                    $relation->save();

                    // Rename the attribute option value to the 'word'
                    $options['value'][$option_id][] = $values[$cnt];
                    $updatedAttributeCount++;
                }
            }

            if ($updatedAttributeCount > 0) {
                $attribute->setData('option', $options);
                $attribute->save();
            }

            // Save the relationship to the guid
            return $updatedAttributeCount;
        }
    }
}

1
ObjectFactory를 주입하고 Object 자체를 주입하지 말고 Object 인스턴스를 작성해야합니다. ORM 오브젝트는 직접 주입되지 않아야합니다.
Ryan Hoerr

어떤 ObjectFactory? 50과 같습니다. \ Magento \ Framework \ Api \ ObjectFactory를보고 있지만 ObjectManager의 래퍼처럼 보입니다. 왜 객체 관리자 자체를 구현하지 않는지 잘 모르겠습니다. 이 새 버전에는 래퍼를위한 래퍼가 너무 많습니다.
CarComp

1
나는 초록으로 말하고 있었다. 말 그대로 'ObjectFactory'가 아니라 지정된 객체에 Factory를 삽입하십시오. 사용하는 특정 유형마다 팩토리를 주입하고 필요에 따라 작성해야합니다. 예, 처음에는 지저분 해 보이지만 그럴만한 이유가 있습니다. ECG 코드 표준 외에는 ObjectManager를 직접 사용하는 것은 금지되어 있습니다. 전체 주제를 설명하는 Alan Storm의 기사를 참조하십시오. alanstorm.com/magento_2_object_manager_instance_objects
Ryan Hoerr

사용하려는 객체에 공장이없는 경우 어떻게해야합니까? 예를 들어, 옵션 관리를 '제조'하는 방법을 찾을 수 없습니다. Magento \ Eav \ Model \ AttributeFactory도-> create () 대신 이상한-> createAttribute (vars)를 사용합니다. 나는 단지 당신이 제품이나 물건에 내장 된 카테고리로 작업하지 않을 때 조금 이상해집니다.
CarComp

1
모든 물체가 공장을 필요로하는 것은 아닙니다. 그럴 경우 공장은 기본적으로 존재하지 않을 수 있습니다. 존재하지 않는 것은 런타임 (DI 생성) 또는 컴파일 중에 생성됩니다. 내가 링크 한 기사를 읽으십시오. 그것에 대해 어떤 식 으로든, 당신은 Magento2로 작업하는 법을 배우지 말아야합니다. 예, 학습 곡선이 있습니다. 아직 그렇지 않은 경우 PhpStorm 또는 유사한 IDE를 선택하는 것이 좋습니다.
Ryan Hoerr

0

업데이트 2016-09-11 : quickshiftin이 지적했듯이이 솔루션은 M2.1 이상에서는 작동하지 않습니다. CategorySetup설정 외부 에서 클래스 를 의존성 주입하려고 하면 치명적인 오류가 발생합니다. 보다 강력한 솔루션은 /magento//a/103951/1905를 참조하십시오.


\Magento\Catalog\Setup\CategorySetup이것을 위해 수업을 사용하십시오 . 여기에는 1.x addAttributeOption()와 동일한 방식으로 작동 하는 메소드가 포함 eav/entity_setup::addAttributeOption()되어 있습니다. 도움이 될만한 다른 속성 방법이 있습니다.

종속성 주입을 사용하여 설정 프로세스 외부에서도 언제든지이 클래스를 가져올 수 있습니다.

구체적으로 특별히:

/**
 * Constructor.
 *
 * @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository
 * @param \Magento\Catalog\Setup\CategorySetupFactory $categorySetupFactory
 */
public function __construct(
    \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository,
    \Magento\Catalog\Setup\CategorySetupFactory $categorySetupFactory
) {
    $this->attributeRepository = $attributeRepository;
    $this->categorySetupFactory = $categorySetupFactory;
}

/**
 * Create a matching attribute option
 *
 * @param string $attributeCode Attribute the option should exist in
 * @param string $label Label to add
 * @return void
 */
public function addOption($attributeCode, $label) {
    $attribute = $this->attributeRepository->get($attributeCode);

    $categorySetup = $this->categorySetupFactory->create();
    $categorySetup->addAttributeOption(
        [
            'attribute_id'  => $attribute->getAttributeId(),
            'order'         => [0],
            'value'         => [
                [
                    0 => $label, // store_id => label
                ],
            ],
        ]
    );
}

원하는 경우 attributeRepository클래스를 제거하고에서 getAttribute()직접 사용할 수 있습니다 categorySetup. 매번 엔터티 유형 ID 만 포함하면됩니다.


안녕 라이언, 나는를 사용하여 에서 a CategorySetupFactory를 인스턴스화 하려고 하지만 치명적인 오류가 발생하면 :CategorySetupConsole\Command$factory->setup()PHP Fatal error: Uncaught TypeError: Argument 1 passed to Magento\Setup\Module\DataSetup::__construct() must be an instance of Magento\Framework\Module\Setup\Context, instance of Magento\Framework\ObjectManager\ObjectManager given
quickshiftin

Ahh, 나는 이 스레드 를 우연히 발견했는데 Magento 2.1 (사용중인)에서 작동이 중지되었다고 말합니다. ... 지금 내 코드를 개정, 그러나뿐만 아니라 그 효과로이 답변에 메모를 넣어 최선을 prob는
quickshiftin

0

Magento 2는 프로그래밍 방식으로 특정 속성 옵션 값을 추가합니다.

url 다음에 magento의 루트 디렉토리에서이 스크립트를 실행하십시오.

$objectManager = \Magento\Framework\App\ObjectManager::getInstance(); // instance of object manager
try{
      $entityType = 'catalog_product';
      $attributeCode = 'manufacturer';
      $attributeInfo = $objectManager->get(\Magento\Eav\Model\Entity\Attribute::class)
                                 ->loadByCode($entityType, $attributeCode);


      $attributeFactory = $objectManager->get('\Magento\Catalog\Model\ResourceModel\Eav\Attribute');

      $attributeId = $attributeInfo->getAttributeId();
      //$manufacturer = $item->{'Manufacturer'};
      $attribute_arr = ['aaa','bbb','ccc','ddd'];

      $option = array();
      $option['attribute_id'] = $attributeId;
      foreach($attribute_arr as $key=>$value){
          $option['value'][$value][0]=$value;
          foreach($storeManager as $store){
              $option['value'][$value][$store->getId()] = $value;
          }
      }
      if ($option) {
        $eavSetupFactory = $objectManager->create('\Magento\Eav\Setup\EavSetup');
        print_r($eavSetupFactory->getAttributeOption());
        die();
        $eavSetupFactory->addAttributeOption($option);
      }
    }catch(Exception $e){
      echo $e->getMessage();
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.