Como posso usar um modelo de origem personalizado para um atributo de produto com seleção múltipla no Magento 2

7

Eu criei um atributo no Magento 2 do tipo multiselect e agora quero que ele seja preenchido por um modelo de origem personalizado.

Agora, lembro do Magento 1 que, quando você deseja fazer isso, você deve editar manualmente o atributo no banco de dados e definir o source_model o caminho do modelo de origem.

No entanto, quando faço isso no Magento 2, recebo um erro. Eu mudei source_modelem eav_attributea Vendor\Module\Model\Config\Source\Product\Attributes, mas quando eu quiser editar o produto no admin, eu recebo o seguinte erro:

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

Alguém sabe como posso criar um atributo de produto com um modelo de origem personalizado?

Editar:

Modelo de fonte atual:

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;
    }
}

Classe 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 [];
    }
}
Giel Berkers
fonte
Poste seu código de modelo de origem atual.
Ryan Hoerr
Adicionei meu modelo de origem e a classe abstrata que ele estende. A classe abstrata nada mais é do que um método que gera a toOptionArray()saída.
Giel Berkers

Respostas:

6

Deixa comigo! Acontece que a seleção múltipla usa o modelo de back-end Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend. Por esse motivo, o modelo de origem também deve levar o EAV em consideração. Como podemos fazer isso? Simples: apenas estenda seu modelo de origem Attribute\Source\AbstractSourcee implemente o getAllOptions()-method (que retorna uma matriz bidimensional com as teclas valuee label:

/**
 * @return array
 */
public function getAllOptions()
{
    $arr = $this->toArray();
    $ret = [];

    foreach ($arr as $key => $value) {
        $ret[] = [
            'value' => $key,
            'label' => $value
        ];
    }

    return $ret;
}

É isso aí! Aproveite o uso do seu modelo de origem personalizado para atributos de seleção múltipla.

Giel Berkers
fonte