Skip to content

LacusSolutions/br-utils-php

br-utils for PHP

Packagist Version Packagist Downloads PHP Version Test Status Last Update Date Project License

🚀 Full support for the new alphanumeric CNPJ format.

🌎 Acessar documentação em português

A PHP toolkit to handle the main operations with Brazilian-related data: CPF (Individual's Taxpayer ID) and CNPJ (Business Tax ID). It provides a top-level BrUtils wrapper around lacus/cpf-utils and lacus/cnpj-utils, exposing all bundled resources under unified namespaces.

PHP Support

PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
Passing ✔ Passing ✔ Passing ✔ Passing ✔

Features

  • Unified top-level API: One BrUtils instance with $cpf and $cnpj domain accessors
  • Bundled domains: lacus/cpf-utils and lacus/cnpj-utils installed together
  • Alphanumeric CNPJ: Full support for the new alphanumeric CNPJ format (introduced in 2026)
  • Configurable defaults: Set formatter, generator, and (for CNPJ) validator options on each domain instance
  • Per-call overrides: Override any component option for a single method call
  • Dual API style: Top-level façade (BrUtils), domain aggregators (CpfUtils, CnpjUtils), standalone components, and functional helpers
  • Shared namespaces: CPF symbols under Lacus\BrUtils\Cpf\; CNPJ symbols under Lacus\BrUtils\Cnpj\
  • Typed error handling: Dedicated exception hierarchies from bundled packages (CNPJ v2 TypeError / Exception model; CPF v1 InvalidArgumentException for invalid options)

Installation

# using Composer
$ composer require lacus/br-utils

This installs lacus/br-utils together with lacus/cpf-utils and lacus/cnpj-utils (which in turn pulls in the CNPJ component packages). You do not need separate composer require calls for the domain packages when using lacus/br-utils.

Import

Pick the API that fits your use case.

Top-level façade:

<?php

use Lacus\BrUtils;

Domain aggregators:

<?php

use Lacus\BrUtils\Cpf\CpfUtils;
use Lacus\BrUtils\Cnpj\CnpjUtils;

CPF components (object-oriented):

<?php

use Lacus\BrUtils\Cpf\CpfFormatter;
use Lacus\BrUtils\Cpf\CpfFormatterOptions;
use Lacus\BrUtils\Cpf\CpfGenerator;
use Lacus\BrUtils\Cpf\CpfGeneratorOptions;
use Lacus\BrUtils\Cpf\CpfValidator;

CNPJ components (object-oriented):

<?php

use Lacus\BrUtils\Cnpj\CnpjFormatter;
use Lacus\BrUtils\Cnpj\CnpjFormatterOptions;
use Lacus\BrUtils\Cnpj\CnpjGenerator;
use Lacus\BrUtils\Cnpj\CnpjGeneratorOptions;
use Lacus\BrUtils\Cnpj\CnpjValidator;
use Lacus\BrUtils\Cnpj\CnpjValidatorOptions;
use Lacus\BrUtils\Cnpj\Enums\CnpjType as CnpjGenerationType;
use Lacus\BrUtils\Cnpj\Enums\CnpjValidationType;

Functional helpers:

<?php

use function Lacus\BrUtils\Cpf\cpf_fmt;
use function Lacus\BrUtils\Cpf\cpf_gen;
use function Lacus\BrUtils\Cpf\cpf_val;
use function Lacus\BrUtils\Cnpj\cnpj_fmt;
use function Lacus\BrUtils\Cnpj\cnpj_gen;
use function Lacus\BrUtils\Cnpj\cnpj_val;

Quick start

With BrUtils (all-in-one):

<?php

use Lacus\BrUtils;

$utils = new BrUtils();
$cpf = '11144477735';
$cnpj = '03603568000195';

$utils->cpf->format($cpf);      // '111.444.777-35'
$utils->cpf->isValid($cpf);     // true
$utils->cpf->generate();        // e.g. '11508890048'

$utils->cnpj->format($cnpj);    // '03.603.568/0001-95'
$utils->cnpj->isValid($cnpj);   // true
$utils->cnpj->generate();       // e.g. '1GJTR3J3XSSA96'

With domain aggregators:

<?php

use Lacus\BrUtils\Cpf\CpfUtils;
use Lacus\BrUtils\Cnpj\CnpjUtils;

$cpf = '11144477735';
$cnpj = '03603568000195';

(new CpfUtils())->format($cpf);      // '111.444.777-35'
(new CnpjUtils())->format($cnpj);    // '03.603.568/0001-95'
(new CpfUtils())->isValid($cpf);     // true
(new CnpjUtils())->isValid($cnpj);   // true

With functional helpers:

<?php

use function Lacus\BrUtils\Cpf\cpf_fmt;
use function Lacus\BrUtils\Cpf\cpf_val;
use function Lacus\BrUtils\Cnpj\cnpj_fmt;
use function Lacus\BrUtils\Cnpj\cnpj_val;

$cpf = '11144477735';
$cnpj = '03603568000195';

cpf_fmt($cpf);     // '111.444.777-35'
cpf_val($cpf);     // true
cnpj_fmt($cnpj);   // '03.603.568/0001-95'
cnpj_val($cnpj);   // true

Usage

You can work in four equivalent ways:

  1. BrUtils — single instance with shared defaults across both CPF and CNPJ domains.
  2. Domain aggregatorsCpfUtils and CnpjUtils directly (same classes used internally by BrUtils).
  3. Component classesCpfFormatter, CnpjGenerator, and so on.
  4. Functional helperscpf_fmt(), cnpj_gen(), and related functions for one-off calls.

All approaches expose the same options and behavior within each domain. For full option tables and component-specific details, see the README of each bundled package.

BrUtils

  • __construct: new BrUtils($cpf = [], $cnpj = [])

    Each $cpf / $cnpj argument may be a pre-built CpfUtils / CnpjUtils instance or a configuration array spread into the corresponding utils constructor. Within that array, each resource key (formatter, generator, and validator for CNPJ) accepts either an options object or an associative array of option values.

    Example: new BrUtils(cpf: ['formatter' => ['hidden' => true]], cnpj: ['validator' => ['type' => CnpjValidationType::Numeric]]).

  • $cpf, $cnpj: Property-style access to the domain utils instances (CpfUtils and CnpjUtils).

  • getCpfUtils(), getCnpjUtils(): Return the internal domain instances for direct use.

<?php

use Lacus\BrUtils;
use Lacus\BrUtils\Cnpj\Enums\CnpjType as CnpjGenerationType;
use Lacus\BrUtils\Cnpj\Enums\CnpjValidationType;

$utils = new BrUtils();

$utils->cpf->format('11144477735');    // '111.444.777-35'
$utils->cpf->isValid('11144477735');   // true
$utils->cpf->generate();               // e.g. '11508890048'

$utils->cnpj->format('03603568000195');    // '03.603.568/0001-95'
$utils->cnpj->format('12ABC34500DE99');    // '12.ABC.345/00DE-99'
$utils->cnpj->isValid('1QB5UKALPYFP59');   // true
$utils->cnpj->generate(format: true);      // e.g. 'V1.J0V.8WE/DVZ7-50'
$utils->cnpj->generate(                    // e.g. '15381773354961'
    type: CnpjGenerationType::Numeric,
);

Instance defaults and per-call overrides

$utils = new BrUtils(
    cpf: [
        'formatter' => ['hidden' => true, 'hiddenKey' => '#'],
        'generator' => ['format' => true],
    ],
    cnpj: [
        'formatter' => ['hidden' => true, 'hiddenKey' => '#'],
        'generator' => ['format' => true],
        'validator' => ['type' => CnpjValidationType::Numeric],
    ],
);

$cpf = '11144477735';
$cnpj = '03603568000195';

$utils->cpf->format($cpf);                  // '111.###.###-##'
$utils->cpf->format($cpf, hidden: false);   // '111.444.777-35'
$utils->cpf->generate(format: false);       // e.g. '58450042259'

$utils->cnpj->format($cnpj);                  // '03.603.###/####-##'
$utils->cnpj->format($cnpj, hidden: false);   // '03.603.568/0001-95'
$utils->cnpj->isValid('1QB5UKALPYFP59');      // false
$utils->cnpj->isValid(                        // true
    '1QB5UKALPYFP59',
    type: CnpjValidationType::Alphanumeric,
);

Passing a CnpjFormatterOptions, CnpjGeneratorOptions, or CnpjValidatorOptions instance to the BrUtils constructor stores that object by reference — mutating it later affects subsequent calls with no per-call override.

CPF operations

CPF methods are accessed via $utils->cpf, CpfUtils, or the cpf_*() helpers. CPF uses the v1 API from lacus/cpf-utils: string-only input, positional/named formatter and generator options, and no validator settings.

Formatting (format / cpf_fmt)

Parameter Type Default Description
escape ?bool false When true, HTML-escapes the final string
hidden ?bool false When true, replaces the inclusive index range [hiddenStart, hiddenEnd] on the normalized 11-digit string before punctuation is applied
hiddenKey ?string '*' Replacement for each hidden position
hiddenStart ?int 3 Start index 010 (inclusive)
hiddenEnd ?int 10 End index 010 (inclusive)
dotKey ?string '.' Separator between digit groups
dashKey ?string '-' Separator before the last two digits
onFail ?\Closure see below Closure(mixed $value, Exception $e): string — used when sanitized length ≠ 11

Default onFail returns the original input unchanged. Invalid length does not throw from format().

$cpf = '11144477735';

$utils->cpf->format($cpf);                                        // '111.444.777-35'
$utils->cpf->format($cpf, hidden: true, hiddenKey: '#');          // '111.###.###-##'
$utils->cpf->format($cpf, dotKey: '', dashKey: '_');             // '111444777_35'

cpf_fmt($cpf, hidden: true);                                       // '111.***.***-**'

Generation (generate / cpf_gen)

Parameter Type Default Description
format ?bool false When true, returns formatted CPF (000.000.000-00); otherwise returns compact 11-digit output
prefix ?string '' Base seed for generation. Non-digit characters are stripped; only the first 9 digits (indexes 08) are used
$utils->cpf->generate();                      // e.g. '11508890048'
$utils->cpf->generate(format: true);          // e.g. '661.134.831-00'
$utils->cpf->generate(prefix: '123456789');   // '12345678909'
cpf_gen(prefix: '123456789', format: true);   // '123.456.789-09'

Validation (isValid / cpf_val)

Accepts formatted or unformatted CPF strings. Returns true or false without throwing for invalid CPF.

$utils->cpf->isValid('11144477735');      // true
$utils->cpf->isValid('111.444.777-35');   // true
$utils->cpf->isValid('11144477736');      // false
cpf_val('11144477735');                   // true

CNPJ operations

CNPJ methods are accessed via $utils->cnpj, CnpjUtils, or the cnpj_*() helpers. CNPJ uses the v2 API from lacus/cnpj-utils.

Formatting (format / cnpj_fmt)

Supports the same options as lacus/cnpj-fmt. Input accepts string or list<string>.

Parameter Type Default Description
hidden ?bool false When true, replaces the inclusive index range [hiddenStart, hiddenEnd] on the normalized 14-character string before punctuation is applied
hiddenKey ?string '*' Replacement for each hidden position (may be multi-character or empty); must not use disallowed key characters
hiddenStart ?int 5 Start index 013 (inclusive)
hiddenEnd ?int 13 End index 013 (inclusive); if hiddenStart > hiddenEnd, they are swapped
dotKey ?string '.' Separator between groups XX / XXX / XXX
slashKey ?string '/' Separator before the branch block
dashKey ?string '-' Separator before the last two characters
escape ?bool false When true, HTML-escapes the final string
encode ?bool false When true, URL-encodes the final string
onFail ?\Closure see below Closure(mixed $value, CnpjFormatterException $e): string — used when sanitized length ≠ 14

Default onFail returns an empty string. Wrong input types throw CnpjFormatterInputTypeError.

$cnpj = '03603568000195';

$utils->cnpj->format($cnpj);              // '03.603.568/0001-95'
$utils->cnpj->format('12ABC34500DE99');   // '12.ABC.345/00DE-99'
$utils->cnpj->format(                     // '03.603.###/####-##'
    $cnpj,
    hidden: true,
    hiddenKey: '#',
);
$utils->cnpj->format(                     // '03603568|0001_95'
    $cnpj,
    dotKey: '',
    slashKey: '|',
    dashKey: '_',
);

cnpj_fmt($cnpj);   // '03.603.568/0001-95'

Generation (generate / cnpj_gen)

Supports the same options as lacus/cnpj-gen.

Parameter Type Default Description
format ?bool false When true, returns formatted CNPJ (XX.XXX.XXX/XXXX-XX); otherwise returns compact 14-character output
prefix ?string '' Base seed for generation. Non-alphanumeric chars are stripped, letters are uppercased, and only first 12 chars (indexes 011) are used; characters at index 12+ are ignored
type CnpjGenerationType|'alphanumeric'|'alphabetic'|'numeric'|null CnpjGenerationType::Alphanumeric Character family used for generated base positions

prefix validation rules:

  • base ID 00000000 is rejected (when first 8 chars are present)
  • branch ID 0000 is rejected (when chars 9–12 are present)
  • 12 repeated numeric digits are rejected (e.g. 111111111111)
$utils->cnpj->generate();               // e.g. '1GJTR3J3XSSA96'
$utils->cnpj->generate(format: true);   // e.g. 'V1.J0V.8WE/DVZ7-50'
$utils->cnpj->generate(                 // e.g. '12345678855883'
    prefix: '12345678',
    type: CnpjGenerationType::Numeric,
);

Validation (isValid / cnpj_val)

Supports the same options as lacus/cnpj-val. Input accepts string or list<string>.

Parameter Type Default Description
type CnpjValidationType|'alphanumeric'|'numeric'|null CnpjValidationType::Alphanumeric Character set after sanitization
caseSensitive ?bool true When false, lowercase letters are uppercased before alphanumeric validation
$utils->cnpj->isValid('98765432000198');   // true
$utils->cnpj->isValid('98765432000199');   // false
$utils->cnpj->isValid('1QB5UKALPYFP59');   // true
$utils->cnpj->isValid('1QB5UKALpyfp59');   // false
$utils->cnpj->isValid(                     // true
    '1QB5UKALpyfp59',
    caseSensitive: false,
);
$utils->cnpj->isValid(                     // false
    '1QB5UKALPYFP59',
    type: CnpjValidationType::Numeric,
);

cnpj_val('98765432000198');                         // true
cnpj_val('1QB5UKALpyfp59', caseSensitive: false);   // true
cnpj_val(                                           // false
    '1QB5UKALPYFP59',
    type: CnpjValidationType::Numeric,
);

Invalid CNPJ returns false without throwing. Wrong input types throw CnpjValidatorInputTypeError.

Domain aggregators (standalone)

Use CpfUtils or CnpjUtils directly when you only need one domain:

<?php

use Lacus\BrUtils\Cpf\CpfUtils;
use Lacus\BrUtils\Cnpj\CnpjUtils;
use Lacus\BrUtils\Cnpj\Enums\CnpjValidationType;

$cpfUtils = new CpfUtils(
    formatter: ['hidden' => true],
    generator: ['format' => true],
);

$cnpjUtils = new CnpjUtils(
    formatter: ['hidden' => true],
    generator: ['format' => true],
    validator: ['type' => CnpjValidationType::Numeric],
);

$cpfUtils->format('11144477735');       // '111.***.***-**'
$cnpjUtils->format('03603568000195');   // '03.603.***/****-**'

Accessing components

Each domain aggregator exposes its internal formatter, generator, and validator:

$utils = new BrUtils();

$utils->cpf->getFormatter()->format(                   // '111.***.***-**'
    '11144477735',
    hidden: true,
);
$utils->cpf->getGenerator()->generate(format: true);   // e.g. '545.507.690-68'
$utils->cpf->getValidator()->isValid('11144477735');   // true

$utils->cnpj->getFormatter()->format('12ABC34500DE99');    // '12.ABC.345/00DE-99'
$utils->cnpj->getGenerator()->generate(format: true);      // e.g. '8O.BE5.2KL/UI0Y-06'
$utils->cnpj->getValidator()->isValid('03603568000195');   // true

Use getCpfUtils() / getCnpjUtils() on BrUtils, or the component getters on each domain utils instance, when you already have a configured instance and want the underlying component without creating a new one.

Mixing styles

Use BrUtils where a shared configuration helps, and standalone components or helpers elsewhere — they are the same underlying classes:

<?php

use Lacus\BrUtils;
use Lacus\BrUtils\Cnpj\CnpjFormatter;
use Lacus\BrUtils\Cnpj\Enums\CnpjValidationType;

use function Lacus\BrUtils\Cpf\cpf_fmt;
use function Lacus\BrUtils\Cnpj\cnpj_val;

$utils = new BrUtils(cnpj: ['validator' => ['type' => CnpjValidationType::Numeric]]);

// Via façade
$utils->cpf->format('11144477735');   // '111.444.777-35'

// Via component returned by the façade
$utils->cnpj->getFormatter()->format('12ABC34500DE99');   // '12.ABC.345/00DE-99'

// Via a separate component instance
(new CnpjFormatter())->format('03603568000195');   // '03.603.568/0001-95'

// Via functional helpers
cpf_fmt('11144477735');           // '111.444.777-35'
cnpj_val('98.765.432/0001-98');   // true

Errors & exceptions

BrUtils does not define its own exception types; it propagates errors from the bundled packages:

  • CPF formatting / generation: InvalidArgumentException for invalid option types or values (e.g. out-of-range hiddenStart, prefix longer than 9 digits).
  • CNPJ formatting: CnpjFormatterInputTypeError, CnpjFormatterOptionsTypeError, CnpjFormatterOptionsHiddenRangeInvalidException, CnpjFormatterOptionsForbiddenKeyCharacterException, and related classes.
  • CNPJ generation: CnpjGeneratorOptionsTypeError, CnpjGeneratorOptionPrefixInvalidException, CnpjGeneratorOptionTypeInvalidException, and related classes.
  • CNPJ validation: CnpjValidatorInputTypeError, CnpjValidatorOptionsTypeError, CnpjValidatorOptionTypeInvalidException, and related classes.

Invalid option types on CNPJ are TypeError subclasses; invalid option values are Exception subclasses. CPF and CNPJ validation failures return false. CPF formatting length failure is handled by onFail (default: return input); CNPJ formatting length failure uses onFail (default: return '').

<?php

use Lacus\BrUtils;
use Lacus\BrUtils\Cnpj\Exceptions\CnpjFormatterInputTypeError;
use Lacus\BrUtils\Cnpj\Exceptions\CnpjValidatorInputTypeError;

$brUtils = new BrUtils();

try {
    $brUtils->cnpj->format(12345);   // throws CnpjFormatterInputTypeError
} catch (CnpjFormatterInputTypeError $e) {
    echo $e->getMessage();
}

try {
    $brUtils->cnpj->isValid(12345678000198);   // throws CnpjValidatorInputTypeError
} catch (CnpjValidatorInputTypeError $e) {
    echo $e->getMessage();
}

$cpfOut = $brUtils->cpf->format(     // 'invalid'
    'short',
    onFail: static fn ($value) => 'invalid'
);
$cnpjOut = $brUtils->cnpj->format(   // 'invalid'
    'short',
    onFail: static fn () => 'invalid',
);

For exhaustive exception lists and edge-case behavior, see each bundled package README.

Bundled packages

Package Main resources README
lacus/cpf-utils CpfUtils, CpfFormatter, CpfGenerator, CpfValidator, cpf_fmt(), cpf_gen(), cpf_val() docs
lacus/cnpj-utils CnpjUtils, CnpjFormatter, CnpjGenerator, CnpjValidator, CnpjType, CnpjValidationType, cnpj_fmt(), cnpj_gen(), cnpj_val() docs

All CPF symbols are available under Lacus\BrUtils\Cpf\; all CNPJ symbols under Lacus\BrUtils\Cnpj\. Interactive demos: CPF and CNPJ.

API

  • BrUtils: Top-level façade with $cpf / $cnpj property access and getCpfUtils() / getCnpjUtils()
  • CpfUtils: Domain aggregator for CPF format, generate, and validate
  • CnpjUtils: Domain aggregator for CNPJ format, generate, and validate
  • CpfFormatter, CpfFormatterOptions, CpfGenerator, CpfGeneratorOptions, CpfValidator: CPF component classes
  • CnpjFormatter, CnpjFormatterOptions, CnpjGenerator, CnpjGeneratorOptions, CnpjValidator, CnpjValidatorOptions: CNPJ component classes
  • CnpjGenerationType, CnpjValidationType: CNPJ generation and validation enums
  • cpf_fmt(), cpf_gen(), cpf_val(): CPF functional helpers (Lacus\BrUtils\Cpf\)
  • cnpj_fmt(), cnpj_gen(), cnpj_val(): CNPJ functional helpers (Lacus\BrUtils\Cnpj\)
  • Exceptions: CPF — InvalidArgumentException for invalid options; CNPJ — full TypeError / Exception hierarchies from bundled packages (see linked READMEs)

Contribution & Support

We welcome contributions! Please see our Contributing Guidelines for details. If you find this project helpful, please consider:

License

This project is licensed under the MIT License — see the LICENSE file for details.

Changelog

See CHANGELOG for a list of changes and version history.


Made with ❤️ by Lacus Solutions

Contributors

Languages