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

  • OptionManagement และ Option มาจาก _contstructor
  • ด้วย OptionManagement ฉันสามารถดึงรายการที่มีอยู่ดังนั้นควรจะโอเค ..

setLabel()และsetValue()เป็นค่าเริ่มต้น แต่ฉันได้ลองsetDataแล้วโหลดตัวเลือกอินสแตนซ์และผ่านOptionManagement->getItemsไปเพื่อเพิ่ม (... ) "อีกครั้ง" แต่ข้อผิดพลาดยังคงมีอยู่ ...

ความคิดใด ๆ ฉันจะผนวกตัวเลือก EAV (swatches) ได้อย่างไรในระหว่างกระบวนการนำเข้า (ไม่ได้อยู่ในการตั้งค่าโมดูล)


อัปเดต:

วิธีอื่นที่ฉันสามารถเพิ่มตัวเลือก:

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

รัน 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 อย่างถูกต้อง แต่ถ้ามูลค่า $ ของคุณเป็นอะไรเช่น "10 แบล็ก" มันจะแปลงเป็น 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

โซลูชันของคุณใช้งานได้ แต่เมื่อตัวเลือกเป็นตัวเลือกที่ไม่ทำงานสำหรับจำนวนเต็ม
Ajay Patel

ทำไมมันไม่ทำงานสำหรับค่าจำนวนเต็ม?
Vincent Teyssier

0

ดูเหมือนว่าจะเป็นปัญหาการตรวจสอบ คีย์ลบในข้อมูลมาจากฟอร์มในแบ็กเอนด์ดังนั้นให้ลองเพิ่มคีย์ลบที่ว่างเปล่าด้วยวิธีนี้:

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

มันสามารถใช้งานได้


ไม่น่าเศร้า OptionManager เพิ่ม (.. ) แยกพารามิเตอร์ $ option อีกครั้งและปล่อยปุ่ม 'ลบ' ว่างเปล่าฉันไม่ได้เพราะอะไร ... แต่ฉันพบวิธีอื่น ....
Interpigeon

เยี่ยมมากโปรดเพิ่มโซลูชันของคุณเป็นคำตอบเพื่อแก้ไขคำถาม
MauroNigrele

ฉันไม่สามารถตอบคำถามของฉันเอง แต่ฉันได้อัปเดตคำถาม ฉันคิดว่าวิธีแก้ปัญหาของฉันคือวิธีแก้ปัญหา ...
Interpigeon

เฮ้คุณสามารถตอบคำถามของคุณเป็นเรื่องธรรมดา
MauroNigrele

0

ฉันสิ้นสุดการเขียนคำตอบทั้งหมดนี้ใหม่โดยใช้วิธีการ ObjectFactory ที่แนะนำโดย Ryan H.

มันจบลงด้วยการเป็น 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

ObjectFactory ใด มี 50 คนฉันกำลังดู \ Magento \ Framework \ Api \ ObjectFactory แต่มันดูเหมือนเสื้อคลุมสำหรับ ObjectManager ฉันไม่แน่ใจว่าทำไมฉันถึงไม่ใช้ตัวจัดการวัตถุเอง มีตัวห่อมากมายสำหรับห่อสิ่งต่าง ๆ ในรุ่นใหม่นี้
CarComp

1
ฉันกำลังพูดในเชิงนามธรรม ฉีด Factory สำหรับวัตถุที่คุณกำหนดไม่ใช่ 'ObjectFactory' คุณควรฉีดโรงงานสำหรับแต่ละประเภทที่คุณใช้และสร้างพวกเขาตามที่ต้องการ ใช่ดูเหมือนว่ายุ่งในตอนแรก ... แต่มีเหตุผลที่ดีมากสำหรับมัน นอกจากนี้รหัสมาตรฐาน ECG ทั้งหมดยกเว้นการใช้ ObjectManager โดยตรง ดูบทความของ Alan Storm ที่อธิบายหัวข้อทั้งหมด: alanstorm.com/magento_2_object_manager_instance_objects
Ryan Hoerr

ฉันควรทำอย่างไรเมื่อวัตถุที่ฉันต้องการใช้ไม่มีโรงงาน ตัวอย่างเช่นฉันไม่สามารถหาวิธี 'จัดการ' ตัวเลือกการจัดการตัวเลือกได้ Magento \ Eav \ Model \ AttributeFactory ยังใช้รูปแบบแปลก -> createAttribute (vars) แทน just -> 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โดยตรงบนคุณต้องใส่รหัสประเภทเอนทิตีทุกครั้ง


สวัสดี Ryan ฉันกำลังพยายามใช้CategorySetupFactorya เพื่อยกตัวอย่างCategorySetupจาก a 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 (ซึ่งฉันใช้อยู่) การแก้ไขรหัสของฉันตอนนี้ แต่ prob ที่ดีที่สุดที่จะนำข้อความในคำตอบนี้ที่มีผลเช่นกัน ...
quickshiftin

0

Magento 2 เพิ่มตัวเลือกคุณลักษณะเฉพาะค่าทางโปรแกรม

เรียกใช้สคริปต์นี้ในไดเรกทอรีรากของ magento หลังจาก 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();
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.