Magento 2.3 develop data and schema patches

Magento 2.3 have changed logic process setup data/schema via develop data and schema patches”.
So, In this post, we will learn how “patch data” work and utilize.

A data patch is a class that contains data modification instructions. It is defined in a //Setup/Patch/Data/.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 //Setup/Patch/Schema/.php file and implements \Magento\Framework\Setup\Patch\SchemaPatchInterface.

Unlike the declarative schema approach, patches will only be applied once. A list of applied patches is stored in the patch_list database table. An unapplied patch will be applied when running the setup:upgrade from the Magento CLI.

Optionally, if you plan to enable rollback for your patch during module uninstallation, then you must implement \Magento\Framework\Setup\Patch\PatchRevertableInterface.

The declarative schema approach removes the version from the setup_module table (in a backward compatible way), leaving only the Composer version. Therefore, you can create all new patches and modules without specifying a setup_module version.
How is it works?

Magento process apply patch via class:
Magento\Framework\Setup\Patch\PatchApplier.php
Your Setup Patch can apply, revert, register via functions:
applyDataPatch(): Apply all patches for one module 
revertDataPatches(): Revert data patches for specific module
applySchemaPatch(): Apply all patches for one module. That schema patches are not revertable
prepareRegistry(): Register all patches in registry in order to manipulate chains and dependencies of patches
Where are we specify file directory?

We can see default patch in function getPatchClassesPerModule() in class Magento\Framework\Setup\Patch\PatchReader.php
    private function getPatchClassesPerModule($moduleName, $modulePath)
    {
        $patchClasses = [];
        $patchesPath = $this->getPatchFolder($modulePath);
        $specificPatchPath = $patchesPath . DIRECTORY_SEPARATOR . $this->getTypeFolder();
        $patchesMask = $specificPatchPath . DIRECTORY_SEPARATOR . '*.php';

        foreach (Glob::glob($patchesMask) as $patchPath) {
            $moduleName = $this->getModuleNameForNamespace($moduleName);
            $patchClasses[] = $moduleName . '\\Setup\\' .
                self::SETUP_PATCH_FOLDER . '\\' .
                $this->getTypeFolder() . '\\' .
                basename($patchPath, '.php');
        }

        return $patchClasses;
    }
Magento get all class php in folder [your module]/Setup/Patch/[data or schema]/*.php After saving patch, we can see it via table “patch_list”
Implement setup patch required function apply() and getAlias()
 
apply(): where execute your code
getAlias():Get aliases (previous names) for the patch
Example: Update attribute vat_id in class: ​​​ Magento\Customer\Setup\Patch\Data\UpdateVATNumber.php
public function apply()
    {
        $customerSetup = $this->customerSetupFactory->create(['resourceConnection' => $this->moduleDataSetup]);
        $customerSetup->updateAttribute('customer_address', 'vat_id', 'frontend_label', 'VAT Number');
    }
Will old scripts work in newer versions?

Old scripts will work with new versions of Magento. However, if you want to convert your old scripts to the new format, implement \Magento\Framework\Setup\Patch\PatchVersionInterface. This interface allows you to specify the setup version of the module in your database. If the version of the module is higher than the version specified in your patch, then the patch is skipped. If the version in the database is equal or lower, then the patch installs.

Leave a Reply