X
    Categories: Magento 2 BlogsMagento Tutorials, Tips and Guides

Magento 2 Setup Scripts For Custom Modules

If you’re a Magento extension developer, there’s a chance that at some point you’ll want the extension to create and delete records from the database. You might even want to add more tables to the database or new columns to the table when you upgrade the module version. Such are the cases when Setup scripts can come in handy.

Setup scripts in Magento 2 are essential when writing custom modules. There are many differences between how these scripts are handled in Magento 2 and Magento 1. In Magento 2, we have 6 different types of Setup Scripts that can be used with our custom modules:

  • InstallSchema
  • UpgradeSchema
  • InstallData
  • UpgradeData
  • Recurring
  • Uninstall

In Magento 1, we have to create separate folders for Setup and Data scripts with the separate version numbering files. However, in Magento 2 this has been simplified. Now we only have to create a single folder called Setup in the root of the module directory and create only one file for each script. For the reference, all mentioned Setup Scripts are located at /setup/src/Magento/Setup/.

Setup scripts in Magento 2 are triggered using the Command Line Interface (CLI). When a Magento 2 module is first installed, an entry to the setup_module table is added for that particular module, using the setup_version attribute specified in the module.xml file that can be found in the Namespace/ModuleName/etc directory.

Install Schema and Install Data

As the names suggest, the InstallSchema.php and InstallData.php scripts run when the module is first installed in Magento 2. These scripts are used to modify the data and structure of the database respectively. It means, if InstallSchema.php and InstallData.php are created after the installation of the module, they will never be executed.

The example of an InstallSchema.php script looks like this:

<?php

 

namespace Namespace\ModuleName\Setup;

 

use Magento\Framework\Setup\InstallSchemaInterface;

use Magento\Framework\Setup\SchemaSetupInterface;

use Magento\Framework\Setup\ModuleContextInterface;

 

class InstallSchema implements InstallSchemaInterface

{

    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)

    {

        $installer = $setup;

        $installer->startSetup();

        $connection = $installer->getConnection();

        //cart table

        $connection->addColumn(

                $installer->getTable('quote_item'),

                'remarks',

                [

                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,

                    'length' => 255,

                    'comment' =>'Remarks'

                ]

            );

        $installer->endSetup();

    }

}

Notice that the InstallSchemaInterface interface has been implemented, and all of the setup code is placed within the install function. The example code uses DDL to add a column called remarks in the quote_item table.

The InstallData.php script uses a similar practice. However, it implements InstallDataInterface instead of InstallSchemaInterface. Take a look at this example:

<?php

 

namespace Namespace\ModuleName\Setup;

 

use Magento\Framework\Setup\InstallDataInterface;

use Magento\Framework\Setup\ModuleContextInterface;

use Magento\Framework\Setup\ModuleDataSetupInterface;

 

class InstallData implements InstallDataInterface

{

    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)

    {

        $setup->startSetup();

        //Any Query

        //$setup->getConnection()->query("INSERT INTO .....");

        $setup->endSetup();

    }

}

Upgrade Schema and Upgrade Data

The UpgradeSchema.php and UpgradeData.php scripts help in updating the database data and its structure. Updating the module version in module.xml will allow the Upgrade scripts to be run when the magento setup:upgrade CLI command is executed.

Here’s an example of UpgradeSchema.php script:

<?php

 

namespace Namespace\ModuleName\Setup;

 

use Magento\Framework\Setup\UpgradeSchemaInterface;

use Magento\Framework\Setup\SchemaSetupInterface;

use Magento\Framework\Setup\ModuleContextInterface;

 

class UpgradeSchema implements UpgradeSchemaInterface

{

    public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)

    {

        if (version_compare($context->getVersion(), '1.0.1') < 0) {

        $installer = $setup;

        $installer->startSetup();

        $connection = $installer->getConnection();

        //Order address table

        $connection->addColumn(

                $installer->getTable('sales_order'),

                'remarks',

                [

                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,

                    'length' => 255,

                    'comment' =>'Remarks'

 

                ]

            );

        $installer->endSetup();

       }

    }

}

In the above code, notice that the pattern is same as the InstallSchema.php script. However, here UpgradeSchema.php implements UpgradeSchemaInterface, and the rest of the code is placed in the upgrade function. The main thing to notice here is the use of the following code to confine the changes:

if (version_compare($context->getVersion(), ‘1.0.1’) < 0)

This ensures that the changes will only run when the module version is changed to 1.0.1 and will be ignored on further updates of the version. At the same time, any code outside this condition will be executed on each upgrade.

The UpgradeData.php script uses a similar practice.

<?php

 

namespace Namespace\ModuleName\Setup;

 

use Magento\Framework\Setup\UpgradeDataInterface;

use Magento\Framework\Setup\ModuleContextInterface;

use Magento\Framework\Setup\ModuleDataSetupInterface;

 

class UpgradeData implements UpgradeDataInterface

{

    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)

    {

        if (version_compare($context->getVersion(), '1.0.1') < 0) {

        $setup->startSetup();

        //Any Query

        //$setup->getConnection()->query("INSERT INTO .....");

        $setup->endSetup();

       }

    }

}

The above code for UpgradeData.php script also compares the module version to ensure if the upgrades are restricted to a particular version.

Recurring

The Recurring script is a new feature introduced in Magento 2. It runs whenever magento setup:upgrade command is called in CLI. It works just like the Upgrade script but doesn’t have a version comparison condition. The Recurring script executes whenever the module version is incremented. You can notice the use of recurring scripts in Magento\Indexer\Setup\Recurring.

Take a look at the following example that shows how to use a Recurring script:

<?php

 

namespace Namespace\ModuleName\Setup;

 

use Magento\Framework\Setup\InstallSchemaInterface;

use Magento\Framework\Setup\ModuleContextInterface;

use Magento\Framework\Setup\SchemaSetupInterface;

 

class Recurring implements InstallSchemaInterface

{

    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)

    {

        $setup->startSetup();

        //Any code here

        $setup->endSetup();

    }

}

In the above code, the Recurring scripts do not implement its own interface type. They reuse InstallSchemaInterface, and the further code is inside the install function.

Uninstall

The Uninstall script is another feature that was introduced in Magento 2. The purpose of Uninstall script is to remove all the tables, columns, data from the database as if the module never created them in the first place. I recommend that all Magento 2 extensions have the Uninstall script because this would simplify the database cleanup process in case the extension is no longer needed.

The pattern is of the Uninstall.php script is the same as the patterns mentioned above:

<?php

 

namespace Namespace\ModuleName\Setup;

 

use Magento\Framework\Setup\UninstallSchemaInterface;

use Magento\Framework\Setup\ModuleContextInterface;

use Magento\Framework\Setup\SchemaSetupInterface;

 

class Recurring implements UninstallSchemaInterface

{

    public function uninstall(SchemaSetupInterface $setup, ModuleContextInterface $context)

    {

        $setup->startSetup();

        //Any Query

        //$setup->getConnection()->query("DROP table .....");

        $setup->endSetup();

    }

}

It is important to remember that the Uninstall scripts only work when a module has been installed via Composer and uninstalled using the module:uninstall CLI command.

Wrapping Up

The complex implementation of Setup scripts in Magento 1 where the module version was part of the file name has now been simplified in Magento 2. However, there’s a cost to maintain, since all the updates will initiate from a single script file and could lead to some very dilated codes.

Therefore, the responsibility will be on the Magento 2 Developer to implement the best coding practices and make life easy for everyone.

If you have any queries, please leave a message in the comment section below.

Fayyaz Khattak :Fayyaz is a Magento Community Manager at Cloudways - A Managed Magento Hosting Platform. His objective is to learn & share about PHP & Magento Development in Community. Fayyaz is a food lover and enjoys driving. You can email him at m.fayyaz@cloudways.com