Cách Magento2 thêm tùy chọn thuộc tính theo chương trình (không phải trong thiết lập)


15

Tôi cố gắng thêm tùy chọn cho các thuộc tính kích thước và màu sắc trong chế độ nhà nhập khẩu của mình nhưng tôi không làm thế nào ...:

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

Báo cáo này một lỗi (tôi sửa đổi báo cáo về ngoại lệ OptionMaganger.phpđể Exception-> nhắn )

Không thể lưu kích thước thuộc tính Lưu ý: Chỉ mục không xác định: xóa trong /var/www/html/magento2/vendor/magento/module-swatches/Model/Plugin/EavAttribution.php trên dòng 177

  • Tùy chọn Quản lý và Tùy chọn đến từ _contstructor
  • Với Quản lý tùy chọn, tôi có thể truy xuất các mục hiện có, vì vậy sẽ ổn thôi ..

setLabel()setValue()được mặc định, nhưng tôi đã thử setData , tải phiên bản tùy chọn và chuyển qua OptionManagement->getItemsđể thêm (...) "lần nữa", nhưng lỗi vẫn tồn tại ...

Bất kỳ ý tưởng, làm thế nào tôi có thể nối thêm Tùy chọn EAV (swatches?) Trong quá trình nhập? (không phải trong thiết lập modul)


Cập nhật:

Cách khác tôi có thể thêm tùy chọn:

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

Bằng cách này, Magento2 có thể lưu một tùy chọn cho thuộc tính, nhưng tôi không biết cách "chính thức" là gì :)


tùy chọn đã thêm bất kỳ giá trị nào dưới dạng chuỗi không được hỗ trợ cho số nguyên
Ajay Patel

Câu trả lời:


2
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Store\Model\StoreManagerInterface;

khai báo:

protected $_eavSetupFactory;

constructor :

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

thực hiện 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)

}

Bạn có lỗi nghiêm trọng trong mã của mình: $ tùy chọn ['value'] [$ value] [0] - không nên là $ value mà là "tùy chọn_id" - số nguyên, đối với một tùy chọn mới được đặt 0. Cái này được chuyển thành số nguyên, vì vậy nếu bạn có chuỗi không có số, ví dụ "đen" thì nó sẽ là 0 chính xác. Nhưng nếu giá trị $ của bạn giống như "10 Đen", nó sẽ chuyển thành 10 và cập nhật thực thể cơ sở dữ liệu với tùy chọn_id = 10 thay vì tạo mới. Điều này có thể gây ra sự lộn xộn nghiêm trọng trong cơ sở dữ liệu cửa hàng của bạn.
A.Maksymiuk

cảm ơn anh thông báo. Nếu bạn tìm thấy bất kỳ lỗi nào hơn bạn có thể cập nhật câu trả lời của tôi @ A.Maksymiuk
Ronak Chauhan

Đã làm nó. Hãy chấp nhận, sau đó tôi sẽ hoàn nguyên downvote của tôi.
A.Maksymiuk 16/03/18

Đã chấp thuận, nhưng bỏ phiếu bất kỳ câu trả lời nào không phải là cách thích hợp, nếu bạn nghĩ rằng câu trả lời đó không liên quan hoặc không theo yêu cầu thì bạn không thể bỏ phiếu trả lời cho bất kỳ ai. @ A.Maksymiuk
Ronak Chauhan

Tôi đã làm điều đó để cảnh báo bất cứ ai sử dụng mã này, bởi vì nó sẽ gây ra thiệt hại nghiêm trọng trong tính toàn vẹn dữ liệu. Ví dụ, thay vào đó, thêm tùy chọn mới có tên "42" (kích thước) tập lệnh của bạn được cập nhật tùy chọn_id = 42 (vốn là tùy chọn hiện có của thuộc tính hoàn toàn khác nhau). May mắn thay, nó rất vui với tôi trên máy chủ thử nghiệm và cơ sở dữ liệu mới.
A.Maksymiuk 16/03/18

2

Cách khác tôi có thể thêm tùy chọn:

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

Bằng cách này, Magento2 có thể lưu một tùy chọn cho thuộc tính, nhưng tôi không biết cách "chính thức" là gì.


Xem đường của tôi Tôi tin rằng đó là 'chính thức'
CarComp

giải pháp của bạn là công việc nhưng chỉ khi tùy chọn là tùy chọn không hoạt động cho số nguyên
Ajay Patel

Tại sao nó không hoạt động cho các giá trị nguyên?
Vincent Teyssier

0

Có vẻ là một vấn đề xác nhận. Khóa xóa trong dữ liệu xuất phát từ biểu mẫu trong phần phụ trợ, vì vậy hãy thử thêm một phím xóa trống theo cách đó:

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

Nó có thể làm việc.


Thật đáng buồn không. OptionManager thêm (..) lặp lại tham số tùy chọn $ và để trống phím 'xóa', tôi không biết tại sao ... Nhưng tôi đã tìm thấy một cách khác ....
Interpigeon

Tuyệt vời, vui lòng thêm giải pháp của bạn làm câu trả lời để giải quyết câu hỏi.
MauroNigrele

Tôi không thể trả lời câu hỏi của riêng mình, nhưng tôi đã cập nhật câu hỏi. Tôi nghĩ giải pháp của tôi là một cách giải quyết ...
Interpigeon

Này, bạn có thể trả lời câu hỏi của bạn là khá phổ biến.
MauroNigrele

0

Cuối cùng tôi đã viết lại toàn bộ câu trả lời này bằng các phương pháp ObjectFactory được đề xuất bởi Ryan H.

Cuối cùng, nó là Lớp người trợ giúp sử dụng một số thuộc tính tôi đã tạo trên đối tượng khách hàng, nhưng ý tưởng là có cách sử dụng EAV + ObjectFactories để thao tác các tùy chọn thuộc tính

<?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
Bạn nên tiêm ObjectFactory và tạo các thể hiện của Object từ đó, chứ không phải tiêm Object. Đối tượng ORM không được tiêm trực tiếp.
Ryan Hoerr

Đối tượng nào? Có khoảng 50. Tôi đang xem \ Magento \ Framework \ Api \ ObjectFactory nhưng nó trông giống như một trình bao bọc cho ObjectManager. Tôi không chắc tại sao tôi sẽ không thực hiện chính trình điều khiển. Có rất nhiều trình bao bọc cho trình bao bọc mọi thứ trong phiên bản mới này.
CarComp

1
Tôi đã nói một cách trừu tượng. Tiêm Nhà máy cho đối tượng cụ thể của bạn, không phải theo nghĩa đen là 'ObjectFactory'. Bạn nên tiêm nhà máy cho từng loại cụ thể bạn sử dụng và tạo chúng khi cần thiết. Vâng, ban đầu có vẻ lộn xộn ... nhưng có những lý do rất tốt cho nó. Bên cạnh đó, tất cả các tiêu chuẩn mã ECG đều cấm sử dụng ObjectManager trực tiếp. Xem bài viết của Alan Storm giải thích toàn bộ chủ đề: alanstorm.com/magento_2_object_manager_instance_objects
Ryan Hoerr

Tôi nên làm gì khi các đối tượng tôi muốn sử dụng không có nhà máy? Chẳng hạn, tôi không thể tìm cách 'xuất xưởng' các công cụ quản lý tùy chọn. Magento \ Eav \ Model \ AttributionFactory cũng sử dụng một cách kỳ lạ -> createAttribution (vars) thay vì chỉ -> create (). Tôi chỉ nói rằng, khi bạn không làm việc với một sản phẩm, hoặc một danh mục được xây dựng trong công cụ, mọi thứ trở nên hơi kỳ lạ.
CarComp

1
Không phải tất cả các đối tượng sẽ yêu cầu một nhà máy. Đối với những người làm như vậy, nhà máy có thể không tồn tại bên ngoài - bất kỳ thứ gì không tồn tại sẽ được tạo ra trong thời gian chạy (với thế hệ DI) hoặc trong quá trình biên dịch. Đọc bài viết tôi liên kết. Dù bằng cách nào, bạn cần học cách làm việc với Magento2, chứ không phải chống lại nó. Vâng, có một đường cong học tập. Nếu bạn chưa có, tôi thực sự khuyên bạn nên chọn PhpStorm hoặc IDE tương tự.
Ryan Hoerr

0

CẬP NHẬT 2016-09-11: Như quickshiftin đã chỉ ra, giải pháp này không hoạt động cho M2.1 +. Cố gắng phụ thuộc vào CategorySetuplớp bên ngoài thiết lập sẽ cho bạn một lỗi nghiêm trọng. Xem ở đây để có giải pháp mạnh mẽ hơn: /magento//a/103951/1905


Sử dụng \Magento\Catalog\Setup\CategorySetuplớp cho việc này. Nó bao gồm một addAttributeOption()phương thức, hoạt động chính xác giống như eav/entity_setup::addAttributeOption()trong 1.x. Có một số phương pháp thuộc tính khác cũng có thể hữu ích.

Bạn có thể sử dụng phép nội xạ phụ thuộc để có được lớp này bất cứ lúc nào, ngay cả ngoài quy trình thiết lập.

Đặc biệt:

/**
 * 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
                ],
            ],
        ]
    );
}

Nếu muốn, bạn có thể loại bỏ attributeRepositorylớp và sử dụng getAttribute()trực tiếp categorySetup. Bạn chỉ cần bao gồm ID loại thực thể mỗi lần.


Xin chào Ryan, tôi đang cố gắng sử dụng CategorySetupFactoryđể khởi tạo a CategorySetuptừ a Console\Command, tuy nhiên khi tôi gọi $factory->setup()một lỗi nghiêm trọng xảy ra: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, bây giờ tôi đã vấp phải chủ đề này trong đó bạn nói rằng nó đã ngừng hoạt động trong Magento 2.1 (mà tôi đang sử dụng). Sửa đổi mã của tôi ngay bây giờ, nhưng tốt nhất là nên ghi chú vào câu trả lời này cho hiệu ứng đó ...
quickshiftin

0

Magento 2 thêm tùy chọn thuộc tính cụ thể Giá trị theo chương trình.

Chạy Script này trong thư mục gốc của magento sau 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();
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.