bdc/module-declarative

BDCrops 为 Magento 2 扩展提供的声明式模块。

安装: 0

依赖: 0

建议者: 0

安全: 0

星标: 7

关注者: 4

分支: 3

类型:magento2-module

dev-master 2019-11-06 07:54 UTC

This package is auto-updated.

Last update: 2024-09-25 16:13:28 UTC


README

声明式架构:Magento 2.3x 引入了一个新的声明式架构功能,旨在消除过多的工作量,并加快安装和升级过程。

大多数模块开发人员都熟悉为他们的模块创建创建、更新和操作自定义表的 PHP 脚本。这些文件将存放在模块目录中;

  • /app/code/NameSpace/ModuleName/Setup/InstallSchema.php
  • /app/code/NameSpace/ModuleName/Setup/UpgradeSchema.php

从 Magento 2.3.0 开始,您现在可以使用声明式数据库架构 XML 在单个 XML 文件中创建和更新您的数据库表。此文件位于您的模块中;

/app/code/NameSpace/ModuleName/etc/db_schema.xml

一旦开始使用,这个变化将非常实用。PHP 架构脚本可能很长,难以阅读。XML 短小精悍,使得它易于工作。

目标

  • 创建表(etc/db_schema.xml)

  • 架构白名单(etc/db_schema_whitelist.json)

  • 数据补丁/插入数据(安装和升级数据)

  • 如何安装和升级 BDC_Declarative

  • 声明式架构常见问题解答

  • 认证助理/专业开发者问题及解决方案

1. 如何安装和升级声明式架构模块

1.1. 复制粘贴

如果您不希望通过 composer 安装,可以使用这种方式。

  • 在此处下载最新版本:[下载链接](https://github.com/bdcrops/module-declarative/archive/master.zip)

1.2. 通过 composer 安装

composer require bdc/module-declarative

2. 声明式架构模块步骤详解

  • 创建 app/code/BDC/Declarative/registration.php

    源代码
    <?php
    \Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::MODULE,
        'BDC_Declarative',
        __DIR__
    );
    
  • 创建 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="BDC_Declarative" setup_version="1.0.0"/>
     </config>
     ```
    
  • 创建 etc/db_schema.xml

    源代码
     ```
     <?xml version="1.0"?>
     <schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
     <table name="bdc_declarative" resource="default" engine="innodb" comment="bdcrops declarative table">
      <column xsi:type="smallint" name="id" padding="6" unsigned="false" nullable="false" identity="true" comment="ID"/>
      <column xsi:type="varchar" name="name" nullable="false" length="25" comment="Name"/>
      <column xsi:type="varchar" name="email" nullable="false" length="25" comment="Email"/>
      <column xsi:type="varchar" name="note" nullable="false" length="255" comment="Descrition"/>
      <column xsi:type="timestamp" name="created"  comment="Time of event"/>
      <column xsi:type="timestamp" name="date_closed"  comment="Time of event"/>
      <constraint xsi:type="primary" referenceId="PRIMARY">   <column name="id"/> </constraint>
     </table>
     </schema>
     ```
    

    在“BDC/Declarative/etc”文件夹内创建名为“db_schema.xml”的文件,并写入以下代码

    显示图片

    db_schema

  • 创建 Setup/Schema/Sample.php

    源代码
     ```
     <?php
     declare(strict_types=1);
    
     namespace BDC\Declarative\Setup\Patch\Schema;
    
     use Magento\Framework\Setup\Patch\SchemaPatchInterface;
     use Magento\Framework\Setup\ModuleDataSetupInterface;
     /**
     * Patch is mechanism, that allows to do atomic upgrade data changes
     */
     class Sample implements SchemaPatchInterface{
      /**
       * @var ModuleDataSetupInterface $moduleDataSetup
       */
      private $moduleDataSetup;
      /**
       * @param ModuleDataSetupInterface $moduleDataSetup
       */
      public function __construct(ModuleDataSetupInterface $moduleDataSetup) {
          $this->moduleDataSetup = $moduleDataSetup;
      }
      /**
       * Do Upgrade
       *
       * @return void
       */
      public function apply() { }
      /**
       * {@inheritdoc}
       */
      public function getAliases() { return []; }
      /**
       * {@inheritdoc}
       */
      public static function getDependencies() { return [ ]; }
     }
    
     ```
    
  • 创建 Setup/Patch/Data/NonRevertable.php

    源代码
       ```
       <?php
       declare(strict_types=1);
       namespace BDC\Declarative\Setup\Patch\Data;
    
       use Magento\Framework\Setup\Patch\DataPatchInterface;
       use Magento\Framework\Setup\ModuleDataSetupInterface;
       /**
       * Class NonRevertable
       * @package BDC\Declarative\Setup\Patch\Data
       */
       class NonRevertable implements DataPatchInterface{
       /**
       * @var ModuleDataSetupInterface $moduleDataSetup
       */
       private $moduleDataSetup;
       /**
       * @param ModuleDataSetupInterface $moduleDataSetup
       */
       public function __construct(ModuleDataSetupInterface $moduleDataSetup){
          $this->moduleDataSetup = $moduleDataSetup;
       }
       /**
       * Do Upgrade
       * @return void
       */
       public function apply(){
          $data = ['name' => 'Matin Rahman', 'email' => 'matinict@gmail.com','note' => 'Declarative insert'];
          $this->moduleDataSetup->getConnection()->insert('bdc_declarative', $data);
       }
       /**
       * {@inheritdoc}
       */
       public function getAliases(){ return []; }
       /**
       * {@inheritdoc}
       */
       public static function getDependencies(){ return []; }
       }
    
       ```
    
  • 创建 Setup/Patch/Data/Revertable.php

    源代码
      ```
      <?php
      declare(strict_types=1);
    
      namespace BDC\Declarative\Setup\Patch\Data;
    
      use Magento\Framework\Setup\Patch\DataPatchInterface;
      use Magento\Framework\Setup\ModuleDataSetupInterface;
      /**
       * Class Revertable
       * @package BDC\Declarative\Setup\Patch\Data
       */
      class Revertable implements DataPatchInterface {
          /**
           * @var ModuleDataSetupInterface $moduleDataSetup
           */
          private $moduleDataSetup;
    
          /**
           * @param ModuleDataSetupInterface $moduleDataSetup
           */
          public function __construct(ModuleDataSetupInterface $moduleDataSetup){
              $this->moduleDataSetup = $moduleDataSetup;
          }
    
          /**
           * Do Upgrade
           *
           * @return void
           */
          public function apply() { }
    
          /**
           * {@inheritdoc}
           */
          public function getAliases() { return []; }
          /**
           * {@inheritdoc}
           */
          public static function getDependencies() { return [ ]; }
      }
    
      ```
    
  • 运行架构白名单:在运行声明模式之前,您必须创建架构白名单。注意:建议为每个版本生成一个新的白名单进行双重检查。在运行升级命令之前,您需要通过运行以下命令将您的架构添加到 db_whitelist_schema.json 文件中。为此,您需要一个 //etc/db_schema_whitelist.json 文件,它将存储使用声明式架构添加的所有内容。要生成此文件,请运行

    显示图片

    db_schema

    php bin/magento setup:db-declaration:generate-whitelist [options]
    php bin/magento setup:db-declaration:generate-whitelist --module-name=vendor_module
    php bin/magento setup:db-declaration:generate-whitelist --module-name=BDC_Declarative
    php bin/magento setup:upgrade --dry-run=1 --keep-generated
    

    现在,将在 /vendor/module/etc 文件夹中创建 db_whitelist_schema.json 文件。插入 NonRevertable.php 和 Revertable.php 数据

    显示图片

    Insertdata

    Run php bin/magento setup:upgrade
    
    显示图片

    InsertData

3. 声明式架构常见问题解答

什么是声明式架构?

declarative-schema

为什么需要声明式架构?

Issues with Setup Scripts

声明式架构会帮到吗?

Declarative Schema Offers

如何声明/创建一个表?

声明一个表 以下示例创建了一个具有四个列的声明式_table 表。id_column 列是主键。

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
+    <table name="declarative_table">
+        <column xsi:type="int" name="id_column" padding="10" unsigned="true" nullable="false" comment="Entity Id"/>
+        <column xsi:type="int" name="severity" padding="10" unsigned="true" nullable="false" comment="Severity code"/>
+        <column xsi:type="varchar" name="title" nullable="false" length="255" comment="Title"/>
+        <column xsi:type="timestamp" name="time_occurred" padding="10" comment="Time of event"/>
+        <constraint xsi:type="primary" referenceId="PRIMARY">
+            <column name="id_column"/>
+        </constraint>
+    </table>
</schema>

在创建新表时,请记住生成 db_schema_whitelist.json 文件。

什么是属性?

属性

Attributes

属性(继续)

Attributes (Contd)

什么是整数列?

如何声明整数列?

如何声明文本列?

文本属性是什么?

如何声明二进制列?

二进制或文本属性是什么?

声明十进制列?

十进制或文本属性?

声明时间列?

时间或文本属性?

声明主键?

声明外键?

声明唯一键?

声明索引?

属性?

如何生成db_schema_whitelist.json?

<module_root>/etc/db_schema_whitelist.json?

使用dry-run测试?

var/log/dry-run-installation.log?

应用数据库模式?

修改表列?

使用安全模式破坏性操作测试?

var/declarative_dumps_csv/{column_name_column_type_other_dimensions}.csv var/declarative_dumps_csv/{table_name}.csv?

恢复模式数据?

卸载模块?

将设置脚本转换为声明性模式?

声明性模式的限制?

什么是模式补丁?

在哪里定义模式补丁?

我们将实现哪些方法?

如何应用模式补丁?

应用模式补丁后幕后发生了什么?

什么是数据补丁?

在哪里定义数据补丁文件?

什么是版本补丁?

版本补丁 • 用于与较旧的设置脚本的向后兼容性 • 可以定义版本号 • Magento检查设置模块版本 • 如果模块版本高于补丁中指定的版本,则跳过补丁 • 如果数据库中的版本等于或低于,则安装补丁。 • 已标记为已弃用

如何将模式/补丁转换为版本补丁?

什么是可逆补丁?

可逆补丁 • 补丁可以在移除模块时回滚 • 单个补丁不能回滚 • 需要触发模块卸载 • 该功能仍然有bug,并且正在发生更改

如何将模式/补丁转换为可逆补丁?

如何卸载模块?

新的CLI命令生成补丁?

php bin/magento help setup:db-declaration:generate-patch
php bin/magento setup:db-declaration:generate-patch Bdcrops_TicketingSystem Example --type=data
php bin/magento setup:db-declaration:generate-patch Bdcrops_TicketingSystem Example --type=schema

如何删除表?

删除declarative_table表已完全从db-schema.xml文件中删除。

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
        //Remove All Content, Table will be Drop after whitelist & Upgrade run
</schema>

什么是顶级节点?

顶级节点表示模式节点,位于schema.xsd文件中。

schema.xsd文件的位置是:<magento_root_directory>/vendor/magento/framework/Setup/Declaration/Schema/etc/schema.xsd

什么是表节点?

我们可以在同一个db_schema.xml文件中创建多个表,每个表节点在数据库中创建一个新表。表节点可以包含以下属性

  • 名称:表的名称
  • 引擎:SQL引擎,此值必须是InnoDB或memory。
  • 资源:安装表的数据库分片。此值必须是default、checkout或sales。
  • 注释:表注释。表节点包含三种不同类型的子节点
  • 约束
  • 索引

什么是列节点?

列节点定义在表节点内部,每个列节点都有自己的声明。列节点可以包含以下属性

  • 类型:列类型应包含blob(包括blob、mediumblob、longblob)、布尔值、日期、datetime、int(包括smallint、bigint、tinyint)、real(包括decimal、float、double、real)、text(包括text、mediumtext、longtext)、timestamp、varbinary和varchar。
  • 名称:列的名称
  • 填充:表示整数列的大小
  • 无符号:表示列是否包含正负值或仅包含正值
  • 可空:表示列是否可以为空
  • 注释:表示列的注释
  • 长度:表示列的长度

如何重命名表?

<table name="declarative_table">
 Changed as below
<table name="new_declarative_table" onCreate="migrateDataFromAnotherTable(declarative_table)">

如何向表中添加列?

以下示例添加了 date_closed 列。

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="declarative_table">
        <column .../> ...

+       <column xsi:type="timestamp" name="date_closed" padding="10" comment="Time of event"/>

        <constraint ..>...</constraint>
    </table>
</schema>

当向表中添加新列时,请记住生成 db_schema_whitelist.json 文件。

如何从表中删除列?

以下示例通过删除其列节点来删除 date_closed 列。要删除在另一个模块中声明的列,请使用 disabled 属性设置为 true 的方式重新声明它。

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="declarative_table">
        <column xsi:type="int" name="id_column" padding="10" unsigned="true" nullable="false" comment="Entity Id"/>
        <column xsi:type="int" name="severity" padding="10" unsigned="true" nullable="false" comment="Severity code"/>
        <column xsi:type="varchar" name="title" nullable="false" length="255" comment="Title"/>
        <column xsi:type="timestamp" name="time_occurred" padding="10" comment="Time of event"/>
-       <column xsi:type="timestamp" name="date_closed" padding="10" comment="Time of event"/>
        <constraint xsi:type="primary" referenceId="PRIMARY">
            <column name="id_column"/>
        </constraint>
    </table>
</schema>

只有在 db_schema_whitelist.json 文件中存在该列时,才能删除列。

如何更改列类型?

以下示例将 title 列的类型从 varchar 更改为 tinytext。

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="declarative_table">
        <column .../>
        <column .../>
-       <column xsi:type="varchar" name="title" nullable="false" length="255" comment="Title"/>
+       <column xsi:type="tinytext" name="title" nullable="false" length="255" comment="Title"/>
        <column xsi:type="timestamp" name="time_occurred" padding="10" comment="Time of event"/>
        <constraint ...>....</constraint>
    </table>
</schema>

如何重命名列?

要重命名列,请删除原始列声明并创建一个新的声明。在新列声明中,使用 onCreate 属性指定从哪个列迁移数据。使用以下构造来迁移同一表中的数据。

onCreate="migrateDataFrom(entity_id)"

当重命名列时,请记住重新生成 db_schema_whitelist.json 文件,使其包含新名称以及旧名称。

如何添加索引?

以下示例将 INDEX_SEVERITY 索引添加到 declarative_table 表。

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="declarative_table">
        <column .... />
        <constraint ...> <column name="id_column"/> </constraint>

+       <index referenceId="INDEX_SEVERITY" indexType="btree">
+           <column name="severity"/>
+       </index>
    </table>
</schema>

如何创建外键?

在以下示例中,所选约束节点定义了 FL_ALLOWED_SEVERITIES 外键的特性。

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="declarative_table">
        <column ../> ...
        <constraint...> ...    </constraint>

+     <constraint xsi:type="foreign" referenceId="FL_ALLOWED_SEVERITIES" table="declarative_table"
+       column="severity" referenceTable="severities" referenceColumn="severity_identifier"
+       onDelete="CASCADE"/>

    </table>
</schema>

如何删除外键?

以下示例通过删除其约束节点来删除 FL_ALLOWED_SEVERITIES 外键。要删除在另一个模块中声明的约束,请使用 disabled 属性设置为 true 的方式重新声明它。

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="declarative_table">
      ......
-  <constraint xsi:type="foreign" referenceId="FL_ALLOWED_SEVERITIES" table="declarative_table"
-  column="severity" referenceTable="severities" referenceColumn="severity_identifier"
-   onDelete="CASCADE"/>

    </table>
</schema>

如何重新创建外键?

在此示例中,模块 A 定义了一个包含主键 id_column 的新表。模块 B 声明了自己的模式,在其中创建了一个新列(new_id_column)并更改了主索引到该列。模块 B 禁用了原始主键并设置了一个具有不同 referenceId 值的新主键(不同于 PRIMARY)。虽然这个值不同,但数据库中主键的真实名称仍然是 PRIMARY。

模块 A 声明

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="declarative_table">
        <column xsi:type="int" name="id_column" padding="10" unsigned="true" nullable="false" comment="Entity Id"/>
        <constraint xsi:type="primary" referenceId="PRIMARY">
            <column name="id_column"/>
        </constraint>
    </table>
</schema>

模块 B 声明

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="declarative_table">
        <column xsi:type="int" name="new_id_column" padding="10" unsigned="true" nullable="false"
                comment="New Entity Id"/>
        <constraint xsi:type="primary" referenceId="PRIMARY" disabled="true"/>
        <constraint xsi:type="primary" referenceId="NEW_PRIMARY">
            <column name="new_id_column"/>
        </constraint>
    </table>
</schema>

什么是数据补丁?

包含数据修改指令的类。它可以依赖于其他数据或模式补丁。

什么是可逆数据补丁?

可以回滚为模块或路径卸载或删除的补丁。可逆操作是数据查询语言(DQL)和数据操作语言(DML)操作:INSERT、UPDATE。

什么是迁移?

一种不可逆的数据补丁,可以应用但不能回滚。任何复杂操作,例如包含应用层(例如,Collections 或 Serializers)的操作都是不可逆的。SQL 删除操作是不可逆的,因为它们可以触发。

什么是模式补丁和允许操作?

包含自定义模式修改指令的类。模式补丁与声明性模式一起使用,但这些补丁允许复杂的操作,例如

  • 添加触发器、存储过程、函数

  • 执行包含 DDL 操作的数据迁移

  • 重命名表、列和其他实体

  • 向表中添加分区和选项

Magento 2 认证开发人员考试

(4.4 展示使用声明性模式的能力)

您如何使用声明性模式添加列?

以下示例添加了 date_closed 列。

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="declarative_table">
        <column .../> ...

+       <column xsi:type="timestamp" name="date_closed" padding="10" comment="Time of event"/>

        <constraint ..>...</constraint>
    </table>
</schema>

当向表中添加新列时,请记住生成 db_schema_whitelist.json 文件。

您如何修改由另一个模块添加的表?

假设我们想在 core 表 customer_entity 等/db_schema.xml 中添加新列 name="referred_by"。

--<?xml version="1.0"?>
--<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
--This below content oly if exist declaration
    <table name="customer_entity">
    <column xsi:type="int" name="referred_by" padding="10" unsigned="true" nullable="false"
    comment="Referred By"/>

    </table>

--</schema>

然后运行以下命令生成 db_schema_whitelist.json

php bin/magento setup:db-declaration:generate-whitelist --module-name=BDC_Declarative
php bin/magento setup:upgrade --dry-run=1 --keep-generated
php bin/magento setup:upgrade

您可以根据需要修改代码。

您如何删除列?

以下示例通过删除其列节点来删除 date_closed 列。要删除在另一个模块中声明的列,请使用 disabled 属性设置为 true 的方式重新声明它。

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="declarative_table">
        <column xsi:type="int" name="id_column" padding="10" unsigned="true" nullable="false" comment="Entity Id"/>
        <column xsi:type="int" name="severity" padding="10" unsigned="true" nullable="false" comment="Severity code"/>
        <column xsi:type="varchar" name="title" nullable="false" length="255" comment="Title"/>
        <column xsi:type="timestamp" name="time_occurred" padding="10" comment="Time of event"/>
-       <column xsi:type="timestamp" name="date_closed" padding="10" comment="Time of event"/>
        <constraint xsi:type="primary" referenceId="PRIMARY">
            <column name="id_column"/>
        </constraint>
    </table>
</schema>

只有在 db_schema_whitelist.json 文件中存在该列时,才能删除列。

“声明性模式”与“扩展属性”的区别?

“声明式模式”用于在Magento中创建新的表。使用声明式模式,您享有变体的优势。“扩展属性”用于在现有的表中添加新字段。这样,您就不会扩展原始模型。因此,在上面的例子中,最佳的方法是使用扩展属性。magento-2-what-are-extension-attributes

如何添加索引?

添加索引:以下示例向声明式_table表添加INDEX_SEVERITY索引。

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="declarative_table">
        <column xsi:type="int" name="id_column" padding="10" unsigned="true" nullable="false" comment="Entity Id"/>
        <column xsi:type="int" name="severity" padding="10" unsigned="true" nullable="false" comment="Severity code"/>
        <column xsi:type="tinytext" name="title" nullable="false" length="255" comment="Title"/>
        <column xsi:type="timestamp" name="time_occurred" padding="10" comment="Time of event"/>
        <constraint xsi:type="primary" referenceId="PRIMARY">
            <column name="id_column"/>
        </constraint>
+       <index referenceId="INDEX_SEVERITY" indexType="btree">
+           <column name="severity"/>
+       </index>
    </table>
</schema>

如何使用声明式模式添加外键?

  • 创建外键以下示例中,选定的约束节点定义了FL_ALLOWED_SEVERITIES外键的特征。
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="declarative_table">
        <column xsi:type="int" name="id_column" padding="10" unsigned="true" nullable="false" comment="Entity Id"/>
        <column xsi:type="int" name="severity" padding="10" unsigned="true" nullable="false" comment="Severity code"/>
        <column xsi:type="varchar" name="title" nullable="false" length="255" comment="Title"/>
        <column xsi:type="timestamp" name="time_occurred" padding="10" comment="Time of event"/>
        <constraint xsi:type="primary" referenceId="PRIMARY">
            <column name="id_column"/>
        </constraint>
+       <constraint xsi:type="foreign" referenceId="FL_ALLOWED_SEVERITIES" table="declarative_table"
+               column="severity" referenceTable="severities" referenceColumn="severity_identifier"
+               onDelete="CASCADE"/>
    </table>
</schema>
  • 删除外键以下示例通过删除其约束节点来删除FL_ALLOWED_SEVERITIES外键。要删除另一个模块中声明的约束,将其重新声明并设置为禁用属性为true。
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="declarative_table">
        <column xsi:type="int" name="id_column" padding="10" unsigned="true" nullable="false" comment="Entity Id"/>
        <column xsi:type="int" name="severity" padding="10" unsigned="true" nullable="false" comment="Severity code"/>
        <column xsi:type="varchar" name="title" nullable="false" length="255" comment="Title"/>
        <column xsi:type="timestamp" name="time_occurred" padding="10" comment="Time of event"/>
        <constraint xsi:type="primary" referenceId="PRIMARY">
            <column name="id_column"/>
        </constraint>
-       <constraint xsi:type="foreign" referenceId="FL_ALLOWED_SEVERITIES" table="declarative_table"
-               column="severity" referenceTable="severities" referenceColumn="severity_identifier"
-               onDelete="CASCADE"/>
    </table>
</schema>

只有当外键存在于db_schema_whitelist.json文件中时,才能删除外键。

  • 重新创建外键在此示例中,模块A定义了一个新的表,其中包含主键id_column。模块B声明其自己的模式,在其中创建了一个新列(new_id_column)并更改了主索引到该列。模块B禁用了原始主键,并设置了一个新的具有不同referenceId值的主键(不同于PRIMARY)。尽管这个值不同,但在数据库中主键的真实名称仍然是PRIMARY。

模块 A 声明

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="declarative_table">
        <column xsi:type="int" name="id_column" padding="10" unsigned="true" nullable="false" comment="Entity Id"/>
        <constraint xsi:type="primary" referenceId="PRIMARY">
            <column name="id_column"/>
        </constraint>
    </table>
</schema>

模块 B 声明

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="declarative_table">
        <column xsi:type="int" name="new_id_column" padding="10" unsigned="true" nullable="false"
                comment="New Entity Id"/>
        <constraint xsi:type="primary" referenceId="PRIMARY" disabled="true"/>
        <constraint xsi:type="primary" referenceId="NEW_PRIMARY">
            <column name="new_id_column"/>
        </constraint>
    </table>
</schema>

如何使用数据补丁操作数据?

数据补丁是一个包含数据修改指令的类。它定义在/<Module_Name>/Setup/Patch/Data/<Patch_Name>.php文件中,并实现了\Magento\Framework\Setup\Patch\DataPatchInterface。

模式补丁的目的是什么?

模式补丁包含自定义模式修改指令。这些修改可能很复杂。它定义在/<Module_Name>/Setup/Patch/Schema/<Patch_Name>.php文件中,并实现了\Magento\Framework\Setup\Patch\SchemaPatchInterface。

与声明式模式方法不同,补丁将只应用一次。已应用补丁的列表存储在patch_list数据库表中。未应用的补丁将在运行从Magento CLI的setup:upgrade时应用。

Magento 2认证专业开发者考试

4.4 展示使用声明式模式的能力

  • 您如何使用声明性模式添加列?
  • 如何修改另一个模块添加的表?||
  • 如何删除列?||
  • 如何使用声明式模式添加索引或外键?||
  • 如何使用数据补丁操作数据?
  • 模式补丁的目的是什么?

如何使用声明式模式操作列和键?

  • 向表中添加列以下示例添加了date_closed列。

  • 从表中删除列以下示例通过删除其列节点来删除date_closed列。要删除另一个模块中声明的列,将其重新声明并设置为禁用属性为true。

  • 更改列类型以下示例将标题列的类型从varchar更改为tinytext。

  • 重命名列要重命名列,请删除原始列声明并创建一个新的。在新声明中,使用onCreate属性指定从哪个列迁移数据。使用以下结构从同一表迁移数据。onCreate="migrateDataFrom(entity_id)"

要从另一个表迁移数据,指定类似以下值:onCreate="migrateDataFromAnotherTable(catalog_category_entity,entity_id)"

  • 添加索引以下示例将INDEX_SEVERITY索引添加到table_name表中。

  • 创建外键以下示例中,选定的约束节点定义了FL_ALLOWED_SEVERITIES外键的特征。

  • 删除外键以下示例通过删除其约束节点来删除FL_ALLOWED_SEVERITIES外键。要删除在其他模块中声明的约束,必须将其重新声明为禁用属性设置为true。

白名单的目的是什么?

白名单的用途:在没有创建模式白名单的情况下,您无法运行声明模式。由于必须保持向后兼容性,声明模式不会自动删除db_schema.xml中未定义的数据库表、列或键。这是我们拥有db_schema_whitelist.json的原因之一。它显示了使用声明模式添加的所有表、列和键的历史记录,并且在删除操作中是必需的。

注意:建议为每个版本生成一个新的白名单以进行双重检查。在运行升级命令之前,您需要通过运行以下命令将您的模式添加到db_whitelist_schema.json文件中。为此,您需要一个//etc/db_schema_whitelist.json文件,该文件将存储使用声明模式添加的所有内容。要生成此文件,请运行

db_schema

php bin/magento setup:db-declaration:generate-whitelist [options]
php bin/magento setup:db-declaration:generate-whitelist --module-name=vendor_module
php bin/magento setup:db-declaration:generate-whitelist --module-name=BDC_Declarative
php bin/magento setup:upgrade --dry-run=1 --keep-generated

现在,将在/vendor/module/etc文件夹中创建db_whitelist_schema.json文件。

您可以在该命令的末尾添加一些选项。例如,您可以使用“–module-name=YourModule”来指定您想要为其生成白名单的模块。类似地,您也可以设置“–module-name=all”,尽管默认情况下它将生成所有模块的白名单。

如何使用数据和模式补丁?

  • 数据补丁:

  • 模式补丁:

如何管理补丁文件之间的依赖关系?

模式补丁包含自定义模式修改指令。这些修改可能很复杂。它在/<Module_Name>/Setup/Patch/Schema/<Patch_Name>.php文件中定义,并实现了\Magento\Framework\Setup\Patch\SchemaPatchInterface。

与声明式模式方法不同,补丁将只应用一次。已应用补丁的列表存储在patch_list数据库表中。未应用的补丁将在运行从Magento CLI的setup:upgrade时应用。

可选地,如果您计划在模块卸载期间启用补丁的回滚,则必须实现\Magento\Framework\Setup\Patch\PatchRevertableInterface。

旧脚本与新版本的Magento兼容。但是,如果您想将旧脚本转换为新的格式,请实现\ Magento\Framework\Setup\Patch\PatchVersionInterface接口。此接口允许您在数据库中指定模块的设置版本。如果模块的版本高于或等于您补丁中指定的版本,则跳过补丁。如果数据库中的版本较低,则安装补丁

如何通过声明性模式创建EAV属性?

在Magento 2.3及以上版本中,您可以通过DataPatch创建属性。例如,创建一个文件:Vendor_Module\Setup\Patch\Data\ApplyNewAttribute.php

<?php
namespace Vendor\Module\Setup\Patch\Data;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Framework\Setup\Patch\PatchVersionInterface;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
/**
 * Class ApplyNewAttribute
 * @package Vendor\Module\Setup\Patch\Data
 */
class ApplyNewAttribute implements DataPatchInterface, PatchVersionInterface
{
    /**
     * @var ModuleDataSetupInterface
     */
    private $moduleDataSetup;
    /**
     * @var EavSetupFactory
     */
    private $eavSetupFactory;
    /**
     * ApplyNewAttribute constructor.
     *
     * @param ModuleDataSetupInterface $moduleDataSetup
     * @param EavSetupFactory $eavSetupFactory
     */
    public function __construct(
        ModuleDataSetupInterface $moduleDataSetup,
        EavSetupFactory $eavSetupFactory
    ) {
        $this->moduleDataSetup = $moduleDataSetup;
        $this->eavSetupFactory = $eavSetupFactory;
    }
    /**
     * {@inheritdoc}
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     */
    public function apply()
    {
        /** @var EavSetup $eavSetup */
        $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]);
        $eavSetup->addAttribute(
            \Magento\Catalog\Model\Product::ENTITY,
            /** Add your attribute here.……….*/
       );
        $setup->endSetup();
    }
}

bsscommerce

参考