7

I've created an attribute in Magento 2 of the type multiselect and now I want to have it populated by a custom source model.

Now I remember from Magento 1 that when you want to do this, you had to manually edit the attribute in the database and set the source_model to the path of the source model.

However, when I do this in Magento 2, I get an error. I changed source_model in eav_attribute to Vendor\Module\Model\Config\Source\Product\Attributes, but when I want to edit the product in the admin, I get the following error:

Fatal error: Uncaught Error: Call to undefined method Vendor\Module\Model\Config\Source\Product\Attributes::setAttribute() in .../vendor/magento/module-eav/Model/Entity/Attribute/AbstractAttribute.php:547
Stack trace: #0 .../var/generation/Magento/Catalog/Model/ResourceModel/Eav/Attribute/Interceptor.php(1129): Magento\Eav\Model\Entity\Attribute\AbstractAttribute->getSource()
#1 .../vendor/magento/module-backend/Block/Widget/Form.php(232): Magento\Catalog\Model\ResourceModel\Eav\Attribute\Interceptor->getSource()
#2 .../vendor/magento/module-backend/Block/Widget/Form.php(201): Magento\Backend\Block\Widget\Form->_applyTypeSpecificConfig('multiselect', Object(Magento\Framework\Data\Form\Element\Multiselect), Object(Magento\Catalog\Model\ResourceModel\Eav\Attribute\Interceptor))
#3 .../vendor/magento/module-catalog/Block/Adminhtml/Product/Edit/Tab/Attributes.php(51): Magento\Backend\Block\Widget\Form->_setFieldset(Array, Object(Magento\Framework\Data\Form\El in .../vendor/magento/module-eav/Model/Entity/Attribute/AbstractAttribute.php on line 547

Does anyone know how I can create a product attribute with a custom source model?

Edit:

Current Source Model:

use Vendor\Module\Model\Config\Source\AbstractSource;
use Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory;
use Magento\Eav\Model\Entity\Attribute;
use Magento\Eav\Model\Entity\TypeFactory;
/**
 * Class Attributes
 */
class Attributes extends AbstractSource
{
 /**
 * @var AttributeFactory
 */
 protected $attributeFactory;
 /**
 * @var TypeFactory
 */
 protected $eavTypeFactory;
 /**
 * Attributes constructor.
 * @param AttributeFactory $attributeFactory
 @param TypeFactory $typeFactory
 */
 public function __construct(
 AttributeFactory $attributeFactory,
 TypeFactory $typeFactory
 )
 {
 $this->attributeFactory = $attributeFactory;
 $this->eavTypeFactory = $typeFactory;
 }
 /**
 * @return array
 */
 public function toArray()
 {
 $arr = [];
 $entityType = $this->eavTypeFactory->create()->loadByCode('catalog_product'); 
 $collection = $this->attributeFactory->create()->getCollection();
 $collection->addFieldToFilter('entity_type_id', $entityType->getId());
 $collection->setOrder('attribute_code');
 /** @var Attribute $attribute */
 foreach ($collection as $attribute) {
 $arr[$attribute->getAttributeId()] = $attribute->getFrontendLabel();
 }
 return $arr;
 }
}

Class Vendor\Module\Model\Config\Source\AbstractSource:

namespace Vendor\Module\Model\Config\Source;
abstract class AbstractSource implements \Magento\Framework\Option\ArrayInterface
{
 /**
 * Options getter
 * @return array
 */
 final public function toOptionArray()
 {
 $arr = $this->toArray();
 $ret = [];
 foreach ($arr as $key => $value) {
 $ret[] = [
 'value' => $key,
 'label' => $value
 ];
 }
 return $ret;
 }
 /**
 * Get options in "key-value" format
 * @return array
 */
 public function toArray()
 {
 return [];
 }
}
asked May 31, 2016 at 11:04
2
  • Post your current source model code. Commented May 31, 2016 at 11:26
  • I've added my source model and the abstract class it extends. The abstract class is nothing more than a method that generates the toOptionArray() output. Commented May 31, 2016 at 11:33

2 Answers 2

6

I got it! It turns out that multiselect uses the backend model Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend. For this reason, the source model, must also take EAV into account. How can we do this? Simple: just extend your source model from Attribute\Source\AbstractSource and implement the getAllOptions()-method (which returns a 2-dimensional array with value and label-keys:

/**
 * @return array
 */
public function getAllOptions()
{
 $arr = $this->toArray();
 $ret = [];
 foreach ($arr as $key => $value) {
 $ret[] = [
 'value' => $key,
 'label' => $value
 ];
 }
 return $ret;
}

That's it! Enjoy using your custom source model for multiselect attributes.

answered Jun 8, 2016 at 11:34
0
<?php
/**
 * Created by PhpStorm
 * User: moazzam
 * Date: 31/10/22
 * Time: 7:59 AM
 */
namespace NbrolMarket\LocalMarket\Model\Config;
use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
use NbrolMarket\LocalMarket\Model\ResourceModel\Market\CollectionFactory as MarketCollectionFactory;
/**
 * Create market options
 *
 * Class MarketOptions
 */
class MarketOptions extends AbstractSource
{
 /**
 * @var MarketCollectionFactory
 */
 private MarketCollectionFactory $marketCollectionFactory;
 /**
 * @param MarketCollectionFactory $marketCollectionFactory
 */
 public function __construct(MarketCollectionFactory $marketCollectionFactory)
 {
 $this->marketCollectionFactory = $marketCollectionFactory;
 }
 /**
 * Retrieve All options
 *
 * @return array
 */
 public function getAllOptions()
 {
 $marketCollection = $this->marketCollectionFactory->create();
 $marketCollection->addFieldToSelect("*")->load()->getItems();
 if ($marketCollection->getSize() > 0){
 $options[] = ['label' => __('--Select--'), 'value' => ''];
 foreach ($marketCollection as $markets){
 $name = __($markets->getData('name'));
 $code = $markets->getData("code");
 $options[] = [
 'label'=> $name ,'value'=> $code
 ];
 }
 return $options;
 }
 }
}
answered Dec 3, 2022 at 12:14

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.