Skip to the guide
All guides

قواعد التحقق وتحويل Eloquent

استخدم قواعد التحقق الإيرانية في نماذج Laravel، وخزّن التواريخ الجلالية في نماذج Eloquent عبر JalaliCast، واعرضها في Blade.

app RTLY-Kit 0.2.0checked reading 7 minutes

On this page

قواعد التحقق

بعد تثبيت الحزمة (إعداد Laravel) تتوفر ست قواعد (بسبعة أسماء، لأن mobile اسم مختصر لـ iran_mobile) في أي مُحقِّق أو طلب نموذج (form request) أو استدعاء $request->validate(). وهي تغلّف أدوات التحقق الموثقة في صفحات التحقق.

القاعدةتقبلالتفاصيل
national_codeالرقم الوطني الإيرانيالرقم الوطني
shebaشبا / IBAN، مع البادئة IR أو بدونهاشبا والبطاقة المصرفية
bank_cardرقم بطاقة مصرفية من 16 رقماً (فحص Luhn)شبا والبطاقة المصرفية
iran_mobileرقم جوال إيرانيالجوال والرمز البريدي واللوحة
mobileاسم مختصر بديل لـ iran_mobileسلوك مطابق
postal_codeرمز بريدي إيراني من 10 أرقامالجوال والرمز البريدي واللوحة
vehicle_plateلوحة مركبة إيرانية، مثل 12ب345-67الجوال والرمز البريدي واللوحة

من المفيد أن تعرف. الكلمة mobile عامة. فإذا سجّلت حزمة أخرى أو شيفرتك قاعدة باسم mobile، فاستخدم iran_mobile في كل مكان لتجنب الالتباس.

استخدامها

PHP
use Illuminate\Http\Request;

public function store(Request $request)
{
    $data = $request->validate([
        'national_code' => 'required|national_code',
        'mobile'        => 'required|iran_mobile',
        'card'          => 'nullable|bank_card',
        'iban'          => 'nullable|sheba',
        'postal'        => 'required|postal_code',
        'plate'         => 'nullable|vehicle_plate',
    ]);
}

عند التشغيل على بيانات سيئة بلغة fa، أنتج تشغيل تحقق فعلي ما يلي:

PHP
// national_code = '1234567890', mobile = '0912', iban = 'IR000000000000000000000000'
// card وpostal وplate تحمل قيماً صالحة وتجتاز التحقق.
//
// national_code: national code کد ملی معتبر نیست.
// mobile: mobile شماره موبایل معتبر نیست.
// iban: iban شماره شبا معتبر نیست.

النص الإنجليزي هو "The national code is not a valid Iranian national code." والنص العربي متوفر أيضاً؛ راجع الترجمات وتجاوز الرسائل.

المدخلات التي تقبلها القواعد

  • السلاسل النصية. تُقبل الأرقام الفارسية والعربية: ۰۰۱۳۵۴۲۴۱۹ تجتاز national_code .
  • الأعداد الصحيحة والعشرية تُحوَّل إلى سلسلة نصية أولًا. احذر من الأعداد التي تبدأ بصفر: فالعدد 13542419 في JSON فقد الأصفار البادئة في 0013542419 و يفشل . أرسل الأرقام الوطنية وأرقام الجوال والرموز البريدية سلاسل نصية.
  • المصفوفات والكائنات والقيم المنطقية لا تصل إلى أداة التحقق أبدًا وتفشل في القاعدة ببساطة.
  • القيم الفارغة. كما في قواعد Laravel نفسها، تُتخطى السلسلة الفارغة والمفتاح المفقود ما لم يكن الحقل required . أما null الصريحة فتفشل ما لم يكن الحقل nullable . عبّر عما تقصده بـ required أو nullable .
PHP
$f->make(['n' => '۰۰۱۳۵۴۲۴۱۹'], ['n' => 'national_code'])->passes();          // true
$f->make(['n' => 13542419],      ['n' => 'national_code'])->passes();          // false (فُقدت الأصفار البادئة)
$f->make(['n' => null],          ['n' => 'nullable|national_code'])->passes(); // true
$f->make(['n' => null],          ['n' => 'national_code'])->passes();          // false
$f->make(['n' => ''],            ['n' => 'national_code'])->passes();          // true  (تُتخطى)
$f->make(['n' => ''],            ['n' => 'required|national_code'])->passes(); // false
$f->make([],                     ['n' => 'national_code'])->passes();          // true  (المفتاح مفقود)

إذا احتجت إلى سبب فشل القيمة (طول خاطئ أو مجموع تحقق سيئ أو نوع خاطئ)، فاستدعِ أدوات التحقق المستقلة التي تُرجع Result منظّمة؛ راجع نظرة عامة على أدوات التحقق.

تحويل Eloquent باسم JalaliCast

يُبقي RtlyKit\Laravel\Casts\JalaliCast عمود قاعدة البيانات ميلاديًا (Y-m-d H:i:s) كما تتوقع كل الأدوات، ويُظهر السمة في النموذج كائنًا غير قابل للتغيير من RtlyKit\Calendar\Jalali.

PHP
use Illuminate\Database\Eloquent\Model;
use RtlyKit\Laravel\Casts\JalaliCast;

class Post extends Model
{
    protected $guarded = [];

    protected $casts = [
        'published_at' => JalaliCast::class,
    ];
}

$post = new Post();
$post->published_at = '1404/01/15 10:30';

echo $post->getAttributes()['published_at'];          // 2025-04-04 10:30:00   (القيمة المخزَّنة)
echo $post->published_at->format('Y/m/d H:i');        // 1404/01/15 10:30
echo get_class($post->published_at);                  // RtlyKit\Calendar\Jalali
echo $post->published_at->addDays(20)->format('Y/m/d'); // 1404/02/04

يبقى نوع العمود datetime أو timestamp؛ ولا حاجة إلى تغيير في الترحيل (migration).

القيم المقبولة عند الإسناد

القيمة المُسنَدةالمخزَّن (ميلادي)
سلسلة جلالية '1404/01/15 10:30'2025-04-04 10:30:00
تاريخ جلالي فقط بأرقام فارسية وشرطات '۱۴۰۴-۰۱-۱۵'2025-04-04 00:00:00
سلسلة ميلادية '2025-04-04 08:00:00'2025-04-04 08:00:00
طابع زمني Unix (int) 17437536002025-04-04 08:00:00 (مع منطقة زمنية افتراضية UTC)
أي DateTimeInterface (بما فيها Carbon)اللحظة نفسها، بصيغة Y-m-d H:i:s
كائن Jalaliما يعادله ميلاديًا
null أو ''null

تُقرأ السلسلة جلالية إذا كانت سنتها بين 1200 و1599 وكان الفاصل / أو -، مع وقت اختياري HH:MM أو HH:MM:SS بعد مسافة أو T. وأي سلسلة أخرى تمرّ عبر محلِّل التواريخ العادي على أنها ميلادية.

الأخطاء

المدخل السيئ يُطلق RtlyKit\Exceptions\InvalidDateException لحظة إسناده، ولا يظهر خطأ PHP خام أبدًا:

PHP
$post->published_at = '1404/13/01';   // Invalid Jalali date: 1404/13/1
$post->published_at = '1404/07/31';   // Invalid Jalali date: 1404/7/31   (شهر مهر 30 يوماً)
$post->published_at = 'not a date';   // Unable to parse date: not a date
$post->published_at = 1.5;            // Cannot cast value for 'published_at' to a date.
$post->published_at = ['x'];          // Cannot cast value for 'published_at' to a date.

تحقق من مدخلات المستخدم قبل أن تصل إلى النموذج (انظر مثال طلب النموذج أدناه)، كي يؤدي الخطأ الإملائي إلى خطأ في الحقل بدل استثناء. القراءة متساهلة مع null والسلسلة الفارغة (كلتاهما تعطي null)، لكن السمة التي تحمل نصًا غير قابل للتحليل في قاعدة البيانات تُطلق InvalidDateException عند قراءتها.

تسلسل النموذج

تنفّذ Jalali وHijri وHebrew الواجهة JsonSerializable: فاستدعاء toJson() على نموذج فيه سمة JalaliCast يعطي النص نفسه الذي يعطيه (string) $date، مثل {"published_at":"1404/01/01 10:00:00"}. أما toArray() فتُبقي كائن Jalali؛ نسّقه بنفسك إذا احتجت إلى نمط آخر.

طلبات النماذج

لا توجد قاعدة مضمّنة لحقل تاريخ جلالي، فتحقق من الصيغة بقاعدة regex في Laravel أو بقاعدة مخصصة صغيرة، ثم دع التحويل (cast) يتولى التحويل:

PHP
public function rules(): array
{
    return [
        'published_at' => ['required', 'regex:/^1[2-5]\d\d[\/-]\d{1,2}[\/-]\d{1,2}$/u'],
    ];
}

التاريخ حسن الصياغة لكنه مستحيل مثل 1404/07/31 يصل إلى التحويل ويُطلق الاستثناء هناك؛ فالتقط InvalidDateException في قاعدة مخصصة أو في المتحكم (controller) إذا كان المستخدمون يكتبون نصًا حرًا.

Blade

يمنحك التحويل كائن Jalali، فلا يحتاج Blade إلى أي دالة مساعدة:

PHP
{{ $post->published_at?->format('Y/m/d') }}            {{-- 1404/01/15 --}}
{{ $post->published_at?->format('l j F Y') }}          {{-- جمعه 15 فروردین 1404 --}}
{{ \RtlyKit\to_persian_digits($post->published_at->format('Y/m/d')) }}  {{-- ۱۴۰۴/۰۱/۱۵ --}}

أما العمود غير المحوَّل، مثل created_at القياسي (وهو نسخة Carbon)، فاستخدم الدالة المساعدة ضمن فضاء الأسماء. الدوال المساعدة ضمن فضاء الأسماء محمَّلة دائماً، فلا حاجة إلى تسجيل:

PHP
{{ \RtlyKit\jdate($post->created_at)->format('Y/m/d H:i') }}   {{-- 1404/01/15 08:00 --}}

استورد الدالة في أعلى ملف Blade بـ @php use function RtlyKit\jdate; @endphp إن كنت تستخدمها كثيرًا. ومع ماكروات Carbon يصبح الأمر $post->created_at->jformat('Y/m/d')؛ راجع ماكروات Carbon.

ملاحظة. السمة الفارغة (null) لا تُنسَّق من تلقاء نفسها: استخدم عامل nullsafe (?->) كما هو موضح، وإلا أطلق Blade خطأً عند null. وللاطلاع على القائمة الكاملة لحروف التنسيق راجع صفحة التقويم الجلالي.