Magento 2 setup script

Magento 2 setup script

Magento 2 Setup script is a installer script to create a database table from the module. However this is already known from magento 1.x the coding structure vary in the magento 2.x. In magento 1.x these sql scripts are written in mysql4-install-{module version number}.php. In magento 2 these sql code should be come under the Installschema class. Before moving to setup script you should be aware of the basic module development structure click here.For module development click here.Create a directory ‘Setup’ in the module folder. create Installschema file, this will execute during the module installation.

<?php
#file Explorer\Test\Setup\InstallSchema.php
namespace Explorer\Test\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\DB\Adapter\AdapterInterface;


class InstallSchema implements InstallSchemaInterface
{
    
    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $installer = $setup;

        $installer->startSetup();
       
        $table = $installer->getConnection()->newTable(
            $installer->getTable('explorer_test')
        )->addColumn(
            'test_id',
            \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
            null,
            ['identity' => true, 'nullable' => false, 'primary' => true],
            'Test ID'
        )->addColumn(
            'full_name',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            255,
            ['nullable' => false],
            'Test Full Name'
        )->addColumn(
            'email',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            255,
            ['nullable' => false],
            'Test Email'
        )->addColumn(
            'created_at',
            \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
            null,
            ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT],
            'Test created at'
        )->addColumn(
            'updated_at',
            \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
            null,
            ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE],
            'Test Modification Time'
        )->addColumn(
            'is_active',
            \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
            null,
            ['nullable' => false, 'default' => '1'],
            'Is Test Active'
        )->addIndex(
            $setup->getIdxName(
                $installer->getTable('explorer_test'),
                ['full_name', 'email'],
                AdapterInterface::INDEX_TYPE_FULLTEXT
            ),
            ['full_name', 'email'],
            ['type' => AdapterInterface::INDEX_TYPE_FULLTEXT]
        )->setComment(
            'ExplorerTest Table'
        );
        $installer->getConnection()->createTable($table);

        $installer->endSetup();
    }
}

Setup module table

The setup module table will do the core resource table functions in Magento 2. If you are module was already installed, you can do the re-installation by deleting your module name record in setup module table.

Model for table

Ofcourse to use the data from our custom table we need to create the model,resource model and collection file for the table. The basic model file includes the following

<?php
#file Explorer\Test\Model\Test.php
namespace Explorer\Test\Model;

class Test extends \Magento\Framework\Model\AbstractModel
{
    
    const STATUS_ENABLED = 1;
    const STATUS_DISABLED = 0;

    
    const CACHE_TAG = 'explorer_test';

    
    protected $_cacheTag = 'explorer_test';

    
    protected $_eventPrefix = 'explorer_test';

    
    protected function _construct()
    {
        $this->_init('Explorer\Test\Model\ResourceModel\Test');
    }

    
    public function getIdentities()
    {
        return [self::CACHE_TAG . '_' . $this->getId(), self::CACHE_TAG . '_' . $this->getId()];
    }

   
    public function getAvailableStatuses()
    {
        return [self::STATUS_ENABLED => __('Enabled'), self::STATUS_DISABLED => __('Disabled')];
    }

}

The two caches tag are needed for magento 2.0 operating cache. The event prefix are used to create event name for observers later on. The important thing is to define the resource model name in the construct function. It is not necessary to use getIdentities() function but it is useful for proper cache management.

Resource model for table

The basic resource model file includes the following stucture.

<?php

namespace Explorer\Test\Model\ResourceModel;

class Test extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
    
    protected function _construct()
    {
        $this->_init('explorer_test', 'test_id');
    }
          
}

The most important thing here is defining the table primary key in constuct() function.

Create collection

The basic collection files includes the following structure.

<?php
#file Explorer\Test\Model\ResourceModel\Test\Collection.php
namespace Explorer\Test\Model\ResourceModel\Test;

class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
    
    protected $_idFieldName = 'test_id';

    protected $storeManager;

    public function __construct(
        \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
        \Psr\Log\LoggerInterface $logger,
        \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
        \Magento\Framework\Event\ManagerInterface $eventManager,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
        \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null
    ) {
        parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
        $this->storeManager = $storeManager;
    }

    protected function _construct()
    {
        $this->_init('Explorer\Test\Model\Test', 'Explorer\Test\Model\ResourceModel\Test');
    }
}

The important thing here is to define the model name and resource model name in the construct function.

Upgrade script

In module development, we frequently need to modify the table structure or to create a new table for our module. In such case we have to go with upgradeschema. In magento 1.x this scripts are written in mysql4-upgrade-{module old version number}-{module new version number}.php. In magento 2 it comes under upgradeschema class.

<?php
#file Explorer\Test\Setup\UpgradeSchema.php
namespace Explorer\Test\Setup;

use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;


class UpgradeSchema implements UpgradeSchemaInterface
{

    public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        if (version_compare($context->getVersion(), '0.0.2') < 0) {
            $setup->startSetup();
            $setup->getConnection()->addColumn(
                $setup->getTable('explorer_test'),
                'test_column',
                [
                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
                    'length' => null,
                    'nullable' => false,
                    'default' => 0,
                    'comment' => 'Test Column'
                ]
            );
            $setup->endSetup();
        }
    }
}

From the above example, we added a new column called ‘test_column’ in the explorer_test table. This upgrade runs only when the module reaches the version 0.0.2.

To use data from custom table, we need to have to template file and the block class belonging to it.

Block to use the model

The basic block class with the following code.

<?php
#file Explorer\Test\Block\Test.php
namespace Explorer\Test\Block;

use Magento\Framework\View\Element\Template;

class Test extends Template
{
    
    protected $test;

    
    protected $testFactory;

    
    protected $itemCollectionFactory;

    
    protected $items;

    public function __construct(
        Template\Context $context,
        \Explorer\Test\Model\Test $test,
        \Explorer\Test\Model\TestFactory $testFactory,
        \Explorer\Test\Model\ResourceModel\Test\CollectionFactory $itemCollectionFactory,
        array $data = []
    ) {
        $this->test = $test;
        $this->testFactory = $testFactory;
        $this->itemCollectionFactory = $itemCollectionFactory;
        parent::__construct($context, $data);
    }
    
    public function getTestModel()
    {
        if (!$this->hasData('test')) {
            if ($this->getTestId()) {
                $test = $this->testFactory->create();
                $test->load($this->getTestId());
            } else {
                $test = $this->test;
            }
            $this->setData('test', $test);
        }
        return $this->getData('test');
    }

    public function getItems()
    { 
        if (!$this->items) {
            $this->items = $this->itemCollectionFactory->create()->addFieldToSelect(
                '*'
            )->addFieldToFilter(
                'is_active',
                ['eq' => \Explorer\Test\Model\Test::STATUS_ENABLED]
            )->setOrder(
                'created_at',
                'desc'
            );
            
        }
        return $this->items;
    }

    public function getTestId()
    {
        return 1;
    }

    
    public function getIdentities()
    {
        return [\Aion\Test\Model\Test::CACHE_TAG . '_' . $this->getTestModel()->getId()];
    }
} 

We previously created the Test model and collection model only. But you can see the new classes TestFactory and CollectionFactory in the construct function. Which is generated by Magento 2.0 in var/generation folder.

Template

Next we are set with all required files to use our custom table in the module. Just load the block function and insert in the loop to use in template file now. The template file code is

	
	<div class="aion-test">
    <h2><?php echo __('This is a test extension!') ?></h2>
    <?php $items = $block->getItems(); ?>
    <?php if ($items->getSize()) : ?>
        <?php foreach ($items as $item) : ?>
            <h3><?php echo $block->stripTags($item->getName()) ?></h3>
            <p>
                <span><?php echo __('Email:'); ?></span>&nbsp;
                <span><?php echo $item->getEmail() ?></span>
            </p>
        <?php endforeach; ?>
    <?php endif; ?>
</div>

Have a great day 🙂