magento2如何在代码里创建属性

社区版只能在后台创建产品属性,其他的比如customer/category属性只能用代码来创建。
因为product/customer/category都是eav模型结构,所以要创建属性。也就是把属性存到对应的eav属性值表里去。
比如customer属性,是varchar的话,它的属性值就保存在customer_entity_varchar里。

虽然eav_entity_type表里也有order/invoice/creditmemo/shipment这些实体。
但是这几个实体 不是把属性值存到对应的属性值表里 而是当作字段存在实体表里的。
比如order的属性是直接保存在sales_order表里的。
可能是magento官方觉得order/invoice/creditmemo/shipment这些实体没必要搞那么麻烦 没必要保存到对应的属性值表里 就直接保存在实体表里了。
所以你如果要想创建order属性的话,直接创建字段就行了,具体的可以谷歌下。

我还是在插件Zou_Demo里写代码,因为这插件已经装过了,所以代码需要写在Setup/UpgradeData.php里。相当于是升级数据脚本。

我需要创建的属性清单为:

实体属性code属性label属性值类型(type)前台显示类型(input)备注
productcolours_and_materialsColours And Materialstexttextarea文本框需要开启所见即所得编辑器
productsubtitleSubtitlevarchartext输入框 
categorydisplay_small_imageDisplay Small Imageintselect下拉框 
categorysmall_imageSmall Imagevarcharimage图片 
customercustomer_codeCustomer Codevarchartext输入框 

好了,开始写代码了。

第一步 写升级脚本代码

<?php
namespace Zou\Demo\Setup;

use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\UpgradeDataInterface;
// use Magento\Framework\Setup\SchemaSetupInterface;

use Magento\Customer\Setup\CustomerSetupFactory;
use Magento\Customer\Model\Customer;
use Magento\Eav\Model\Entity\Attribute\Set as AttributeSet;
use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;
use Magento\Quote\Setup\QuoteSetupFactory;
use Magento\Sales\Setup\SalesSetupFactory;
use Magento\Catalog\Setup\CategorySetupFactory;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
/**
 * @codeCoverageIgnore
 */
class UpgradeData implements UpgradeDataInterface
{
    protected $salesSetupFactory;
    /**
     * @var CustomerSetupFactory
     */
    protected $customerSetupFactory;
    protected $schemaSetup;
    private $categorySetupFactory;
    private $eavSetupFactory;
    private $attributeSetFactory;
    protected $quoteSetupFactory;
    public function __construct(
        SalesSetupFactory $salesSetupFactory,
        CustomerSetupFactory $customerSetupFactory,
        AttributeSetFactory $attributeSetFactory,
        CategorySetupFactory $categorySetupFactory,
        EavSetupFactory $eavSetupFactory,
        QuoteSetupFactory $quoteSetupFactory
        //         SchemaSetupInterface $schemaSetup
        ) {
            $this->customerSetupFactory = $customerSetupFactory;
            $this->attributeSetFactory = $attributeSetFactory;
            $this->categorySetupFactory = $categorySetupFactory;
            $this->eavSetupFactory = $eavSetupFactory;
            $this->quoteSetupFactory = $quoteSetupFactory;
            $this->salesSetupFactory = $salesSetupFactory;
            //             $this->schemaSetup = $schemaSetup;
    }
    /**
     * {@inheritdoc}
     */
    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $setup->startSetup();
        if (version_compare($context->getVersion(), '0.1.1', '<')) {
        	//代码写在这里
        }
        $setup->endSetup();
    }

代码写在:

if (version_compare($context->getVersion(), '0.1.1', '<')) {
        	//代码写在这里
        }

这个0.1.1是什么意思呢?

因为我这插件当前版本是0.1.0,(不清楚的可以看插件的module.xml)。
如果你不把版本号改高点的话,代码是不会执行进来的,因为数据库setup_module表里的Zou_Demo记录的版本还是0.1.0
你把module.xml的版本改高后,系统才会识别到你有数据来更新,才会执行进来。执行没问题的话,系统就会把setup_module表里的Zou_Demo的版本改成0.1.1

所以我这里的意思是:当版本为0.1.1的时候就执行这里的代码。

具体代码如下:

public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $setup->startSetup();
        if (version_compare($context->getVersion(), '0.1.1', '<')) {
            $attributes = array(
                'subtitle' => array(
                    'type' => 'varchar',
                    'label' => 'Subtitle',
                    'input' => 'text',
                ),
                'colours_and_materials' => array(
                    'type' => 'text',
                    'label' => 'Colours And Materials',
                    'input' => 'textarea',
                    'wysiwyg_enabled'=>true, //这个用来开启所见即所得编辑器的.要text类型才行。
                    'group'=>'Content'//放到Content组下面去,后台产品编辑页面会看到`Content`这个组的
                )
            );
            $this->createProductAttribute($setup, $attributes);

            $attributes = array(
                'small_image' => array(
                    'type' => 'varchar',
                    'label' => 'Small Image',
                    'input' => 'image',
                    'group'=>'Content', //放到Content组下面去,后台分类编辑页面会看到`Content`这个组的
                    'sort_order'=>6, //给属性设置排序,越大就放在越后面
                    'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
                    'backend' => 'Magento\Catalog\Model\Category\Attribute\Backend\Image'
                ),
                'display_small_image' => array(
                    'type' => 'int',
                    'label' => 'Display Small Image',
                    'input' => 'boolean',//这个boolean就是0和1这2个选项,magento会转换成select下拉框
                    'group'=>'Content',//放到Content组下面去,后台分类编辑页面会看到`Content`这个组的
                    'sort_order' => 9,//给属性设置排序,越大就放在越后面
                    'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
                ),
            );
            $this->createCategoryAttribute($setup, $attributes);

            $attributes = array(
                'customer_code' => array(
                    'type' => 'varchar',
                    'label' => 'Customer Code',
                    'input' => 'text',
                )
            );
            $this->createCustomerAttribute($setup, $attributes);

        }
        $setup->endSetup();
    }

注意:我这里封装了创建属性的函数。具体代码见插件demo。

第二步 修改module.xml的版本号

代码写完后,就修改module.xml,把版本号改成0.1.1

如果不改这里的版本号的话,系统是不是会执行的。具体原因我上面有写。

<?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="Zou_Demo" schema_version="0.1.1"  setup_version="0.1.1">
    ...

第三步 执行升级数据的命令

php bin/magento setup:upgrade

没报错的话 就说明已经升级数据成功了。
打开数据库eav_attribute表就可以看到最新添加的属性了。

第四步 测试

产品属性:

  • 直接打开后台产品新建/编辑页面就可以看到新添加的属性了

分类属性:

  • 后台分类新建/编辑页面没有新添加的属性,需要写ui_component代码
vim 插件目录/view/adminhtml/ui_component/category_form.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <fieldset name="content">
    	<field name="display_small_image">
            <argument name="data" xsi:type="array">
            	<item name="options" xsi:type="object">Magento\Eav\Model\Entity\Attribute\Source\Boolean</item>
                <item name="config" xsi:type="array">
                    <item name="sortOrder" xsi:type="number">33</item>
                    <item name="dataType" xsi:type="string">string</item>
                    <item name="formElement" xsi:type="string">select</item>
                    <item name="label" xsi:type="string" translate="true">Display Small Image</item>
                    <item name="default" xsi:type="number">0</item>
                </item>
            </argument>
        </field>
        <field name="small_image">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="dataType" xsi:type="string">string</item>
                    <item name="source" xsi:type="string">category</item>
                    <item name="label" xsi:type="string" translate="true">Small Image</item>
                    <item name="visible" xsi:type="boolean">true</item>
                    <item name="formElement" xsi:type="string">fileUploader</item>
                    <item name="elementTmpl" xsi:type="string">ui/form/element/uploader/uploader</item>
                    <item name="previewTmpl" xsi:type="string">Magento_Catalog/image-preview</item>
                    <item name="required" xsi:type="boolean">false</item>
                    <item name="sortOrder" xsi:type="number">34</item>
                    <item name="uploaderConfig" xsi:type="array">
                        <item name="url" xsi:type="url" path="catalog/category_image/upload"/>
                    </item>
                </item>
            </argument>
        </field>
    </fieldset>
</form>

customer属性:

  • 直接打开后台customer新建/编辑页面 就可以看到新添加的属性了

具体的代码见插件demo

https://gitee.com/zouhongzhao/magento2-action-extension-demo

<?php
namespace Zou\Demo\Setup;

use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\UpgradeDataInterface;
// use Magento\Framework\Setup\SchemaSetupInterface;

use Magento\Customer\Setup\CustomerSetupFactory;
use Magento\Customer\Model\Customer;
use Magento\Eav\Model\Entity\Attribute\Set as AttributeSet;
use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;
use Magento\Quote\Setup\QuoteSetupFactory;
use Magento\Sales\Setup\SalesSetupFactory;
use Magento\Catalog\Setup\CategorySetupFactory;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
/**
 * @codeCoverageIgnore
 */
class UpgradeData implements UpgradeDataInterface
{
    protected $salesSetupFactory;
    /**
     * @var CustomerSetupFactory
     */
    protected $customerSetupFactory;
    protected $schemaSetup;
    private $categorySetupFactory;
    private $eavSetupFactory;
    private $attributeSetFactory;
    protected $quoteSetupFactory;
    public function __construct(
        SalesSetupFactory $salesSetupFactory,
        CustomerSetupFactory $customerSetupFactory,
        AttributeSetFactory $attributeSetFactory,
        CategorySetupFactory $categorySetupFactory,
        EavSetupFactory $eavSetupFactory,
        QuoteSetupFactory $quoteSetupFactory
        //         SchemaSetupInterface $schemaSetup
        ) {
            $this->customerSetupFactory = $customerSetupFactory;
            $this->attributeSetFactory = $attributeSetFactory;
            $this->categorySetupFactory = $categorySetupFactory;
            $this->eavSetupFactory = $eavSetupFactory;
            $this->quoteSetupFactory = $quoteSetupFactory;
            $this->salesSetupFactory = $salesSetupFactory;
            //             $this->schemaSetup = $schemaSetup;
    }
    /**
     * {@inheritdoc}
     */
    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $setup->startSetup();
        if (version_compare($context->getVersion(), '0.1.1', '<')) {
            $attributes = array(
                'subtitle' => array(
                    'type' => 'varchar',
                    'label' => 'Subtitle',
                    'input' => 'text',
                ),
                'colours_and_materials' => array(
                    'type' => 'text',
                    'label' => 'Colours And Materials',
                    'input' => 'textarea',
                    'wysiwyg_enabled'=>true, //这个用来开启所见即所得编辑器的.要text类型才行。
                    'group'=>'Content'//放到Content组下面去,后台产品编辑页面会看到`Content`这个组的
                )
            );
            $this->createProductAttribute($setup, $attributes);

            $attributes = array(
                'small_image' => array(
                    'type' => 'varchar',
                    'label' => 'Small Image',
                    'input' => 'image',
                    'group'=>'Content', //放到Content组下面去,后台分类编辑页面会看到`Content`这个组的
                    'sort_order'=>6, //给属性设置排序,越大就放在越后面
                    'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
                    'backend' => 'Magento\Catalog\Model\Category\Attribute\Backend\Image'
                ),
                'display_small_image' => array(
                    'type' => 'int',
                    'label' => 'Display Small Image',
                    'input' => 'boolean',//这个boolean就是0和1这2个选项,magento会转换成select下拉框
                    'group'=>'Content',//放到Content组下面去,后台分类编辑页面会看到`Content`这个组的
                    'sort_order' => 9,//给属性设置排序,越大就放在越后面
                    'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
                ),
            );
            $this->createCategoryAttribute($setup, $attributes);

            $attributes = array(
                'customer_code' => array(
                    'type' => 'varchar',
                    'label' => 'Customer Code',
                    'input' => 'text',
                )
            );
            $this->createCustomerAttribute($setup, $attributes);

        }
        $setup->endSetup();
    }
    
    function createCustomerAttribute($setup,$attributes) {
        $customerSetup = $this->customerSetupFactory->create(['resourceName' => 'customer_setup','setup' => $setup]);
        $customerEntity = $customerSetup->getEavConfig()->getEntityType('customer');
        $attributeSetId = $customerEntity->getDefaultAttributeSetId();
        $attributeGroupId = $this->attributeSetFactory->create()->getDefaultGroupId($attributeSetId);

        $aScope = \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL;
        foreach ($attributes as $code=>$_attribute){
            if(isset($_attribute['type']) &&  $_attribute['type']
                && isset($_attribute['input']) &&  $_attribute['input']
                && isset($_attribute['label']) &&  $_attribute['label']
                ){
                    $input = $_attribute['input'];
                    if ($input == "boolean") {
                        $_attribute['source'] = "Magento\Eav\Model\Entity\Attribute\Source\Boolean";
                    }
                    $customerSetup->addAttribute(
                        \Magento\Customer\Model\Customer::ENTITY,
                        $code,
                        [
                            'type' => $_attribute['type'],
                            'label' => $_attribute['label'],
                            'input' => $_attribute['input'],
                            'backend' => isset($_attribute['backend'])?$_attribute['backend']:null,
                            'required' => isset($_attribute['required'])?$_attribute['required']:false,
                            'global' => isset($_attribute['global'])?$_attribute['global']:$aScope,
                            'source' => isset($_attribute['source'])?$_attribute['source']:'',
                            'wysiwyg_enabled'=>isset($_attribute['wysiwyg_enabled'])?$_attribute['wysiwyg_enabled']:false,
                            'visible'      => true,
                            'user_defined' => true,
                            'sort_order' => isset($_attribute['sort_order'])?$_attribute['sort_order']:1000,
                            'position' => isset($_attribute['sort_order'])?$_attribute['sort_order']:1000,
                            'system'       => 0,
                        ]
                    );

                    // more used_in_forms ['adminhtml_checkout','adminhtml_customer','adminhtml_customer_address','customer_account_edit','customer_address_edit','customer_register_address']
                    $customerAttribute = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, $code)
                    ->addData([
                        'attribute_set_id' => $attributeSetId,
                        'attribute_group_id' => $attributeGroupId,
                        'used_in_forms' => ['adminhtml_customer','customer_account_edit','customer_account_create'],
                    ]);
                    $customerAttribute->save();
            }
        }
    
    }

    function createProductAttribute($setup,$attributes) {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
        $aScope = \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL;
        foreach ($attributes as $code=>$_attribute){
            if(isset($_attribute['type']) &&  $_attribute['type']
                && isset($_attribute['input']) &&  $_attribute['input']
                && isset($_attribute['label']) &&  $_attribute['label']
                ){
                    $input = $_attribute['input'];
                    if ($input == "boolean") {
                        $_attribute['source'] = "Magento\Eav\Model\Entity\Attribute\Source\Boolean";
                    }
                    $eavSetup->addAttribute(
                        \Magento\Catalog\Model\Product::ENTITY, $code, [
                            'group' => isset($_attribute['group'])?$_attribute['group']:'General',
                            'type' => $_attribute['type'],
                            'label' => $_attribute['label'],
                            'input' => $_attribute['input'],
                            'backend' => isset($_attribute['backend'])?$_attribute['backend']:null,
                            'required' => isset($_attribute['required'])?$_attribute['required']:false,
                            'sort_order' => isset($_attribute['sort_order'])?$_attribute['sort_order']:1000,
                            'user_defined' => isset($_attribute['user_defined'])?$_attribute['user_defined']:true,
                            'global' => isset($_attribute['global'])?$_attribute['global']:$aScope,
                            'used_in_product_listing' => true,
                            'visible' => true,
                            'source' => isset($_attribute['source'])?$_attribute['source']:'',
                            'wysiwyg_enabled'=>isset($_attribute['wysiwyg_enabled'])?$_attribute['wysiwyg_enabled']:false,
                            'default' => isset($_attribute['default'])?$_attribute['default']:null
                        ]
                        );
            }
        }
    
    }
    function createCategoryAttribute($setup,$attributes) {
        $categorySetup = $this->categorySetupFactory->create(['setup' => $setup]);
        $aScope = \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL;
        foreach ($attributes as $code=>$_attribute){
            if(isset($_attribute['type']) &&  $_attribute['type']
                && isset($_attribute['input']) &&  $_attribute['input']
                && isset($_attribute['label']) &&  $_attribute['label']
                ){
                    $input = $_attribute['input'];
                    if ($input == "boolean") {
                        $_attribute['source'] = "Magento\Eav\Model\Entity\Attribute\Source\Boolean";
                    }
                    $categorySetup->addAttribute(
                       \Magento\Catalog\Model\Category::ENTITY, $code, [
                            'group' => isset($_attribute['group'])?$_attribute['group']:'General Information',
                            'type' => $_attribute['type'],
                            'label' => $_attribute['label'],
                            'input' => $_attribute['input'],
                            'backend' => isset($_attribute['backend'])?$_attribute['backend']:null,
                            'required' => isset($_attribute['required'])?$_attribute['required']:false,
                            'sort_order' => isset($_attribute['sort_order'])?$_attribute['sort_order']:1000,
                            'user_defined' => isset($_attribute['user_defined'])?$_attribute['user_defined']:true,
                            'global' => isset($_attribute['global'])?$_attribute['global']:$aScope,
                            'used_in_product_listing' => isset($_attribute['used_in_product_listing'])?$_attribute['used_in_product_listing']:true,
                            'is_used_in_grid' => isset($_attribute['is_used_in_grid'])?$_attribute['is_used_in_grid']:true,
                            'is_visible_in_grid' => isset($_attribute['is_visible_in_grid'])?$_attribute['is_visible_in_grid']:false,
                            'is_filterable_in_grid' => isset($_attribute['is_filterable_in_grid'])?$_attribute['is_filterable_in_grid']:true,
                            'visible' => true,
                            'source' => isset($_attribute['source'])?$_attribute['source']:'',
                            'wysiwyg_enabled'=>isset($_attribute['wysiwyg_enabled'])?$_attribute['wysiwyg_enabled']:false,
                            'default' => isset($_attribute['default'])?$_attribute['default']:null
                        ]
                        );
            }
        }
    
    }


    function removeAttribute($setup, $codes = array(), $type = 'product'){
        $entityTypeCode = false;
        switch ($type) {
            case 'category':
                $entityTypeCode = \Magento\Catalog\Model\Category::ENTITY;
            break;
            case 'customer':
                $entityTypeCode = \Magento\Customer\Model\Customer::ENTITY;
            break;
            case 'product':
                $entityTypeCode = \Magento\Catalog\Model\Product::ENTITY;
            break;
            default:
                $entityTypeCode = false;
            break;
        }
        if($entityTypeCode && $codes){
            if(!is_array($codes)){
                $codes = array($codes);
            }
            $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
            //$entityTypeId = $eavSetup->getEntityType($entityTypeCode);
            foreach ($codes as $code){
                $eavSetup->removeAttribute($entityTypeCode, $code);
            }
        }
    }
}

复制

如果本文档还不能解决你的问题的话,先谷歌一下,不懂的再问我。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值