magento2

m2的核心源代码通过composer install后,存放在vendor/magento

db

app/etc/文件夹下会多出config.php和env.php两个php文件,config.php可以看到magento2加载了那些模块;env.php保存了连接的数据库的一些信息

eav

1、eav_entity_type 表:
eav_entity_code: 代表 实体(表名)
attribute_model: 实例化model
entity_table: 实体所对应的最关键表(XXX_entity表)

2、eav_attribute 表:
eav_entity_id: 关联eav_entity_type表
attribute_code: 代表 属性(字段名)

3、xxx_eav_atrribute 表:
eav_attribute 表的属性的具体设置

4、eav_entity_attribute 表:
作为 eav_entity_type 和 eav_attribute 的中间表

5、XXX_entity 表:
记录一条数据

6、XXX_entity_{type} 表:
记录 XXX_entity 数据的各个属性(字段)值

1、2、3、4为表结构设置表;
5、6为对应的“数据—值”表

search

1、时间(时区)格式化

$timezone = ObjectManager::getInstance()->get('Magento\Framework\Stdlib\DateTime\TimezoneInterface');
var_dump($timezone->date($sourceData)->format('Y-m-d H:i:s'));

2、获取eav中的表数据

// 获取id=$id的数据的name字段值
$objectManager = ObjectManager::getInstance();
$productObj = $objectManager->get('Magento\Catalog\Model\Product')->load($id);
$productObj->getName();

表结构操作

app/code/重写目录/重写插件/Setup/

1、update

<?php

namespace StanJY\ProductList\Setup;

use Magento\Eav\Setup\EavSetup;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\UpgradeDataInterface;

class UpgradeData implements UpgradeDataInterface
{

    private $eavSetupFactory;

    public function __construct(EavSetup $eavSetupFactory)
    {
        $this->eavSetupFactory = $eavSetupFactory;
    }
    
    //改变属性值
    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $setup->startSetup();
        // 第一种(通过id):entity_type_id、attribute_id
        $this->eavSetupFactory->updateAttribute(4,82,'is_visible', 0, null);
        //第二种(通过code):entity_type_code、attribute_code
        $this->eavSetupFactory->updateAttribute('catalog_product','weight','is_visible', 0, null);
        
        $setup->endSetup();
    }
}

<?php


namespace StanJY\ChooseStore\Setup;

use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
class UpgradeSchema implements UpgradeSchemaInterface
{
	// 改变表字段类型
    public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $setup->startSetup();

        if (version_compare($context->getVersion(), '2.0.2', '<')) {
            $setup->getConnection()->changeColumn(
                $setup->getTable('inventory_source'),
                'email',
                'email',
                [
                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                    'nullable' => false,
                    'default' => '',
                    'comment' => 'email'
                ]
            );
        }
        $setup->endSetup();

    }

}

2、add\delete

<?php
namespace StanJY\Menu\Setup;

use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Setup\{
    ModuleContextInterface,
    ModuleDataSetupInterface,
    InstallDataInterface
};

class InstallData implements InstallDataInterface
{
    private $eavSetupFactory;

    public function __construct(EavSetupFactory $eavSetupFactory) {
        $this->eavSetupFactory = $eavSetupFactory;
    }

    /**
     * @throws \Zend_Validate_Exception
     * @throws LocalizedException
     */
    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
		
		// 删除属性
        $eavSetup->removeAttribute(\Magento\Catalog\Model\Category::ENTITY, 'jpa_name');
        // 增加属性
        $eavSetup->addAttribute(\Magento\Catalog\Model\Category::ENTITY, 'jpa_name', [
            'group' => 'Display Settings',
            'type' => 'varchar',
            'backend' => '',
            'frontend' => '',
            'sort_order' => 10,
            'label' => 'Jpa name',
            'input' => 'text',
            'class' => '',
            'source' => '',
            'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
            'visible' => true,
            'required' => false,
            'user_defined' => false,
            'default' => '',
            'searchable' => false,
            'filterable' => false,
            'comparable' => false,
            'visible_on_front' => false,
            'used_in_product_listing' => true,
            'apply_to' => ''
        ]);
    }
}
<?php
/**
 * Magezon
 *
 * This source file is subject to the Magezon Software License, which is available at https://www.magezon.com/license
 * Do not edit or add to this file if you wish to upgrade the to newer versions in the future.
 * If you wish to customize this module for your needs.
 * Please refer to https://www.magezon.com for more information.
 *
 * @category  Magezon
 * @package   Magezon_Newsletter
 * @copyright Copyright (C) 2020 Magezon (https://www.magezon.com)
 */

namespace StanJY\ChooseStore\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\DB\Ddl\Table;

class InstallSchema implements InstallSchemaInterface
{
	// 增加表字段
    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $installer = $setup;

        $installer->startSetup();
        $setup->getConnection()->addColumn(
            $setup->getTable('inventory_source'),
            'name_hk',
            [
                'type'    => Table::TYPE_TEXT,
                'length'  => 255,
                'comment' => 'Chinese Store Name'
            ]
        );
        $installer->endSetup();
    }
}

3、delete

<?php


namespace StanJY\ChooseStore\Setup;

use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
class UpgradeSchema implements UpgradeSchemaInterface
{
    public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $setup->startSetup();
		// 删除inventory_source表的description字段
        $setup->getConnection()->dropColumn(
                $setup->getTable('inventory_source'),
                'description'
        );
        $setup->endSetup();

    }

}

表数据操作

1、update

<?php

	$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
	$resource = $objectManager->get('Magento\Framework\App\ResourceConnection');
    $connection = $resource->getConnection();
    $connection->update(
    	'inventory_source', // 目标表
        ['email' => $email], // 目标字段
        ['source_code=(?)' => $code] // where 条件
    );
    
	// 批量修改
	$updateData['fieldName1'] = 'value1';
	$updateData['fieldName2'] = 'value2';
	$connection->update(
    	'inventory_source', // 目标表
        $updateData, // 批量
        ['id=(?)' => $id] // where 条件
    );
    
namespace Test\Test;

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Model\ResourceModel\Product\Action;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\App\ResourceConnection;

class A {
	protected $productRepository;
    protected $dbOperate;
    protected $action;

	public function __construct()
    {
    	// magento product模块自带 (product为eav结构)
        $this->productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class);
        // magento product模块自带
        $this->action = ObjectManager::getInstance()->get(Action::class);
        $this->dbOperate = ObjectManager::getInstance()->get(ResourceConnection::class)
            ->getConnection();
    }
	public function fun() {
		// 普通表search
		$store_id = $this->dbOperate->fetchOne("select store_id from store where code='xxx'");

		// 获取product对象
		$productObj = $this->productRepository->get($code);
		$productId = $productObj->getId();

		// 修改product数据
		$updateAttrEn['fieldName'] = 'value';
		$this->action->updateAttributes([$productId ],$updateAttrEn,0);
	}
}



常用命令

在/magento目录下执行

1、数据库/模块变更

php bin/magento setup:upgrade

2、di.xml 依赖关系变更

php bin/magento setup:di:compile

3、强制部署静态文件(清楚缓存后)

php bin/magento setup:static-content:deploy -f
// 合并执行
rm -rf ./pub/static/*/* && sudo rm -rf ./var/view_preprocessed/* && sudo php bin/magento setup:static-content:deploy -f && sudo php bin/magento cache:clean && sudo chmod 777 var -R && sudo chmod 777 pub -R

清缓存

php bin/magento cache:clean

刷新缓存

php bin/magento cache:flush

删除缓存文件

sudo rm -rf ./pub/static/*/* && sudo rm -rf ./var/view_preprocessed/*

4、修改为开发模式

php bin/magento deploy:mode:set developer

5、禁用二重验证

php bin/magento module:disable Magento_TwoFactorAuth



layout

1、联动隐藏节点

	<!-- File Path: /ui_component/inventory_source_form.xml -->
		<field name="is_pickup_location_active" formElement="checkbox" sortOrder="65">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="default" xsi:type="number">0</item>
                </item>
            </argument>
            <settings>
                <dataScope>extension_attributes.is_pickup_location_active</dataScope>
                <dataType>boolean</dataType>
                <label translate="true">Use as Pickup Location</label>
                <notice translate="true">The Default Source can not be used for In-Store Pickup Delivery.</notice>
                <!-- 配置联动 -->
                <switcherConfig>
                    <rules>
                    	<!-- name: rule 序号-->
                        <rule name="0">
                        	<!-- is_pickup_location_active 属性的值为1时的情况 -->
                            <value>1</value>
                            <actions>
                            	<!-- name: action 序号 -->
                                <action name="0">
                                	<!-- 目标节点,是否隐藏 -->
                                	<!-- 当前xml文件的namespace:"inventory_source_form", 需重复两次;
                                		 当前field的fieldset: "general";
                                		 目标节点:"pickup_locations_unused_start_time" -->
                                    <target>inventory_source_form.inventory_source_form.general.pickup_locations_unused_start_time</target>
                                    <callback>hide</callback>
                                </action>
                                <action name="1">
                                    <target>inventory_source_form.inventory_source_form.general.pickup_locations_unused_end_time</target>
                                    <callback>hide</callback>
                                </action>
                            </actions>
                        </rule>
                        <rule name="1">
                            <value>0</value>
                            <actions>
                                <action name="0">
                                    <target>inventory_source_form.inventory_source_form.general.pickup_locations_unused_start_time</target>
                                    <callback>show</callback>
                                </action>
                                <action name="1">
                                    <target>inventory_source_form.inventory_source_form.general.pickup_locations_unused_end_time</target>
                                    <callback>show</callback>
                                </action>
                            </actions>
                        </rule>
                    </rules>
                    <!-- 必需 -->
                    <enabled>true</enabled>
                </switcherConfig>
            </settings>
            <formElements>
                <checkbox>
                    <settings>
                        <valueMap>
                            <map name="false" xsi:type="number">0</map>
                            <map name="true" xsi:type="number">1</map>
                        </valueMap>
                        <prefer>toggle</prefer>
                    </settings>
                </checkbox>
            </formElements>
        </field>
        <field name="pickup_locations_unused_start_time" formElement="date" sortOrder="71">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="source" xsi:type="string">menu</item>
                    <item name="options" xsi:type="array">
                        <item name="dateFormat" xsi:type="string">yyyy-MM-dd</item>
                        <item name="timeFormat" xsi:type="string">HH:mm:ss</item>
                        <item name="showsTime" xsi:type="boolean">true</item>
                    </item>
                </item>
            </argument>
            <settings>
                <dataType>text</dataType>
                <label translate="true">Start Time</label>
                <visible>true</visible>
            </settings>
        </field>
        <field name="pickup_locations_unused_end_time" formElement="date" sortOrder="72">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="source" xsi:type="string">menu</item>
                    <item name="options" xsi:type="array">
                        <item name="dateFormat" xsi:type="string">yyyy-MM-dd</item>
                        <item name="timeFormat" xsi:type="string">HH:mm:ss</item>
                        <item name="showsTime" xsi:type="boolean">true</item>
                    </item>
                </item>
            </argument>
            <settings>
                <dataType>text</dataType>
                <label translate="true">End Time</label>
                <visible>true</visible>
            </settings>
        </field>

2、联动隐藏节点 (js)

/view/adminhtml/ui_component/inventory_source_form.xml

<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
	<argument name="data" xsi:type="array">
        <item name="js_config" xsi:type="array">
            <item name="provider" xsi:type="string">inventory_source_form.inventory_source_form_data_source</item>
        </item>
        <item name="label" xsi:type="string" translate="true">Source Information</item>
        <item name="template" xsi:type="string">templates/form/collapsible</item>
    </argument>
    <settings>
        <dataScope>data</dataScope>
        <namespace>inventory_source_form</namespace>
        <deps>
            <dep>inventory_source_form.inventory_source_form_data_source</dep>
        </deps>
        <buttons>
            <button name="back">
                <url path="*/*/index"/>
                <class>back</class>
                <label translate="true">Back</label>
            </button>
            <button name="reset">
                <class>reset</class>
                <label translate="true">Reset</label>
            </button>
            <button name="save" class="Magento\InventoryAdminUi\Ui\Component\Control\Source\SaveSplitButton"/>
        </buttons>
    </settings>
    <dataSource name="inventory_source_form_data_source" component="Magento_Ui/js/form/provider">
        <settings>
            <submitUrl path="*/*/save"/>
        </settings>
        <dataProvider class="Magento\InventoryAdminUi\Ui\DataProvider\SourceDataProvider" name="inventory_source_form_data_source">
            <settings>
                <requestFieldName>source_code</requestFieldName>
                <primaryFieldName>source_code</primaryFieldName>
            </settings>
        </dataProvider>
    </dataSource>
    <fieldset name="general" sortOrder="10">
        <settings>
            <label translate="true">General</label>
            <collapsible>true</collapsible>
            <opened>true</opened>
            <dataScope>general</dataScope>
        </settings>
        <!-- 联动:checkbox 为 1 时,preparation_time字段隐藏 -->
        <field name="is_pickup_location_active" formElement="checkbox" sortOrder="70">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="default" xsi:type="number">0</item>
                </item>
            </argument>
            <settings>
                <dataScope>extension_attributes.is_pickup_location_active</dataScope>
                <dataType>boolean</dataType>
                <label translate="true">Use as Pickup Location</label>
                <notice translate="true">The Default Source can not be used for In-Store Pickup Delivery.</notice>
            </settings>
            <formElements>
                <checkbox>
                    <settings>
                        <valueMap>
                            <map name="false" xsi:type="number">0</map>
                            <map name="true" xsi:type="number">1</map>
                        </valueMap>
                        <prefer>toggle</prefer>
                    </settings>
                </checkbox>
            </formElements>
        </field>
	</fieldset>
	
	<fieldset name="extension_info" sortOrder="50">
        <settings>
            <label translate="true">Store Extension Information</label>
            <collapsible>true</collapsible>
            <opened>false</opened>
            <dataScope>extension_info</dataScope>
        </settings>
        <!-- 联动js -->
        <field name="preparation_time" formElement="input"  component="StanJY_ChooseStore/js/fieldset" sortOrder="140">
            <settings>
                <dataType>int</dataType>
                <label translate="true">Preparation Time(minute)</label>
                <!-- 传入联动js的参数;name='参数名',tag content:参数值 -->
                <imports>
                    <link name="visible">${ $.provider }:data.general.extension_attributes.is_pickup_location_active</link>
                </imports>
            </settings>
        </field>
	</fieldset>
</form> 

/view/adminhtml/web/js/fieldset.js

/*
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
define([
    'Magento_Ui/js/form/components/fieldset',
    'ko'
], function (Fieldset, ko) {
    'use strict';

    /**
     * TODO Remove when issue is resolved in core.
     * @see Please check issue in core for more details: https://github.com/magento/magento2/issues/22067.
     */
    return Fieldset.extend(ko).extend(
        {
            /**
             * Convert `visible` value from string ('1', '0') to bool (true, false)
             */
            initialize: function () {
                this._super();

                // eslint-disable-next-line vars-on-top
                var visible = this.visible;

                this.visible = ko.computed({
                    /**
                     * @returns {Boolean}
                     */
                    read: function () {
                        return visible();
                    },

                    /**
                     * @param {String} value
                     */
                    write: function (value) {
                        value = Boolean(value) === value ? value : Boolean(parseInt(value, 0));
                        visible(value);
                    },
                    owner: this
                });
                this.visible(visible());
            }
        }
    );
});

3、layout.xml select下拉框关联js

/view/adminhtml/layout/inventory_source_edit.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
    	<!-- 引入js -->
        <link src="StanJY_ChooseStore::js/validator.js"/>
    </head>
    <body>
        <referenceContainer name="content">
            <uiComponent name="inventory_source_form"/>
        </referenceContainer>
    </body>
</page>

/view/adminhtml/ui_component/inventory_source_form.xml

<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">

<fieldset name="address" sortOrder="30">
        <settings>
            <label translate="true">Address Data</label>
            <collapsible>true</collapsible>
            <opened>false</opened>
            <dataScope>general</dataScope>
        </settings>

		<field name="regions" formElement="select" sortOrder="110">
            <settings>
                <dataType>text</dataType>
                <label translate="true">Region</label>
                <validation>
                	<!-- magento 自带必填验证 -->
                    <rule name="required-entry" xsi:type="boolean">true</rule>
                    <!-- 自定义验证 -->
                    <rule name="source-region-check-validation" xsi:type="boolean">true</rule>
                </validation>
            </settings>
            <formElements>
                <select>
                    <settings>
                    	<!-- 下拉选项数据来源 -->
                        <options class="StanJY\ManagementAddress\Model\Config\Soure\ParentInfo"/>
                    </settings>
                </select>
            </formElements>
        </field>
</fieldset>
</form>

/view/adminhtml/web/js/validator.js

require(
    [
        'Magento_Ui/js/lib/validation/validator',
        'jquery',
        'mage/translate'
    ], function(validator, $){

        validator.addRule(
            'source-region-check-validation',
            function (value) {
                if (value == 0) {
                    let ele = $("[name='general[regions]']");
                    ele.addClass("required");
                    $(window).scrollTop(ele.offset().top);
                    return false;
                } else {
                    $("[name='general[regions]']").removeClass("required");
                    return true
                }
            }
            ,$.mage.__('')
        );
    });

4、字段是否必填联动 (js)

/view/adminhtml/ui_component/inventory_source_form.xml

<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
	<argument name="data" xsi:type="array">
        <item name="js_config" xsi:type="array">
            <item name="provider" xsi:type="string">inventory_source_form.inventory_source_form_data_source</item>
        </item>
        <item name="label" xsi:type="string" translate="true">Source Information</item>
        <item name="template" xsi:type="string">templates/form/collapsible</item>
    </argument>
    <settings>
        <dataScope>data</dataScope>
        <namespace>inventory_source_form</namespace>
        <deps>
            <dep>inventory_source_form.inventory_source_form_data_source</dep>
        </deps>
        <buttons>
            <button name="back">
                <url path="*/*/index"/>
                <class>back</class>
                <label translate="true">Back</label>
            </button>
            <button name="reset">
                <class>reset</class>
                <label translate="true">Reset</label>
            </button>
            <button name="save" class="Magento\InventoryAdminUi\Ui\Component\Control\Source\SaveSplitButton"/>
        </buttons>
    </settings>
    <dataSource name="inventory_source_form_data_source" component="Magento_Ui/js/form/provider">
        <settings>
            <submitUrl path="*/*/save"/>
        </settings>
        <dataProvider class="Magento\InventoryAdminUi\Ui\DataProvider\SourceDataProvider" name="inventory_source_form_data_source">
            <settings>
                <requestFieldName>source_code</requestFieldName>
                <primaryFieldName>source_code</primaryFieldName>
            </settings>
        </dataProvider>
    </dataSource>
    <fieldset name="general" sortOrder="10">
        <settings>
            <label translate="true">General</label>
            <collapsible>true</collapsible>
            <opened>true</opened>
            <dataScope>general</dataScope>
        </settings>
        <!-- 联动:下拉选择为2、3时,preparation_time字段为必填字段 -->
        <field name="order_mode" formElement="select" sortOrder="60">
            <settings>
                <dataType>text</dataType>
                <label translate="true">Order Mode</label>
                <validation>
                    <rule name="required-entry" xsi:type="boolean">true</rule>
                </validation>
            </settings>
            <formElements>
                <select>
                    <settings>
                        <options class="StanJY\ChooseStore\Model\Config\Soure\OrderMode"/>
                    </settings>
                </select>
            </formElements>
        </field>
	</fieldset>
	
	<fieldset name="extension_info" sortOrder="50">
        <settings>
            <label translate="true">Store Extension Information</label>
            <collapsible>true</collapsible>
            <opened>false</opened>
            <dataScope>extension_info</dataScope>
        </settings>
        <!-- 联动js -->
        <field name="preparation_time" formElement="input"  component="StanJY_ChooseStore/js/conditional-required" sortOrder="140">
            <settings>
                <dataType>int</dataType>
                <label translate="true">Preparation Time(minute)</label>
                <!-- 传入联动js的参数;name='参数名',tag content:参数值 -->
                <imports>
                    <link name="orderMode">${ $.provider }:data.general.order_mode</link>
                    <link name="locationActive">${ $.provider }:data.general.extension_attributes.is_pickup_location_active</link>
                </imports>
            </settings>
        </field>
	</fieldset>
</form> 

/view/adminhtml/web/js/conditional-required.js

/*
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
define([
    'Magento_Ui/js/form/element/abstract',
    'ko',
    'underscore',
    'mageUtils'
], function (uiElement, ko, _, utils) {
    'use strict';

    /**
     * Provide possibility to make field required by dependency on other field value.
     */
    return uiElement.extend(
        {
            /**
             * `required` value is string ('', '1', '2', '3')
             */
            initialize: function () {
                this._super();

                // 判断是否需要必填验证的唯一标识
                var required = this.required;

				// 将初始值提出来,并全局化管理,可用于其他方法中联动
                var param = this.orderMode;
                // 构造需被监控的属性
                this.orderMode = ko.computed({
                    /**
                     * @returns {Boolean}
                     */
                    read: function () {
                        return required();
                    },

                    /**
                     * @param {String|Boolean} value
                     */
                    write: function (value) {
                        if (Boolean(value)) {
                            value = value === true || parseInt(value) === 1 || parseInt(value) === 3;
                        } else {
                            value = false;
                        }

						// 赋值为最新值
                        param = value;
                        if (required() !== value) {
                            required(value);
                            this.setValidation('required-entry', required());
                        }
                    },
                    owner: this
                });

                var param2 = this.locationActive;
                this.locationActive = ko.computed({
                    /**
                     * @returns {Boolean}
                     */
                    read: function () {
                        return required();
                    },

                    /**
                     * @param {String|Boolean} value
                     */
                    write: function (value) {
                        if (Boolean(value)) {
                            value = value === true || parseInt(value) === 1;
                        } else {
                            value = false;
                        }
                        // 联动,两个参数都为true时,才为true
                        value = value && param

                        if (required() !== value) {
                            required(value);
                            this.setValidation('required-entry', required());
                        }
                    },
                    owner: this
                });

				// 顺序执行,下两行代码各自为自身computed初始化赋值
                this.locationActive(param2)
                this.orderMode(param);
            },

            /**
             * @param {(String|Object)} rule
             * @param {(Object|Boolean)} [options]
             * @returns {Abstract} Chainable.
             */
            setValidation: function (rule, options) {
                var rules = utils.copy(this.validation),
                    changed;

                if (_.isObject(rule)) {
                    _.extend(this.validation, rule);
                } else {
                    this.validation[rule] = options;
                }

                changed = !utils.compare(rules, this.validation).equal;

                if (changed) {
                    this.required(!!this.validation['required-entry']);
                    this.validate();
                }

                return this;
            }
        }
    );
});

5、select类型字段

        <!-- component: magento select组件 -->
		<column name="is_add_on_item"
                component="Magento_Ui/js/grid/columns/select"
                sortOrder="78">
            <settings>
            	<!-- 声明类型,才可将value转为string(0->'Disabled') -->
                <dataType>select</dataType>
                <!-- 查询条件配置 -->
                <filter>select</filter>
                <!-- 字段不可排序 -->
                <sortable>false</sortable>
                <label translate="true">Is Add On Item</label>
                <options>
                    <option name="0" xsi:type="array">
                        <item name="value" xsi:type="number">1</item>
                        <item name="label" xsi:type="string" translate="true">Enabled</item>
                    </option>
                    <option name="1" xsi:type="array">
                        <item name="value" xsi:type="number">0</item>
                        <item name="label" xsi:type="string" translate="true">Disabled</item>
                    </option>
                </options>
            </settings>
        </column>



6、block 标签,render其中内容

<?xml version="1.0"?>
<!--
/**
 * MB "Vienas bitas" (Magetrend.com)
 *
 * @category MageTrend
 * @package  Magetend/Scheduler
 * @author   Edvinas St. <edwin@magetrend.com>
 * @license  http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link     http://www.magetrend.com/magento-2-scheduler
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="adminhtml.scheduler.schedule.container">
            <block class="Magetrend\Scheduler\Block\Adminhtml\Schedule\Grid" name="adminhtml.scheduler.schedule.grid" as="grid">
                <arguments>
                    <argument name="id" xsi:type="string">scheduleGrid</argument>
                    <argument name="dataSource" xsi:type="object">StanJY\Scheduler\Model\ResourceModel\Schedule\Collection</argument>
                    <argument name="default_sort" xsi:type="string">entity_id</argument>
                    <argument name="default_dir" xsi:type="string">desc</argument>
                    <argument name="use_ajax" xsi:type="string">1</argument>
                    <argument name="grid_url" xsi:type="url" path="*/*/grid">
                        <param name="_current">1</param>
                    </argument>
                </arguments>

                <block class="Magento\Backend\Block\Widget\Grid\ColumnSet" name="adminhtml.scheduler.schedule.grid.columnSet" as="grid.columnSet">
					<arguments>
                        <argument name="rowUrl" xsi:type="array">
                            <item name="path" xsi:type="string">*/*/edit</item>
                            <item name="extraParamsTemplate" xsi:type="array">
                                <item name="id" xsi:type="string">getId</item>
                            </item>
                        </argument>
                    </arguments>
                    <block class="Magento\Backend\Block\Widget\Grid\Column" as="store_id">
                        <arguments>
                            <argument name="header" xsi:type="string" translate="true">Store View</argument>
                            <argument name="index" xsi:type="string">store_id</argument>
                            <argument name="header_css_class" xsi:type="string">col-description</argument>
                            <argument name="column_css_class" xsi:type="string">col-description</argument>
                            <argument name="renderer" xsi:type="string">StanJY\Scheduler\Block\Adminhtml\Schedule\Grid\Column\Renderer\Store</argument>
                        </arguments>
                    </block>
                </block>
            </block>
        </referenceBlock>
    </body>
</page>

app\code\StanJY\Scheduler\Block\Adminhtml\Schedule\Grid\Column\Renderer\Store.php

<?php
/**
 * MB "Vienas bitas" (Magetrend.com)
 *
 * @category MageTrend
 * @package  Magetend/Scheduler
 * @author   Edvinas St. <edwin@magetrend.com>
 * @license  http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link     http://www.magetrend.com/magento-2-scheduler
 */

namespace StanJY\Scheduler\Block\Adminhtml\Schedule\Grid\Column\Renderer;

use Magento\Framework\DataObject;
use Magetrend\Scheduler\Api\Data\ScheduleInterface;

/**
 * Schedule status column rednderer class
 */
class Store extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer
{

    /**
     * @var \StanJY\Scheduler\Model\Config\Source\ScheduleStore
     */
    public $Store;

    public function __construct(
        \Magento\Backend\Block\Context $context,
        \StanJY\Scheduler\Model\Config\Source\ScheduleStore $store,
        array $data = []
    ) {
        $this->store =$store;
        parent::__construct($context, $data);
    }

    public function render(DataObject $row)
    {
        $index = $this->getColumn()->getIndex();
        $value = $row->getData($index);
        $label = $value;

        $config = $this->store->toArray();
        if (isset($config[$value])) {
            $label = $config[$value];
        }

        return '<span>'.$label.'</span>';
    }

}

app\code\StanJY\Scheduler\Model\Config\Source\ScheduleStore.php

<?php
/**
 * MB "Vienas bitas" (Magetrend.com)
 *
 * @category MageTrend
 * @package  Magetend/Scheduler
 * @author   Edvinas St. <edwin@magetrend.com>
 * @license  http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link     http://www.magetrend.com/magento-2-scheduler
 */

namespace StanJY\Scheduler\Model\Config\Source;

use Magetrend\Scheduler\Api\Data\ScheduleInterface;

/**
 * Schedule status source class
 */
class ScheduleStore implements \Magento\Framework\Option\ArrayInterface
{
    /**
     * Options getter
     *
     * @return array
     */
    public function toOptionArray()
    {
        $data = $this->toArray();
        $optionArray = [];
        foreach ($data as $value => $label) {
            $optionArray[] = [
                'value' => $value,
                'label' => $label
            ];
        }

        return $optionArray;
    }

    /**
     * Get options in "key-value" format
     * @return array
     */
    public function toArray()
    {
        $statuses = [];
        foreach ($this->getConfig() as $status) {
            $statuses[$status['value']] = $status['label'];
        }
        return $statuses;
    }

    /**
     * Returns statuses
     * @return array
     */
    public function getConfig()
    {
        $config = [
            [
                'value' => 0,
                'label' => 'All Store View',
            ],[
                'value' => 2,
                'label' => 'English Store View',
            ],[
                'value' => 1,
                'label' => 'Chinese Store View',
            ],
        ];

        return $config;
    }
}

7、admin后台自定义module添加语言分类

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="editor"/>
    <body>
        <referenceContainer name="page.main.actions">
            <block class="Magento\Backend\Block\Store\Switcher" name="mxstarbucks.store.switcher" template="Magento_Backend::store/switcher.phtml"/>
        </referenceContainer>
        <referenceContainer name="content">
            <uiComponent name="stanjy_promotion_plpcategorybanner_form"/>
        </referenceContainer>
    </body>
</page>

重写插件

请添加图片描述
1、模块声明
app/code/重写目录/重写插件/etc/module.xml

File: app/code/StanJY/ChooseStore/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="StanJY_ChooseStore" setup_version="1.0.0">
    </module>
</config>
  • name:module的名称
  • setup_version: module的版本号

2、注册模块
app/code/重写目录/重写插件/registration.php

File: app/code/StanJY/ChooseStore/registration.php

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

执行php bin/magento setup:upgrade命令后,可在app/etc/config.php查看到该激活模块

3、路由声明
app/code/重写目录/重写插件/etc/(adminhtml | frontend)/routes.xml

File: app/code/StanJY/ChooseStore/etc/adminhtml/routes.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="admin">
        <route id="admin_choose_store" frontName="admin_choose_store">
            <module name="StanJY_ChooseStore"/>
        </route>
    </router>
</config>

<router>标签说明:

id = standard 表示前端路由;

<route>标签说明:

id : 对于router的唯一标识名;

frontName : 前端URL的控制名称;

<module>标签说明:

name : 声明module的名称;

before : 表示在定义module之前加载;

after : 表示在定义moduel之后加载;

备注:“before” et “after” 在创建module时不是必须的

4、创建控制器
app/code/重写目录/重写插件/Controller/(Adminhtml | Index)/xxx.php
请添加图片描述

<?php
namespace StanJY\ChooseStore\Controller\Adminhtml\Source;

use Magento\Framework\Controller\ResultInterface;

class Save extends \Magento\InventoryAdminUi\Controller\Adminhtml\Source\Save
{
    const ADMIN_RESOURCE = 'Magento_InventoryApi::source_save';

    public function execute(): ResultInterface
    {
    	// ...
    }
}

再将di.xml的依赖关系改写,调用原有save方法时,将改调新的save方法

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
    <preference for="Magento\InventoryAdminUi\Controller\Adminhtml\Source\Save" type="StanJY\ChooseStore\Controller\Adminhtml\Source\Save" />
</config>

注意: 若改写的class文件在其他文件的__construct()构造方法中,则不能直接改变依赖。需将上一层的class文件的__construct()拓展。

<?php

namespace StanJY\AmastyNotifications\Model;

use Amasty\PushNotifications\Model\Builder\NotificationBuilder;

// 将NotificationProcessor在di.xml改写依赖
class NotificationProcessor extends \Amasty\PushNotifications\Model\Processor\NotificationProcessor
{
    /**
     * @var NotificationBuilder
     */
    private $newNotificationBuilder;

    public function __construct(
        NotificationBuilder $notificationBuilder
    ) {
        parent::__construct(
            $notificationBuilder
        );
        // 重写NotificationBuilder注入,该类不需要再在di.xml改写依赖
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $this->newNotificationBuilder = $objectManager->get('StanJY\AmastyNotifications\Model\NotificationBuilder');
    }

5、创建block
app/code/重写目录/重写插件/Block/(Adminhtml | Frontend)/xxx.php
真正与浏览器页面最相关的还是由对应的Block输出数据。

<?php
namespace StanJY\ProductList\Block;

use Magento\Checkout\Model\Session;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\View\Element\Template;

class IsInCart extends Template
{
    protected Session $_checkoutSession;
    public function __construct(
        Template\Context $context,
        Session $session,
        array $data = []
    )
    {
        $this->_checkoutSession = $session;
        parent::__construct($context, $data);
    }

    public function getCartProductQty($_product): int
    {
        $qty = 0;
        return $qty;
    }
}

第二种:单独引入js

<?php
namespace StanJY\ChooseStore\Block\Adminhtml\Form;

class ApplyChange extends \Magento\Framework\View\Element\Template
{
    protected $_template = 'applyChange.phtml';
}

6、创建Layout布局文件
app/code/重写目录/重写插件/view(adminhtml | frontend)/layout/xxx.xml

布局文件的命名规则为:<Router Name>_<Controller Name>_<Action Name>

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
    	<!-- template: module.xml配置的"name":: templates文件下的"路径"  -->
        <referenceBlock name="category.products.list" template="StanJY_ProductList::product/list.phtml">
            <block class="StanJY\ProductList\Block\IsInCart" name="genki_catalog_isincart" cacheable="false"/>
        </referenceBlock>
    </body>
</page>

第二种:单独引入js

		<container name="page_initialize" sortOrder="50">
            <htmlContent name="html_content">
                <block name="apply_change" class="StanJY\ChooseStore\Block\Adminhtml\Form\ApplyChange"/>
            </htmlContent>
        </container>

7、创建模板文件
app/code/重写目录/重写插件/view(adminhtml | frontend)/templates/xxx/xxx.phtml

<?php
use Magento\Framework\App\Action\Action;
?>
<?php
// genki_catalog_isincart: layout.xml <block>注册的name
$isInCart = $block->getChildBlock('genki_catalog_isincart');

?>

<p>Qty: <?=$isInCart->getCartProductQty()?></p>

第二种:单独引入js

<?php
/**
 * @var $bolck \StanJY\ChooseStore\Block\Adminhtml\Form\ApplyChange
 */

?>


<script>

require(['jquery'], function ($) {
    'use strict'
    $(function () {
        console.log("hello world");
    });
})
</script>

问题及解决

去掉后台不需要的menu item

步骤:
1、先确定目标module所在位置,查看其 /etc/adminhtml/menu.xml 文件,确认id。

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
    <menu>
    	<!-- 确认id -->
        <add id="Magento_LoginAsCustomerLog::login_log"
             title="Login as Customer Log"
             module="Magento_LoginAsCustomerLog"
             parent="Magento_Customer::customer"
             sortOrder="40"
             resource="Magento_LoginAsCustomerLog::login_log"
             action="loginascustomer_log/log/index"
             dependsOnConfig="login_as_customer/general/enabled"/>
    </menu>
</config>

2、在重写目录下新建一个module,并在/etc/adminhtml/创建menu.xml
请添加图片描述

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
    <menu>
        <remove id="Magento_LoginAsCustomerLog::login_log" />
    </menu>
</config>

表格列表中列的顺序不受sortOrder影响

是因为列的顺序被缓存到了ui_bookmark表中,通过namespace 关键字查询。

SELECT * FROM ui_bookmark WHERE namespace LIKE "%customer_listing%"

API声明

路由跳转

// 错误弹框
$this->messageManager->addErrorMessage(__('error message.'));
// 成功弹框
$this->messageManager->addSuccessMessage(__('success message.'));
// 异常弹框
$this->messageManager->addExceptionMessage($e);
// 路由跳转
$resultRedirect = $this->resultRedirectFactory->create();
$resultRedirect->setPath(
            '*/*/edit',	 // 路由地址
            [
                'source_code' => $sourceCode,  // 参数
                '_current' => true,
            ]
        );

filter筛选

1、第一种
app/code/重写目录/重写插件/Ui/DataProvider/Product/ProductDataProvider.php

<?php
namespace StanJY\ProductList\Ui\DataProvider\Product;



class ProductDataProvider extends \Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider {


    /**
     * @throws Exception
     */
    public function getData()
    {
    	// 添加查询字段(eav结构有效)
        $this->addField('is_add_on_item');
        return parent::getData();
    }

    public function addFilter(\Magento\Framework\Api\Filter $filter)
    {
    	// 特殊判断
        if ($filter->getField() == 'category_id') {
            $this->getCollection()->addCategoriesFilter(array('in' => $filter->getValue()));
        } else if (isset($this->addFilterStrategies[$filter->getField()])) {
            $this->addFilterStrategies[$filter->getField()]
                ->addFilter(
                    $this->getCollection(),
                    $filter->getField(),
                    [$filter->getConditionType() => $filter->getValue()]
                );
        } else {
            parent::addFilter($filter);
        }
    }
}

被继承的源文件

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Catalog\Ui\DataProvider\Product;

use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Framework\App\ObjectManager;
use Magento\Store\Model\Store;
use Magento\Ui\DataProvider\Modifier\ModifierInterface;
use Magento\Ui\DataProvider\Modifier\PoolInterface;

/**
 * Class ProductDataProvider
 *
 * @api
 * @since 100.0.2
 */
class ProductDataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{
    /**
     * Product collection
     *
     * @var \Magento\Catalog\Model\ResourceModel\Product\Collection
     */
    protected $collection;

    /**
     * @var \Magento\Ui\DataProvider\AddFieldToCollectionInterface[]
     */
    protected $addFieldStrategies;

    /**
     * @var \Magento\Ui\DataProvider\AddFilterToCollectionInterface[]
     */
    protected $addFilterStrategies;

    /**
     * @var PoolInterface
     */
    private $modifiersPool;

    /**
     * @param string $name
     * @param string $primaryFieldName
     * @param string $requestFieldName
     * @param CollectionFactory $collectionFactory
     * @param \Magento\Ui\DataProvider\AddFieldToCollectionInterface[] $addFieldStrategies
     * @param \Magento\Ui\DataProvider\AddFilterToCollectionInterface[] $addFilterStrategies
     * @param array $meta
     * @param array $data
     * @param PoolInterface|null $modifiersPool
     */
    public function __construct(
        $name,
        $primaryFieldName,
        $requestFieldName,
        CollectionFactory $collectionFactory,
        array $addFieldStrategies = [],
        array $addFilterStrategies = [],
        array $meta = [],
        array $data = [],
        PoolInterface $modifiersPool = null
    ) {
        parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
        $this->collection = $collectionFactory->create();
        $this->addFieldStrategies = $addFieldStrategies;
        $this->addFilterStrategies = $addFilterStrategies;
        $this->modifiersPool = $modifiersPool ?: ObjectManager::getInstance()->get(PoolInterface::class);
        $this->collection->setStoreId(Store::DEFAULT_STORE_ID);
    }

    /**
     * Get data
     *
     * @return array
     */
    public function getData()
    {
        if (!$this->getCollection()->isLoaded()) {
            $this->getCollection()->load();
        }
        $items = $this->getCollection()->toArray();

        $data = [
            'totalRecords' => $this->getCollection()->getSize(),
            'items' => array_values($items),
        ];

        /** @var ModifierInterface $modifier */
        foreach ($this->modifiersPool->getModifiersInstances() as $modifier) {
            $data = $modifier->modifyData($data);
        }
        return $data;
    }

    /**
     * Add field to select
     *
     * @param string|array $field
     * @param string|null $alias
     * @return void
     */
    public function addField($field, $alias = null)
    {
        if (isset($this->addFieldStrategies[$field])) {
            $this->addFieldStrategies[$field]->addField($this->getCollection(), $field, $alias);
        } else {
            parent::addField($field, $alias);
        }
    }

    /**
     * @inheritdoc
     */
    public function addFilter(\Magento\Framework\Api\Filter $filter)
    {
        if (isset($this->addFilterStrategies[$filter->getField()])) {
            $this->addFilterStrategies[$filter->getField()]
                ->addFilter(
                    $this->getCollection(),
                    $filter->getField(),
                    [$filter->getConditionType() => $filter->getValue()]
                );
        } else {
            parent::addFilter($filter);
        }
    }

    /**
     * @inheritdoc
     * @since 103.0.0
     */
    public function getMeta()
    {
        $meta = parent::getMeta();

        /** @var ModifierInterface $modifier */
        foreach ($this->modifiersPool->getModifiersInstances() as $modifier) {
            $meta = $modifier->modifyMeta($meta);
        }

        return $meta;
    }
}

2、第二种

https://amasty.com/knowledge-base/how-to-add-a-custom-filter-to-the-product-grid-in-magento-2.html

Products list 添加categories filter功能

https://meetanshi.com/blog/add-category-column-to-product-grid-in-magento-2/

filter 筛选时,合并筛选条件

app/code/重写目录/重写插件/Ui/DataProvider/xxxDataProvider.php

<?php
namespace StanJY\ChooseStore\Ui\DataProvider;

use Exception;
use Magento\Backend\Model\Session;
use Magento\Framework\Api\FilterBuilder;
use Magento\Framework\Api\Search\ReportingInterface;
use Magento\Framework\Api\Search\SearchCriteriaBuilder;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\App\RequestInterface;
use Magento\InventoryApi\Api\Data\SourceInterface;
use Magento\InventoryApi\Api\SourceRepositoryInterface;
use Magento\Ui\DataProvider\Modifier\PoolInterface;
use Magento\Ui\DataProvider\SearchResultFactory;

class SourceDataProvider extends \Magento\InventoryAdminUi\Ui\DataProvider\SourceDataProvider
{


    protected $searchCriteriaBuilder;

    private $sourceRepository;

    private $searchResultFactory;

	// 新增接收合并条件的condition数组
    private $filterOrs = [];

    /**
     * @param string $name
     * @param string $primaryFieldName
     * @param string $requestFieldName
     * @param ReportingInterface $reporting
     * @param SearchCriteriaBuilder $searchCriteriaBuilder
     * @param RequestInterface $request
     * @param FilterBuilder $filterBuilder
     * @param SourceRepositoryInterface $sourceRepository
     * @param SearchResultFactory $searchResultFactory
     * @param Session $session
     * @param array $meta
     * @param array $data
     * @param PoolInterface|null $pool
     * @SuppressWarnings(PHPMD.ExcessiveParameterList) All parameters are needed for backward compatibility
     */
    public function __construct(
        $name,
        $primaryFieldName,
        $requestFieldName,
        ReportingInterface $reporting,
        SearchCriteriaBuilder $searchCriteriaBuilder,
        RequestInterface $request,
        FilterBuilder $filterBuilder,
        SourceRepositoryInterface $sourceRepository,
        SearchResultFactory $searchResultFactory,
        Session $session,
        array $meta = [],
        array $data = [],
        PoolInterface $pool = null
    ) {
        parent::__construct(
            $name,
            $primaryFieldName,
            $requestFieldName,
            $reporting,
            $searchCriteriaBuilder,
            $request,
            $filterBuilder,
            $sourceRepository,
            $searchResultFactory,
            $session,
            $meta,
            $data,
            $pool
        );
        $this->sourceRepository = $sourceRepository;
        $this->searchResultFactory = $searchResultFactory;
        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
//        $this->searchCriteriaBuilder = ObjectManager::getInstance()->get('StanJY\ChooseStore\Ui\Api\Search\SearchCriteriaBuilder');
    }

    /**
     * @throws Exception
     */
    public function getData()
    {
        return parent::getData();;
    }

    public function addFilter(\Magento\Framework\Api\Filter $filter)
    {
    	// 过滤条件
        if ($filter->getField() == 'name') {
            $nameHKFilter = $this->filterBuilder
                ->setField('name_hk')
                ->setValue('%'.$filter->getValue().'%')
                ->setConditionType('like')
                ->create();
            $filterGroupBuilder = ObjectManager::getInstance()->get('Magento\Framework\Api\Search\FilterGroupBuilder');
            // 合并筛选条件
            $filterOr = $filterGroupBuilder
                ->addFilter($filter)
                ->addFilter($nameHKFilter)
                ->create();
            $this->addFilterOrs($filterOr);
        } else {
            $this->searchCriteriaBuilder->addFilter($filter);
        }
    }

    /**
     * @inheritdoc
     */
    public function getSearchResult()
    {

        $searchCriteria = $this->getSearchCriteria();
        // condition数组存在时,加入到filterGroups中
        if (count($this->filterOrs) != 0) {
            $searchCriteria->setFilterGroups($this->filterOrs);
        }
        $result = $this->sourceRepository->getList($searchCriteria);

        return $this->searchResultFactory->create(
            $result->getItems(),
            $result->getTotalCount(),
            $searchCriteria,
            SourceInterface::SOURCE_CODE
        );
    }

    public function addFilterOrs($filterOrs) {
        $this->filterOrs[] = $filterOrs;
    }
}

联表查询,及filter过滤

app/code/重写目录/重写插件/Model/ResourceModel/Order/Grid/Collection

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace StanJY\SalesOrder\Model\ResourceModel\Order\Grid;

use Magento\Framework\App\ObjectManager;
use Magento\Framework\Data\Collection\Db\FetchStrategyInterface as FetchStrategy;
use Magento\Framework\Data\Collection\EntityFactoryInterface as EntityFactory;
use Magento\Framework\Event\ManagerInterface as EventManager;
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
use Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult;
use Magento\Sales\Model\ResourceModel\Order;
use StanJY\Common\Helper\CommonHelper;
use Psr\Log\LoggerInterface as Logger;

/**
 * Order grid collection
 */
class Collection extends Order\Grid\Collection
{


    /**
     * @inheritdoc
     */
    protected function _initSelect()
    {
        $where='';
        $sourceCode = (new CommonHelper())->getSourceCodeByUserRole();
        if($sourceCode){
            $where = " and order.source_code = '$sourceCode'";
        }
        parent::_initSelect();
        $this->getSelect()
            ->joinLeft(
                ['address' => 'sales_order_address'],
                'main_table.entity_id = address.parent_id',
                ['lastname','firstname','email','region_id','city','street','telephone']
            )
            ->joinLeft(
                ['order' => 'sales_order'],
                'main_table.entity_id = order.entity_id',
                ['status','appointment_time','total_qty_ordered','pick_up_method','point',
                    'edw_sync_status','pos_sync_status','crm_sync_status','node_sync_status']
            )->joinLeft(
                ['source' => 'inventory_source'],
                'order.source_code = source.source_code',
                ['source_code','pickup_store_name' => 'name','pickup_store_phone' => 'phone']
            )
//            ->joinLeft(
//                ['item' => 'sales_order_item'],
//                'main_table.entity_id = item.order_id',
//                ['sku','name','description','price','original_price','qty_ordered']
//            )
            ->joinLeft(
                ['payment' => 'sales_order_payment'],
                'main_table.entity_id = payment.parent_id',
                ['method']
            )->where("address.address_type='billing'".$where); // To ensure all the orders will be shown in the grid
        return $this;
    }

    public function addFieldToFilter($field, $condition = null)
    {
        if ($field === 'title') {
            $field = "main_table.increment_id";
            return parent::addFieldToFilter($field, $condition);
        }
        return parent::addFieldToFilter($field, $condition);
    }


}

Disable inline edit in ui listing

		<column name="email" sortOrder="40">
            <settings>
                <editor>
                    <editorType>false</editorType>
                </editor>
            </settings>
        </column>

ready for override ui-component

new module/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="MxGenki_Backend" setup_version="1.0.0">
        <sequence><!-- 在下面声明后,新module的ui-component的xml文件才会生效 -->
            <module name="Magento_Backend"/>  <!-- 需要override的module -->
        </sequence>
    </module>
</config>

How to add category selector on admin form?

https://magento.stackexchange.com/questions/149148/magento-2-how-to-add-category-selector-on-admin-form#

ui-component.xml add category-selector

<field name="category">
            <argument name="data" xsi:type="array">
                <item name="options" xsi:type="object">Magento\Catalog\Ui\Component\Product\Form\Categories\Options</item>
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string" translate="true">Category</item>
                    <item name="componentType" xsi:type="string">field</item>
                    <item name="formElement" xsi:type="string">select</item>
                    <item name="component" xsi:type="string">Magento_Catalog/js/components/new-category</item>
                    <item name="elementTmpl" xsi:type="string">ui/grid/filters/elements/ui-select</item>
                    <item name="dataScope" xsi:type="string">category</item>
                    <item name="filterOptions" xsi:type="boolean">true</item>
                    <item name="showCheckbox" xsi:type="boolean">false</item>
                    <item name="disableLabel" xsi:type="boolean">true</item>
                    <item name="multiple" xsi:type="boolean">true</item>
                    <item name="levelsVisibility" xsi:type="number">1</item>
                    <item name="sortOrder" xsi:type="number">20</item>
                    <item name="required" xsi:type="boolean">true</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">true</item>
                    </item>
                    <item name="listens" xsi:type="array">
                        <item name="${ $.namespace }.${ $.namespace }:responseData" xsi:type="string">setParsed</item>
                    </item>
                </item>
            </argument>
        </field>

结束

参考文献:https://segmentfault.com/a/1190000006198555#articleHeader11

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐