في هذه الصفحة
البدء السريع#
<?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():
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 )
ما الذي يُفحص#
تجري الفحوص بهذا الترتيب وتتوقف عند أول فشل:
- النوع والحجم. تُقبل النصوص و
intوfloatذو القيمة الصحيحة؛ وأي شيء آخر هوinvalid_type، والنص الذي يزيد على 4096 بايت هوinput_too_long. - التطبيع. تتحول الأرقام الفارسية والعربية إلى إنجليزية؛ وتُحذف المسافات والشرطات والمسافات الصفرية (ZWNJ) ويُقصّ الطرفان.
- الصيغة. 10 أرقام بالضبط، وإلا
invalid_format. - الأرقام المكررة. تمرّ الأرقام من
0000000000إلى9999999999من الحساب بمحض المصادفة لكنها ليست أرقامًا حقيقية، فتُرجعrepeated_digits. - رقم التحقق (قاعدة 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 فعلًا.
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.5 | invalid_type |
12.0 | يُقرأ على أنه '12'، فيكون invalid_format |
| 4097 نويسة | input_too_long |
لا تُعامل فواصلَ إلا المسافات والشرطات وZWNJ. أما الشرطات المائلة والنقاط والحروف فلا تُحذف وتسبب invalid_format.
للحصول على الصيغة المنظَّفة دون تحقق، استدعِ NationalCode::normalize():
echo NationalCode::normalize(' ۰۴۹-۹۳۷ ۰۸۹۹ '); // 0499370899
تفاصيل Result#
| المفتاح | النوع | المعنى |
|---|---|---|
normalized | string | الرقم بعد التطبيع (فارغ في حالتي invalid_type / input_too_long) |
location | array أو null | {province, city} للرقم الصالح الذي توجد بادئته في الجدول، وإلا null |
مفاتيح الأخطاء: invalid_format وrepeated_digits وinvalid_checksum وinvalid_type وinput_too_long. ومعنى كل منها في جدول مفاتيح الأخطاء.
تلميح مكان الإصدار#
الأرقام الثلاثة الأولى من الرقم الوطني بادئة يخصصها السجل المدني. تحوّلها NationalCode::getLocation() إلى محافظة ومدينة، وتُرجع null حين يكون الرقم غير صالح أو حين لا تكون البادئة في الجدول:
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 وما يشبهها) نظام مختلف وغير مشمولة.
الاستخدام في نموذج#
اعرض للمستخدم رسالة تختارها بحسب مفتاح الخطأ، واحفظ القيمة المطبَّعة:
$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.