How to Validate Iranian National Card Numbers with laravel-validate

Use the ValidNationalCard rule from the milwad-dev/laravel-validate package to validate 10-digit Iranian Melli Codes using the official government checksum algorithm.

The milwad-dev/laravel-validate package provides a robust, ready-to-use validation rule specifically designed for Iranian National Card numbers (also known as Melli Codes). This rule implements the standard Iranian national code checksum algorithm in src/Rules/ValidNationalCard.php, ensuring that user input conforms to the mathematical validation rules used by the Iranian National Organization for Civil Registration.

Understanding the ValidNationalCard Implementation

The validation logic resides in src/Rules/ValidNationalCard.php and implements Laravel’s Illuminate\Contracts\Validation\Rule contract. This design allows the rule to integrate seamlessly with request->validate(), Form Request classes, and manual Validator::make() calls without additional configuration.

The Iranian National Code Algorithm

The passes($attribute, $value) method executes a multi-layer validation sequence:

  1. Format validation: The input must match the regex /^\d{10}$/, ensuring exactly ten digits with no letters or symbols.
  2. Repetition check: The rule rejects strings consisting of a single repeated digit (e.g., 1111111111) using the pattern /^(.)\1*$/u.
  3. Checksum verification:
    • Multiply each of the first nine digits by a decreasing weight from 10 down to 2 (position 1 × 10, position 2 × 9, etc.).
    • Calculate the sum of these products and compute sum % 11.
    • If the remainder is less than 2, it must equal the 10th digit; otherwise, 11 - remainder must equal the 10th digit.

This algorithm matches the official validation used by Iranian government systems to detect typographical errors in national card numbers.

Class Structure and Error Handling

The class provides two required methods:

  • passes($attribute, $value): Returns true if the value passes all validation layers.
  • message(): Returns the translation key __('validate.national-card'), allowing localization through resources/lang/{locale}/validate.php.

The LaravelValidateServiceProvider registers the package’s translation namespace, ensuring the error message resolves correctly across locales.

Validating Iranian National Cards in Practice

Controller Validation

Use the rule directly within controller validation logic:

use Milwad\LaravelValidate\Rules\ValidNationalCard;
use Illuminate\Http\Request;

public function store(Request $request)
{
    $validated = $request->validate([
        'national_card' => ['required', new ValidNationalCard],
    ]);

    // $validated['national_card'] contains a verified Iranian Melli Code
}

Form Request Classes

For cleaner controllers, implement the rule in a dedicated Form Request:

// app/Http/Requests/StoreUserRequest.php
use Milwad\LaravelValidate\Rules\ValidNationalCard;
use Illuminate\Foundation\Http\FormRequest;

class StoreUserRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'national_card' => ['required', new ValidNationalCard],
            'name' => 'required|string',
        ];
    }
}

Manual Validator Instances

When validating data outside of HTTP requests, use the Validator facade:

use Milwad\LaravelValidate\Rules\ValidNationalCard;
use Illuminate\Support\Facades\Validator;

$data = ['national_card' => '0151016437'];
$validator = Validator::make($data, [
    'national_card' => ['required', new ValidNationalCard],
]);

if ($validator->fails()) {
    // Handle invalid Iranian national card number
}

The test suite in tests/Rules/ValidNationalCardTest.php confirms that valid codes like 0151016437 pass, while invalid checksums like 0151016438 or malformed inputs like 101010 correctly fail validation.

Customizing Error Messages

The rule retrieves error messages using the translation key validate.national-card. Override this in your application’s language files to provide locale-specific feedback:

// resources/lang/fa/validate.php
return [
    'national-card' => 'کد ملی وارد شده معتبر نیست.',
];

// resources/lang/en/validate.php
return [
    'national-card' => 'The provided national card number is invalid.',
];

Place these files in resources/lang/{locale}/validate.php and Laravel will automatically resolve the appropriate message based on the application’s current locale.

Summary

  • The ValidNationalCard rule in milwad-dev/laravel-validate validates 10-digit Iranian Melli Codes using the official checksum algorithm implemented in src/Rules/ValidNationalCard.php.
  • The rule rejects repeated digits (e.g., 1111111111) and validates the mathematical checksum of the first nine digits against the tenth control digit.
  • It implements Laravel’s Rule contract, enabling use in controllers, Form Requests, and manual Validator instances.
  • Error messages are customizable via the validate.national-card translation key in resources/lang/*/validate.php.
  • The package includes comprehensive unit tests in tests/Rules/ValidNationalCardTest.php covering valid codes (0151016437) and invalid scenarios.

Frequently Asked Questions

What is the valid format for an Iranian national card number?

A valid Iranian national card number consists of exactly ten digits. The first nine digits form the unique identifier, while the tenth digit serves as a control number calculated using a weighted checksum algorithm. The ValidNationalCard rule enforces this 10-digit requirement and validates the checksum relationship.

Does this rule verify if the number is registered with the Iranian government?

No. The ValidNationalCard rule only performs syntactic and checksum validation to ensure the number follows the correct format and mathematical logic. It does not query government databases to confirm if the number is actively registered or assigned to a specific individual. For existence verification, you must integrate with official National Organization for Civil Registration APIs.

Can I use this rule alongside other Laravel validation rules?

Yes. Because ValidNationalCard implements Illuminate\Contracts\Validation\Rule, it composes naturally with standard Laravel validation rules. You can combine it with required, unique:users, or custom rules in the same validation array: 'national_card' => ['required', 'unique:users', new ValidNationalCard].

How do I change the error message for invalid national card numbers?

Publish or create a translation file at resources/lang/{locale}/validate.php and define the national-card key. The rule’s message() method returns __('validate.national-card'), so Laravel will automatically use your custom text when validation fails for that locale.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →