Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Data and schema patches

A patch is a class that makes a change to the database once, when setup:upgrade runs. Patches add initial records, settings and attributes. Magento remembers applied patches and does not run them again — this way all servers end up with the same data.

Where patches live

Module folderWhat is in it
Setup/Patch/DataData patches: adding and changing records
Setup/Patch/SchemaSchema patches: structure changes that cannot be described in db_schema.xml

There is no command to create one — the file is written by hand. The class name should say what it does.

app/code/Acme/Hello/
└── Setup/
    └── Patch/
        └── Data/
            └── AddSampleReviews.php    new file

A data patch

Let's add two records to the reviews table so that the /hello page has something to show:

// app/code/Acme/Hello/Setup/Patch/Data/AddSampleReviews.php
namespace Acme\Hello\Setup\Patch\Data;
 
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;
 
class AddSampleReviews implements DataPatchInterface
{
    public function __construct(private ModuleDataSetupInterface $setup) {}
 
    public function apply(): self
    {
        $this->setup->getConnection()->insertMultiple(
            $this->setup->getTable('acme_hello_review'),
            [
                ['product_id' => 1, 'author' => 'Anna', 'rating' => 5, 'content' => 'A great bag'],
                ['product_id' => 1, 'author' => 'John', 'rating' => 4, 'content' => 'Handy but gets dirty fast'],
            ],
        );
 
        return $this;
    }
 
    public static function getDependencies(): array
    {
        return [];
    }
 
    public function getAliases(): array
    {
        return [];
    }
}

The apply() method does the work; the other two methods are required by the interface. The getTable() method returns the table name with the prefix chosen at installation. If you added the foreign key from the schema lesson, the product with ID 1 must exist — the sample data has it.

Running

bin/magento setup:upgrade

The command applies the patch, and two reviews appear on the /hello page. On later setup:upgrade runs the patch is skipped.

How Magento remembers patches

The names of applied patches are stored in the patch_list table. To run a patch again during development, delete its row from this table and run setup:upgrade once more. Do not do this on a production server.

Execution order

If a patch needs the data of another patch, list that class in getDependencies():

// app/code/Acme/Hello/Setup/Patch/Data/AddMoreReviews.php
public static function getDependencies(): array
{
    return [AddSampleReviews::class];
}

Magento first applies AddSampleReviews and then this patch. Patches without dependencies run in no particular order.

A schema patch

Table structure is described by db_schema.xml, and that is almost always enough. A schema patch is needed in rare cases, for example to move data out of an old column before dropping it. It is built the same way but lives in Setup/Patch/Schema, implements Magento\Framework\Setup\Patch\SchemaPatchInterface and receives Magento\Framework\Setup\SchemaSetupInterface in its constructor.

What patches are used for

TaskWhat to use
Initial records of your own tablesThe connection from ModuleDataSetupInterface
A product or customer attributeEavSetupFactory — covered in a later lesson
A configuration valueA row in the core_config_data table
A CMS page or blockThe repositories of the Magento_Cms module

Common mistake

A patch has already been applied, then its code was fixed and the change is expected to take effect. Magento sees the class name in patch_list and does not run it again; a colleague's server and the live site keep the old data. Write a new patch for every new change.

Thanks for reading!

Donate to the site — we work hard for you.