Skip to content

Exemplos Oficiais — packages/people

Implementações de referência para os contratos documentados em contracts.md. Utilize-as como ponto de partida ao criar pacotes próprios ou adaptar a validação para novos países.

CPF (Brasil) — BrCpfValidator

php
final class BrCpfValidator implements DocumentValidatorContract
{
    public function key(): string
    {
        return 'br.cpf';
    }

    public function pattern(): string
    {
        return '/^\d{3}\.\d{3}\.\d{3}\-\d{2}$/';
    }

    public function normalize(string $document): string
    {
        return preg_replace('/\D/', '', $document);
    }

    public function validate(string $document): bool
    {
        $digits = $this->normalize($document);
        if (strlen($digits) !== 11 || preg_match('/^(\\d)\\1{10}$/', $digits)) {
            return false;
        }

        $calc = static function (array $numbers, int $factor): int {
            $sum = 0;
            foreach ($numbers as $number) {
                $sum += $number * $factor--;
            }
            $result = ($sum * 10) % 11;
            return $result === 10 ? 0 : $result;
        };

        $base = array_map('intval', str_split(substr($digits, 0, 9)));
        $dv1 = $calc($base, 10);
        $dv2 = $calc(array_merge($base, [$dv1]), 11);

        return $digits[9] == $dv1 && $digits[10] == $dv2;
    }
}
  • Armazene o regex padrão (pattern()) em tabela de configurações para permitir edições posteriores.
  • Adicione testes com CPFs válidos e inválidos em tests/Contracts/Document/BrCpfValidatorTest.php.

CNPJ (Brasil) — BrCnpjValidator

Segue lógica semelhante ao CPF, porém com 14 dígitos e pesos distintos. Recomenda-se extrair o cálculo dos dígitos verificadores para uma trait reutilizável (CalculatesBrazilianDv).

NIF Português — PtNifValidator

  • Regex: /^\d{9}$/.
  • Aplicar algoritmo de validação módulo 11.
  • Permitir prefixos específicos (1, 2, 3, 5, 6, 8, 9) de acordo com a legislação.

Lookup de Endereço com ViaCEP — ViaCepProvider

php
final class ViaCepProvider implements AddressLookupContract
{
    public function countryCode(): string
    {
        return 'BR';
    }

    public function lookupByPostalCode(string $postalCode): AddressDto
    {
        $normalized = preg_replace('/\D/', '', $postalCode);
        $response = Http::get("https://viacep.com.br/ws/{$normalized}/json/");

        if ($response->failed() || $response->json('erro')) {
            return AddressDto::empty();
        }

        return new AddressDto(
            street: $response['logradouro'] ?? '',
            number: null,
            district: $response['bairro'] ?? '',
            city: $response['localidade'] ?? '',
            state: $response['uf'] ?? '',
            postalCode: $normalized,
            country: 'BR'
        );
    }
}
  • Adicione cache (Cache::remember) para reduzir chamadas.
  • Documente limites de uso conforme a política da API.

Normalizador de Telefone com libphonenumber — LibPhoneNumberNormalizer

php
final class LibPhoneNumberNormalizer implements ContactNormalizerContract
{
    public function supports(string $type): bool
    {
        return $type === 'phone';
    }

    public function normalize(string $value): string
    {
        $util = PhoneNumberUtil::getInstance();
        $phone = $util->parse($value, 'BR'); // padrão configurável
        return $util->format($phone, PhoneNumberFormat::E164);
    }

    public function isValid(string $value): bool
    {
        try {
            $util = PhoneNumberUtil::getInstance();
            $phone = $util->parse($value, 'BR');
            return $util->isValidNumber($phone);
        } catch (\Throwable $e) {
            return false;
        }
    }
}
  • Permita sobrescrever o país padrão via config (people.contacts.default_region).
  • Adicione testes com números válidos/invalidos e cenários de exceção.

Normalizador de E-mail — DnsEmailNormalizer

  • supports('email').
  • Usa Str::lower(trim($value)).
  • Valida com filter_var($value, FILTER_VALIDATE_EMAIL) e consulta DNS MX (checkdnsrr).
  • Opcional: integra com serviços de verificação (Kickbox, ZeroBounce) via eventos.

Campos Customizados

Exemplo para student_id com máscara e cast para string.

php
final class StudentIdAttribute implements PersonAttributeContract
{
    public function key(): string
    {
        return 'student_id';
    }

    public function rules(): array
    {
        return ['nullable', 'regex:/^[A-Z]{3}\-\d{4}$/'];
    }

    public function cast(mixed $value): ?string
    {
        return $value ? strtoupper((string) $value) : null;
    }
}

Checklist de Implementação

  • [ ] Registrar contratos no service provider do pacote (DocumentValidatorRegistry, AddressLookupRegistry).
  • [ ] Criar testes de contrato e snapshots para payloads normalizados.
  • [ ] Documentar configuração (config/people.php) e fornecer comandos Artisan para listar validadores.
  • [ ] Publicar exemplos na documentação oficial e manter changelog por implementação.

Documentação privada do ecossistema Filament Core.