1

We have a table that has data linked to products.

MyCustomDataTable {
    id,
    product_id,
    text_value
}

We want to be able to search for products using the MyCustomDataTable.text_value value. To do this I tried making a Data Patch and a custom source option.

namespace Vendor\Module\Setup\Patch\Data;

use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;

class AddProductCustomData implements DataPatchInterface
{
    const ATTRIBUTE_NAME = "text_value";
    private $eavSetupFactory;
    private $moduleDataSetup;

    public function __construct(
        ModuleDataSetupInterface $moduleDataSetup,
        EavSetupFactory $eavSetupFactory
    ) {
        $this->moduleDataSetup = $moduleDataSetup;
        $this->eavSetupFactory = $eavSetupFactory;
    }

    public static function getDependencies()
    {
        return [];
    }


    public function getAliases()
    {
        return [];
    }

    public function apply()
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]);
        $eavSetup->addAttribute(\Magento\Catalog\Model\Product::ENTITY, self::ATTRIBUTE_NAME, [
            'position' => 200,
            'type'  => 'text',
            'label' => 'My Custom Data',
            'input' => 'multiselect',
            'user_defined' => false,
            'required' => false,

            'is_global' => true,
            'is_searchable' => true,
            'is_used_in_grid' => true,
            'is_visible_in_grid' => true,
            'is_filterable_in_grid' => true,
            'search_weight' => 5,

            'source' => 'Vendor\Module\Model\Config\Product\ExtensionOption',
            'global' => \Magento\Catalog\Model\ResourceModel\Eav\Attribute::SCOPE_STORE,
            'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend'
        ]);

        return $this;
    }
}
<?php
namespace Vendor\Module\Model\Config\Product;

use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
use Vendor\Module\Model\CustomDataFactory;

class ExtensionOption extends AbstractSource
{
    protected $_customDataFactory;

    public function __construct(CustomDataFactory $customDataFactory)
    {
        $this->_customDataFactory = $customDataFactory;
    }

    public function getAllOptions()
    {
        if ($this->options === null) {
            $collection = $this->_customDataFactory->create();
            $collection->addFieldToSelect('*');

            // TODO: Filter data based on product

            $this->options = [];
            foreach ($collection as $item) {
                $this->options[] = [
                    'value' => $item->getText(),
                    'label' => $item->getText()
                ];
            }
        }

        return $this->options;
    }
}

I need to limit the amount of options to only those that are linked to the product.

How do I do this or is there a better way?

1

Instead the below code for your below class:

app/code/Vendor/Module/Model/Config/Product/ExtensionOption.php

<?php
namespace Vendor\Module\Model\Config\Product;

use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
use Vendor\Module\Model\CustomDataFactory;
use Magento\Framework\App\Request\Http;

class ExtensionOption extends AbstractSource
{
    protected $_customDataFactory;

    protected $_request;

    public function __construct(
        CustomDataFactory $customDataFactory,
        Http $request
    ) {
        $this->_customDataFactory = $customDataFactory;
        $this->_request = $request;
    }

    public function getAllOptions()
    {
        if ($this->options === null) {
            $collection = $this->_customDataFactory->create();
            $collection->addFieldToSelect('*');

            if ($id = $this->_request->getParam('id')) {
                $collection->addFieldToFilter('product_id', $id);
            }

            $this->options = [];
            foreach ($collection as $item) {
                $this->options[] = [
                    'value' => $item->getText(),
                    'label' => $item->getText()
                ];
            }
        }

        return $this->options;
    }
}

The above is for Product Edit page. Also if there is no value in your custom table then all the options will be shown. Or you can do according to your requirement.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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