配置声明模式

配置声明模式

在 Magento 2.3 之前,扩展开发者需要编写代码(PHP 脚本)来改变数据库模式。在 Magento 2.3 之前,存在以下类型的脚本。

  • InstallData 和 InstallSchema 脚本,它们在第一次安装模块时被执行。
  • UpgradeData 和 UpgradeSchema 增量脚本,用于补充现有模块模式。
  • 循环脚本,在你每次安装或升级 Magento 时执行。

每个脚本都会反复增加变化。在安装过程中,升级脚本只应用那些尚未应用的变化。例如,如果你安装了一个版本为 2.1.8 的模块,而最新的版本是 2.1.11,那么当你升级到 2.1.11 时,2.1.9、2.1.10 和 2.1.11 的升级脚本变化将被依次应用。每个升级脚本都负责检查每个变化所需的版本,以便应用。Magento 安装只知道一个模块有一个升级脚本,而不知道它影响了哪些版本。这个程序被称为迁移设置或迁移脚本。

这种方法的主要缺点是,Magento 会盲目地应用变化。例如,在一个版本中可能会引入一个新的数据库列,但在下一个版本中却被删除。声明式设置消除了这种类型的不必要的工作。

声明式设置是基于数据库结构声明的,并被用于 Doctrine 等项目。模式文件声明了数据库结构应该是什么,而 Magento 则确定当前表结构和它应该是什么之间的差异。这些差异可以用原子化的 SQL 操作来表示。

Magento 会优先考虑声明性模式,并在数据和模式补丁之前执行声明性安装模式。

下面的例子是从 Catalog/etc/db_schema.xml 文件中提取的,定义了 catalog_product_entity_datetime 表。

<table name="catalog_product_entity_datetime" resource="default" engine="innodb"
           comment="Catalog Product Datetime Attribute Backend Table">
    <column xsi:type="int" name="value_id" padding="11" unsigned="false" nullable="false" identity="true" comment="Value ID"/>
    <column xsi:type="smallint" name="attribute_id" padding="5" unsigned="true" nullable="false" identity="false" default="0" comment="Attribute ID"/>
    <column xsi:type="smallint" name="store_id" padding="5" unsigned="true" nullable="false" identity="false" default="0" comment="Store ID"/>
    <column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="false" default="0" comment="Entity ID"/>
    <column xsi:type="datetime" name="value" on_update="false" nullable="true" comment="Value"/>
    <constraint xsi:type="primary" referenceId="PRIMARY">
        <column name="value_id"/>
    </constraint>
    <constraint xsi:type="foreign" referenceId="CAT_PRD_ENTT_DTIME_ATTR_ID_EAV_ATTR_ATTR_ID" table="catalog_product_entity_datetime" column="attribute_id" referenceTable="eav_attribute" referenceColumn="attribute_id" onDelete="CASCADE"/>
    <constraint xsi:type="foreign" referenceId="CAT_PRD_ENTT_DTIME_ENTT_ID_CAT_PRD_ENTT_ENTT_ID" table="catalog_product_entity_datetime" column="entity_id" referenceTable="catalog_product_entity" referenceColumn="entity_id" onDelete="CASCADE"/>
    <constraint xsi:type="foreign" referenceId="CATALOG_PRODUCT_ENTITY_DATETIME_STORE_ID_STORE_STORE_ID" table="catalog_product_entity_datetime" column="store_id" referenceTable="store" referenceColumn="store_id" onDelete="CASCADE"/>
    <constraint xsi:type="unique" referenceId="CATALOG_PRODUCT_ENTITY_DATETIME_ENTITY_ID_ATTRIBUTE_ID_STORE_ID">
        <column name="entity_id"/>
        <column name="attribute_id"/>
        <column name="store_id"/>
    </constraint>
    <index referenceId="CATALOG_PRODUCT_ENTITY_DATETIME_ATTRIBUTE_ID" indexType="btree">
        <column name="attribute_id"/>
    </index>
    <index referenceId="CATALOG_PRODUCT_ENTITY_DATETIME_STORE_ID" indexType="btree">
        <column name="store_id"/>
    </index>
</table>

db_schema 结构

The <Module_Vendor>/<Module_Name>/etc/db_schema.xml 文件声明了一个模块的数据库结构。

如果你已经启用了 URN 高亮,你可以在选择一个节点的 xsi:type 之后使用 PhpStorm 的自动完成功能。这也将允许你查看在你的 db_schema.xml 文件的每一行中哪些属性是可用的

Top-level node

Schema 节点定义了 schema.xsd 文件的位置。

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

table node

每个 db_schema.xml 文件应该包含一个或多个表节点。每个表节点代表数据库中的一个表。一个表节点可以包含以下属性。

  • Name - 表名.
  • engine - SQL 引擎,innodb or memory.
  • resource - The database shard on which to install the table。values: default, checkout 或者 sales
  • Comment - 表注释

一个 table node 可以包含三个类型的子节点 subsides:

  • column
  • constraint
  • index

column subnode

column subnode 定义了了表中的一个字段,每个字段有各自的声明, 例如:

ATTRIBUTE DESCRIPTION
xsi:type Specifies the column type. Must be one of the following:
blob (includes blob, mediumblob, longblob)
boolean
date
datetime
decimal
float
int (includes smallint, bigint, tinyint)
real (includes decimal, float, double, real)
smallint
text (includes text, mediumtext, longtext)
timestamp
varbinary
varchar
default Initializes the column with the specified default value. The default value should have the same datatype defined in xsi:type.
disabled Disables or deletes the declared table, column, constraint, or index.
identity Indicates whether a column is auto incremented.
length Specifies the length of a column. Can be used for char, varchar, and varbinary types.
nullable Indicates whether column can be nullable.
onCreate This is a DDL trigger that allows you to move data from an existing column to a newly created column. This trigger works only when a column is created.
padding The size of an integer column.
precision The number of allowed digits in a real data type.
scale The number of digits after the decimal in a real data type.
unsigned For numeric data types, specifies whether the column can contain positive and negative values or only positive values.

关于每个类型的更多信息,可以参阅相应的 XSD 文件中的注释.

  • Composer 或者 Github 安装:

    <Magento_root_directory/lib/internal/Magento/Framework/Setup/Declaration/Schema/etc

    
    <column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="true" comment="Credit ID"/>
    
    

约束子节点 constraint subnode

约束子节点使用包含下名的属性

ATTRIBUTE DESCRIPTION
type One of primary, unique, or foreign
referenceId A custom identifier that is used only for relation mapping in the scope of db_schema.xml files. The real entity in the database has a system-generated name. The most convenient way to set the value of this attribute is to use the value that is written in the module’s db_schema_whitelist.json file when you run the generate-whitelist command.

主约束和唯一约束被称为 "内部 "约束,因为它们只能应用于创建它们的表的范围内。内部约束定义了一个或多个列的子节点。每个子节点都定义了一个受约束的列。

下面的例子显示了一个内部约束的格式。

<constraint xsi:type="primary" referenceId="PRIMARY">
    <column name="entity_id"/>
</constraint>

外来约束类似于 SQL 中的外键。这种类型的约束将两个表相互连接起来。以下属性定义了一个外置约束。

ATTRIBUTE DESCRIPTION
table The name of the current table
column A column in the current table that refers to a specific column in another table
referenceTable The table being referenced
referenceColumn A column in the referenceTable
onDelete Foreign key trigger. The value must be CASCADE, SET NULL, or NO ACTION

为了保持实体标识符为不可变的值,声明式模式不支持约束的 ON UPDATE 动作。

例如:


<constraint xsi:type="foreign" referenceId="COMPANY_CREDIT_COMPANY_ID_DIRECTORY_COUNTRY_COUNTRY_ID" table="company_credit" column="company_id" referenceTable="company" referenceColumn="entity_id" onDelete="CASCADE"/>


更多内容参考:

https://devdocs.magento.com/guides/v2.3/extension-dev-guide/declarative-schema/db-schema.html