Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Inscricaoestadual Laravel Package

thiagocfn/inscricaoestadual

Validate, format, and mask Brazilian state registration numbers (Inscrição Estadual) for all 27 states. Provides per-state validation rules, formatting helpers, and Laravel validation integration, making it easy to verify IE numbers and detect their issuing state in forms and APIs.

Deep Wiki
Context7

Getting Started

The package is a plain PHP library (thiagocfn/inscricaoestadual) with no Laravel-specific service provider, facade, or config file. Installation is a single Composer require:

composer require thiagocfn/inscricaoestadual

The entry point is the Thiagocfn\InscricaoEstadual\InscricaoEstadual class. Everything you need lives behind a single validation call that takes the registration number and the state (UF) it belongs to:

use Thiagocfn\InscricaoEstadual\InscricaoEstadual;

$validator = new InscricaoEstadual();
$validator->validate('110042490114', 'SP'); // true/false

Look first at the package's per-state classes (one validator per UF is what gives the library its coverage — 27 states). The README is minimal; the real contract is "pass raw digits + UF, get a boolean."

Your first real use case in a Laravel app is almost always form validation: a customer registration or checkout form where the user types an IE alongside a UF. Wire the validator into a FormRequest or custom rule (see below) and you have the whole day-one workflow.

Implementation Patterns

1. Custom validation rule (the canonical pattern)

Wrap the call in a Laravel rule so it composes with $request->validate() and Validator::extend:

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;
use Thiagocfn\InscricaoEstadual\InscricaoEstadual;

class InscricaoEstadualRule implements Rule
{
    public function __construct(private string $uf) {}

    public function passes($attribute, $value): bool
    {
        $digits = preg_replace('/\D+/', '', (string) $value);

        if ($digits === '') {
            return true; // let `required` handle emptiness
        }

        return (new InscricaoEstadual())->validate($digits, $this->uf);
    }

    public function message(): string
    {
        return 'A inscrição estadual informada não é válida para o estado selecionado.';
    }
}

2. FormRequest + dependent state

The IE validator depends on the UF, so pull it from the same request and pass it into the rule. Validate order matters: ensure the UF is one of the 27 accepted values before validating the IE.

public function rules(): array
{
    return [
        'uf' => ['required', Rule::in(['AC','AL','AP','AM','BA','CE','DF','ES','GO','MA','MT','MS','MG','PA','PB','PR','PE','PI','RJ','RN','RS','RO','RR','SC','SP','SE','TO'])],
        'inscricao_estadual' => ['nullable', new InscricaoEstadualRule($this->input('uf'))],
    ];
}

3. State from IBGE code instead of the UF string

Many Brazilian e-commerce payloads carry the two-digit IBGE state code. Maintain a tiny map (35 => 'SP', 33 => 'RJ', 31 => 'MG', ...) and normalize before calling the validator. This keeps your API contract numeric while the library stays UF-based.

4. Model attribute casting / mutator

For persistence, strip masks in a mutator and validate at the boundary (rules), not the model:

protected function inscricaoEstadual(): Attribute
{
    return Attribute::make(
        set: fn ($v) => $v === null ? null : preg_replace('/\D+/', '', $v),
        get: fn ($v) => $v, // format with a presenter if UI needs the mask
    );
}

5. API resources and display formatting

Keep storage as raw digits; apply the state-specific mask only when serializing (SP 000.000.000.000, RJ 00.000.00-0, MG 000.000.000/0000, etc.). This avoids re-validating masked input later and keeps DB indexing clean.

6. Bulk import workflow

On CSV import of suppliers/customers, run the validator inside a foreach with per-row error capture. The validator is stateless and cheap, so you can validate tens of thousands of rows without a service container or caching layer. Collect rows that fail and return them for manual review rather than aborting the import.

Gotchas and Tips

  • Digits only. Almost every "false" report turns out to be a mask or punctuation sneaking through. Always preg_replace('/\D+/', '', $value) before calling validate(). Leading zeros matter (e.g., SP and SE), so never cast to int.
  • UF case matters. Pass uppercase 'SP', not 'sp'. Normalize with strtoupper() on input; the per-state lookup is typically exact-match, so lowercase will fail or throw.
  • No Laravel registration to do. There is no service provider or facade to publish. Register the rule class in your own App\Rules namespace and inject the validator, or just new InscricaoEstadual() where needed. Do not search for a config file — there isn't one.
  • Boolean contract, no error messages. validate() returns true/false (or null/false for empty input in some builds). All user-facing messaging must be built in your rule. This is by design, not a limitation to fight.
  • State list completeness. The library covers all 27 UFs, but rule implementations differ in strictness for edge cases (DF, SE, and some legacy formats). Add a small table of known-valid samples per state to your test suite so you can detect regressions after composer update.
  • Empty vs. invalid. Decide explicitly whether "blank IE" is valid (skip the rule) or a failure; don't rely on the library's handling of empty strings, which has varied across versions.
  • Version pinning. With only ~14 stars and no active repo link in the metadata, treat it as a low-traffic library: pin a specific version ("thiagocfn/inscricaoestadual": "^1.0") and wrap it behind your own rule class so a fork or replacement (e.g., laravellegends/pt-br-validator or a custom implementation) is a one-file swap if the package goes stale.
  • Don't use it as an identity check. IE validates the checksum, not whether the number is registered with the SEFAZ of that state. Pair with an official SEFAZ consultation only when regulatory need requires it.
  • Performance is a non-issue. No I/O, no container resolution — call it directly in loops and closures. Caching results is premature optimization unless you're re-validating the same record repeatedly in a hot path.
  • Testing tip. In Pest/PHPUnit, data-provide [uf, validSample, invalidSample] triples and assert both directions. This catches the most common bug: a validator that accepts too much (e.g., passing all-same-digit strings for states where the checksum should reject them).
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels