Como criar tabelas personalizadas no banco de dados com db_schema.xml no Magento 2
Tags: php, magento2, tutorial, braziliandevs
Published: 2021-10-07 22:06:42

# Contextualizando

## O que é uma tabela?

Tabelas são objetos que contêm um número infinito de colunas e número ilimitado de linhas (ou tuplas) que armazenam os dados de um banco de dados. Nas tabelas, os dados são organizados de maneira lógica em um formato de linha e coluna, onde cada linha representa um registro exclusivo e cada coluna representa um campo no registro e caracterizam os tipos de dados que deverão constar.

## Por que fazer uma tabela?

As tabelas são utilizadas para organizar e agrupar os dados por características ou princípios em comum. O banco de dados pode conter quantas tabelas forem necessárias para organizar os seus dados (limitado somente pela quantidade de espaço de armazenamento). Tabelas podem ser desenvolvidas para representar entidades, já que a entidade preocupa-se apenas com os dados de um objeto.

---

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

## db_schema.xml

*Declarative Setup* (configurações declarativas) são baseadas na estrutura de declaração, estes arquivos declaram como as estruturas do banco devem ser e determinam a diferença entre a estrutura da tabela atual e o que a tabela deveria ser. Essas diferenças podem ser representadas com operações de SQL atômico.

Os arquivos de configurações declarativas são priorizados e executados antes dos scripts de *Install Schema* e depois dos scripts de *Data Patch*. Para criar uma nova tabela no banco de dados, basta adicionar o nó `<table>` com os nós filhos e atributos preenchidos, e para deletar uma tabela basta remover o nó `<table>` com seus respectivos filhos e atributos do arquivo.

Esses arquivos devem seguir a estruturas de pastas `\{Vendor}\{Module}\etc\db_schema.xml`.

```xml
<?xml version="1.0"?>
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="{table_name}" resource="{resource_value}" engine="{engine_value}" comment="{Table Comment}">
        <column xsi:type="int" name="{integer_column_name}" padding="{length}" unsigned="{true/false}" nullable="{true/false}" identity="{true/false}" comment="{Column Comment}" />
        <column xsi:type="varchar" name="{varchar_column_name}" nullable="{true/false}" length="{lenght}" comment="{Column Comment}" />
        <column xsi:type="decimal" name="{decimal_column_name}" scale="{length}" precision="{length}" unsigned="{true/false}" nullable="{true/false}" comment="{Column Comment}"/>
        <column xsi:type="boolean" name="{boolean_column_name}" default="{true/false}" comment="{Column Comment}" />
        <column xsi:type="date" name="{date_column_name}" comment="{Column Comment}" />
        <column xsi:type="timestamp" name="created_at" on_update="false" nullable="false" default="CURRENT_TIMESTAMP" comment="Created At"/>
        <column xsi:type="timestamp" name="updated_at" on_update="true" nullable="false" default="CURRENT_TIMESTAMP" comment="Updated At"/>

        <constraint xsi:type="{constraint_value}" referenceId="{REFERENCE_ID}">
            <column name="{column_name}"/>
        </constraint>

        <constraint 
            xsi:type="foreign" 
            referenceId="{CURRENT_TABLE_NAME}_{COLUMN_NAME}_{REFERENCE_TABLE_NAME}_{REFERENCE_COLUMN_NAME}"
            table="{current_table_name}" 
            column="{column_name}" 
            referenceTable="{reference_table_name}"
            referenceColumn="{reference_column_name}"
            onDelete="{TRIGGER FOREIGN VALUE}"
        >
            <column name="{column_name}"/>
        </constraint>

        <index referenceId="{CURRENT_TABLE_NAME}_{COLUMN_NAME}" indexType="{index_value}">
            <column name="{column_name}"/>
        </index>
    </table>
</schema>
```

Cada arquivo `db_schema.xml` deve ter um ou mais nós `<table>`, cada nó desses representa uma tabela no banco de dados. Este nó pode possuir `<column>`, `<constraint>` e/ou `<index>` como nós filhos.

É possível renomear as tabelas. Nos esquemas declarativos serão criados uma nova tabela com um novo nome e deletado a tabela com o antigo nome. Para migrar os dados das colunas da antiga tabela para as colunas da nova tabela é necessário utilizar o atributo `onCreate` na declaração do nó `<table>` e adicionar o nome da tabela fonte.

### Atributos do nó table

| Atributos | Descrição                                                                                 |
|-----------|-------------------------------------------------------------------------------------------|
| name      | Nome da tabela no banco de dados.                                                         |
| engine    | Motor de busca do SQL, o valor deve serinnodb ou memory.                                  |
| resource  | Onde o banco de dados irá instalar a tabela. O valor deve ser default, checkout ou sales. |
| comment   | Comentário da tabela no banco de dados.                                                   |

O nó `<column>` é um nó filho do nó `<table>` que representa uma coluna dentro da respectiva tabela no banco de dados. Para criar uma nova coluna na tabela, basta adicionar o nó `<column>` com os atributos preenchidos e para deletar uma coluna, basta remover o nó `<column>` com seus respectivos atributos do arquivo. Este nó pode possuir os seguintes atributos:

### Atributos do nó column

| Atributos | Descrição                                                                                                                                                                                                                                                                                                                                                                                                                           |
|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| xsi:type  | Específica o tipo da coluna. Deve ser um dos seguintes valores:  <br /> - blob (podendo ser blob, mediumblob ou longblob)  <br /> - boolean  <br /> - date  <br /> - datetime  <br /> - int (podendo ser smallint, bigint ou tinyint)  <br />- json  <br /> - real (podendo ser decimal, float, double ou real)  <br /> - text (podendo ser text, mediumtext ou longtext)  <br /> - timestamp  <br /> - varbinary  <br /> - varchar |
| default   | Inicializa a coluna com o valor especificado no valor do atributo. O valor padrão deve ser do mesmo tipo definido no atributo xsi:type                                                                                                                                                                                                                                                                                              |
| disabled  | Desabilita ou deleta a tabela, coluna, restrição ou índice declarado.                                                                                                                                                                                                                                                                                                                                                               |
| identify  | Indica se a coluna é auto incrementada.                                                                                                                                                                                                                                                                                                                                                                                             |
| length    | Especifica o tamanho da coluna. Os valores podem ser do tipo char, varchar e varbinary.                                                                                                                                                                                                                                                                                                                                             |
| nullable  | Indica se o valor inserido na coluna pode ser nulo.                                                                                                                                                                                                                                                                                                                                                                                 |
| onCreate  | Gatilho do tipo DDL que permite mover dados de uma coluna existente para um nova coluna criada. Este gatilho funciona apernas quando a coluna é criada.                                                                                                                                                                                                                                                                             |
| padding   | O tamanho de uma coluna do tipo integer.                                                                                                                                                                                                                                                                                                                                                                                            |
| precision | O número de dígitos permitidos no tipo real.                                                                                                                                                                                                                                                                                                                                                                                        |
| scale     | O número de dígitos após o decimal no tipo real.                                                                                                                                                                                                                                                                                                                                                                                    |
| unsigned  | Para dados do tipo numérico, o valor de um tipo booleano determina se a coluna pode conter números positivos e negativos ou apenas valores positivos.                                                                                                                                                                                                                                                                               |

O nó `<constraint>` é um nó filho do nó `<table>` que representa as restrições das colunas da tabela no banco de dados, cada nó filho do nó `<constraint>` define uma coluna restrita. Para criar uma nova coluna restritiva na tabela, basta adicionar o nó `<constraint>` com os atributos e os nós filhos preenchidos e para deletar uma coluna restritiva, basta remover o nó `<constraint>` com seus respectivos atributos e filhos do arquivo. 

Os tipos `primary` e `unique` são chamados de tipos "restritivos internos", pois só podem ser aplicados no escopo da tabela onde são criadas. Restrições internas definem um ou mais nós filhos do atributo `column`. A restrição do tipo `foreign` é similar as chaves estrangeiras do SQL, este tipo de restrição conecta duas tabelas entre si. Este nó pode possuir os seguintes atributos:

### Atributos do nó constraint

| Atributos       | Descrição                                                                                                                                                                                                                                                                                              |
|-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| type            | Indica o tipo restritivo da coluna, podendo ser primary, unique ou foreign.                                                                                                                                                                                                                            |
| referenceId     | Um identificador personalizado que é utilizado para mapeamento da relação no escopo dos arquivos db_schema.xml. A entidade real no banco de dados possui um nome gerado pelo sistema. A maneira mais conveniente de definir o valor desse atributo é usar o valor do arquivo db_schema_whitelist.json. |
| table           | O nome da tabela atual. Este atributo só está disponível para o tipo foreign.                                                                                                                                                                                                                          |
| column          | A coluna na tabela que é referenciada em outra tabela. Este atributo só está disponível para o tipo foreign.                                                                                                                                                                                           |
| referenceTable  | Tabela que está sendo referenciada. Este atributo só está disponível para o tipo foreign.                                                                                                                                                                                                              |
| referenceColumn | Coluna que está sendo referenciada na tabela referenceTable. Este atributo só está disponível para o tipo foreign.                                                                                                                                                                                     |
| onDelete        | Gatilho da chave estrangeira. Os valores podem ser CASCADE, SET NULL ou NO ACTION. Este atributo só está disponível para o tipo foreign.                                                                                                                                                               |

Para criar uma nova coluna com índice na tabela, basta adicionar o nó `<index>` com os atributos e os nós filhos preenchidos e para deletar uma coluna com índice, basta remover o nó `<index>` com seus respectivos atributos e filhos do arquivo. Este nó pode possuir os seguintes atributos:

### Atributos do nó index

| Atributos   | Descrição                                                                                                                                                                                                                                                                                              |
|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| type        | Indica o tipo restritivo da coluna, podendo ser btree, fulltext ou hash.                                                                                                                                                                                                                               |
| referenceId | Um identificador personalizado que é utilizado para mapeamento da relação no escopo dos arquivos db_schema.xml. A entidade real no banco de dados possui um nome gerado pelo sistema. A maneira mais conveniente de definir o valor desse atributo é usar o valor do arquivo db_schema_whitelist.json. |
| indexType   | O nome da tabela atual. Este atributo só está disponível para o tipo foreign.                                                                                                                                                                                                                          |

---

# Finalizando

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

## Habilitando o alterações

Comando para atualizar os 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/
            - db_schema.xml
            - module.xml
          - registration.php
          - composer.json
```