Visão Geral da Arquitetura
O middag-account segue uma arquitetura DDD Light com direção de dependência estrita. A lógica de domínio reside em PHP puro, sem nenhuma importação do WordPress. O WordPress atua como adaptador de infraestrutura.
Camadas
src/
├── Core/ # DI Container, Kernel, ServiceProvider, Middleware
├── Domain/ # PHP puro — ZERO dependências WordPress
├── WordPress/ # Camada de abstração CMS (6 adaptadores)
├── Api/V1/ # REST controllers (middag-account/v1)
├── Integration/ # HubSpot, Stripe, ISSNet, BancoInter, Cloudflare, SolidAffiliate
└── UI/ # Inertia page controllers, Router, FormPanelDataDireção de Dependência
WordPress/ ──→ Domain/
Api/ ──→ Domain/
Integration/ → Domain/
UI/ ──→ Domain/O Domain nunca importa de WordPress, Api, Integration ou UI. Isso é garantido pela análise estática do PHPStan.
Symfony DI Container 7.4
Todas as classes utilizam injeção de construtor. Zero chamadas estáticas a serviços.
Auto-discovery por sufixo: classes com sufixo Service, Repository, Controller, Handler, Hooks ou Registrar são registradas automaticamente. Adicionar uma nova classe com o sufixo correto é suficiente -- nenhum registro manual é necessário.
O container é compilado em produção para melhor desempenho.
Mapeamento de Namespaces (PSR-4)
| Namespace | Diretório |
|---|---|
Middag\Account\Core\ | src/Core/ |
Middag\Account\Domain\{Name}\ | src/Domain/{Name} |
Middag\Account\WordPress\ | src/WordPress/ |
Middag\Account\Api\V1\ | src/Api/V1/ |
Middag\Account\Integration\{Name}\ | src/Integration/ |
Middag\Account\UI\ | src/UI/ |
Camada de Domínio
Cada domínio segue uma estrutura padrão:
Domain/{Name}/
├── {Name}Entity.php # Imutável (readonly), JsonSerializable
├── {Name}DTO.php # Data Transfer Object
├── {Name}RepositoryInterface.php # Contrato (interface)
├── {Name}Service.php # Lógica de negócio, orquestração
├── {Name}Status.php # Enum de status com transições
└── {Name}Exception.php # Exceções específicas do domínioAs entidades utilizam propriedades readonly do PHP 8.4, backed enums para status e métodos factory fromArray() que aceitam tanto chaves snake_case da API quanto chaves com prefixo CCT.
Camada de Abstração WordPress (6 Adaptadores)
| Adaptador | Responsabilidade |
|---|---|
| PostType | Registro de CPT (middag_{domain}), capabilities customizadas |
| Database | Abstração sobre wp_posts + wp_postmeta, toggle CCT |
| Hook | HookInterface com register(), prefixo middag/ |
| Rest | Registro de rotas REST com permission_callback |
| Cron | Handlers leves de WP-Cron delegando para serviços de domínio |
Templates sobregraváveis pelo tema via TemplateRenderer |
Padrão Repository
O código de domínio define interfaces de repositório. A camada adaptadora WordPress fornece implementações concretas usando QueryBuilder e MetaRepository. O container DI vincula a interface à implementação.
// Camada de domínio — interface PHP pura
namespace Middag\Account\Domain\Organization;
interface OrganizationRepositoryInterface
{
public function findById(int $id): ?OrganizationEntity;
public function findByOwnerId(int $ownerId): array;
public function save(OrganizationDTO $dto): int;
}// Camada WordPress — implementação concreta
namespace Middag\Account\WordPress\Repository;
final class OrganizationRepository implements OrganizationRepositoryInterface
{
// Usa QueryBuilder + MetaRepository internamente
}Toggle de Repositório Dual
A opção middag_migration_complete alterna entre repositórios CCT ($wpdb direto) e repositórios baseados em wp_posts. Isso permite migração gradual sem perda de dados.
Sequência de Boot
O plugin inicializa no hook plugins_loaded -- nunca imediatamente. O Kernel compila o container DI, registra hooks e carrega serviços auto-descobertos.
add_action('plugins_loaded', function (): void {
$kernel = new Kernel();
$kernel->boot();
});Recursos do PHP 8.4+
- Backed enums nativos para todos os tipos de status
- Classes e propriedades
readonlyem todas as entidades - Expressões match para transições de status
- Named arguments em toda a base de código
- Tipagem estrita aplicada em todos os arquivos