Creating a new category attribute should be easy in Magento 2. It is, more or less. Follow these steps and you will get to it:

Files you will need to create

A quick screenshot of how your module will look once you create it:

YourCompany/YourModule/registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'YourCompany_YourModule',
    __DIR__
);

YourCompany/YourModule/etc/module.xml

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
	<module name="YourCompany_YourModule" setup_version="1.0.0">
		<sequence>
			<module name="Magento_Catalog"/>
		</sequence>
	</module>
</config>

YourCompany/YourModule/Setup/InstallData.php

<?php

namespace YourCompany\YourModule\Setup;

use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;

/**
 * Class InstallData
 *
 * @package YourCompany\YourModule\Setup
 */
class InstallData implements InstallDataInterface
{

    private $eavSetupFactory;

    /**
     * Constructor
     *
     * @param \Magento\Eav\Setup\EavSetupFactory $eavSetupFactory
     */
    public function __construct(EavSetupFactory $eavSetupFactory)
    {
        $this->eavSetupFactory = $eavSetupFactory;
    }

    /**
     * {@inheritdoc}
     */
    public function install(
        ModuleDataSetupInterface $setup,
        ModuleContextInterface $context
    )
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
        $eavSetup->addAttribute(\Magento\Catalog\Model\Category::ENTITY, 'your_attribute_code', [
            'type'     => 'int',
            'label'    => 'Your Attribute Label',
            'input'    => 'boolean',
            'source'   => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
            'visible'  => true,
            'default'  => '0',
            'required' => false,
            'global'   => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
            'group' => 'General Information'
        ]);
    }
}

YourCompany/YourModule/view/adminhtml/ui_component/category_form.xml

<?xml version="1.0" ?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
	<fieldset name="general">
        <field name="your_attribute_code" sortOrder="22" formElement="checkbox">
            <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="dataType" xsi:type="string">boolean</item>
                <item name="formElement" xsi:type="string">checkbox</item>
                <item name="label" xsi:type="string" translate="true">Your Attribute Name</item>
                <item name="prefer" xsi:type="string">toggle</item>
                <item name="valueMap" xsi:type="array">
                    <item name="true" xsi:type="string">1</item>
                    <item name="false" xsi:type="string">0</item>
                </item>
                <item name="default" xsi:type="number">0</item>
                <item name="scopeLabel" xsi:type="string">[STORE VIEW]</item>
            </item>
        </argument>
        </field>
	</fieldset>
</form>

This code should be enough to create the category attribute. However, even though we have created the attribute passing the parameter ‘global’ = \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE, you’ll see that it will be impossible to set the attribute value at a store view level.

This is because the way the attribute is displayed in the backoffice. It is created as an ui_component and that means many tricky things. This should work by default, but it doesn’t. Someone is working on it on this Magento bug. However, there is a workaround.

Make the attribute work at store view level

It is necessary to add some modifications to Category DataProvider. Let’s go. You need to create 2 more files:

YourCompany/YourModule/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Catalog\Model\Category\DataProvider">
        <plugin name="categoryCustomAttributes" type="YourCompany\YourModule\Plugin\Model\Category\DataProvider" sortOrder="1" disabled="false"/>
    </type>
</config>

YourCompany/YourModule/Plugin/Model/Category/DataProvider.php

Here you will need to add your attribute to the native function PrepareMeta:

<?php

namespace Brildor\Category\Plugin\Model\Category;

class DataProvider extends \Magento\Catalog\Model\Category\DataProvider
{
    private $eavConfig;

    public function __construct(\Magento\Eav\Model\Config $eavConfig)
    {
        $this->eavConfig = $eavConfig;
    }

    public function afterPrepareMeta(\Magento\Catalog\Model\Category\DataProvider $subject, $result)
    {
        $meta = array_replace_recursive($result, $this->_prepareFieldsMeta(
            $this->_getFieldsMap(),
            $subject->getAttributesMeta($this->eavConfig->getEntityType('catalog_category'))
        ));

        return $meta;
    }

    public function _prepareFieldsMeta($fieldsMap, $fieldsMeta)
    {
        $result = [];
        foreach ($fieldsMap as $fieldSet => $fields) {
            foreach ($fields as $field) {
                if (isset($fieldsMeta[$field])) {
                    $result[$fieldSet]['children'][$field]['arguments']['data']['config'] = $fieldsMeta[$field];
                }
            }
        }
        return $result;
    }

    protected function _getFieldsMap()
    {
        $fields = parent::getFieldsMap();
        $fields['general'][] = 'your_attribute_code';

        return $fields;
    }
}


0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.