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

Laravel Rif Validation Laravel Package

wilsenhc/laravel-rif-validation

Laravel validation rule for Venezuelan RIF (Registro de Información Fiscal) numbers. Adds a reusable rule to verify RIF format and check digit, so tax IDs are validated cleanly in form requests and validators without custom logic.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package via Composer; Laravel's package auto-discovery registers the service provider that extends the validator with a rif rule:

composer require wilsenhc/laravel-rif-validation

The first thing to verify after install is which version of the underlying rif-validation library you actually got. v2.0.1 exists specifically to pin that dependency to a stable release, so if you are coming from v2.0.0 (which could resolve to a non-stable constraint), run:

composer update wilsenhc/laravel-rif-validation --with-dependencies

and confirm the resolved version in composer.lock before trusting results in CI.

The first real use case is a FormRequest on any entity that stores a Venezuelan tax ID (customers, suppliers, billing profiles):

public function rules(): array
{
    return [
        'rif' => ['required', 'string', 'rif'],
    ];
}

That single rule replaces the hand-rolled regex plus check-digit logic most teams end up writing, and it gives you a proper validation failure instead of an exception or a silent false.

Implementation Patterns

FormRequest as the default home. Keep the rule in a FormRequest rather than inline $request->validate() calls so the RIF contract lives in one place per resource and is reusable by Livewire/Inertia controllers.

Normalize before validating. Users paste RIFs with varying case and separators. Normalize in prepareForValidation() so the rule sees a canonical value:

protected function prepareForValidation(): void
{
    $this->merge([
        'rif' => strtoupper(trim((string) $this->rif)),
    ]);
}

Persist the normalized form too — otherwise you get j-12345678-9, J-12345678-9 and J123456789 as three "different" records in the same table.

Compose with uniqueness and existence. The rule validates shape, not identity, so pair it with the database rules on the same field:

'rif' => ['required', 'string', 'rif', Rule::unique('customers', 'rif')->ignore($this->route('customer'))],

Custom messages and localization. Add a rif key to lang/{locale}/validation.php so the failure reads naturally instead of leaking the raw rule name:

'rif' => 'El RIF ingresado no es válido.',

Alternatively pass it inline: ['rif' => ['required', 'rif']], [], ['rif' => 'RIF'] in the validate() attributes argument.

Cast on the model. Where the RIF is a first-class attribute, wrap reads through an accessor or cast so formatted output (J-12345678-9) is consistent across API resources and PDFs, while the column stores the normalized string.

Test it as a data provider. Because the rule is a pure string predicate, table-driven tests are cheap and catch regressions when you upgrade:

public static function rifProvider(): array
{
    return [
        'valid'   => ['J-12345678-9', true],
        'bad digit' => ['J-12345678-0', false],
        'missing prefix' => ['12345678-9', false],
    ];
}

UI-level validation. If you validate on the frontend for UX, still keep the server-side rule — the browser check is a convenience, not the source of truth, and the two implementations will drift.

Gotchas and Tips

The v2.0.1 change is about dependency stability, not behavior. Don't expect the rule itself to accept or reject anything differently from v2.0.0. The practical impact is reproducibility: a stable pinned rif-validation means the same input produces the same verdict across machines and CI runs. If you had a green build on v2.0.0 and it goes red after upgrading, suspect that a previously-tolerated value was only passing because you were resolving an unstable dependency — that's a bug in your data, not a regression in the package.

Clear Composer caches in CI. Because this release only changes the constraint graph, stale composer.lock files or cached vendor layers can silently keep you on the old resolution. composer update --with-dependencies locally, commit the lock file, and let CI install from it.

Format expectations are strict. The rule validates the standard X-########-# shape (prefix letter, body, check digit). Decide deliberately whether you accept only the canonical hyphenated form or pre-normalize; the rule generally will not guess at missing separators or lowercase prefixes for you.

Order of rules matters for optional fields. 'nullable', 'rif' works; 'rif', 'nullable' will fail on null. Use sometimes for PATCH-style endpoints where the field may be absent entirely.

Uniqueness uses the normalized value. If you normalize in prepareForValidation() but existing rows were written with mixed formatting, Rule::unique will happily create duplicates. Backfill the column once, then enforce.

Debugging a surprising failure. Isolate it in Tinker with Validator::make(['rif' => 'J-12345678-9'], ['rif' => 'rif'])->errors() to confirm the rule is registered at all — a "validation rule not found" style error usually means the service provider wasn't discovered (check composer dump-autoload after manual installs, or that the package is supported by your Laravel version).

Extension point. If your domain needs stricter semantics (e.g. prefix must match the entity type — J for jurídico, V/E for natural persons), wrap rather than fork: build a custom Rule object that calls the package rule first and then applies your business constraint. Keeping the check digit logic in the package means you inherit upstream fixes for free.

Version pinning. For a single-rule package, pin a caret constraint on the minor (^2.0) and treat majors as review-worthy — this release is a reminder that even patch bumps can change what lands in your dependency tree.

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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin