2

Can anyone provide a working example for creating a visual swatch (or even a text swatch) attribute as part of a setup script.

I've tried the example on Magento 2 create custom swatch attribute programmatically but it doesn't work for me.

The issue I've ran into there is that the the attribute repository cannot find the new attribute that was created. I tried putting some cache clearing in between but no luck.

Thanks.

6
  • You can set directly it from admin. May 4, 2017 at 8:39
  • I'm looking to do this in a setup script.
    – Paul
    May 4, 2017 at 9:01
  • @AnkitShah that's the one that I've tried and it doesn't work - the set up script cannot find the attribute after it's created it.
    – Paul
    May 8, 2017 at 7:38
  • Hi Konstantin Gerasimov Could you Please help to add an image in visual swatch attribute option programmatically. Please help me to do this. Thanks Jun 18, 2019 at 13:42

2 Answers 2

11
+150

Disclaimer: Parts of this code were taken from Magento_SwatchesSampleData core module. Also you might not need colorMap but I just put it there.

This code was tested on Magento 2.1.4.

I assume you have an extension called Goivvy_Custom. I also assume you know how to install the extension and have magento run install scripts.

The code below will create new_swatch_attribute Visual Swatch.

Here is Goivvy/Custom/Setup/InstallData.php:

<?php                                                                                                                                                                             

namespace Goivvy\Custom\Setup;

use Magento\Framework\Setup;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Catalog\Model\Product\Type;
use Magento\Catalog\Model\ResourceModel\Eav\Attribute as eavAttribute;

class InstallData implements Setup\InstallDataInterface
{

private $attrOptionCollectionFactory;
private $eavSetupFactory;
private $eavConfig;

protected $colorMap = [
    'Black'     => '#000000',
    'Blue'      => '#1857f7',
    'Brown'     => '#945454',
    'Gray'      => '#8f8f8f',
    'Green'     => '#53a828',
    'Lavender'  => '#ce64d4',
    'Multi'     => '#ffffff',
    'Orange'    => '#eb6703',
    'Purple'    => '#ef3dff',
    'Red'       => '#ff0000',
    'White'     => '#ffffff',
    'Yellow'    => '#ffd500',
];      

public function __construct(EavSetupFactory $eavSetupFactory,
                           \Magento\Eav\Model\Config $eavConfig,
                           \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory $attrOptionCollectionFactory
                           )
{     
    $this->eavConfig = $eavConfig;
    $this->eavSetupFactory = $eavSetupFactory;
    $this->attrOptionCollectionFactory = $attrOptionCollectionFactory;
}      

public function install(Setup\ModuleDataSetupInterface $setup, Setup\ModuleContextInterface $moduleContext)
{   
    $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
    if(version_compare($moduleContext->getVersion(),'1.0.0') < 0){
     $eavSetup->addAttribute(
        \Magento\Catalog\Model\Product::ENTITY,
        'new_swatch_attribute',
        [
           'type' => 'int',
           'label' => 'New Swatch Attribute',
           'input' => 'select',
           'required' => false,
           'user_defined' => true,
           'searchable' => true,
           'filterable' => true,
           'comparable' => true,
           'visible_in_advanced_search' => true,
           'apply_to' => implode(',', [Type::TYPE_SIMPLE, Type::TYPE_VIRTUAL]),
           'is_used_in_grid' => true,
           'is_visible_in_grid' => false,
           'option' => [
               'values' => [
                   'Black',
                   'Blue',
                   'Brown',
                   'Gray',
                   'Green',
                   'Lavender',
                   'Multi',
                   'Orange',
                   'Purple',
                   'Red',
                   'White',
                   'Yellow'
               ]
           ]
        ]
     );
     $this->eavConfig->clear();
     $attribute = $this->eavConfig->getAttribute('catalog_product', 'new_swatch_attribute');
     if (!$attribute) {
        return;
     }
     $attributeData['option'] = $this->addExistingOptions($attribute);
     $attributeData['frontend_input'] = 'select';
     $attributeData['swatch_input_type'] = 'visual';
     $attributeData['update_product_preview_image'] = 1;
     $attributeData['use_product_image_for_swatch'] = 0;
     $attributeData['optionvisual'] = $this->getOptionSwatch($attributeData);
     $attributeData['defaultvisual'] = $this->getOptionDefaultVisual($attributeData);
     $attributeData['swatchvisual'] = $this->getOptionSwatchVisual($attributeData);
     $attribute->addData($attributeData);
     $attribute->save();
    }
}

protected function getOptionSwatch(array $attributeData)
{
    $optionSwatch = ['order' => [], 'value' => [], 'delete' => []];
    $i = 0;
    foreach ($attributeData['option'] as $optionKey => $optionValue) {
        $optionSwatch['delete'][$optionKey] = '';
        $optionSwatch['order'][$optionKey] = (string)$i++;                                                                                                                    
         $optionSwatch['value'][$optionKey] = [$optionValue, ''];
    }
    return $optionSwatch;
}

private function getOptionSwatchVisual(array $attributeData)
{
    $optionSwatch = ['value' => []];
    foreach ($attributeData['option'] as $optionKey => $optionValue) {
        if (substr($optionValue, 0, 1) == '#' && strlen($optionValue) == 7) {
            $optionSwatch['value'][$optionKey] = $optionValue;
        } else if ($this->colorMap[$optionValue]) {
            $optionSwatch['value'][$optionKey] = $this->colorMap[$optionValue];
        } else {
            $optionSwatch['value'][$optionKey] = $this->colorMap['White'];
        }
    }
    return $optionSwatch;
}

private function getOptionDefaultVisual(array $attributeData)
{
    $optionSwatch = $this->getOptionSwatchVisual($attributeData);
    if(isset(array_keys($optionSwatch['value'])[0]))
     return [array_keys($optionSwatch['value'])[0]];
    else  
     return [''];
}

private function addExistingOptions(eavAttribute $attribute)
{
    $options = [];
    $attributeId = $attribute->getId();
    if ($attributeId) {
        $this->loadOptionCollection($attributeId);
        foreach ($this->optionCollection[$attributeId] as $option) {
            $options[$option->getId()] = $option->getValue();
        }
    }
    return $options;
}

private function loadOptionCollection($attributeId)
{
    if (empty($this->optionCollection[$attributeId])) {
        $this->optionCollection[$attributeId] = $this->attrOptionCollectionFactory->create()
            ->setAttributeFilter($attributeId)
            ->setPositionOrder('asc', true)
            ->load();                                                                                                                                                         
    }
 }
}  

Here is how it looks in Magento 2.1.4:

enter image description here

Any questions - let me know.

5
  • Thank you, that works! I had to include an EAV cache clean after the attribute was created. I've propose a couple of edits just to make it clearer for anyone else who needs it. Thanks again.
    – Paul
    May 9, 2017 at 9:17
  • you are very welcome! May 9, 2017 at 13:41
  • Can you please help me i have to add options from CSV with visual swatch value. I have to import attribute option with visual swatch and swatch value is colorcode. I am following this link for upload attribute options it's working but not getting solution to add visual swatch value. Please help me. pearlbells.co.uk/…
    – Magecode
    Dec 6, 2017 at 12:33
  • Can you please help me, How to add text swatch. Nov 14, 2019 at 16:46
  • how can we add custom images in this example ? Jul 25 at 6:17
0

There is a different and more direct way to add visual swatch attributes. If you check this unit test from the Magento Native code: https://github.com/magento/magento2/blob/2.4-develop/dev/tests/integration/testsuite/Magento/Swatches/_files/product_visual_swatch_attribute.php

They propose the following solution:

 $attribute->setData(
    [
        'frontend_label' => ['Visual swatch attribute'],
        'entity_type_id' => $entityType,
        'frontend_input' => 'select',
        'backend_type' => 'int',
        'is_required' => '0',
        'attribute_code' => 'visual_swatch_attribute',
        'is_global' => '1',
        'is_user_defined' => 1,
        'is_unique' => '0',
        'is_searchable' => '0',
        'is_comparable' => '0',
        'is_filterable' => '1',
        'is_filterable_in_search' => '0',
        'is_used_for_promo_rules' => '0',
        'is_html_allowed_on_front' => '1',
        'used_in_product_listing' => '1',
        'used_for_sort_by' => '0',
        'swatch_input_type' => 'visual',
        'swatchvisual' => [
            'value' => [
                'option_1' => '#555555',
                'option_2' => '#aaaaaa',
                'option_3' => '#ffffff',
            ],
        ],
        'optionvisual' => [
            'value' => [
                'option_1' => ['option 1'],
                'option_2' => ['option 2'],
                'option_3' => ['option 3']
            ],
        ],
        'options' => [
            'option' => [
                ['label' => 'Option 1', 'value' => 'option_1'],
                ['label' => 'Option 2', 'value' => 'option_2'],
                ['label' => 'Option 3', 'value' => 'option_3'],
            ],
        ],
    ]
);
$attributeRepository->save($attribute);
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.