Files
claude-plugins/perfex-dev/skills/perfex-migrations/SKILL.md
T

5.0 KiB

name, description, layer
name description layer
perfex-migrations Migrações e upgrades de módulos Perfex CRM — gestão de versões, ficheiros de migração e actualizações de base de dados. Baseado apenas na documentação oficial. wiki

/perfex-migrations - Migrations Perfex CRM

Sistema de migrações e upgrades de módulos. Zero assumptions, zero hallucinations - apenas documentação oficial.


Documentação Base


Como Funciona

O Perfex CRM compara:

  • Versão no init file (header Version:)
  • Versão na base de dados (tabela tblmodules)

Se forem diferentes → Sistema mostra "Database upgrade required".


Estrutura de Migrations

modules/meu_modulo/
├── meu_modulo.php          # Init file com Version: X.Y.Z
└── migrations/
    ├── 001_version_100.php  # v1.0.0 → v1.0.1
    ├── 002_version_101.php  # v1.0.1 → v1.0.2
    ├── 100_version_100.php  # v1.0.0 inicial (alternativa)
    ├── 110_version_110.php  # v1.1.0
    └── 200_version_200.php  # v2.0.0

Formato do Ficheiro

Nomenclatura (CRÍTICO)

O Perfex usa Sequential Migration (não Timestamp).

NNN_version_NNN.php
│   │       │
│   │       └── Versão sem pontos (110 = 1.1.0)
│   └── Literal "version"
└── Número sequencial (3 dígitos, sem gaps)

Exemplos:

Versão Ficheiro
1.0.0 001_version_100.php ou 100_version_100.php
1.0.1 002_version_101.php ou 101_version_101.php
1.1.0 003_version_110.php ou 110_version_110.php
2.0.0 004_version_200.php ou 200_version_200.php

Convenção recomendada: Usar versão como prefixo (100, 110, 200...).


Template Migration

<?php

defined('BASEPATH') or exit('No direct script access allowed');

class Migration_Version_110 extends App_module_migration
{
    /**
     * Executado durante upgrade
     */
    public function up()
    {
        // Alterações de base de dados aqui
    }
}

Notas Importantes

  1. Classe: Migration_Version_NNN (NNN = versão sem pontos)
  2. Extends: App_module_migration
  3. Método: Apenas up() - não há down() (downgrades não suportados)
  4. Pode ser vazio: Se não houver alterações de BD, deixar up() vazio

Exemplos de Migrations

Adicionar Coluna

<?php

defined('BASEPATH') or exit('No direct script access allowed');

class Migration_Version_110 extends App_module_migration
{
    public function up()
    {
        $CI = &get_instance();

        // Adicionar coluna se não existir
        if (!$CI->db->field_exists('new_column', db_prefix() . 'meu_modulo')) {
            $CI->db->query('ALTER TABLE `' . db_prefix() . 'meu_modulo`
                ADD COLUMN `new_column` VARCHAR(255) DEFAULT NULL AFTER `name`');
        }
    }
}

Criar Nova Tabela

<?php

defined('BASEPATH') or exit('No direct script access allowed');

class Migration_Version_120 extends App_module_migration
{
    public function up()
    {
        $CI = &get_instance();

        if (!$CI->db->table_exists(db_prefix() . 'meu_modulo_items')) {
            $CI->db->query('
                CREATE TABLE `' . db_prefix() . 'meu_modulo_items` (
                    `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
                    `parent_id` INT(11) UNSIGNED NOT NULL,
                    `name` VARCHAR(255) NOT NULL,
                    `quantity` INT(11) NOT NULL DEFAULT 1,
                    PRIMARY KEY (`id`),
                    KEY `parent_id` (`parent_id`)
                ) ENGINE=InnoDB DEFAULT CHARSET=' . $CI->db->char_set . ';
            ');
        }
    }
}

Modificar Coluna

<?php

defined('BASEPATH') or exit('No direct script access allowed');

class Migration_Version_130 extends App_module_migration
{
    public function up()
    {
        $CI = &get_instance();

        // Alterar tipo de coluna
        $CI->db->query('ALTER TABLE `' . db_prefix() . 'meu_modulo`
            MODIFY COLUMN `amount` DECIMAL(15,2) NOT NULL DEFAULT 0.00');
    }
}

Adicionar Índice

<?php

defined('BASEPATH') or exit('No direct script access allowed');

class Migration_Version_140 extends App_module_migration
{
    public function up()
    {
        $CI = &get_instance();

        // Verificar se índice existe (evitar erro)
        $indexes = $CI->db->query('SHOW INDEX FROM `' . db_prefix() . 'meu_modulo`
            WHERE Key_name = "idx_status"')->result();

        if (count($indexes) == 0) {
            $CI->db->query('ALTER TABLE `' . db_prefix() . 'meu_modulo`
                ADD INDEX `idx_status` (`status`)');
        }
    }
}

Migração de Dados

<?php

defined('BASEPATH') or exit('No direct script access allowed');

class Migration_Version_150 extends App_module_migration
{
    public function up()
    {
        $CI = &get_instance();

        // Migrar dados existentes