jeffersongoncalves/laravel-cnpj
A Laravel package for working with CNPJ, the Brazilian company registration number. It offers validation, formatting, and generation helpers, plus a Laravel validation rule to sanitize input, apply the standard mask, and create valid CNPJ values for forms, tests, and seed data.
Install the package with Composer, then publish and run its migration before touching any CNPJ field:
composer require <vendor>/cnpj
php artisan vendor:publish --tag="cnpj-migrations"
php artisan migrate
Look first at:
config/cnpj.php (if published) — formatting, strictness, and table/config options.database/migrations/create_cnpj_table.php.stub in the package — this is the canonical schema; the published copy is what actually runs.src/ for the validation rule and any formatter/normalizer, since that defines the behavior you will rely on.First use case: validating a CNPJ on a registration form and persisting the normalized value.
// app/Http/Requests/StoreCompanyRequest.php
public function rules(): array
{
return [
'name' => ['required', 'string', 'max:255'],
'cnpj' => ['required', 'cnpj'], // use the package's rule/alias
];
}
Normalize before saving so validation and storage agree on format:
$company = Company::create([
'name' => $request->validated('name'),
'cnpj' => preg_replace('/\D/', '', $request->validated('cnpj')),
]);
Validation at the boundary, normalization at the model. Use the package rule in Form Requests or $request->validate(), then strip punctuation in a mutator, cast, or observer. Keeping one canonical storage format (digits only is the common choice) avoids duplicate-looking records and makes unique indexes trustworthy.
protected function cnpj(): Attribute
{
return Attribute::make(
set: fn (string $value) => preg_replace('/\D/', '', $value),
);
}
Pair the rule with a unique constraint. CNPJ is an identifier; validate format with the package and uniqueness with the database.
'cnpj' => ['required', 'cnpj', Rule::unique('companies', 'cnpj')],
Customize the migration by editing the published stub copy. The publish command copies create_cnpj_table.php.stub into database/migrations/. Add your own columns, indexes, or tenant keys there, not in the package. Treat the published file as application code from that point on.
Use it in factories and seeders. Generate/validate test values through the package or a fixture set of known-valid CNPJs rather than hand-rolling check digits.
Reuse the rule compositionally. If the package exposes a rule object, instantiate it directly for reusable validation in actions or DTOs; if it exposes a helper/formatter, wrap it behind your own service so a future package swap is a one-file change.
API and import flows. Validate each row on import and collect failures rather than aborting the whole batch; for APIs, return the package rule's message alongside a machine-readable error code.
Version pinning. This is a small utility package; pin to a minor range (^1.0) and run your CNPJ test suite after upgrades.
Migration stub change in 1.0.2 is packaging-only. The migration now ships as create_cnpj_table.php.stub, matching the other packages, and the publish command is unchanged (--tag="cnpj-migrations"). No breaking change and no action required if you already published the migration — your published copy is untouched by the upgrade.
Published migrations do not track the stub. Once published, the file in database/migrations/ is a snapshot. Upstream stub changes will not reach existing apps. To pick up schema changes, diff the package stub against your published migration and edit manually, or republish with --force on a throwaway environment and review the diff. Never --force publish over a migration that has already run in production.
Watch the publish tag. The tag is cnpj-migrations; a typo silently publishes nothing. Run php artisan vendor:publish interactively to confirm the provider and tags are registered, and clear config cache (php artisan config:clear) if a newly published config seems ignored.
Formatting drift is the classic bug. Storing formatted values in one path and digits in another creates "duplicate" CNPJs and broken unique indexes. Enforce normalization centrally (cast/mutator) and add a test asserting the stored column contains digits only.
Validation passes but lookups fail. Trim whitespace and non-breaking spaces from user input before validating; copy-pasted CNPJs often carry invisible characters.
Debugging invalid values. Test against a handful of known-valid and known-invalid CNPJs, including repeated-digit values like 11.111.111/1111-11, which are commonly rejected despite passing check-digit math. Confirm the package's behavior rather than assuming.
Alphanumeric CNPJ readiness. Brazil's CNPJ format is evolving toward alphanumeric identifiers. If you store CNPJ in a numeric-only column, plan a VARCHAR migration; check the package changelog for rule support before relying on it for the new format.
Extension points. Prefer your own Form Request messages, a wrapper service around the package validator, and edits to the published migration stub. Avoid editing files under vendor/; changes there are lost on composer update.
How can I help you explore Laravel packages today?