Skip to main content
Em vez de strings e inteiros soltos, todos os campos de domínio nos SDKs SUOT são representados por Value Objects — objetos imutáveis que carregam um valor validado, transmitem o significado exato do campo e são completamente compreensíveis por IDEs, PHPStan e agentes de IA. Se um CNPJ inválido for fornecido, o erro acontece na construção do objeto, não em algum ponto imprevisível durante a execução.

O que é um Value Object

Um Value Object é um objeto cujo valor define sua identidade — dois Cnpj com o mesmo número são equivalentes, independentemente de serem instâncias diferentes. Nos SDKs SUOT, Value Objects têm três propriedades fundamentais:
  • Imutabilidade — após construído, o valor não pode ser alterado
  • Validação no construtor — dados inválidos lançam exceção imediatamente, na origem
  • Tipagem explícitaCnpj não é intercambiável com Cpf, mesmo que ambos sejam strings por baixo
Essa abordagem elimina uma categoria inteira de bugs: passar um CPF onde um CNPJ é esperado torna-se um erro de tipo detectado pelo PHPStan, não um erro em produção.

Value Objects disponíveis

A tabela abaixo lista os Value Objects presentes nos SDKs SUOT. Consulte a documentação de cada SDK para o conjunto completo.
Value ObjectRepresentaExemplo de construção
CnpjCNPJ válido (14 dígitos, com ou sem formatação)new Cnpj('12345678000195')
CpfCPF válido (11 dígitos, com ou sem formatação)new Cpf('12345678909')
ChaveCTeChave de acesso do CT-e (44 dígitos)new ChaveCTe('35240112345678000195570010000000011000000014')
ChaveMDFeChave de acesso do MDF-e (44 dígitos)new ChaveMDFe('41240112345678000195580010000000021000000025')
ProtocoloNúmero de protocolo de autorização SEFAZnew Protocolo('135240000012345')
InscricaoEstadualInscrição Estadual do emitentenew InscricaoEstadual('110042490114')
RntrcRegistro Nacional de Transportadores Rodoviários de Cargasnew Rntrc('12345678')
PlacaPlaca de veículo no padrão Mercosul ou antigonew Placa('ABC1D23')
Value Objects aceitam strings com ou sem formatação (pontos, barras, hífens). A normalização ocorre internamente — você não precisa limpar a string antes de construir o objeto.

Validação embutida

A validação acontece no construtor, não em um método validate() separado que você precisa lembrar de chamar. Isso significa que um Value Object que existe em memória é, por definição, válido.
<?php

use Suot\Fiscal\ValueObjects\Cnpj;
use Suot\Fiscal\ValueObjects\ChaveCTe;
use Suot\Fiscal\ValueObjects\Protocolo;
use Suot\Fiscal\Exceptions\InvalidValueException;

// ✅ Construção bem-sucedida — CNPJ válido
$cnpj = new Cnpj('12345678000195');

// ❌ Lança InvalidValueException imediatamente — CNPJ com dígito verificador errado
try {
    $cnpjInvalido = new Cnpj('12345678000100');
} catch (InvalidValueException $e) {
    // O erro está aqui, na origem, não dentro do Handler ou no retorno da SEFAZ.
    echo $e->getMessage(); // "CNPJ inválido: dígito verificador incorreto."
}

// ❌ Lança InvalidValueException — chave com comprimento errado
try {
    $chaveIncompleta = new ChaveCTe('35240112345678');
} catch (InvalidValueException $e) {
    echo $e->getMessage(); // "ChaveCTe deve ter exatamente 44 dígitos."
}
Nunca capture InvalidValueException para silenciar o erro e continuar o fluxo. Essa exceção indica que os dados de entrada são inválidos — a aplicação deve rejeitá-los antes de tentar qualquer operação fiscal ou regulatória.

Value Objects e PHPStan

Os SDKs SUOT são desenvolvidos com PHPStan ao nível máximo. Todos os métodos de Commands, Handlers e Results usam tipos concretos de Value Objects em suas assinaturas — nunca string onde um Cnpj é esperado.
<?php

// O PHPStan detecta esse erro antes da execução:
// Argument #1 ($emitente) of CteAutorizacaoCommand::__construct()
// expects Suot\Fiscal\ValueObjects\Cnpj, string given.

$command = new CteAutorizacaoCommand(
    emitente: '12345678000195', // ← erro de tipo detectado estaticamente
    chave: new ChaveCTe('35240112345678000195570010000000011000000014'),
    xml: $xmlAssinado,
);
Isso significa que erros de integração que normalmente só apareceriam em produção são detectados no pipeline de CI — ou diretamente na sua IDE, antes mesmo de rodar o código.

Usando Value Objects com named arguments

A combinação de Value Objects e named arguments torna o código de integração autoexplicativo. Não é necessário consultar a documentação para entender o que cada argumento representa.
<?php

use Suot\Antt\Rntrc\ConsultaRntrcCommand;
use Suot\Antt\ValueObjects\Rntrc;
use Suot\Antt\ValueObjects\Cnpj;

// Named arguments + Value Objects = intent clara, sem ambiguidade
$command = new ConsultaRntrcCommand(
    transportador: new Cnpj('98765432000188'),
    rntrc: new Rntrc('87654321'),
);

// Comparação: o mesmo código sem Value Objects e sem named arguments
// $command = new ConsultaRntrcCommand('98765432000188', '87654321');
// ↑ Qual é o transportador? Qual é o RNTRC? Qual é a ordem dos argumentos?
//   Isso só pode ser respondido consultando a assinatura do construtor.
Se a sua IDE exibir o tipo incorreto para um Value Object (por exemplo, inferir mixed em vez do tipo concreto), verifique se o PHPStan e o servidor de linguagem PHP da sua IDE estão usando a mesma versão do php.ini e do autoloader. Editores como PhpStorm e VS Code com Intelephense resolvem tipos de Value Objects automaticamente quando o Composer autoload está configurado corretamente.