Skip to content
intermediate Phase 39 · Database Operations

Data Patches

Data patches in Magento 2 using DataPatchInterface for data installation, migration, and rollback

45m
0 problems
Topic Progress 0%

What Are Data Patches?

Data Patches vs Setup Scripts

Data patches provide a structured way to install and migrate data:

// Old approach: InstallData.php
public function install()
{
    $installer = $this->setup->newSetup();
    $installer->startSetup();
    // Data manipulation
    $installer->endSetup();
}

// New approach: Data Patch
class InstallSampleData implements DataPatchInterface
{
    public function __construct(
        private SampleDataTable $sampleDataTable,
        private ModuleDataSetupInterface $setup
    ) {}

    public function install(): void
    {
        $this->setup->startSetup();
        $this->sampleDataTable->save([
            'name' => 'Sample Item',
            'status' => 1
        ]);
        $this->setup->endSetup();
    }

    public function getAliases(): array { return []; }
    public function getDependencies(): array { return []; }
}

Patch Location

app/code/Vendor/Module/
├── Setup/
│   └── Patch/
│       └── Data/
│           ├── InstallSampleData.php
│           ├── AddCustomAttribute.php
│           └── MigrateOldData.php
├── etc/
│   └── db_schema.xml
└── registration.php

DataPatchInterface

Interface Methods

use Magento\Framework\Setup\Patch\DataPatchInterface;

interface DataPatchInterface
{
    /**
     * Run the patch
     */
    public function install(): void;

    /**
     * List of aliases for the patch
     */
    public function getAliases(): array;

    /**
     * List of dependencies (patches that must run first)
     */
    public function getDependencies(): array;
}

Complete Example

<?php
namespace Vendor\Module\Setup\Patch\Data;

use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

class InstallProductAttributes implements DataPatchInterface
{
    public function __construct(
        private ModuleDataSetupInterface $setup,
        private \Magento\Eav\Model\Config $eavConfig,
        private \Magento\Eav\Setup\EavSetupFactory $eavSetupFactory
    ) {}

    public function install(): void
    {
        $this->setup->startSetup();

        $eavSetup = $this->eavSetupFactory->create(['setup' => $this->setup]);

        // Add attribute to catalog_product entity
        $eavSetup->addAttribute(
            \Magento\Catalog\Model\Product::ENTITY,
            'custom_field',
            [
                'type' => 'varchar',
                'label' => 'Custom Field',
                'input' => 'text',
                'required' => false,
                'sort_order' => 100,
                'group' => 'General',
            ]
        );

        $this->setup->endSetup();
    }

    public function getAliases(): array
    {
        return ['install_product_attributes_v2'];
    }

    public function getDependencies(): array
    {
        return [
            \Vendor\Module\Setup\Patch\Data\InstallSampleData::class
        ];
    }
}

Data Patch Operations

Installing Data

public function install(): void
{
    $this->setup->startSetup();

    // Insert new records
    $connection = $this->setup->getConnection();
    $table = $this->setup->getTable('vendor_module_custom');

    $connection->insert($table, [
        'name' => 'First Item',
        'status' => 1,
        'created_at' => date('Y-m-d H:i:s')
    ]);

    // Bulk insert
    $connection->insertMultiple($table, [
        ['name' => 'Item 2', 'status' => 1],
        ['name' => 'Item 3', 'status' => 0],
    ]);

    $this->setup->endSetup();
}

Migrating Data

public function install(): void
{
    $this->setup->startSetup();
    $connection = $this->setup->getConnection();

    // Migrate data from old table to new table
    $oldTable = $this->setup->getTable('old_module_data');
    $newTable = $this->setup->getTable('new_module_data');

    $select = $connection->select()
        ->from($oldTable)
        ->where('status = ?', 1);

    $data = $connection->fetchAll($select);

    foreach ($data as $row) {
        $connection->insert($newTable, [
            'name' => $row['name'],
            'description' => $row['desc'],
            'status' => $row['status'],
        ]);
    }

    // Update existing records
    $connection->update(
        $newTable,
        ['status' => 2],
        ['entity_id > ?' => 100]
    );

    $this->setup->endSetup();
}

Rollback

// Rollback is handled by the patch class
// Implement RollbackInterface if needed

use Magento\Framework\Setup\Patch\PatchRevertableInterface;

class InstallSampleData implements DataPatchInterface, PatchRevertableInterface
{
    public function install(): void
    {
        $this->setup->startSetup();
        // Install data
        $this->setup->endSetup();
    }

    public function revert(): void
    {
        $this->setup->startSetup();
        $connection = $this->setup->getConnection();
        $connection->delete($this->setup->getTable('vendor_module_data'));
        $this->setup->endSetup();
    }
}

Managing Patches

Patch Status

# Check patch status
bin/magento setup:patch:status

# Apply all patches
bin/magento setup:upgrade

# Apply specific patch
bin/magento setup:patch:apply --patch=Vendor_Module::InstallSampleData

Patch Dependencies

// Define dependencies - these patches must run first
public function getDependencies(): array
{
    return [
        \Magento\Catalog\Setup\Patch\Data\UpdateProductData::class,
        \Vendor\Module\Setup\Patch\Data\InstallSampleData::class,
    ];
}

// Define aliases (for tracking completed patches)
public function getAliases(): array
{
    return [
        'install_product_data_v2',
        'add_custom_attributes_v1'
    ];
}

Tracking Patches

-- Track completed patches in setup_module
SELECT name, schema_version, data_version
FROM setup_module
WHERE name = 'Vendor_Module';
+--------------+----------------+---------------+
| name         | schema_version | data_version  |
+--------------+----------------+---------------+
| Vendor_Module | 1.0.0          | 1.0.1         |
+--------------+----------------+---------------+

-- Track patch status
SELECT * FROM setup_module WHERE name LIKE 'Vendor%';

Best Practices

1. One patch per logical change
2. Always implement getDependencies()
3. Use getAliases() for renamed patches
4. Test patches in development first
5. Implement revert() for critical changes
6. Use transactions for atomic operations
7. Never modify applied patches - create new ones

Quiz

1. What interface do data patches implement?

Question 1 options

2. What is the purpose of getDependencies()?

Question 2 options

3. How do you rollback a data patch?

Question 3 options

Flashcards

Question

What is a data patch?

Answer

A PHP class implementing DataPatchInterface for data installation and migration

Question

What methods must DataPatchInterface implement?

Answer

install(), getAliases(), getDependencies()

Question

How to rollback a patch?

Answer

Implement PatchRevertableInterface with revert() method

Question

Where are patches stored?

Answer

app/code/Vendor/Module/Setup/Patch/Data/

Question

How to check patch status?

Answer

bin/magento setup:patch:status

Revision Notes

Key Takeaways

  • 1. Data patches implement DataPatchInterface with install(), getAliases(), getDependencies()
  • 2. Patches stored in Setup/Patch/Data/ directory
  • 3. Dependencies ensure correct execution order
  • 4. Implement PatchRevertableInterface for rollback support
  • 5. Always test patches in development first

Interview Tips

  • Explain the difference between data and schema patches
  • Discuss how patch dependencies work
  • Describe the rollback mechanism for data patches

Cheat Sheet

DataPatchInterface:
  install()      → Run the patch
  getAliases()   → List aliases for tracking
  getDependencies() → Patches that must run first

PatchRevertableInterface:
  revert() → Undo the patch

Location:
  app/code/Vendor/Module/Setup/Patch/Data/

Commands:
  bin/magento setup:patch:status
  bin/magento setup:upgrade