Question

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?

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top