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.