Declarative Schema Trong Magento2 (Phần 2)

Table of Contents

  1. Lời mở đầu
  2. Cách thao tác với CSDL hay gặp
  3. Tổng Kết

1.Lời mở đầu

Declarative Schema

  • Trước phiên bản Magento 2.3, viết các install/upgrade script là cách duy nhất để chúng ta làm việc với database (Tham khảo Tạo Và Chỉnh Sửa Bảng với Setup/Upgrade Script Trong Magento2). Tuy nhiên, với phiên bản 2.3 được phát hành năm 2018, một trong những thay đổi lớn được giới thiệu đó là Declarative Schema, một cách mới mà chúng ta có thể làm việc với database mà không cần phải viết nhiều script nữa.

  • Nối tiếp Phần 1 Declarative Schema Trong Magento2 (Phần 1) viết về Declarative Schema, bài viết này sẽ đi vào cụ thể các use-case hay gặp. Bắt đầu thôi nào.

2. Cách thao tác với CSDL hay gặp

  • Mục này mình trình bày các thao tác chúng ta hay gặp với CSDL, mình sử dụng git diff để minh hoa.

2.1 Tạo một bảng

  • Ví dụ sau đây tạo một bảng declarative_table với 4 cột, trong đó id_column là khóa chính.
1
2
3
4
5
6
7
8
9
10
11
12
<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>
  • Lưu ý Khi tạo bảng mới cần phải chạy command generate file db_schema_whitelist.json

2.2 Xóa một bảng

  • Thực hiện như sau, bảng declarative_table sẽ được xóa hoàn toàn.
1
2
3
4
5
6
7
8
9
10
11
12
<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>
  • Lưu ý: Khi xóa một bảng, không được xóa bảng đó trong file db_schema_whitelist.json, nếu không thì bảng sẽ không được xóa.

2.3 Đổi tên bảng.

  • Declarative Schema sẽ tạo một bảng mới với tên mới và xóa bảng bảng tên cũ (chữ không thực hiện đổi tên bảng).
  • Do đó chúng ta phải thực hiện migrate dữ liệu từ bảng cũ sang bảng mới, dùng trigger onCreate="migrateDataFromAnotherTable(declarative_table)"
1
2
3
4
5
6
7
8
9
10
11
12
13
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
+ <table name="new_declarative_table" onCreate="migrateDataFromAnotherTable(declarative_table)">
- <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>
  • Lưu ý Khi đổi tên bảng cần phải chạy lại command generate file db_schema_whitelist.json

2.4 Thêm cột.

  • Ví dụ sau thêm cột date_closed
1
2
3
4
5
6
7
8
9
10
11
12
13
<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>
  • Lưu ý Khi thêm cột mới cần phải chạy lại command generate file db_schema_whitelist.json

2.5 Xóa cột.

  • Để xóa một cột chỉ cần xóa thẻ <column> của cột đó. Nếu muốn xóa một cột mà được định nghĩa ở module khác, thì chúng ta phải khai báo lại nó với thuộc tính disabled bằng true
1
2
3
4
5
6
7
8
9
10
11
12
13
<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>
  • Lưu ý Chỉ có thể xóa một cột khi cột đó được định nghĩa trong file db_schema_whitelist.json

2.6 Thay đổi kiểu dữ liệu của cột.

  • Ví dụ sau thay đổi kiểu dữ liệu của cột title từ varchar sang text
1
2
3
4
5
6
7
8
9
10
11
12
13
<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="text" name="title" nullable="false" 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>

2.7 Đổi tên cột.

  • Cũng giống như khi đổi tên bảng, muốn đổi tên cột chúng ta cũng phải xóa cột cũ đi và định nghĩa lại cột mới, đồng thời sử dụng attribute onCreate để migrate dữ liệu từ cột cũ sang cột mới.

    onCreate="migrateDataFrom(entity_id)"

  • Lưu ý Khi đổi tên cột, cần phải chạy lại command generate file db_schema_whitelist.json

2.8 Thêm một chỉ mục cho bảng.

  • Ví dụ dưới đây thêm một chỉ mục có tên INDEX_SEVERITY cho bảng declarative_table
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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="text" 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>

2.9 Tạo một khóa ngoại cho bảng.

  • Ví dụ sau tạo một khóa ngoại có tên là FL_ALLOWED_SEVERITIES định nghĩa rằng cột severity là khóa ngoại của bảng declarative_table tham chiếu đến cột severity_identifier của bảng severity_identifier
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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>

2.10 Xoá một khóa ngoại của bảng.

  • Ví dụ dưới đây sẽ xóa khóa ngoại FL_ALLOWED_SEVERITIES bằng việc xóa đi thẻ constraint. Để có thể xóa một khóa ngoại được định nghĩa ở module khác, ta định nghĩa lại khóa ngoại này với attribute disabled="true"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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>
  • Lưu ý Chỉ có thể xóa một khóa ngoại nếu nó tồn tại trong file db_schema_whitelist.json

2.11 Tạo khóa chính khác cho bảng.

  • Xem xét trường hợp sau: Giả sử module A định nghĩa một bảng với khóa chính là id_column. Module B khái báo file db_schema.xml của riêng nó, định nghĩa một cột mới là new_id_column và muốn đổi khóa chính của bảng từ id_column sang new_id_column

  • Với trường hợp trên, module B sẽ phải disable khóa chính ban đầu và tạo một khóa chính mới với một referenceId mặc dù không phải là PRIMARY, tuy nhiên giá trị referenceId chỉ là tên của ràng buộc ở trong file db_schema.xml, còn tên thực sự của khóa chính này ở trong Database vẫn là PRIMARY

  • File db_schema.xml của module A

1
2
3
4
5
6
7
8
9
<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>
  • File db_schema.xml của module B
1
2
3
4
5
6
7
8
9
10
11
<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>

3. Tổng Kết

  • Bài viết này mình đã trình bày các trường hợp hay gặp với Declarative Schema, mong sẽ bao phủ đa số các trường hợp các bạn cần.

  • Tham khảo thêm Phần 1 về Declarative SChema Declarative Schema Trong Magento2 (Phần 1)
    Hẹn gặp lại các bạn trong các bài viết tiếp theo. Ciao!

    Thankyou