Table of Contents
- Lời mở đầu
- Tại sao lại sử dụng Declarative Schema
- Cấu trúc db_schema
- Whitelist
- Chế độ DRY RUN
- Tổng Kết Phần 1
1.Lời mở đầu
- Trong bài viết trước Tạo Và Chỉnh Sửa Bảng với Setup/Upgrade Script Trong Magento2, chúng ta đã tìm hiểu cách để tạo bảng, cập nhật bảng với các PHP script, như:
- InstallData và InstallSchema: được chạy vào lần đầu tiên mà module được cài đặt.
- UpgradeData và UpgradeSchema: được chạy vào mỗi lần upgrade module, dựa vào version của module, để cập nhật bảng và dữ liệu cho bảng.
- Trước phiên bản Magento 2.3, đây là cách duy nhất để chúng ta làm việc với database. 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.
2.Tại sao lại sử dụng Declarative Schema
- Lợi ích của việc sử dụng Declarative Schema là gì? Trước tiên việc chúng ta phải viết những PHP database script như trước đây không phải là một giải pháp hoàn hảo.
- Bởi vì, những script sẽ apply những thay đổi dựa vào version của module, khi bạn upgrade một module lên vài version so với hiện tại, vì tất cả các script giữa 2 version này sẽ đều được thực thi. Ví dụ bạn có một module với version
1.0.0
và phiên bản mới nhất của module là1.0.4
. Khi bạn upgrade module, những script cho version1.0.1
,1.0.2
,1.0.3
cũng sẽ được apply! - Nhược điểm của cách này là Magento sẽ thực apply những thay đổi một cách mù quáng, chẳng hạn như trong một version, bạn tạo mới một cột trong bảng CSDL, đến version tiếp theo bạn lại xóa nó đi. Declarative Schema sẽ giúp loại bỏ những bước thừa, không cần thiết này.
- Declarative Schema sẽ khai báo cấu trúc của database, Magento so sánh phiên bản database cuối cùng này với phiên bản hiện tại và chỉ apply những thay đổi giữa phiên bản cuối cùng và phiên bản hiện tại.
- Đây là một ví dụ lấy từ
Catalog/etc/db_schema.xml
, định nghiã bảngcatalog_product_entity_datetime
1 | <table name="catalog_product_entity_datetime" resource="default" engine="innodb" |
3. Cấu trúc db_schema
- File db_schema.xml khai báo cấu trúc database của một module được định nghĩa ở
[Module_Vendor]/[Module_Name]/etc/db_schema.xml
3.1 Thẻ <chema>
- File db_chema.xml mở đầu với thẻ
<schema>
1 | <schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd"> |
3.2 Thẻ <table>
- Mỗi một file db_schema.xml sẽ chứa một hoặc nhiều node table. Mỗi một node table đại diện cho một bảng trong database.
- Một node table có thể chứa những attribute sau:
ATTRIBUTE DESCRIPTION name
Tên của table engine
SQL engine. Sẽ là innodb
hoặcmemory
resource
Phân đoạn CSDL nào mà chúng ta cài đặt bảng. Sẽ là default
,checkout
, hoặcfalse
.comment
Comment chúng ta viết cho bảng. - Một node table có thể bao gồm 3 loại node con sau:
column
constraint
index
3.3 Thẻ <column>
Node
column
định nghĩa column của một bảng.Một
column
sẽ có các thuộc tính sau:ATTRIBUTE DESCRIPTION xsi:type
Chỉ định kiểu dữ liệu của cột. Sẽ là những kiểu sau: - blob, boolean, date, datetime, decimal, float, int (bao gồm cả smallint, bigint, tinyint), json, real (bao gồm cả decimal, float, double, real), smallint, text (bao gồm cả text, mediumtext, longtext), timestamp, varbinary, varchar default
Giá trị mặc định của cột khi được khởi tạo. Giá trị này phải cùng kiểu dữ liệu khai báo với xsi:type
disabled
Vô hiệu hóa hoặc xóa cột. identity
Chỉ định cột là tự động tăng. length
Chỉ định độ dài của dữ liệu cột. Dùng với các kiểu dữ liệu char
,varchar
, vàvarbinary
.nullable
Cột có thể null hay không. onCreate
Đây là một DDL Trigger cho phép bạn chuyển dữ liệu từ một cột đang tồn tại sang một cột mới. Trigger này chỉ hoạt động khi một cột được tạo. padding
Size của một cột kiểu integer. precision
Độ chính xác của một dữ liệu kiểu real. scale
Số chữ số đằng sau dấu phẩy của một dữ liệu kiểu real. unsigned
Đối với một cột có dữ liệu kiểu numberic, chỉ định liệu dữ liệu đó có thể là số dương hoặc số âm không hay chỉ có thể là số dương. Ví dụ sau tạo một cột
entity_id
tự động tăng
1 | <column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="true" comment="Credit ID"/> |
3.4 Thẻ <constrain>
Một node
<constrain>
luôn chứa các thuộc tính sauATTRIBUTE DESCRIPTION type
primary
,unique
, hoặcforeign
referenceId
Tên của ràng buộc. Bạn có thể tự đặt tên cho nó nhưng cách đơn giản nhất là bạn lấy luôn tên được generate trong file db_schema_whitelist.json
khi chạy command generate-whitelist. Lưu ý tên ràng buộc này chỉ được sử dụng trong phạm vi các filedb_schema.xml
, còn trong database tên ràng buộc có thể khác và do hệ thống tự tạoRàng buộc
primary
vàunique
là ràng buộc nội bộ, chỉ liên quan đến 1 bảng, có thể định nghĩa nhiều cột cùng một lúc (nhiều columnunique
trong bảng hay 2 cột đồng thời là khóa chính)Ví dụ tạo một khóa chính
1 | <constraint xsi:type="primary" referenceId="PRIMARY"> |
Khóa ngoại
foreign
kết nối 2 bảng với nhau. Một khóa ngoại có thể bao gồm các attribute sau:ATTRIBUTE DESCRIPTION table
Tên của table hiện tại. column
Tên cột trong bảng hiện tại mà tham chiếu đến một cột trong bảng khác. referenceTable
Bảng được tham chiếu. referenceColumn
Cột được tham chiếu trong bảng referenceTable
onDelete
Trigger khi delete bản ghi với khóa ngoại, có thể là CASCADE
,SET NULL
, hoặcNO ACTION
Ví dụ sau khai báo một khóa ngoại, cột
entity_id
là khóa chính của bảngcompany
nhưng là khóa ngoại của bảngcompany_credit
1 | <constraint xsi:type="foreign" referenceId="COMPANY_CREDIT_COMPANY_ID_COMPANY_ENTITY_ID" table="company_credit" column="company_id" referenceTable="company" referenceColumn="entity_id" onDelete="CASCADE"/> |
3.5 Thẻ <index>
Định nghĩa chỉ mục cho bảng với thẻ
<index>
, giúp tăng tốc khi thực hiện các hành động DQL (Doctrine Query Language)Một thẻ
<index>
có các attribute sau:ATTRIBUTE DESCRIPTION indexType
Có thể là btree
,fulltext
, hoặchash
referenceId
Tên của chỉ mục. Bạn có thể tự đặt tên cho nó nhưng cách đơn giản nhất là bạn lấy luôn tên được generate trong file db_schema_whitelist.json
khi chạy command generate-whitelistVí dụ:
1 | <index referenceId="NEWSLETTER_SUBSCRIBER_CUSTOMER_ID" indexType="btree"> |
4. Whitelist
- Declarative Schema sẽ không thể xóa các bảng, các cột và các khóa ràng buộc nếu nó chưa được định nghĩa trong db_schema.xml
- Vì lý do trên chúng ta phải cần đến file
db_schema_whitelist.json
, file này sẽ cho thấy lịch sử của các bảng, các cột và ràng buộc nào đã được thêm vào db_schema.xml. Nói một cách dễ hình dung, giả sử như bạn muốn mang thiết bị vào một tòa nhà, bạn phải đăng kí thông tin ở quầy lễ tân(filedb_schema_whitelist.json
), như vậy bạn mới được phép khi vận chuyện thiết bị ra khỏi tòa nhà. - Như vậy bạn chỉ có thể xóa bảng, xóa cột, xóa ràng buộc khi nó đã được định nghĩa trong file
db_schema_whitelist.json
- Để generate file
db_schema_whitelist.json
, chạy command sau
1 | $ bin/magento setup:db-declaration:generate-whitelist [options] |
[options]
có thể là --module-name[=MODULE-NAME]
để chỉ định tên module bạn muốn generate file whitelist. Nếu không có module nào được chỉ định, mặc định sẽ là generate cho tất cả các module
5. Chế độ DRY RUN
- Một điều rất cool mà Declarative Schema mang lại cho chúng ta đó là chế độ Dry Run. Chúng ta có thể kiểm tra trước tất cả các câu lệnh DDL SQL (Data Definition Language) mà được generate trong quá trình chạy declarative schema.
- Ở trong chế độ Dry Run, database sẽ KHÔNG bị thay đổi.
- Để chạy trong chế độ DRY RUN, chạy 1 trong các command sau:
1 | $ bin/magento setup:install --dry-run=1 |
hoặc
1 | $ bin/magento setup:upgrade --dry-run=1 |
- Với flag
--dry-run=1
, Magento sẽ tạo ra một file log ở<Magento_Root>/var/log/dry-run-installation.log
. - File này sẽ chứa tất cả các câu lệnh DDL SQL được generate trong quá trình cài đặt. Bạn có thể sử dụng chúng để debug và xử lý tối ưu performance
6. Tổng Kết Phần 1
Bài viết này mình trình bày cách sử dụng Declarative Schema, cấu trúc của một file db_schema.xml. Mong rằng qua bài viết này các bạn biết thêm một cách hữu ích có thể thay thế các tập lệnh Install/Upgrade Script để tạo và update cấu trúc của bảng trong CSDL.
Bài viết này còn tiếp. Trong phần 2 mính sẽ trình bày cụ thể các trường hợp mà bạn hay gặp như: Tạo bảng như nào, đổi tên bảng như nào, đổi tên cột, xóa cột…
See ya!