Download the PHP package bensondevs/indonesian-ktp without Composer
On this page you can find all versions of the php package bensondevs/indonesian-ktp. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download bensondevs/indonesian-ktp
More information about bensondevs/indonesian-ktp
Files in bensondevs/indonesian-ktp
Package indonesian-ktp
Short Description Validate Indonesian NIK (Nomor Induk Kependudukan) using compiled wilayah data (cahyadsn/wilayah, MIT).
License MIT
Informations about the package indonesian-ktp
🇮🇩 Indonesian KTP (NIK) validation
Validate Indonesian NIK (Nomor Induk Kependudukan) with structural checks and bundled wilayah data (no MySQL, no Nusantara). Public API: KTP.
Table of contents
- What gets validated
- Requirements
- Install
- Quick start
- Usage
- Basic validation
- Laravel Validator (rule object and ktp-nik)
- Quick checks
- Expectations and aliases
- validate() and ValidationResult
- Parsed values
- Region inputs
- Two-digit birth years: ambiguity and asOf()
- Region hierarchy lookup
- Eloquent HasIndonesianKtp
- Explicit matchers
- Trait methods
- NIK column and accessors
- Develop and test
- Support
- Data source
- Security
- Versioning and support
What gets validated
- Structure — length, digits, birth date / gender encoding.
- Region hierarchy — district code in the NIK must exist in
data/wilayah.php(province → regency → subdistrict).
Optional checks (birth, age, gender, wilayah names/codes): Data source.
Invalid length or unknown district:
Requirements
| Requirement | Notes |
|---|---|
| PHP | 8.3+ |
| Laravel | 10–13; illuminate/contracts, illuminate/database, illuminate/support, illuminate/validation match your app |
| Carbon | nesbot/carbon ^2.67 or ^3.0 |
Install 📦
Quick start ✅
Minimal check (structure + wilayah hierarchy):
Structure + region only until you add expectations (see Usage).
Usage
KTP::nik($raw)returns a fluent, immutableQuery: each chained call is a new instance.isValid()→ onebool.validate()→ValidationResultwith per-flag detail.- Laravel’s
Validatoris supported via Laravel Validator (rule object and ktp-nik).
Basic validation
Laravel Validator (rule object and ktp-nik)
With package discovery, rule object or with a string rule.
Rule object vs string rule
What this checks
| Same as | Plain KTP::nik($value)->isValid() — structure (length, digits, birth/gender segment rules) plus complete wilayah hierarchy for the district code. |
| Does not include | Chained expectations such as expectBirthDate, expectGender, expectProvince, age rules, etc. For those, use the fluent Query API — Expectations and aliases. |
Composing with required / nullable
Use Laravel’s built-in rules for presence: required|string|… when the field must be present, or nullable|string|… when it is optional. The KtpNik rule does not fail on null or '', so optional fields stay easy to express without fighting the custom rule.
Input types
Integer or numeric string values are cast to string before validation. Arrays, objects, and booleans fail. In practice, pair the rule with Laravel’s string rule as in the examples above.
Messages and localization
The default English message lives under the indonesian-ktp namespace (validation.ktp_nik). Override or translate it like any vendor lang line (for example files under lang/vendor/indonesian-ktp). See Laravel localization.
Custom wilayah data
If you rebind Region hierarchy lookup.
Quick checks
match* helpers compare the NIK to a value; they do not add expect* rules to the query.
Gender and birth date
Age / minimum age: matchAge() / matchAtLeastYears() need a resolved birth year — use asOf() as in Two-digit birth years.
Expectations and aliases
Chain then call isValid() or validate(). Each chained call returns a new Query.
| Area | expect* |
Alias |
|---|---|---|
| Birth date | expectBirthDate |
birthDate |
| Integer age | expectAge |
age |
| Minimum age | expectAtLeastYears, expectSeventeenOrOlder, expectTwentyOneOrOlder |
— |
| Gender | expectGender |
gender |
| Province | expectProvince |
province |
| Regency | expectRegency |
regency |
| Subdistrict | expectSubdistrict |
subdistrict |
Full names
Aliases
isValid() is the same as validate()->isFullyValid() (structure + hierarchy + every set expectation). Chaining expectAge / age needs asOf() — see Two-digit birth years.
validate() and ValidationResult
ValidationResult exposes methods (not public properties).
| Method | Return | Notes |
|---|---|---|
hasValidStructure() |
bool |
|
hasValidRegionHierarchy() |
bool |
|
hasValidBirthDate() |
bool or null |
null = expectation not set |
hasValidGender() |
bool or null |
|
hasValidProvince() |
bool or null |
|
hasValidRegency() |
bool or null |
|
hasValidSubdistrict() |
bool or null |
|
hasValidAge() |
bool or null |
|
hasValidMinimumAge() |
bool or null |
|
isFullyValid() |
bool |
Same as isValid() on the Query |
| Alias | Equivalent |
|---|---|
hasValidKabupaten(), hasValidCity() |
hasValidRegency() |
hasValidKecamatan() |
hasValidSubdistrict() |
Parsed values
parsed() returns a Parsed snapshot (read-only fields from the NIK). KTP::nik(...)->parsed() attaches wilayah names from the app’s region lookup when the district code is known; use provinceCode() / regencyCode() / districtCode() for keys from the NIK alone.
| Method | Role |
|---|---|
raw() |
Normalized 16-digit string |
structureValid() |
Structural segment checks |
provinceCode(), regencyCode(), districtCode() |
Wilayah codes from the NIK (e.g. 33, 33.15, 33.15.13) |
province(), provinsi() |
Province display name when the bound lookup resolves the district (e.g. Jawa Tengah); null if unknown or parser-only Parsed without withRegionHierarchy() |
regency(), kabupaten(), kota(), city() |
Regency / city display name when resolved (same value for all four; NIK does not distinguish kabupaten vs kota); null otherwise |
district(), kecamatan() |
Kecamatan display name when resolved; null otherwise |
birthDate() |
Single date, or null if two-digit year is ambiguous (Two-digit birth years) |
possibleBirthDates() |
All plausible dates when ambiguous |
gender(), serial() |
Parsed gender / serial |
age($asOf?), isAtLeastYears($min, $asOf), isSeventeenOrOlder($asOf), isTwentyOneOrOlder($asOf) |
Age helpers (conservative when ambiguous). age() with no argument uses the current instant (Carbon::now()). |
On the Query, resolvedAge() uses the pivot instant when you chained asOf() (Two-digit birth years). For real validation, prefer validate() / isValid().
Region inputs
tests/Feature/Ktp/KtpRegionInputsTest.php.
Unknown district:
Two-digit birth years: ambiguity and asOf()
matchAge / minimum age (needs the same pivot):
| Topic | Behaviour |
|---|---|
Birth / expectBirthDate |
Ambiguous: any matching candidate wins. Pivot: one resolved year. |
parsed()->birthDate() |
null if multiple candidates; use possibleBirthDates(). Pivot: always set when structure is valid. |
age / resolvedAge() |
Can stay null until year is unique; use asOf() or derive from possibleBirthDates(). |
| Minimum-age helpers | Conservative: every plausible birth candidate must pass. |
Edge cases: 17–120 uses calendar boundaries; odd ages or midnight tests may need your own asOf(). Examples: tests/Unit/NIK/ParserTest.php.
Eloquent: same behaviour via indonesianKtpReferenceDate() — NIK column and accessors.
Region hierarchy lookup
- Auto-discovery:
FileRegionHierarchyLookup. KTP::nik()uses the container when the contract is bound; otherwise the bundled path (e.g. some unit tests).
Custom compiled file (same PHP array format), rebind after the package provider:
Eloquent HasIndonesianKtp
HasIndonesianKtp reads the NIK column via getAttribute() (casts and accessors apply). Comparisons against birth date, age, gender, and wilayah fields are explicit: you pass the value you want checked (for example from another column, a relation, or request input). The trait does not scan nik_* or fallback attribute names for you.
Default NIK attribute name: nik (override getIndonesianKtpNikColumn()). Non-digits are stripped after read.
Explicit matchers
Each nik*Is($value) method compares the argument to what is encoded or implied by the NIK. Extra attributes on the model are ignored unless you pass them in. Each short name has a long alias (indonesianIdNumber*Is) for consistency with the rest of the package.
Trait methods
| Method | Purpose |
|---|---|
hasValidNik() |
Structure + district hierarchy; same as hasValidIndonesianIdNumber() |
nikBirthdateIs(mixed $birth) |
NIK birth segment matches $birth; alias indonesianIdNumberBirthdateIs() |
nikGenderIs() |
NIK gender matches the argument (Gender or string); alias indonesianIdNumberGenderIs() |
nikProvinceIs(mixed $expected) |
Wilayah province expectation; alias indonesianIdNumberProvinceIs() |
nikRegencyIs(mixed $expected) |
Regency expectation; aliases indonesianIdNumberRegencyIs(), nikKabupatenIs(), nikCityIs(), nikDistrictIs() and matching indonesianIdNumber* forms |
nikSubdistrictIs(mixed $expected) |
Subdistrict expectation; aliases indonesianIdNumberSubdistrictIs(), nikKecamatanIs(), indonesianIdNumberKecamatanIs() |
nikAgeIs(int $age) |
Completed age from the NIK (per reference date rules) equals $age when unambiguous; alias indonesianIdNumberAgeIs() |
ageFromNik() |
Completed full years from the NIK at the trait’s reference instant; null when ambiguous; alias ageFromIndonesianIdNumber() |
isSeventeenOrOlderFromNik() |
Conservative 17+ check over all birth candidates; alias isSeventeenOrOlderFromIndonesianIdNumber() |
isTwentyOneOrOlderFromNik() |
Conservative 21+ check; alias isTwentyOneOrOlderFromIndonesianIdNumber() |
isAtLeastYearsFromNik(int $years) |
Conservative minimum-age check; alias isAtLeastYearsFromIndonesianIdNumber() |
NIK column and accessors
Override getIndonesianKtpNikColumn() and/or use an accessor on that column. The trait does not expose raw NIK normalization beyond stripping non-digits after getAttribute.
NIK column name
NIK value (accessor on the configured column)
Formatted storage → normalize in an accessor; the trait still strips non-digits after getAttribute.
Applicant-style: custom column names, explicit matchers
When birth date, gender, or wilayah live on other attributes or relations, read them yourself and pass them into nik*Is:
Reference date (indonesianKtpReferenceDate)
Default null → ambiguous two-digit years (like KTP::nik($nik) without asOf()). Return Carbon::now() (or any pivot) so every internal trait query uses asOf() for YY resolution.
Develop and test 🧪
Support
If this package saves you time, you can support ongoing maintenance on GitHub Sponsors or Trakteer.
Data source
Hierarchy file: upstream db/wilayah.sql and ship their own wilayah.php; this repo has no compile script.
Security 🔒
Validation does not send NIKs off-device. Treat NIKs as sensitive in logs and traces. Disclosure: SECURITY.md.
Versioning and support
Semantic Versioning. Upgrades: CHANGELOG.md.
- Releases: Packagist — bensondevs/indonesian-ktp
- Changelog:
CHANGELOG.md - Contributing:
CONTRIBUTING.md - Security:
SECURITY.md
Match supported Laravel majors to composer.json illuminate/* constraints when upgrading.
All versions of indonesian-ktp with dependencies
illuminate/contracts Version ^10.0|^11.0|^12.0|^13.0
illuminate/database Version ^10.0|^11.0|^12.0|^13.0
illuminate/support Version ^10.0|^11.0|^12.0|^13.0
illuminate/validation Version ^10.0|^11.0|^12.0|^13.0
nesbot/carbon Version ^2.67|^3.0