3

How to create text swatch programmatically?

If, I follow method from saving controller in the product-attribute module (admin) then, I got first and the third field saved but not actual text swatch.

2 Answers 2

3

Try to use my code, Basically you'd need to add a select type, then convert it to Text Swatch like SwatchesSampleData module this used some functions from this module

InstallData.php

<?php

namespace Vendor\Module\Setup;

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

class InstallData implements InstallDataInterface
{
    /**
     * @var EavSetupFactory
     */
    protected $eavSetupFactory;

    protected $attrOptionCollectionFactory;
    protected $eavConfig;
    protected $logger;


    protected $optionCollection = [];


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

    /**
     * {@inheritdoc}
     */
    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $setup->startSetup();

        if (version_compare($context->getVersion(), '1.0.0', '<')) {
            /** @var \Magento\Eav\Setup\EavSetup $eavSetup */
            $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);

            $this->installSwatches($eavSetup, $setup);
        }

        $setup->endSetup();
    }


    /**
     * @param EavSetup $eavSetup
     * @param ModuleDataSetupInterface $setup
     * @throws \Exception
     */
    private function installSwatches(
        \Magento\Eav\Setup\EavSetup $eavSetup,
        ModuleDataSetupInterface $setup
    ) {

        try {

            $productTypes = [
                \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE,
                \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL,
                \Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE,
                \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE,
            ];
            $productTypes = join(',', $productTypes);

            $eavSetup->addAttribute(
                \Magento\Catalog\Model\Product::ENTITY,
                'test_text_swatch',
                [
                    'type' => 'int',
                    'label' => 'Test Text Swatch',
                    'input' => 'select',
                    'required' => false,
                    'user_defined' => true,
                    'searchable' => true,
                    'filterable' => true,
                    'comparable' => true,
                    'visible_in_advanced_search' => true,
                    'apply_to' => $productTypes,
                    'is_used_in_grid' => true,
                    'is_visible_in_grid' => false,
                    'option' => [
                        'values' => [
                            'Test'
                        ]
                    ]
                ]
            );

            $this->eavConfig->clear();

            $this->convertAttributeToSwatches();

        } catch (\Exception $e) {
            $this->logger->critical($e);

        }

    }

    public function convertAttributeToSwatches() {
        $attribute = $this->eavConfig->getAttribute('catalog_product', 'test_text_swatch');
        if (!$attribute) {
            return;
        }

        $attributeData['option'] = $this->addExistingOptions($attribute);
        $attributeData['frontend_input'] = 'select';
        $attributeData['swatch_input_type'] = 'text';
        $attributeData['update_product_preview_image'] = 1;
        $attributeData['use_product_image_for_swatch'] = 0;
        $attributeData['optiontext'] = $this->getOptionSwatch($attributeData);
        $attributeData['defaulttext'] = $this->getOptionDefaultText($attributeData);
        $attributeData['swatchtext'] = $this->getOptionSwatchText($attributeData);
        $this->logger->log(100, print_r($attributeData, true));
        $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']['option_' . $optionKey] = [$optionValue, ''];
        }
        return $optionSwatch;
    }

    /**
     * @param array $attributeData
     * @return array
     */
    private function getOptionSwatchText(array $attributeData)
    {
        $optionSwatch = ['value' => []];
        foreach ($attributeData['option'] as $optionKey => $optionValue) {
            $optionSwatch['value'][$optionKey] = [$optionValue, ''];
        }
        return $optionSwatch;
    }

    /**
     * @param array $attributeData
     * @return array
     */
    private function getOptionDefaultText(array $attributeData)
    {
        $optionSwatch = $this->getOptionSwatchText($attributeData);
        return [array_keys($optionSwatch['value'])[0]];
    }

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

    /**
     * @param eavAttribute $attribute
     * @return array
     */
    private function addExistingOptions(eavAttribute $attribute)
    {
        $options = [];
        $attributeId = $attribute->getId();
        if ($attributeId) {
            $this->loadOptionCollection($attributeId);
            /** @var \Magento\Eav\Model\Entity\Attribute\Option $option */
            foreach ($this->optionCollection[$attributeId] as $option) {
                $options[$option->getId()] = $option->getValue();
            }
        }
        return $options;
    }
}

Result

Result

2
  • How to add the new swatch_text option when having several stores? Trying this, it thrown an error "foreign key constraint fails" for the store_id Commented Aug 12, 2019 at 13:12
  • Hi @Tuyen Nguye I know this is not related to the main question, but could you please explain how did you add the Description field? Commented Mar 18, 2020 at 4:48
1

I get this error:

Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (magento.eav_attribute_option_swatch, CONSTRAINT EAV_ATTRIBUTE_OPTION_SWATCH_STORE_ID_STORE_STORE_ID FOREIGN KEY (store_id) REFERENCES store (store_id) ON DELETE CASCADE), query was: INSERT INTO eav_attribute_option_swatch (option_id, store_id, type, value) VALUES (?, ?, ?, ?)

Your Answer

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

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