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

User Id Idcard Bundle Laravel Package

tourze/user-id-idcard-bundle

Symfony bundle for Chinese resident ID card (shenfenzheng) support: validate 18-digit numbers, derive birth date, gender and region from the code, and attach ID data to your user entities. Simple bundle configuration and Doctrine-friendly helpers keep registration and profile forms consistent.

View on GitHub
Deep Wiki
Context7

Getting Started

What this package is. tourze/user-id-idcard-bundle is a small Symfony bundle from the Tourze family of micro-packages. Its purpose is the Chinese resident identity card (身份证 / shenfenzheng) — parsing and validating the 18-character ID string, and exposing the derived data encoded inside it (region code, birth date, gender, checksum). v0.0.1 is the initial tagged release, so treat the surface as provisional.

First steps for a Laravel developer:

  1. composer require tourze/user-id-idcard-bundle:0.0.1 — pin the exact version. Pre-1.0 packages in this ecosystem routinely reshuffle namespaces between tags.
  2. Because it is packaged as a Bundle, there is no Laravel service provider and no package auto-discovery. Do not add it to config/app.php providers. You are using its plain PHP classes directly, not its Symfony wiring.
  3. Read vendor/tourze/user-id-idcard-bundle/src/ first — with no release notes, the source is the documentation. Look for the value object / parser class (typically named around IdCard, IdCardInfo, or UserIdentity) and any Validator or Constraints folder.
  4. Run one string through it in php artisan tinker before writing any code:
$info = (new \Tourze\UserIdIdCardBundle\...\IdCardParser())->parse('11010519491231002X');
// inspect: birthdate, gender, region, checksum validity

The first real use case is almost always registration/profile validation: accept an ID number on a Chinese-facing signup form, reject bad checksums, and derive date of birth and gender instead of asking the user twice.

Implementation Patterns

Wrap it in a Laravel validation rule. The natural integration point is a custom rule rather than a Symfony constraint:

class ChineseIdCard implements ValidationRule
{
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        $result = app(IdCardParser::class)->parse((string) $value);

        if (! $result->isValid()) {
            $fail('The :attribute must be a valid Chinese ID card number.');
        }
    }
}

Register a Validator::extend('id_card', ...) alias too if you prefer the string syntax 'id_card' in form requests — it reads better across dozens of form classes.

Cast to a value object on the model. If the package ships an immutable value object, use a custom cast so the raw string never leaks into your domain code:

protected function casts(): array
{
    return ['id_card' => IdCardCast::class];
}

Store the canonical 18-character uppercase form in the database; normalize on the way in, not on the way out.

Derive and persist, don't re-parse. Compute birthday, gender, and region once at write time into real columns (birth_date, gender, region_code). These are queryable, indexable, and survive a package swap. Re-parsing on every read couples your listing pages to a 0.0.1 dependency.

Pair with a checksum-only fast path. For high-traffic forms, run the (cheap) checksum test before instantiating the full parser, so obviously malformed input fails fast.

Use it in imports and backfills, not just forms. The most valuable day-to-day use is a queued import job: validate each row, collect failures into a report, and hydrate the derived columns in bulk. Do this in chunks with lazyById(); a 50k-row CSV will otherwise hammer memory.

Region codes are data, not logic. If the package exposes a region lookup, wrap it in your own RegionRepository interface with a database-backed implementation. Chinese administrative divisions get merged and renamed; you want to update a table, not a Composer dependency.

Gotchas and Tips

  • No release notes. v0.0.1 ships with only a changelog link. Read the source and write a two-line integration test immediately (one valid ID, one bad checksum) so a future patch bump can't silently break you. Pin 0.0.1 exactly, and re-run that test before any upgrade.
  • It's a Symfony bundle, not a Laravel package. Any services.yaml, DependencyInjection/, or *Extension class is dead weight in Laravel. Avoid pulling in symfony/framework-bundle semantics; construct the classes yourself or bind them in a small IdCardServiceProvider of your own.
  • Trailing X casing. The final checksum character can be X or x. Normalize with strtoupper(trim($value)) before validating, or you will reject legitimate cards — and users paste from documents with full-width characters and stray spaces. Strip non-alphanumerics first.
  • 15-digit legacy numbers. Older citizens' cards still exist. They encode the year as two digits and have no checksum. Decide explicitly whether you support them; if you do, expand to 18 digits before parsing rather than after.
  • Birth dates are tricky at the edges. February 29 is legitimate only in leap years, and a parsed date should be treated as a calendar date, not a UTC timestamp. Compare with Carbon::parse(...)->isBefore(now()) to reject future dates — a checksum-valid but future-dated card is a data-entry or fraud signal, not a parse error.
  • Gender is parity, not a lookup. The 17th digit: odd = male, even = female. Don't trust a package accessor that returns an enum you can't map to your own schema; convert at the boundary.
  • PII handling is on you. This field is sensitive personal data. Do not log the raw ID on validation failure, do not include it in exception messages, and mask it in admin views (110105********002X). Consider encryption-at-rest via a cast for the raw column, and keep the derived columns unencrypted so they stay queryable.
  • Debugging checklist when a "valid" card is rejected: check length after normalization, verify the check digit manually against the weighted modulus-11 algorithm, confirm the birth-date substring is a real date, and confirm you aren't passing an integer — leading zeros in the region code are silently lost if PHP casts it.
  • Extension points. The cleanest long-term posture is a thin adapter: your own IdCardValidator and IdCardInfo DTOs wrapping whatever this package exposes. If Tourze abandons the bundle at 0.0.2 — a real risk for micro-packages — you swap one adapter class instead of hunting down call sites across the app.

Assessment based on v0.0.1. No functional changes are documented in this release beyond the initial tag, so this evaluation reflects the package's structure and stated domain rather than a verified feature list — confirm the actual class names against vendor/ before committing to the patterns above.

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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console