Як 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 до повідомлення «Виняток»> )

Неможливо зберегти розмір атрибута Примітка: Не визначений індекс: видалити в /var/www/html/magento2/vendor/magento/module-swatches/Model/Plugin/EavAttribute.php у рядку 177

  • Опція Управління та Варіант _contstructor
  • За допомогою OptionManagement я можу отримати існуючі елементи, тому повинно бути добре.

setLabel()і setValue()за замовчуванням, але я спробував setData , екземпляр опції завантаження та проходьте повзOptionManagement->getItems щоб додати (...) "знову", але помилка все ще існує ...

Будь-яка ідея, як я можу додати параметри 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)

}

Ви маєте серйозну помилку в своєму коді: $ option ['value'] [$ value] [0] - це не повинно бути $ value, а "option_id" - ціле число, для нової однієї опції встановити 0. Цей варіант передається цілому числу, тож якщо у вас рядок без числа, наприклад "чорний", це буде 0 правильно. Але якщо ваше значення $ щось на зразок "10 чорних", воно приведе до 10 та оновить об'єкт бази даних з параметром option_id = 10 замість створення нового. Це може призвести до серйозного безладу у вашій базі даних магазинів.
А.Максімюк

спасибі повідомити брату. Якщо ви виявили помилку, можете оновити мою відповідь @ A.Maksymiuk
Ronak Chauhan

Зробив це. Прийміть, будь ласка, тоді я скасую свою прихильність.
А.Максімюк

Затверджена, але будь-яка відповідь за будь-який голос не є належним чином, брато. Якщо ви вважаєте, що відповідь не пов'язана чи не відповідно до запитання, ви можете інакше не відмовлятись від відповіді нікого. @ A.Maksymiuk
Ронак Чаухан

Я зробив це, щоб попередити когось використовувати цей код, оскільки це може завдати серйозної шкоди цілісності даних. Наприклад, замість того, щоб додати новий параметр з назвою "42" (розмір), ваш сценарій оновив option_id = 42 (який був існуючий варіант абсолютно іншого атрибута). На щастя, це трапляється зі мною на тестовому сервері та новій новій базі даних.
А.Максімюк

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

чому б це не працювало для цілих значень?
Вінсент

0

Здається, це питання валідації. Ключ видалення в даних надходить із форми в бекенде, тому спробуйте додати порожній ключ видалення таким чином:

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

Це може спрацювати.


На жаль, ні. OptionManager add (..) переділити параметр $ параметр і залишити клавішу "delete" порожньою, я не знаю чому ... Але я знайшов інший спосіб ....
Interpigeon

Чудово, будь ласка, додайте своє рішення як відповідь, щоб вирішити питання.
MauroNigrele

Я не можу відповісти на власне запитання, але я оновив питання. Я думаю, що моє рішення - це
подолання

Гей, ви можете відповісти на ваше запитання досить часто.
MauroNigrele

0

Я закінчив переписати всю цю відповідь за допомогою методів ObjectFactory, запропонованих Райаном Х.

Це в кінцевому підсумку є Helper Class, який використовував деякі атрибути, створені мною на об’єкті клієнта, але існує ідея, як використовувати 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,

Який об’єктфактор? Це як 50. Я дивлюсь на \ Magento \ Framework \ Api \ ObjectFactory, але він просто схожий на обгортку для ObjectManager. Я не впевнений, чому я не просто реалізував би сам об'єкт-менеджер. У цій новій версії так багато обгортків для обгортки речей.
CarComp

1
Я виступав абстрактно. Введіть Фабрику для заданого об'єкта, а не буквально «ObjectFactory». Ви повинні вводити фабрику для кожного конкретного типу, який ви використовуєте, і створювати їх за потребою. Так, спочатку здається безладним ... але для цього є дуже вагомі причини. Окрім того, кодовий ЕКГ нормує все, крім заборони прямого використання ObjectManager. Дивіться статтю Алана Шторма, що пояснює всю тему: alanstorm.com/magento_2_object_manager_instance_objects
Райан Хоерр

Що робити, коли об’єкти, які я хочу використовувати, не мають фабрики? Наприклад, я не можу знайти спосіб "заводу" матеріалів управління параметрами. Magento \ Eav \ Model \ AttributeFactory також використовує дивне -> createAttribute (vars) замість просто -> create (). Я просто кажу, що коли ви не працюєте з продуктом чи категорією, вбудованою в речі, речі стають трохи дивними.
CarComp

1
Не всі об’єкти потребують фабрики. Для тих, хто це робить, фабрика може не існувати поза коробкою - будь-яка, яка не існує, буде створена під час виконання (з генерацією DI) або під час компіляції. Прочитайте статтю, яку я пов’язав. У будь-якому випадку, вам потрібно навчитися працювати з Magento2, а не проти цього. Так, є крива навчання. Якщо ви ще цього не зробили, я настійно рекомендую забрати PhpStorm або подібну IDE.
Ryan Hoerr

0

ОНОВЛЕННЯ 2016-09-11: Як зазначав quickshiftin, це рішення не працює для M2.1 +. Спроба ввести залежність CategorySetupкласу поза установкою призведе до фатальної помилки. Дивіться тут для більш надійного рішення: /magento//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. Вам просто потрібно буде щоразу включати ідентифікатор типу юридичної особи.


Привіт, Райан, я намагаюся використати 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 (який я використовую). Перегляньте мій код зараз, але найкраще попросити помітити цю відповідь також і для цього…
quickshiftin

0

Magento 2 додайте опцію "Специфічний атрибут" Значення програмно.

Запустіть цей скрипт у кореневому каталозі магенто після URL-адреси.

$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();
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.