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.phpException-> message

无法保存属性大小注意:未定义的索引:在第177行的/var/www/html/magento2/vendor/magento/module-swatches/Model/Plugin/EavAttribute.php中删除

  • OptionManagement和Option来自 _contstructor
  • 使用OptionManagement,我可以检索现有项目,因此应该可以。

setLabel()并且setValue()是默认设置,但是我尝试了setData,加载选项实例并OptionManagement->getItems再次传递给add(...),但是错误仍然存​​在...

任何想法,如何在导入过程中附加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

Answers:


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)

}

您的代码中存在严重错误:$ option ['value'] [$ value] [0]-不应为$ value,而应为“ option_id”-整数,对于新的一个选项集0。此选项强制转换为整数,因此,如果您的字符串没有数字,例如“ black”,则正确为0。但是,如果您的$ value类似于“ 10 Black”,它将强制转换为10并使用option_id = 10更新数据库实体,而不是创建新的实体。这可能会在您的商店数据库中造成严重混乱。
A.Maksymiuk

谢谢告知兄弟。如果您发现任何错误,可以更新我的答案@ A.Maksymiuk
Ronak Chauhan

做到了。请接受,然后我将还原我的投票。
A.Maksymiuk

已批准,但对任何答案均不赞成投票,不是正确的方法,如果您认为该答案与要求无关或与要求不符,则可以不对任何人的答案给予否决权。@ A.Maksymiuk
Ronak 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

您的解决方案是工作,但只有当选项的选择不是整数的工作
阿贾伊帕特尔

为什么对整数值不起作用?
文森特·泰西耶

0

似乎是一个验证问题。数据中的删除键来自后端的表单,因此请尝试以这种方式添加一个空的删除键:

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

它可以工作。


可悲的是没有。OptionManager add(..)重新解析$ option参数并将'delete'键保留为空,我不知道为什么...但是我找到了另一种方式
。...– Interpigeon

很好,请添加您的解决方案作为解决问题的答案。
MauroNigrele '16

我无法回答自己的问题,但我更新了问题。我认为我的解决方案是一种解决方法...
Interpigeon

嘿,你可以回答你的问题很普遍。
MauroNigrele '16

0

我最终使用Ryan H建议的ObjectFactory方法重写了整个答案。

最终它是一个Helper类,它利用了我在客户对象上创建的一些属性,但是想法是关于如何利用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对象不能直接注入。
瑞安·霍尔

哪个ObjectFactory?大概是50。我正在看\ Magento \ Framework \ Api \ ObjectFactory,但这看起来就像是ObjectManager的包装。我不确定为什么我不只是实现对象管理器本身。在这个新版本中,有很多包装器用于事物包装器。
CarComp

1
我在摘要中发言。为给定的对象而不是从字面意义上的“ ObjectFactory”注入工厂。您应该为使用的每种特定类型注入工厂,然后根据需要创建它们。是的,乍一看似乎很杂乱……但是有充分的理由。此外,ECG代码标准几乎禁止直接使用ObjectManager。请参阅Alan Storm的文章,其中介绍了整个主题:alanstorm.com/magento_2_object_manager_instance_objects
Ryan

当我要使用的对象没有工厂时该怎么办?例如,我找不到“工厂”选项管理内容的方法。Magento \ Eav \ Model \ AttributeFactory也使用怪异的-> createAttribute(vars)而不是-> create()。我只是说,当您不使用产品或内置的类别时,事情会变得有些奇怪。
CarComp

1
并非所有对象都需要工厂。对于某些工厂,工厂可能不存在,可以在运行时(使用DI生成)或编译期间创建不存在的工厂。阅读我链接的文章。无论如何,您都需要学习使用Magento2,而不是反对它。是的,有一个学习曲线。如果您还没有,我强烈建议您选择PhpStorm或类似的IDE。
Ryan Hoerr

0

更新2016-09-11:正如quickshiftin指出的,该解决方案不适用于M2.1 +。尝试CategorySetup在安装程序之外进行依赖注入类会给您带来致命错误。请参阅此处以获取更强大的解决方案:https : //magento.stackexchange.com/a/103951/1905


\Magento\Catalog\Setup\CategorySetup为此使用类。它包含一种addAttributeOption()方法,其工作方式与eav/entity_setup::addAttributeOption()1.x中的完全相同。还有一些其他的属性方法也可能会有所帮助。

您可以随时使用依赖项注入来获取此类,即使在安装过程之外也可以。

特别:

/**
 * 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实例化一个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

啊,我现在偶然发现了这个线程,您在其中指出该线程在Magento 2.1(我正在使用的)中停止工作。现在修改我的代码,但是最好也对此效果做一个注释...
quickshift in

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();
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.