Skip to the guide
All guides

الرقم الوطني

تحقق من الأرقام الوطنية الإيرانية (کد ملی) برقم التحقق mod-11، مع قبول الأرقام الفارسية والعربية، وقراءة تلميح مكان الإصدار بأمان.

app RTLY-Kit 0.2.0checked reading 5 minutes

On this page

البدء السريع

PHP
<?php
require 'vendor/autoload.php';

use RtlyKit\Validation\NationalCode;

var_dump(NationalCode::isValid('0499370899'));      // bool(true)
var_dump(NationalCode::isValid('۰۴۹۹۳۷۰۸۹۹'));      // bool(true)، أرقام فارسية
var_dump(NationalCode::isValid('049-937-0899'));    // bool(true)، تُحذف الشرطات

$result = NationalCode::validate('0499370899');
echo json_encode($result->details(), JSON_UNESCAPED_UNICODE);
// {"normalized":"0499370899","location":{"province":"تهران","city":"شهرری"}}

تطبّق الفئة عقد Validator المشترك، فتُرجع validate() كائن Result ولا يُلقي شيء استثناءً بسبب مُدخَل سيّئ. والدالتان المساعدتان هما RtlyKit\is_national_code() وRtlyKit\validate_national_code():

PHP
use function RtlyKit\is_national_code;
use function RtlyKit\validate_national_code;

var_dump(is_national_code('۰۴۹۹۳۷۰۸۹۹'));                  // bool(true)
print_r(validate_national_code('0499370898')->errors());  // Array ( [0] => invalid_checksum )

ما الذي يُفحص

تجري الفحوص بهذا الترتيب وتتوقف عند أول فشل:

  1. النوع والحجم. تُقبل النصوص و int و float ذو القيمة الصحيحة؛ وأي شيء آخر هو invalid_type ، والنص الذي يزيد على 4096 بايت هو input_too_long .
  2. التطبيع. تتحول الأرقام الفارسية والعربية إلى إنجليزية؛ وتُحذف المسافات والشرطات والمسافات الصفرية (ZWNJ) ويُقصّ الطرفان.
  3. الصيغة. 10 أرقام بالضبط، وإلا invalid_format .
  4. الأرقام المكررة. تمرّ الأرقام من 0000000000 إلى 9999999999 من الحساب بمحض المصادفة لكنها ليست أرقامًا حقيقية، فتُرجع repeated_digits .
  5. رقم التحقق (قاعدة mod-11 أدناه)، وإلا invalid_checksum .

خوارزمية رقم التحقق

اضرب كلًا من الأرقام التسعة الأولى في وزن من 10 نزولًا إلى 2، واجمع النواتج، وخذ باقي قسمة المجموع على 11. إذا كان الباقي 0 أو 1 فرقم التحقق يساوي الباقي؛ وإلا فهو 11 ناقص الباقي.

للرقم 0499370899: النواتج هي 0 و36 و72 و63 و18 و35 و0 و24 و18، ومجموعها 266. وباقي قسمة 266 على 11 هو 2، فيجب أن يكون رقم التحقق 11 − 2 = 9، وآخر رقم هو 9 فعلًا.

PHP
print_r(NationalCode::validate('0499370898')->errors());   // [invalid_checksum]
print_r(NationalCode::validate('1111111111')->errors());   // [repeated_digits]
print_r(NationalCode::validate('12345')->errors());        // [invalid_format]
print_r(NationalCode::validate('abc')->errors());          // [invalid_format]

أبقِه نصًا. قد يبدأ الرقم الوطني بصفر. فالاستدعاء NationalCode::validate(499370899) يتلقى الأرقام التسعة 499370899 ويُرجع invalid_format. لذلك لا تحوّل القيمة إلى عدد صحيح في أي خطوة بين الإدخال وأداة التحقق، ومن ذلك عمود قاعدة البيانات ورقم JSON.

المُدخَلات المقبولة

المُدخَلالنتيجة
'0499370899'صالح
'۰۴۹۹۳۷۰۸۹۹' (أرقام فارسية)صالح
'٠٤٩٩٣٧٠٨٩٩' (أرقام هندية عربية)صالح
'049-937-0899'، ' 0499370899 'صالح؛ تُحذف الفواصل والمسافات
null، []، 1.5invalid_type
12.0يُقرأ على أنه '12'، فيكون invalid_format
4097 نويسةinput_too_long

لا تُعامل فواصلَ إلا المسافات والشرطات وZWNJ. أما الشرطات المائلة والنقاط والحروف فلا تُحذف وتسبب invalid_format.

للحصول على الصيغة المنظَّفة دون تحقق، استدعِ NationalCode::normalize():

PHP
echo NationalCode::normalize(' ۰۴۹-۹۳۷ ۰۸۹۹ ');   // 0499370899

تفاصيل Result

المفتاحالنوعالمعنى
normalizedstringالرقم بعد التطبيع (فارغ في حالتي invalid_type / input_too_long)
locationarray أو null{province, city} للرقم الصالح الذي توجد بادئته في الجدول، وإلا null

مفاتيح الأخطاء: invalid_format وrepeated_digits وinvalid_checksum وinvalid_type وinput_too_long. ومعنى كل منها في جدول مفاتيح الأخطاء.

تلميح مكان الإصدار

الأرقام الثلاثة الأولى من الرقم الوطني بادئة يخصصها السجل المدني. تحوّلها NationalCode::getLocation() إلى محافظة ومدينة، وتُرجع null حين يكون الرقم غير صالح أو حين لا تكون البادئة في الجدول:

PHP
print_r(NationalCode::getLocation('0499370899'));
// Array ( [province] => تهران [city] => شهرری )

var_dump(NationalCode::getLocation('0499370898'));   // NULL (رقم غير صالح)

$a = NationalCode::validate('0012345679');   // البادئة 001
echo json_encode($a->details()['location'], JSON_UNESCAPED_UNICODE);
// {"province":"تهران","city":"تهران مرکزی"}

$b = NationalCode::validate('9991234561');   // رقم تحقق صحيح، والبادئة 999 غير موجودة في الجدول
var_dump($b->isValid(), $b->details()['location']);   // bool(true)  NULL

من المفيد أن تعرف. تدل البادئة على المكان الذي صدرت فيه شهادة الميلاد أو البطاقة الأصلية، وليس على مكان ولادة الشخص أو إقامته. كثيرون يحملون أرقامًا صدرت في أماكن أخرى، وقد تغيّرت حدود المحافظات منذ الإصدار (كرج مثلًا تظهر تحت طهران). لذلك استخدم المكان معلومة إرشادية فقط، لا للتحقق من الهوية أو الأصل أو الإقامة. لا ينشر السجل المدني قائمة تقرؤها الآلة. والجدول هنا يضم 547 بادئة، وكل بادئة فيه اتفقت عليها ثلاث مجموعات بيانات منشورة على المحافظة والمدينة معًا، ولم تناقضها مجموعة رابعة. وبعض هذه المجموعات مشتق من بعض. والبادئة غير الموجودة تعني «غير معروف» ولا تعني «غير صالح». المصادر في الدقة والبيانات.

ما لا يخبرك به التحقق

  • رقم التحقق الصحيح يعني أن الرقم سليم الصياغة. ولا يعني أن الرقم صدر يومًا أو أنه يخص شخصًا بعينه.
  • تستخدم الأشخاص الاعتبارية معرّفًا مختلفًا من 11 رقمًا. ولا تتعامل معه أداة التحقق هذه، ويُرفض بـ invalid_format .
  • أرقام تعريف الأجانب (Amayesh وما يشبهها) نظام مختلف وغير مشمولة.

الاستخدام في نموذج

اعرض للمستخدم رسالة تختارها بحسب مفتاح الخطأ، واحفظ القيمة المطبَّعة:

PHP
$messages = [
    'invalid_format'   => 'The national code must be 10 digits.',
    'repeated_digits'  => 'This national code is not valid.',
    'invalid_checksum' => 'This national code is not valid.',
];

$result = NationalCode::validate($_POST['national_code'] ?? null);
if (! $result->isValid()) {
    $key = $result->errors()[0];
    echo $messages[$key] ?? 'Invalid input.';
} else {
    $code = $result->details()['normalized'];   // احفظ هذه القيمة
}

وفي Laravel استخدم القاعدة الجاهزة والترجمات بدلًا من ذلك؛ انظر التحقق والتحويل (Cast) في Laravel.