# How to Validate Iranian National Card Numbers with laravel-validate

> Easily validate Iranian National Card Numbers using the ValidNationalCard rule in laravel-validate. Implement the official government checksum algorithm for accurate validation.

- Repository: [Milwad Khosravi/laravel-validate](https://github.com/milwad-dev/laravel-validate)
- Tags: tutorial
- Published: 2026-03-07

---

**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`](https://github.com/milwad-dev/laravel-validate/blob/main/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`](https://github.com/milwad-dev/laravel-validate/blob/main/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:

```php
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:

```php
// 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:

```php
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`](https://github.com/milwad-dev/laravel-validate/blob/main/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:

```php
// 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`](https://github.com/milwad-dev/laravel-validate/blob/main/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`](https://github.com/milwad-dev/laravel-validate/blob/main/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.