Requirements
Demonstrate use of schema. How to manipulate columns and keys using declarative schema? What is the purpose of whitelisting? How to use Data and Schema patches? How to manage dependencies between patch files?
Experiments
using db_schema.xml
to add a new table
Based on 2.3.1, create a new module named VendorName_TestModule
create 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="order_custom_attribute" resource="default" engine="innodb" comment="order_custom_attribute">
<column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="true" comment="Entity ID"/>
<column xsi:type="varchar" name="foo" nullable="true" length="255" comment="foo"/>
<column xsi:type="varchar" name="bar" nullable="true" length="255" comment="bar"/>
<constraint xsi:type="primary" referenceId="PRIMARY">
<column name="entity_id"/>
</constraint>
</table>
</schema>
If you already have install or upgrade script,you can convert them to db_schema.xml files.
To convert your install or upgrade script, run one of the following commands:
bin/magento setup:install --convert-old-scripts=1
bin/magento setup:upgrade --convert-old-scripts=1
To enable dry run mode, run one of the following commands:
bin/magento setup:install --dry-run=1
bin/magento setup:upgrade --dry-run=1
As a result of specifying the —dry-run=1 flag, Magento writes a log file at /var/log/dry-run-installation.log. This file contains all the DDL SQL statements that are generated during installation. You can use these SQL statements for debugging and optimizing performance processes.
Next,we will create a schema whitelist.
run:
bin/magento setup:db-declaration:generate-whitelist --module-name=VendorName_TestModule
We should get a file etc/db_schema_whitelist.json
{
"order_custom_attribute": {
"column": {
"entity_id": true,
"foo": true,
"bar": true
},
"constraint": {
"PRIMARY": true
}
}
}
Our module’s current version is 2.1.7
Now, run:
bin/magento setup:upgrade
Check the databse, now we have the table order_custom_attribute, it has three columns (entity_id, foo, bar)
delete column by edit db_schema.xml
Let’s edit 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="order_custom_attribute" resource="default" engine="innodb" comment="order_custom_attribute">
<column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="true" comment="Entity ID"/>
<column xsi:type="varchar" name="foo" nullable="true" length="255" comment="foo"/>
<!--<column xsi:type="varchar" name="bar" nullable="true" length="255" comment="bar"/>-->
<constraint xsi:type="primary" referenceId="PRIMARY">
<column name="entity_id"/>
</constraint>
</table>
</schema>
We comment the bar column. Then we edit etc/module.xml
make etup_version
to be 2.1.8
run:
bin/magento setup:upgrade
Check table order_custom_attribute
, it has two colums(entity_id, foo),the column bar has been removed.
If you delete db_schema_whitelist.json
, the column drop won’t happen.
data patch example
Let’s create a sample data patch, Setup\Patch\Data\TestPatch.php
<?php
namespace VendorName\TestModule\Setup\Patch\Data;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Framework\Setup\Patch\PatchVersionInterface;
use Magento\Framework\Setup\Patch\PatchRevertableInterface;
class TestPatch implements DataPatchInterface, PatchRevertableInterface, PatchVersionInterface
{
public function getAliases()
{
/**
* This internal Magento method, that means that some patches with time can change their names,
* but changing name should not affect installation process, that's why if we will change name of the patch
* we will add alias here
*/
return [];
}
public function apply()
{
// lets do something
$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/layout_block.xml');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);
$logger->info('TestPatch apply execute');
}
public static function getDependencies()
{
/**
* This is dependency to another patch. Dependency should be applied first
* One patch can have few dependencies
* Patches do not have versions, so if in old approach with Install/Ugrade data scripts you used
* versions, right now you need to point from patch with higher version to patch with lower version
* But please, note, that some of your patches can be independent and can be installed in any sequence
* So use dependencies only if this important for you
*/
// return [
// SomeDependency::class
// ];
return [];
}
public function revert()
{
$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/layout_block.xml');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);
$logger->info('TestPatch revert execute');
}
public static function getVersion()
{
/**
* If the version number of the module in our database is higher than
* the version we specify here in our file, the patch will not execute.
* If it is equal to or lower than the version here, it will execute.
*/
return '2.3.1';
}
}
Our module’s current version is 2.1.9, this is lower than the version (2.3.1) we specify here in our file, so, after you run bin/magento setup:upgrade
, you will see layout_block.xml
log. This means our patch has been applied. Also, you will see our TestPatch in patch_list table.
Let’s remove it from patch_list table, and edit the version in our file to be 2.1.0, after run bin/magento setup:upgrade
. you will see our path is added to patch_list table but not be applied.
run:
bin/magento module:uninstall --non-composer VendorName_TestModule
Ok, our patch is removed from patch_list table and the revert function executed.
Notes
Implementing declarative schema is not a requirement for Magento 2.3. However, upgrade scripts will be phased out in favor of declarative schema
Once you start with data patches, you cannot continue to use upgrade scripts.
Backward compatibility must be maintained. Therefore, declarative schema does not automatically delete database tables, columns or keys that are not defined in a db_schema.xml file. Declarative schema cannot delete these elements because these items can be declared somewhere else, such as in an Setup/UpgradeSchema.php file.
The //etc/db_schema_whitelist.json file provides a history of all tables, columns, and keys added with declarative schema. It is required to allow drop operations.
db_schema_whitelist.json is a temporary solution. It will be removed in the future, when upgrade scripts are no longer supported.
A data patch is a class that contains data modification instructions. It is defined in a <Vendor>/<Module_Name>/Setup/Patch/Data/<Patch_Name>.php
file and implements \Magento\Framework\Setup\Patch\DataPatchInterface
.
A schema patch contains custom schema modification instructions. These modifications can be complex. It is defined in a <Vendor>/<Module_Name>/Setup/Patch/Schema/<Patch_Name>.php
file and implements \Magento\Framework\Setup\Patch\SchemaPatchInterface
.
Currently, use data patch to add eav attributes.
Reference
Develop data and schema patches
Declarative Schema in Magento 2.3 and Higher – a Comprehensive Review