Sistemas Corporativos em CakePHP – Separação de Módulos
Monday, September 20th, 2010
Sistemas Corporativos – A Jornada^
Inicio neste post uma jornada de vários artigos que acompanhará minha empreitada de desenvolver Sistemas Corporativos em CakePHP, como ERPs, CRMs, etc.
Todos sabem que o CakePHP é um ótimo framework para sistemas web, bem como seu inspirador, o Rais, porém poucos usam-o para Sistemas Corporativos. Per si o CakePHP não é completamente funcional neste caso, porém felizmente ele suporta uma gama enorme de especializações como helpers, behaviors e plugins que servirão como base para implementação dos recursos necessários.
Segue abaixo algumas das funcionalidades que acho necessárias pare o uso Corporativo.
- Organização e Separação de Módulos <- Tema deste artigo
- Aplicação de regras de negócio avançadas nos models
- Plataforma de portlets (widgets, gadgets)
- Edição de tabelas filhas “inline” (helper + javascript)
- Filtros avançados e grid dinâmico no índice, com agrupamento, sumarização, etc.
- Histórico transacional com suporte a “dezfazer” última ação no banco de dados
- Exportação simples do resultado do índice para CSV e PDF
- “Rascunho” e “Lixeira” de registros
- Helper de Suggest
- Helper de Gráficos
Organização e Separação de Módulos^
Como Sistemas Corporativos tendem a ter mais de 100 módulos, é imprescindível que haja uma organização de arquivos de tabelas. Acredito que seja uma opinião consensual entre os desenvolvedores desse tipo de sistema.
Organização de Arquivos^

Na imagem acima, podemos perceber que existe uma pasta nova, alheia a estrutura padrão do CakePHP, chamada “modules”. Em sua essência esta pasta é idêntica a “plugins”, comportando uma estrutura nova de “controllers”, “models” e “views” bem como seu próprio “app_model” e “app_controller”. Para esta pasta funcionar, é necessário adicionar as seguinte linhas no arquivo “bootstrap.php”:
-
App::build(array(
-
'plugins' => array(
-
APP . 'plugins' . DS,
-
APP . 'modules' . DS
-
)
-
));
Nota-se uma divisão semântica entre os módulos que gera uma organização modo a agrupar os que são desenvolvidos em conjunto. Adotei um padrão que, para os conceitos básicos do sistema como: países, cidades, etc. utilizando do módulo básico chamado “base” para tal.
Alguns módulos são pré-requisitos de outros, acredito que seja necessário verificar os pré-requisitos porteriorimente.
Organização de Tabelas^
Na imagem acima, podemos perceber que está sendo utilizado um prefixo nas tabelas. Este prefixo é exatamente igual ao nome do módulo no qual ela será utilizada.
Na imagem acima, a estrutura da tabela “financeiro_transacoes”, observamos que as FKs (foreign keys – chaves estrangeiras) para o próprio módulo, não utilizam novamente o prefixo do módulo, como por exemplo “transacao_tipo_id”. Já as FKs que referenciam outro módulo tem em seu nome o prefixo do módulo em questão, como a “pessoa_estabelecimento_id”, que refere-se a tabela “estabelecimento_id” do módulo “pessoa”.
Alterações no Código^
No app_model do módulo^
-
class FinanceiroAppModel extends AppModel {
-
var $tablePrefix = 'financeiro_';
-
}
Para utilizar a tabela “financeiro_transacoes” como simplesmente “financeiro” dentro do módulo, é necessário dizer para o CakePHP que aquela tabela tem aquele prefixo, como exemplificado no código acima.
É absolutamente necessário que todos os models deste módulo extendam o “FinanceiroAppModel” e não o “AppModel” para o correto funcionamento do prefixo.
No Model^
-
class Transacao extends FinanceiroAppModel {
-
var $name = 'Transacao';
-
var $displayField = 'descricao';
-
var $belongsTo = array(
-
'TransacaoTipo' => array(
-
'className' => 'Financeiro.TransacaoTipo',
-
'foreignKey' => 'transacao_tipo_id'
-
),
-
'TransacaoSituacao' => array(
-
'className' => 'Financeiro.TransacaoSituacao',
-
'foreignKey' => 'transacao_situacao_id'
-
),
-
'TransacaoIrma' => array(
-
'className' => 'Financeiro.Transacao',
-
'foreignKey' => 'transacao_irma_id'
-
),
-
'Cliente' => array(
-
'className' => 'Pessoa.Cliente',
-
'foreignKey' => 'pessoa_cliente_id'
-
),
-
'Fornecedor' => array(
-
'className' => 'Pessoa.Fornecedor',
-
'foreignKey' => 'pessoa_fornecedor_id'
-
)
-
);
-
var $hasMany = array(
-
'TransacaoBaixa' => array(
-
'className' => 'Financeiro.TransacaoBaixa',
-
'foreignKey' => 'transacao_id',
-
'dependent' => false
-
),
-
'TransacaoCentro' => array(
-
'className' => 'Financeiro.TransacaoCentro',
-
'foreignKey' => 'transacao_id',
-
'dependent' => false
-
)
-
);
-
}
No código acima, nas FKs, escrevemos o prefixo da tabela na referência utilizando a sintaxe: “Modulo.Model”, como visto no exemplo.
Nos Controller^
-
class TransacoesController extends AppController {
-
function index() {
-
$transacaoTipos = $this->Transacao->TransacaoTipo->find('list');
-
$transacaoSituacoes = $this->Transacao->TransacaoSituacao->find('list');
-
$filterOptions = $this->AdvancedFilter->filterOptions;
-
$transacoes = $this->paginate(null, $this->AdvancedFilter->filter);
-
$this->Transacao->recursive = 0;
-
$this->set(compact('transacoes', 'filterOptions', 'transacaoTipos', 'transacaoSituacoes'));
-
}
No controller, acessamos o model “Transacao” diretamente, sem utilizar o prefixo “Financeiro”.
Nos Links^
-
echo $this->Html->link('Transações', array('plugin' => 'financeiro', 'controller' => 'transacoes', 'action' => 'index'));
Para criar um link para um módulo, utilizamos o índice “plugin” no método “link” do helper “Html”, conforme o código acima. Ele gerará a seguinte URL:
-
/financeiro/transacoes/index
Conclusão^
O CakePHP é um framework extremamente versátil que possibilita organizar o código de diversas maneiras, como pudemos ver no exemplo deste artigo.
Este é o primeiro artigo da série “Sistemas Corporativos”, até a próxima.

