Crear y actualizar tablas con los scripts de instalación en Magento2

Creación de tablas en Magento2

Es momento de empezar a crear datos desde nuestro módulo. Para esto, lo primero será crear nuestra primer tabla a través de los scripts de instalación.

En Magento2 los scripts relacionados con creación y modificación de tablas y actualización de datos se ubican dentro del directorio Setup.

Continuando con el armado del módulo Barbanet_SampleModule, voy a crear mi script de instalación de tabla.

Creamos entonces, dentro de nuestro módulo, el archivo /Setup/InstallSchema.php, y para el ejemplo de mi módulo, tendrá el siguiente contenido.

<?php
 
namespace Barbanet\SampleModule\Setup;
 
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\DB\Adapter\AdapterInterface;
 
/**
 * @codeCoverageIgnore
 */
class InstallSchema implements InstallSchemaInterface
{
    /**
     * {@inheritdoc}
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     */
    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $installer = $setup;
 
        $installer->startSetup();
 
        /**
         * Create table 'samplemodule_table'
         */
        $table = $installer->getConnection()->newTable(
            $installer->getTable('barbanet_samplemodule')
        )->addColumn(
            'row_id',
            \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
            null,
            ['identity' => true, 'nullable' => false, 'primary' => true],
            'Row ID'
        )->addColumn(
            'title',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            255,
            ['nullable' => false],
            'Row Title'
        )->addColumn(
            'content',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            '2M',
            [],
            'Row Content'
        )->addColumn(
            'creation_time',
            \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
            null,
            ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT],
            'Row Creation Time'
        )->addColumn(
            'update_time',
            \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
            null,
            ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE],
            'Row Modification Time'
        )->addColumn(
            'is_active',
            \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
            null,
            ['nullable' => false, 'default' => '1'],
            'Is Row Active'
        )->addIndex(
            $setup->getIdxName(
                $installer->getTable('barbanet_samplemodule'),
                ['title', 'content'],
                AdapterInterface::INDEX_TYPE_FULLTEXT
            ),
            ['title', 'content'],
            ['type' => AdapterInterface::INDEX_TYPE_FULLTEXT]
        )->setComment(
            'Barbanet SampleModule Table'
        );
        $installer->getConnection()->createTable($table);
 
        $installer->endSetup();
    }
}

Hay que tener presente con respecto a los scripts de instalación de Magento2 que desde ahora sólo se usarán 2 archivos: instalación y upgrade. No se utilizan más diferentes archivos por cada salto de versión. (En realidad hay más archivos posibles, que ya veremos más adelante, pero aquí me estoy refiriendo a la creación y actualización de estructura de base de datos).

Otra salvedad a tener en cuenta en este ejemplo. En mi caso, el módulo ya estaba instalado, por lo cual, el script de instalación nunca iba a funcionar. Para poder hacer la prueba, deshabilité el módulo desde la consola:

bin/magento module:disable Barbanet_SampleModule

Y luego lo borré de la tabla setup_module. La tabla setup_module es la equivalente a core_resource en Magento1.

Dicho eso, suponiendo que estoy instalando el módulo por primera vez, lo primero será activar el módulo:

bin/magento module:enable Barbanet_SampleModule

A continuación veremos el siguiente mensaje:

The following modules have been enabled:
- Barbanet_SampleModule
 
To make sure that the enabled modules are properly registered, run 'setup:upgrade'.
Cache cleared successfully.
Generated classes cleared successfully. Please run the 'setup:di:compile' command to generate classes.
Info: Some modules might require static view files to be cleared. To do this, run 'module:enable' with the --clear-static-content option to clear them.

Como puede verse, son bastante claros los pasos a seguir:

bin/magento setup:upgrade

Esto borrará el contenido de var/generation y comenzará a ejecutar los scripts relacionados con la estructura de la base de datos primero, para luego continuar con los scripts de datos. Cuando termine, ejecutamos:

bin/magento setup:di:compile

Un mensaje similar a este se verá cuando termine:

Compilation was started.
Interception cache generation... 7/7 [============================] 100% 3 mins 378.0 MiB
Generated code and dependency injection configuration successfully.

¿Cómo darnos cuenta si todo ha funcionado correctamente?.

Lo primero, puedo ir a Stores -> System -> Configuration -> Advanced -> Advanced. En mi caso, el módulo ya aparece como instalado.

Listado de módulos instalados en Magento2

Y ahora toca revisar la base de datos.

Tablas de Magento2

Resaltada puede verse la tabla que se definió en el script de instalación. Como es de esperarse, la estructura de datos es la del script.

Estructura de la tabla

Supongamos ahora que nos olvidamos de definir algún campo o necesitamos hacer algún cambio.

Para esto vamos a hacer uso del script de actualización. En este caso, el script ha de llamarse /Setup/UpgradeSchema.php, y su contenido (hipotético) será:

<?php

namespace Barbanet\SampleModule\Setup;
 
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\UpgradeSchemaInterface;

class UpgradeSchema implements UpgradeSchemaInterface
{
    /**
     * {@inheritdoc}
     */
    public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $setup->startSetup();
 
        if (version_compare($context->getVersion(), '2.7.0', '<')) {
            $setup->getConnection()->addColumn(
                $setup->getTable('barbanet_samplemodule'),
                'description',
                [
                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                    'length' => 255,
                    'nullable' => false,
                    'comment' => 'Row description'
                ]
            );
        }
        $setup->endSetup();
    }
}

Como comentaba antes, en Magento2 se utiliza un único archivo para las actualizaciones, por lo que dentro del método upgrade empezaremos a ver el uso de IF y la función version_compare para evaluar si corresponde o no, dada la versión actual del módulo, ejecutar tal o cual acción.

Teniendo el módulo ya instalado, volvemos a la consola y el comando a ejecutar será:

bin/magento setup:upgrade

Nuevamente se repetirá el proceso de limpieza de cache, scripts de estructura y luego de scripts de datos. Al finalizar, ejecutamos:

bin/magento setup:di:compile

Para confirmar que todo ha salido bien, revisamos nuevamente la estructura de la tabla y deberíamos ver lo siguiente:

Estructura de la tabla

Los ejemplos de este post están en el tag 2.7.0 del módulo.