slashlab / numerik
Modern PHP 8.3+ library for validating and parsing Polish identification numbers (PESEL, NIP, REGON, KRS).
Requires
- php: ^8.3
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- infection/infection: ^0.29
- phpstan/phpstan: ^2.0
- phpstan/phpstan-strict-rules: ^2.0
- phpunit/phpunit: ^12.0
This package is auto-updated.
Last update: 2026-05-09 03:49:53 UTC
README
Modern PHP 8.3+ library for validating and parsing Polish identification numbers — PESEL, NIP, REGON, KRS, NRB, VAT-EU, IBAN, ID Card, and Passport. Rich value objects, detailed error reasons, zero production dependencies.
Installation
composer require slashlab/numerik
Quick Start
use SlashLab\Numerik\Numerik; // Simple boolean check Numerik::pesel()->isValid('92060512186'); // true Numerik::nip()->isValid('5260250274'); // true // Rich validation result with failure reasons $result = Numerik::pesel()->validate('92060512186'); $result->isValid; // true $result = Numerik::pesel()->validate('92060512185'); // wrong checksum digit $result->isFailed(); // true $result->getFirstFailure()->reason; // ValidationFailureReason::InvalidChecksum // Parse to value object $pesel = Numerik::pesel()->parse('92060512186'); $pesel->getBirthDate()->format('Y-m-d'); // '1992-06-05' $pesel->getGender(); // Gender::Female
Documentation
Full documentation at numerik.slashlab.pl
Laravel Integration
A dedicated Laravel package is available at slashlab/numerik-laravel (requires PHP 8.3+, Laravel 11/12/13). The service provider is auto-discovered — no manual registration needed.
composer require slashlab/numerik-laravel
Use class-based rules or plain strings — both styles work:
use SlashLab\NumerikLaravel\Rules\PeselRule; use SlashLab\NumerikLaravel\Rules\NipRule; use SlashLab\NumerikLaravel\Rules\RegonRule; use SlashLab\NumerikLaravel\Rules\KrsRule; use SlashLab\NumerikLaravel\Rules\NrbRule; use SlashLab\NumerikLaravel\Rules\VatEuRule; use SlashLab\NumerikLaravel\Rules\IbanRule; use SlashLab\NumerikLaravel\Rules\IdCardRule; use SlashLab\NumerikLaravel\Rules\PassportRule; // Class-based (supports options) public function rules(): array { return [ 'pesel' => ['required', new PeselRule()], // strict mode on by default // 'pesel' => ['required', new PeselRule(strict: false)], // disable strict checks 'nip' => ['required', new NipRule()], 'regon' => ['required', new RegonRule()], 'krs' => ['required', new KrsRule()], 'nrb' => ['required', new NrbRule()], 'vat_eu' => ['required', new VatEuRule()], 'iban' => ['required', new IbanRule()], 'id_card' => ['required', new IdCardRule()], 'passport' => ['required', new PassportRule()], ]; } // String-based public function rules(): array { return [ 'pesel' => ['required', 'pesel'], 'nip' => ['required', 'nip'], 'regon' => ['required', 'regon'], 'krs' => ['required', 'krs'], 'nrb' => ['required', 'nrb'], 'vat_eu' => ['required', 'vat_eu'], 'iban' => ['required', 'iban'], 'id_card' => ['required', 'id_card'], 'passport' => ['required', 'passport'], ]; }
Class-based rules return a distinct message per failure reason (e.g. wrong checksum vs invalid length). Messages resolve the field label from validation.attributes when available, falling back to a humanised field name. The package ships with English and Polish translations — publish them with php artisan vendor:publish --tag=numerik-lang.
PeselRule also accepts gender, bornBefore, and bornAfter constraints for stricter identity checks. See the full Laravel documentation for details.
Changelog
See CHANGELOG.md.
Contributing
See CONTRIBUTING.md.
License
MIT — see LICENSE.
If this saved you time → ☕ Buy me a coffee