Como criar/atualizar tabelas com InstallSchema e UpgradeShema no Magento 2
Tags: php, magento2, tutorial, braziliandevs
Published: 2021-10-18 12:36:34

# Contextualizando

Para gerenciar e fazer alterações nos esquemas do banco de dados de forma simplificada, o Magento possui as classes de *Install Schema* e *Upgrade Schema*, que criam scripts para processar o código em SQL e automaticamente inserir as atualizações no banco de dados. 

### Quando utilizar as instalações e atualizações de esquema?

As classes de *Install Schema* e *Upgrade Schema* servem para a alteração, remoção e/ou criação de uma tabela no banco de dados. E elas devem ser usadas em versões anteriores a versão 2.3 do Magento 2, mas para versões posteriores é recomendado o uso de classes do tipo *Schema Patch* e do `db_schema.xml`.

Outro fator para que é decisório para utilização das classes *Install Schema* e *Upgrade Schema* é a incompatibilidade dos módulos, caso a tabela tenha sido criada através do arquivo `db_schema.xml` ou *Schema Patch*, as alterações devem ser feitas por *Schema Patch* e não por classes do tipo *Install Schema* ou *Upgrade Schema*.

Saiba como criar uma tabela personalizada no post "[Como criar tabelas personalizadas no banco de dados com db_schema.xml no Magento 2](https://dev.to/santanaluc94/como-criar-tabelas-personalizadas-no-banco-de-dados-com-dbschema-xml-no-magento-2-3jlh)" e como criar, editar ou remover os esquemas de uma tabela no post "[Como criar/atualizar tabelas e dados com DataPatch e SchemaPatch](https://dev.to/santanaluc94/como-criar-atualizar-tabelas-e-dados-com-datapatch-e-schemapatch-5c79-temp-slug-1624915?preview=b9fb385efd136de47458eb69f0dcd55c23d1fb509a4f865df21a2783af5b28750c8b741c3191c6173c457c71518851ee4dbccc101f12dbcb8f221027)".

---

# Código para a criação/alteração de uma tabela

### Install Schema

Essa classe será executada quando o módulo for instalado para configurar a estrutura do banco de dados, ou seja, este tipo de classe deve ser utilizado para criar, alterar ou remover uma tabela no banco de dados.

A classe *Install Schema* deve seguir a estrutura de pastas `\{Vendor}\{Module}\Setup\InstallSchema` e deve implementar a interface `\Magento\Framework\Setup\InstallSchemaInterface`, que obriga a classe a implementar o método `install(\Magento\Framework\Setup\SchemaSetupInterface $setup, \Magento\Framework\Setup\ModuleContextInterface $context)`. A interface `SchemaSetupInterface` gera através de injeção de dependência um objeto de configuração que fornece muitas funções para interagir com o servidor do banco de dados. A interface `ModuleContextInterface` possui apenas o método `getVersion()`, que retorna a versão atual do módulo, ou seja, retorna o valor do atributo `setup_version` do arquivo `module.xml`.

```php
<?php

namespace {Vendor}\{Module}\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\DB\Ddl\Table;

class InstallSchema implements InstallSchemaInterface
{
    public const TABLE_NAME = '{table_name}';

    public function install(
        SchemaSetupInterface $setup,
        ModuleContextInterface $context
    ): void {
        $setup->startSetup();

        if (!$setup->tableExists(self::TABLE_NAME)) {
            // Add primary column
            $table = $setup->getConnection()->newTable(
                $setup->getTable(self::TABLE_NAME)
            )->addColumn(
                '{entity_column_id}',
                Table::TYPE_INTEGER,
                null,
                [
                    'identity' => true,
                    'nullable' => false,
                    'primary'  => true,
                    'unsigned' => true,
                ],
                '{Entity Table ID}'
            );

            // Add text type column
            $table->addColumn(
                '{column_type_text}',
                Table::TYPE_TEXT,
                255,
                [
                    'nullable' => {true/false}
                ],
                '{Column Type TEXT}'
            );

            // Add int type column
            $table->addColumn(
                '{column_type_integer}',
                Table::TYPE_INTEGER,
                10,
                [],
                '{Column Type INTEGER}'
            );

            // Add bool type column
            $table->addColumn(
                '{column_type_boolean}',
                Table::TYPE_BOOLEAN,
                1,
                [
                    'nullable' => {true/false},
                    'default' => 0
                ],
                '{Column Type BOOLEAN}'
            );

            // Add float type column
            $table->addColumn(
                '{column_type_float}',
                Table::TYPE_FLOAT,
                null,
                [
                    'default' => 0
                ],
                '{Column Type FLOAT}'
            );

            // Add date type column
            $table->addColumn(
                '{column_type_date}',
                Table::TYPE_DATE,
                null,
                [],
                '{Column Type DATE}'
            );

            // Add datetime type column
            $table->addColumn(
                '{column_type_datetime}',
                Table::TYPE_DATETIME,
                null,
                [
                    'nullable' => {true/false},
                ],
                '{Column Type DATETIME}'
            );

            // Add created_at type column
            $table->addColumn(
                'created_at',
                Table::TYPE_TIMESTAMP,
                null,
                [
                    'nullable' => {true/false},
                    'default' => Table::TIMESTAMP_INIT
                ],
                'Created At'
            );

            // Add updated_at type column
            $table->addColumn(
                'updated_at',
                Table::TYPE_TIMESTAMP,
                null,
                [
                    'nullable' => {true/false},
                    'default' => Table::TIMESTAMP_INIT_UPDATE
                ],
                'Updated At'
            )->setComment('{Comment About Table}');

            $setup->getConnection()->createTable($table);
            $setup->endSetup();
        }
    }
}
```

### Upgrade Schema

Essa classe será executada quando o modulo for instalado ou toda vez que o que for atualizado, ou seja, este tipo de classe deve ser utilizada para criar ou alterar uma tabela no banco de dados. Um módulo é atualizado quando a versão do módulo, que pode ser encontrado no atributo `setup_version` do arquivo `module.xml`, com a valor do atributo é possível configurar diferentes funcionalidades para cada versão do módulo.

A classe *Upgrade Schema* deve seguir a estrutura de pastas `\{Vendor}\{Module}\Setup\UpgradeSchema` e deve implementar a interface `\Magento\Framework\Setup\InstallSchemaInterface`, que obriga a classe a implementar o método `upgrade(\Magento\Framework\Setup\SchemaSetupInterface $setup, \Magento\Framework\Setup\ModuleContextInterface $context)`. A interface `SchemaSetupInterface` gera através de injeção de dependência um objeto de configuração que fornece muitas funções para interagir com o servidor do banco de dados. A interface `ModuleContextInterface` possui apenas o método `getVersion()`, que retorna a versão atual do módulo, ou seja, retorna o valor do atributo `setup_version` do arquivo `module.xml`.

```php
<?php

namespace {Vendor}\{Module}\Setup;

use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\DB\Ddl\Table;

class UpgradeSchema implements UpgradeSchemaInterface
{
    public const TABLE_NAME = '{table_name}';

    public function upgrade(
        SchemaSetupInterface $setup,
        ModuleContextInterface $context
    ): void {
        $setup->startSetup();

        if (version_compare($context->getVersion(), '{version_to_implement}', '<')) {
            $this->upgradeNumberVersion($setup);
        }

        $setup->endSetup();
    }

    private function upgradeNumberVersion(SchemaSetupInterface $setup): void
    {
        // Add new column to table
        $setup->getConnection()->addColumn(
            $setup->getTable(self::TABLE_NAME),
            '{new_column}',
            [
                'type' => Table::TYPE_{NAME},
                'nullable' => {true/false},
                'length' => '{length}',
                'comment' => '{column comment}',
                'after' => '{column_name}'
            ]
        );

        // Add new foreign key to table
        $setup->getConnection()->addForeignKey(
            $setup->getFkName(
                self::TABLE_NAME,
                '{entity_column}',
                '{main_table}',
                '{main_column}'
            ),
            '{entity_column}',
            $setup->getTable('{main_table}'),
            '{main_column}',
            Table::ACTION_CASCADE
        );

        // Add new index column to table
        $setup->getConnection()->addIndex(
            $setup->getTable(self::TABLE_NAME),
            $setup->getIdxName(self::TABLE_NAME, ['{column_name}']),
            ['{column_name}'],
        );

        // Change column to table
        $setup->getConnection()->changeColumn(
            $setup->getTable(self::TABLE_NAME),
            '{old_column_name}',
            '{new_column_name}',
            [
                'type' => Table::TYPE_{NAME},
                'nullable' => {true/false},
                'comment' => '{Column Comment}',
            ]
        );

        // Remove column from table
        $setup->getConnection()->dropColumn(
            $setup->getTable(self::TABLE_NAME),
            '{column_name}'
        );
    }
}
```

```xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="{Vendor}_{Module}" setup_version="{version_number}" />
</config>
```

---

# Finalizando

> Valores entre chaves (`{test}`) devem ser alterados na implementação do código.

## Habilitando as alterações

Comando para atualizar os dados do banco de dados e o esquema do banco de dados.

```bash
php bin/magento setup:upgrade
```

## Diretórios e Arquivos

Segue a a lista de diretórios e arquivos que devem ser criados.

```
- app/
  - code/
    - {Vendor}/
        - {Module}/
          - etc/
            - module.xml
          - Setup/
            - InstallSchema.php
            - UpgradeSchema.php
          - registration.php
          - composer.json
```