0

I have a custom product attribute that uses a multiselect input to select one or more product stockists.

The data is being stored correctly, and selecting 1 option adds the information to the "More information' tab on the product frontend page.

Selecting 2 or more options, the information is no longer visible on the frontend.

Attribute config below

$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
$eavSetup->addAttribute(
                \Magento\Catalog\Model\Product::ENTITY,
                'stockist',
                [
                    'type' => 'varchar',
                    'label' => 'Stockist',
                    'input' => 'multiselect',
                    'source' => 'My\Module\Model\Attribute\Source\Stockist',
                    'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
                    'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
                    'visible' => true,
                    'required' => false,
                    'searchable' => true,
                    'filterable' => true,
                    'comparable' => false,
                    'visible_on_front' => true,
                    'used_in_product_listing' => true
                ]
            );

My\Module\Model\Attribute\Source\Stockist:

namespace My\Module\Model\Attribute\Source;

use My\Module\Model\ResourceModel\Stockist\CollectionFactory;
use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;

class Stockist extends AbstractSource
{
    private $collectionFactory;

    public function __construct(CollectionFactory $collectionFactory)
    {
        $this->collectionFactory = $collectionFactory;
    }

    public function getAllOptions()
    {
        $stockistCollection = $this->collectionFactory->create();
        $stockistCollection->addFieldToSelect('*')->load();

        $result = [];

        foreach ($stockistCollection as $stockist) {
            $result[] = [
                'value' => $stockist->getId(),
                'label' => $stockist->getName()
            ];
        }

        return $result;
    }
}
  • When you select more then one options, does it save sucessfully into database? – Dhiren Vasoya Feb 28 at 14:21
  • @DhirenVasoya yes it does, it saves as a comma separated list of IDs – Paul Canning Feb 28 at 14:35
  • how does your My\Module\Model\Attribute\Source\Stockist look like? – HelgeB Feb 28 at 14:57
  • @HelgeB updated my question. – Paul Canning Feb 28 at 15:11
  • OK, do you know how you access the data in Frontend? do you use $product->getAttributeText()? – HelgeB Feb 28 at 15:19
1

Add this method to your Stockist class:

public function getOptionText($value)
{
    $isMultiple = false;
    if (strpos($value, ',')) {
        $isMultiple = true;
        $value = explode(',', $value);
    }

    $options = $this->getAllOptions();

    if (!is_array($value)) {
        $value = [$value];
    }
    $optionsText = [];
    foreach ($options as $item) {
        if (in_array($item['value'], $value)) {
            $optionsText[] = $item['label'];
        }
    }

    if ($isMultiple) {
        return $optionsText;
    } elseif ($optionsText) {
        return $optionsText[0];
    }

    return false;
}

haven't tested it, so watch out for typos and syntax errors.

Off topic things but might help.
You don't need to reload from the db all data each time getAllOptions is called:

class Stockist extends AbstractSource
{
    private $collectionFactory;
    $private $options;

    public function __construct(CollectionFactory $collectionFactory)
    {
        $this->collectionFactory = $collectionFactory;
    }

    public function getAllOptions()
    {
        if ($this->options === null) {
            $stockistCollection = $this->collectionFactory->create();
            $stockistCollection->addFieldToSelect('*')->load();

            $this->options = [];

            foreach ($stockistCollection as $stockist) {
                $this->options[] = [
                    'value' => $stockist->getId(),
                    'label' => $stockist->getName()
                ];
            }
        }
        return $this->options;
    }
}
  • That works great, thank you! Any idea how to get it working with the search and filters? They are set to true in my config, but I assume I'm missing some other methods in my Attribute source model? – Paul Canning Feb 28 at 15:44
  • Do you have Flat Catalog option as enabled? – MageAj Feb 28 at 17:22
  • @PaulCanning It should work if you set it as "used_in_layered_navigation" and "used_in_search" – Marius Mar 1 at 6:32
  • I have only searchable set to true - which I assumed would be enough. Is there documentation as to what attribute options are available? – Paul Canning Mar 1 at 12:21
  • Adding 'used_in_search' => true in the attribute options works, but only when I have one option selected. 2 or more options and they do not get added to the catalogsearch_fulltext_scope1 table – Paul Canning Mar 1 at 12:35

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.