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.

up vote 7 down vote accepted
+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.

  • 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 '17 at 9:17
  • you are very welcome! – Konstantin Gerasimov May 9 '17 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 '17 at 12:33

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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