# validator-docs: Brazilian document validation rules for Laravel

> validator-docs is a PHP library for Laravel that adds validation rules for Brazilian documents, covering personal records such as CPF, CNH, passport, voter title and health card number, company records such as CNPJ and state registration, and vehicle records such as RENAVAM and licence plate. It also separates format checks from validity checks, so a form can demand only the shape of a number or its check digits, or both.

**geekcom/validator-docs** — Validação de CPF, CNPJ, CNH, NIS, DDD, Título Eleitoral e Cartão Nacional de Saúde com Laravel.

- Repository: https://github.com/geekcom/validator-docs
- Stars: 588 · Forks: 99
- Language: PHP
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/geekcom-validator-docs

## Document rules that plug into the Laravel validator

validator-docs, whose README title is Validator Docs - Brasil, is a PHP library for validating Brazilian documents using Laravel. The description calls it a library for validating documents of Brazil with Laravel, and the topics list laravel, laravel-package, laravel-validation, validation-library and laravel10 alongside the individual document types.

The mechanism is the one Laravel developers already know. The package registers validation rules, and you use them in the ordinary validate call:

```php
$this->validate($request, [
    'cpf' => 'required|cpf',
]);
```

There is no service to inject, no configuration file to publish, and no separate validation layer to learn. The rules appear where the other rules appear, which means a form that mixes a document check with a string length and a required field reads the same way it always did.

The set of documents is the substance of the package. Personal records are covered by cpf, which checks whether a CPF is valid, cnh for the national driving licence, passaporte for the Brazilian passport, titulo_eleitor for the voter title, nis for the PIS, PASEP, NIT or NIS number, and cns for the national health card number. Company records are covered by cnpj, which accepts a numeric or an alphanumeric CNPJ, cpf_cnpj which accepts either, and inscricao_estadual for the state registration, which is checked against a specific federative unit.

There is also a family of documents that sits outside that neat split: certidao for a birth, marriage or death certificate, renavam for the national vehicle registry, placa for a vehicle licence plate, and ddd for a Brazilian area code.

The licence is MIT, the package is on Packagist as geekcom/validator-docs, and the repository carries a src/ directory, a tests/ directory, a composer.json, a phpcs.xml and a phpunit.xml.dist, so it is a conventional library with a conventional test setup.

## Format rules and validity rules are different rules

The package draws a distinction that is easy to miss and worth understanding before you use it.

Every document type above has a validation rule that checks the document, and several of them have a separate rule prefixed with formato_ that checks only whether the string is shaped like the document. The format rules are formato_cpf, formato_cnpj, formato_nis, formato_certidao and formato_cpf_cnpj.

So formato_cpf verifies the shape of a CPF in the 999.999.999-99 style, and formato_cnpj verifies the 99.999.999/9999-99 style, and formato_cpf_cnpj checks the shape of either one. The README shows the format of a birth certificate as well, with both the punctuated and the space separated forms.

The valid distinction is the point. A format rule catches a typo, a truncated paste or a field that was filled with the wrong kind of number. A validity rule additionally applies the check digit algorithm, which is what catches a mistyped digit.

The README shows how to combine them when a single field accepts either document type, which is the common case for a field labelled generically as tax id:

```php
$this->validate($request, [
    'cpf_or_cnpj' => 'formato_cpf_cnpj|cpf_cnpj',
]);
```

The first rule establishes the shape, the second establishes validity, and because the pipe separated rules are applied in sequence, a value that is well shaped but has a bad check digit still fails.

The difference matters in a second way. A format rule is safe to apply to a partially typed value in a live form, since it does not depend on a complete number, whereas a validity rule is only meaningful once the whole document has been entered.

## Inscricao_estadual needs the state, and the other rules do not

One rule in the list takes a parameter, and the README flags it in a note under the controller example: to validate a state registration you have to supply the UF, the federative unit.

```php
$this->validate($request, [
    'inscricao_estadual' => 'required|inscricao_estadual:SP',
]);
```

The reason is structural rather than stylistic. A state registration is issued per state, and the checksum and format rules differ between them, so the validator cannot check one without knowing which state issued it. The controller example in the README uses SP, Sao Paulo, and the full example lists the same rule alongside the others.

This is the single place in the package where a validation rule needs more than a field name and the value, and it is a small design point with a real consequence: a form that accepts state registration from users in more than one state has to select the rule parameter dynamically rather than declare one rule per state, which means the field cannot be a plain static rule string in the controller.

Everything else in the list takes just the value, including the rules that look as though they would need context. The ddd rule checks a Brazilian area code, and it needs no state, because area codes are nationally allocated in a way that a single table can describe.

The controller example collects the whole set at once, which is a useful thing to copy because it shows the full vocabulary in one place:

```php
public function store(Request $request)
{
    $data = $request->all();

    $this->validate($request, [
        'cpf' => 'required|cpf',
        'cnpj' => 'required|cnpj',
        'cnh' => 'required|cnh',
        'titulo_eleitor' => 'required|titulo_eleitor',
        'nis' => 'required|nis',
        'cns' => 'required|cns',
        'ddd' => 'required|ddd',
        'renavam' => 'required|renavam',
        'placa' => 'required|placa',
        'certidao' => 'required|certidao',
        'inscricao_estadual' => 'required|inscricao_estadual:SP',
        'passaporte' => 'required|passaporte',
    ]);
```

There is also a cpf_cnpj rule for a field that may hold either, which is the common case for a company form that asks for the owner's tax id.

## Installing the package and running its tests

The installation is described in two ways, and the second is the one most people will use.

The first is adding it to the require block of composer.json:

```json
"require": {
    "geekcom/validator-docs" : "^3.9"
 }
```

The second is the command that does the same thing:

```bash
composer require geekcom/validator-docs
```

after which the dependencies are installed with:

```bash
composer install
```

The version constraint in the README is a caret on 3.9, and the release history shows 3.12.0 as the newest tag, so the constraint still selects the current line.

The README also points to a legacy branch, 5.x.x, for the version compatible with Laravel 5. That is worth noting because the constraint on the main branch assumes a modern Laravel, and a project stuck on the older framework has a separate line rather than a documented upgrade path.

For running the tests, the instructions are to install the project dependencies and then run:

```bash
composer test
```

The project itself is maintained with the usual quality gates. There is a build status badge for a workflow named proposing-changes, a coverage badge pointing at Coveralls, a PHPStan badge, and badges for monthly and total downloads from Packagist.

There is also a section in the README for document generators to use in tests, which is a practical detail that says a lot about how the library is used. Generating valid and invalid sample documents, rather than hardcoding a handful of strings, is how you check that a validation rule rejects the right things.

## What a check digit can and cannot tell you

The honest limitation of this whole class of library is worth stating, because the rules look authoritative and are not.

A CPF, CNPJ, CNH, NIS or CNS validator checks the structure of the number and applies its check digit algorithm. What it cannot do is tell you whether the number was ever issued, whether it belongs to the person who typed it, or whether it has been cancelled. The check digit is a transcription error detector, not an identity check.

That distinction has a practical consequence for a form. A CPF that passes validation is a well formed number, and a mistyped CPF that happens to pass is a well formed number that belongs to somebody else. Any flow where the identity matters, a payroll entry, a credit application, a delivery address, needs the registry consulted as well, and that is a different kind of integration with different costs: a network dependency, latency, availability and the handling of personal data that leaves your infrastructure.

The library is still the right tool for the part it does. Rejecting a mistyped number at the form, before it reaches a database column that someone will later treat as a real identifier, is a genuine improvement over accepting free text, and the difference between a format rule and a validity rule gives you a second, cheaper tier when a full check is not yet warranted.

The CNPJ rule is a small example of the same idea. The README says the cnpj rule checks a numeric or an alphanumeric CNPJ, and the new alphanumeric CNPJ format means a validator written only for the old numeric layout would reject valid identifiers. A library that tracks the format is doing something a hand written regex does not.

## A maintained dependency with a small release surface

The maintenance picture is steady rather than busy.

The visible releases are 3.11.0 on 2025-05-07, 3.11.1 on 2025-05-13, and 3.12.0 on 2026-03-07. The last push to the repository was on 2026-09-16, so the branch is carrying work that is not in a tag, which is normal for a library with a small number of maintainers and a steady user base.

The ten months between the 3.11 releases and 3.12.0 are the interesting gap. A validation ruleset does not need constant updating, and a release gap of that length is a sign that the rules themselves are stable, but it is also a reminder that a new document format, such as the alphanumeric CNPJ, arrives on a schedule nobody in this project controls.

The repository contents are modest and tell you the project is a library rather than a service. There is src/ for the rules, tests/ for the suite, composer.json and composer.lock, phpcs.xml for the coding standard, phpunit.xml.dist for the test configuration, a CHANGELOG.md and a LICENSE.

The MIT licence is the simplest possible case for a dependency, and there is a donation request at the top of the README, which is the usual arrangement for a package maintained by a small team whose users number in the thousands according to the download badges.

For a team, the practical summary is that this is a package you add once, pin, and stop thinking about, except for the one case where a document format changes and the validation rules have to move with it.

## Conclusion

validator-docs suits a Laravel team building forms for Brazilian users, where a mistyped CPF or CNPJ would otherwise reach the database as a real looking identifier, and it suits anyone who wants the check digit rules in one dependency rather than scattered in application code. It does not suit you if you need to know whether a document was genuinely issued, because the library checks structure and check digits, not the registry, and it does not suit a project that is not on Laravel 5 or later, since the Laravel 5 compatible line lives on a separate branch. Check three things before you adopt it: which document types your forms actually collect, whether the ones you need need a state parameter the way state registration does, and whether you are happy with a library whose last tagged release is 3.12.0 while the branch keeps moving. The last push to the repository was on 2026-09-16.

## FAQ

### What can validator-docs validate?

It adds Laravel validation rules for CPF, CNPJ, CNH, passport, voter title, NIS or PIS, national health card number, birth, marriage and death certificates, RENAVAM, vehicle licence plate, DDD area code, state registration and a combined CPF or CNPJ rule, plus separate format-only rules for several of them.

### How do I install validator-docs?

Add geekcom/validator-docs with a caret constraint of ^3.9 to the require block of composer.json and run composer install, or simply run composer require geekcom/validator-docs. A separate 5.x.x branch holds the legacy version compatible with Laravel 5.

### What is the difference between a format rule and a validity rule?

A format rule such as formato_cpf only checks that the string is shaped like the document, while a validity rule such as cpf also applies the check digit algorithm. The README shows combining them as formato_cpf_cnpj|cpf_cnpj when a field may hold either document type.

### Why does inscricao_estadual need a state parameter?

A state registration is issued per federative unit and the rules differ between states, so the validator needs to know which one applies. The README passes the UF as a rule parameter, for example inscricao_estadual:SP, and notes that supplying the UF is required.

### Does validator-docs check that a document really exists?

No. The rules check structure and check digits, which catches transcription errors, but they do not consult any registry, so a valid-looking number is not proof that a document was issued or belongs to the person who entered it.

## Sources

- [geekcom/validator-docs on GitHub](https://github.com/geekcom/validator-docs)
- [Issues](https://github.com/geekcom/validator-docs/issues)
- [License: MIT](https://github.com/geekcom/validator-docs/blob/master/LICENSE)
- [README](https://github.com/geekcom/validator-docs/blob/master/README.md)
- [Releases](https://github.com/geekcom/validator-docs/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/geekcom-validator-docs
