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

これはエラーを報告します(Exception-> messageOptionMaganger.phpへの例外報告を変更しました)

属性サイズを保存できません通知:未定義のインデックス:177行目の/var/www/html/magento2/vendor/magento/module-swatches/Model/Plugin/EavAttribute.phpで削除します

  • OptionManagementとOptionは _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は属性のオプションを保存できますが、「公式」な方法が何なのかわかりません:)


オプションは、整数ではサポートされていない文字列として任意の値を追加
アジャイ・パテル

回答:


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

methodeを実行します。

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)

}

コードに重大なエラーがあります:$ option ['value'] [$ value] [0]-$ valueではなく「option_id」-整数、新しいオプションセット0の場合、これは整数にキャストされます。そのため、「黒」などのように、数値のない文字列がある場合、正しく0になります。ただし、$ valueが「10 Black」のようなものである場合、10にキャストされ、新しいエンティティを作成する代わりにoption_id = 10でデータベースエンティティが更新されます。これは、ショップデータベースに深刻な混乱を引き起こす可能性があります。
-A.Maksymiuk

兄弟に知らせてくれてありがとう。エラーが見つかった場合は、私の回答@ A.Maksymiuk
ロナックチャウハン

それをやった。受け入れてください、それから私は私の下票を取り消します。
-A.Maksymiuk

承認されましたが、答えを下げることは適切な方法ではありません。答えが関連していないか、質問どおりではないと思う場合は、他の人の答えを下げないでください。@ A.Maksymiuk
ロナックチャウハン

データの整合性に重大な損害を与えるため、このコードを使用するようにだれかに警告するためにそれを行いました。たとえば、代わりに「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

あなたのソリューションは、仕事ですが、オプションはオプションではありません整数のために作業しているときにのみ
アジャイ・パテル

整数値ではなぜ機能しないのですか?
ビンセントTeyssier

0

検証の問題のようです。データの削除キーはバックエンドのフォームから取得されるため、空の削除キーをそのように追加してみてください。

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

うまくいくかもしれない。


残念です。OptionManager add(..)は、$ optionパラメーターを再解析し、 'delete'キーを空のままにします。理由はありません...しかし、別の方法を見つけました
。...-Interpigeon

質問を解決するための回答としてソリューションを追加してください。
マウロニグレレ

自分の質問には答えられませんが、質問を更新しました。私の解決策は回避策だと思います
...-Interpigeon

ねえ、あなたの質問に答えることはかなり一般的です。
マウロニグレレ

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オブジェクトは直接注入されません。
ライアンホー16

どのObjectFactoryですか?50などがあります。\ Magento \ Framework \ Api \ ObjectFactoryを見ていますが、ObjectManagerのラッパーのように見えます。objectmanager自体を実装しないのはなぜかわかりません。この新しいバージョンでは、物事のラッパー用のラッパーがたくさんあります。
CarComp

1
アブストラクトで話していました。文字通り「ObjectFactory」ではなく、指定されたオブジェクトのファクトリを注入します。使用する特定のタイプごとにファクトリを注入し、必要に応じて作成する必要があります。はい、最初は面倒です...しかし、それには非常に良い理由があります。また、ECGコード標準では、ObjectManagerの直接使用はすべて禁止されています。件名全体を説明するAlan Stormの記事を参照してください:alanstorm.com/magento_2_object_manager_instance_objects
ライアンホール

使用するオブジェクトにファクトリーがない場合はどうすればよいですか?たとえば、オプション管理を「工場で」行う方法を見つけることができません。Magento \ Eav \ Model \ AttributeFactoryは、単なる-> create()ではなく、奇妙な-> createAttribute(vars)も使用します。製品や組み込みのカテゴリを操作しないと、少し奇妙になります。
CarComp

1
すべてのオブジェクトがファクトリーを必要とするわけではありません。存在する場合、ファクトリはすぐに存在しない場合があります。存在しないものは、実行時(DI生成を使用)またはコンパイル中に作成されます。リンクした記事を読んでください。いずれにせよ、Magento2に反対するのではなく、Magento2を操作することを学ぶ必要があります。はい、学習曲線があります。まだお持ちでない場合は、PhpStormまたは同様のIDEを選択することを強くお勧めします。
ライアンホー16

0

更新2016-09-11:quickshiftinが指摘したように、このソリューションはM2.1 +では機能しません。CategorySetupクラスをセットアップ外で依存性注入しようとすると、致命的なエラーが発生します。より堅牢なソリューションについては、こちらをご覧くださいhttps : //magento.stackexchange.com/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を含める必要があります。


こんにちはライアン、私が使用しようとしているCategorySetupFactoryインスタンス化するCategorySetupからConsole\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

ああ、私はあなたがこれをMagento 2.1(私が使用している)で動作を停止したとあなたが述べているこのスレッドにつまずいた。今すぐコードを修正しますが、その効果に対するこの回答にもメモを入れることをお
勧め

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.