--- name: perfex-module-basics description: Fundamentos de desenvolvimento de módulos Perfex CRM — estrutura de pastas, ficheiro init, headers e integração CodeIgniter. Baseado apenas na documentação oficial. --- # /perfex-module-basics - Estrutura Base Módulos Perfex CRM Fundamentos para desenvolvimento de módulos Perfex CRM. **Zero assumptions, zero hallucinations** - apenas documentação oficial. --- ## Documentação Base - [Module Basics](https://help.perfexcrm.com/module-basics/) - [Introduction to Modules](https://help.perfexcrm.com/introduction-to-perfex-crm-modules/) - [Module File Headers](https://help.perfexcrm.com/module-file-headers/) --- ## Estrutura de Pastas (Obrigatória) ``` modules/ └── meu_modulo/ ├── meu_modulo.php # Init file (OBRIGATÓRIO - mesmo nome da pasta) ├── controllers/ │ └── Meu_modulo.php ├── models/ │ └── Meu_modulo_model.php ├── views/ │ ├── index.php │ └── form.php ├── libraries/ ├── helpers/ ├── language/ │ └── english/ │ └── meu_modulo_lang.php ├── migrations/ │ └── 001_version_100.php ├── config/ └── index.html # SEGURANÇA - prevenir directory listing ``` --- ## Init File (Obrigatório) O ficheiro init é o ponto de entrada do módulo. **DEVE ter o mesmo nome da pasta.** ### Template Mínimo ```php db->table_exists(db_prefix() . 'meu_modulo')) { $CI->db->query('CREATE TABLE `' . db_prefix() . 'meu_modulo` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) NOT NULL, `created_at` DATETIME NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=' . $CI->db->char_set . ';'); } // Adicionar opções add_option('meu_modulo_version', '1.0.0'); } /** * Executado quando o módulo é desactivado */ function meu_modulo_deactivation_hook() { // Limpeza temporária (não apagar dados) } /** * Executado quando o módulo é removido */ function meu_modulo_uninstall_hook() { $CI = &get_instance(); // Remover tabelas $CI->db->query('DROP TABLE IF EXISTS `' . db_prefix() . 'meu_modulo`'); // Remover opções delete_option('meu_modulo_version'); } ``` --- ## File Headers (Meta-Informação) ### Headers Obrigatórios | Header | Descrição | |--------|-----------| | `Module Name` | **ÚNICO OBRIGATÓRIO** - Nome do módulo | ### Headers Opcionais (Recomendados) | Header | Descrição | Exemplo | |--------|-----------|---------| | `Description` | Descrição funcional | `CRM integration module` | | `Version` | Versão semântica | `1.0.0` | | `Requires at least` | Versão mínima Perfex | `2.3.*` | | `Author` | Nome do autor | `Descomplicar` | | `Author URI` | Website do autor | `https://descomplicar.pt` | | `Module URI` | Página do módulo | `https://...` | ### Exemplo Completo ```php /* Module Name: Customer Portal Description: Extended customer self-service portal Version: 2.1.0 Requires at least: 2.3.* Author: Descomplicar Author URI: https://descomplicar.pt Module URI: https://descomplicar.pt/modules/customer-portal */ ``` --- ## Aceder ao CodeIgniter Fora de controllers/models, usar `get_instance()`: ```php $CI = &get_instance(); // Carregar helper $CI->load->helper('meu_modulo/meu_helper'); // Carregar library $CI->load->library('meu_modulo/minha_library'); // Carregar model $CI->load->model('meu_modulo/meu_modulo_model'); // Aceder à BD $CI->db->get(db_prefix() . 'meu_modulo'); ``` --- ## Funções de Módulo Essenciais ### Paths e URLs ```php // URL do módulo $url = module_dir_url('meu_modulo'); // Resultado: https://crm.exemplo.pt/modules/meu_modulo/ // Path absoluto $path = module_dir_path('meu_modulo'); // Resultado: /var/www/html/modules/meu_modulo/ // Path das libraries $libs_path = module_libs_path('meu_modulo'); // Resultado: /var/www/html/modules/meu_modulo/libraries/ ``` ### Opções (Persistência) ```php // Criar opção (não sobrescreve se existir) add_option('meu_modulo_setting', 'valor', 0); // Ler opção $valor = get_option('meu_modulo_setting'); // Actualizar opção (cria se não existir - v2.3.3+) update_option('meu_modulo_setting', 'novo_valor'); // Apagar opção delete_option('meu_modulo_setting'); ``` ### Database Prefix **SEMPRE usar `db_prefix()` em queries:** ```php // CORRECTO $CI->db->get(db_prefix() . 'meu_modulo'); $CI->db->query('SELECT * FROM ' . db_prefix() . 'meu_modulo'); // ERRADO - vai falhar se prefix não for "tbl" $CI->db->get('tblmeu_modulo'); ``` --- ## Convenções de Nomenclatura ### Prefixos (OBRIGATÓRIO) Todas as funções e classes devem ter prefixo único para evitar conflitos: ```php // CORRECTO function meu_modulo_get_data() { } class Meu_modulo_helper { } // ERRADO - pode conflitar com outros módulos/core function get_data() { } class Helper { } ``` ### Nomes de Ficheiros | Tipo | Convenção | Exemplo | |------|-----------|---------| | Controller | Primeira letra maiúscula | `Meu_modulo.php` | | Model | Sufixo `_model` | `Meu_modulo_model.php` | | Helper | Sufixo `_helper` | `meu_modulo_helper.php` | | Language | Sufixo `_lang` | `meu_modulo_lang.php` | --- ## Modo de Desenvolvimento **SEMPRE activar durante desenvolvimento:** 1. Abrir `application/config/config.php` 2. Definir: `$config['development_mode'] = true;` Isto mostra: - Erros PHP - Warnings de depreciação - Stack traces --- ## Anti-Patterns (NUNCA FAZER) | Anti-Pattern | Risco | Alternativa | |--------------|-------|-------------| | Modificar ficheiros core do Perfex | Quebra em updates | Usar hooks | | Hardcode database prefix `tbl` | Falha em instalações custom | `db_prefix()` | | Funções sem prefixo | Conflitos | Prefixar tudo | | Init file com nome diferente da pasta | Módulo não detectado | Nomes iguais | | Desenvolver sem development mode | Erros silenciosos | Activar sempre | | Não incluir index.html nas pastas | Directory listing | Incluir sempre | --- ## Checklist Novo Módulo ``` 1. [ ] Pasta em /modules/ com nome único 2. [ ] Init file com mesmo nome da pasta 3. [ ] Header "Module Name" presente 4. [ ] defined('BASEPATH') em todos os ficheiros PHP 5. [ ] index.html em todas as pastas 6. [ ] Funções com prefixo único 7. [ ] db_prefix() em todas as queries 8. [ ] Development mode activado para testes 9. [ ] Hooks de activation/deactivation/uninstall 10. [ ] Testado em ambiente staging ``` --- **Versão:** 1.0.0 | **Autor:** Descomplicar® **Fonte:** help.perfexcrm.com/module-basics