Models and Collections for Magento2 (Part : 2)

Creation of Models and Collections for Magento2 with real example

Posted on March 16, 2016 in Magento2, PHP

Understanding the flow of schema

Simply put, the role of the schema scripts is to create a database structure supporting your module logic. If we look at our module.xml file, we can notice how schema_version from the database match the setup_version number. if we now change the setup_version number and run the php bin/magento setup:upgrade console command, our database schema_version would get updated to the new version number.

This is done through module’s install scripts. If we take a quick look at the setup/src/Magento/Setup/Model/Installer.php file, we can see a function, getSchemaDataHandler, with content as follow:


private function getSchemaDatahandler($moduleName, $type)
{
    $className = str_replace('_', '\\', $moduleName). '\Setup';

    switch($type) {
        case 'schema-install': 
            $className .= '\InstallSchema';
            $interface = self::SCHEMA_INSTALL;
            break;
        case 'schema-upgrade': 
            $className .= '\UpgradeSchema';
            $interface = self::SCHEMA_UPGRADE;
            break;
        case 'schema-recurring': 
            $className .= '\Recurring';
            $interface = self::SCHEMA_INSTALL;
            break;
        case 'data-install': 
            $className .= '\InstallData';
            $interface = self::DATA_INSTALL;
            break;
        case 'data-upgrade': 
            $className .= '\UpgradeData';
            $interface = self::DATA_UPGRADE;
            break;
        default': 
            throw new \Magento\Setup\Exception("$classname does not exist"); 
    }
    return $this->createShemaDataHandler($className, $interface);
}

This is what tells Magento which classes to pick up and run from the individual module Setup directory.

Creating an install schema script (InstallSchema.php)

Now that we understand that flow of schema and data scripts and their relation to the module version number, let’s go ahead and start assembling our InstallSchema.


#app/code/Jeff/Office/Setup/InstallSchema.php
namespace Jeff\Office\Setup;

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

class InstallSchema implements InstallSchemaInterface
{
    public function install (SchemaSetupInterface $setup, ModuleContextInterface $context) 
    {
         $setup->startSetup();
         //real code here
         $table = $setup->getConnection()->newTable($setup->getTable('jeff_office_department'))
                   ->addColumn(
                      'entity_id', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, null, ['identity'=>true, 'unsigned'=>true, 'nullable'=>false, 'primary'=>true ], 'Entity ID'
                   )
                   ->addColumn(
                     'name', \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 64, [], 'Name'
                  )->setComment('Jeff Office Department Table');
         $setup->getConnection()->createTable($table);

         $employeeEntity = \Jeff\Office\Model\Employee::ENTITY;
         $table->$setup->getConnection()->newTable($setup->getTable($employeeEntity . ' _entity'))
                  ->addColumn(
                       'entity_id', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, null, ['identity'=>true, 'unsigned'=>true, 'nullable'=>false, 'primary'=>true], 'Entity ID'
                 )
                  ->addColumn(
                      'department_id', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, null, ['unsigned'=>true, 'nullable'=>false], 'Department Id'
                 )
                  ->addColumn(
                      'email', \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 64, [], 'Email'
                 )
                  ->addColumn(
                     'first_name', \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 64, [], 'First Name'
                 )
                  ->addColumn(
                     'last_name', \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 64, [], 'Last Name'
                 )->setComment('Jeff Office Employee Table');
          $setup->getConnection()->createTable($table);
          /*
          Depending on the EAV attribute data type, we need to create following tables:
          jeff_office_employee_entity_datetime
          jeff_office_employee_entity_decimal
          jeff_office_employee_entity_int
          jeff_office_employee_entity_text
          jeff_office_employee_entity_varchar
          */
          $table = $setup->getConnection()->newTable($setup->getTable($employeeEntity . '_entity_decimal'))
                 ->addColumn(
                     'value_id', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, null, ['identity'=>true, 'nullable'=>false, 'primary'=>true], 'Value ID'
                )
                 ->addColumn(
                     'attribute_id', \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, null, ['unsigned'=>true, 'nullable'=>false, 'default'=>'0'], 'Attribute ID'
                )
                 ->addColumn(
                     'store_id', \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, null, ['unsigned'=>true, 'nullable'=>false, 'default'=>'0'], 'Store ID'
                )
                 ->addColumn(
                     'entity_id', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, null, ['unsigned'=>true, 'nullable'=>false, 'default'=>'0'], 'Entity ID'
                )
                 ->addColumn(
                     'value', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], 'Value'
                )
                ->addIndex(
                  $setup->getIdxName($employeeEntity . '_entity_decimal', ['entity_id', 'attribute_id', 'store_id'], \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNQUE]), ['entity_id', 'attribute_id', 'store_id'], ['type'=>\Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIUQUE]
               )
                ->addIndex(
                    $setup->getIdxName($employeeEntity . '_entity_decimal' , ['store_id']), ['store_id']
               )
                ->addIndex(
                    $setup->getIdxName($employeeEntity . '_entity_decimal' , ['attribute_id']), ['attribute_id']
               )
                ->addForeignKey(
                   $setup->getFkName(
                        $employeeEntity. '_entity_decimal', 'entity_id', 'eav_attribute', 'entity_id'
                   ),
                   'entity_id',
                   $setup->getTable($employeeEntity . '_entity'),
                   'entity_id',
                   \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
               )
                ->addForeignKey(
                   $setup->getFkName(
                        $employeeEntity. '_entity_decimal', 'store_id', 'store', 'store_id'
                   ),
                   'store_id',
                   $setup->getTable('store'),
                   'store_id',
                   \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
               )
                ->addForeignKey(
                   $setup->getFkName(
                        $employeeEntity. '_entity_decimal', 'attribute_id', 'eav_attribute', 'attribute_id'
                   ),
                   'attribute_id',
                   $setup->getTable('eav_attribute'),
                   'attribute_id',
                   \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
               )->setComment('Employee Decimal Attribute Backend Table');
         $setup->getConnection()->createTable($table);

         /*   four other tables look like above */
          .......
         $setup->endSetup();
    }

}

For the reason of performance and data integrity, it is important to define indexes and foreign key as per good database design practice.

Creating an upgrade schema script (UpgradeSchema.php)

During the first-time module install, an upgrade schema is what gets run immediately after an install schema. We define upgrade schema script as follows:


#app/code/Jeff/Office/Setup/UpgradeSchema.php

namespace Jeff\Office\Setup;

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

class UpgradSchema implements UpgradSchemaInterface 
{
    public function upgrade( SchemaSetupInterface $setup, ModuleContextInterface $context) 
    {
       $setup->startSetup();

       $employeeEntityTable = \Jeff\Office\Model\Employee::ENTITY . '_entity';
       $departmentEntityTable = 'jeff_office_department';
       $setup->getConnection()
              ->addForeignKey(
                     $setup->getFkName($employeeEntityTable , 'department_id', $departmentEntityTable, 'entity_id'),
                     $setup->getTable($employeeEntityTable),
                     'department_id',
                     $setup->getTable($departmentEntityTable),
                      'entity_id', 
                     \Magento\Framework\DB\Dbl\Table::Action_CASCADE
              );
      $setup->endSetup();
    }
}

Above all, we demonstrate how to create InstallSchema and UpgradeSchema for Magento2. Next tutorial topic will be “how to use the model and collection in Magento2”. Please click Here to read next tutorial.


comments powered by Disqus