2.4 · التواريخ والتعابير النمطية (Regex) والرسائل الإلكترونية

المستوى 2 · PHP والويب

2.4التواريخ والتعابير النمطية (Regex) والرسائل الإلكترونية

الهدف: معالجة التواريخ بـ DateTime (المنطقة، صيغة التخزين)، والتحقق بـ filter_var (بدل التعابير المصنوعة) وإرسال الرسائل عبر مكتبات مخصصة — بالاعتماد على الأدوات المُجرَّبة.
الوقت المقدّر: 11 دقيقة · قراءة ذاتية · إذا كان لديك 5 دقائق فقط: اقرأ «الأساسي في 30 ثانية» + المخطط.

الأساسي في 30 ثانية

  • التواريخ بـ DateTime : إنشاء وتنسيق عند العرض (->format) وحساب الفروق (->diff) — المنطقة مضبوطة وإلا الساعات خاطئة.
  • خزن ISO واعرض محليا : نخزن AAAA-MM-JJ (قابل للترتيب وغير ملتبس) وننسق عند العرض فحسب — لا صيغة محلية في القاعدة أبدا.
  • filter_var أولا والتعابير عند الحاجة والمكتبة للرسائل : البريد والرابط عبر filter_var، وأنماط العمل بالتعابير المختبرة، والإرسال عبر PHPMailer أو Symfony Mailer — لا mail() في إنتاج جاد أبدا.

حالة مستمرة — رياد يؤرخ ويراقب ويكتب للأعضاء

الفصل الأخير من المشروع : رياد يؤرخ التسجيلات (2.1) والصور (2.3) بـ DateTime — بعد أن أضاع ظهيرة على ساعات مزاحة بسبب المنطقة غير المضبوطة. يراقب أرقام الأعضاء (صيغة داخلية دقيقة) بتعبير مختبر، لكنه يتحقق من العناوين بـ filter_var بدل تعبير مصنوع. وللنشرة، يهجر mail() لمكتبة مخصصة تدير المصادقة وقابلية التوصيل. مشروع المستوى 2 مُسلَّم : النماذج والجلسات والملفات والتواريخ.

خاتمة الخيط الرابط 2.1-2.3 : موقع رياد يعالج التواريخ والأنماط والرسائل بالأدوات الصحيحة.

1. التواريخ : DateTime والمنطقة والتخزين

التواريخ حاضرة في كل مكان (الإنشاء، الفعاليات، المدد) وPHP الحديث يديرها كائِنيا (Orienté objet) بـ DateTime — وDateTimeImmutable المفضل لأنه غير قابل للتعديل : إنشاء (new DateTime('2026-07-25') وnew DateTime() للآن)، وتَنسيق للعرض (->format('d/m/Y'))، وحساب الفُروق (->diff() بين تاريخين، ويدير السنوات الكبيسة والشهور المتفاوتة)، وإضافة/طرح المدد. الدوال الإجرائية القديمة (date() وtime() وstrtotime()) موجودة — ستصادفها. وحذران : المنطقة الزمنية (تُضبَط صراحة وإلا أزيحت كل الساعات — فخ رياد رقم 1 ؛ وللدولي، خزن بـ UTC وحول عند العرض) وصيغة التخزين : نخزن بالصيغة المعيارية ISO (AAAA-MM-JJ، وهي أيضا للقواعد — قابلة للترتيب وغير ملتبسة) ونُنسِّق عند العرض فحسب — ولا عكس أبدا.

2. التعابير : قوية لكن ليست لكل شيء

التعابير النمطية (Regex) تصف أَنماطا في النص : التحقق من صيغة (الرمز البريدي، مرجع العمل)، واستخراج أجزاء، والاستبدال حسب نمط. وفي PHP : preg_match() (هل يطابق ؟)، وpreg_match_all()، وpreg_replace()، وpreg_split(). وهي قَوية لكنها صعبة السمعة (صياغة غامضة، سهلة الكتابة السيئة — صارمة جدا أو متساهلة جدا، وبطيئة أحيانا). ومن هنا القاعدة : للتحققات الشائِعة (البريد، الرابط، IP، العدد الصحيح)، لا تكتب تعبيرك — استعمل filter_var() (FILTER_VALIDATE_EMAIL وFILTER_VALIDATE_URL) المُجرَّب والموثوق (فالتحقق من بريد صحيح بتعبير صعب على نحو مدهش). واحتفظ بالتعابير للأنماط الخاصة غير المغطاة بالمرشحات — كرقم عضو رياد — باختبارها بعناية والتعليق عليها. وللمعالجات البَسيطة (البحث، الاستبدال، التقطيع)، فضل دوال السلاسل، فهي أقرأ وأسرع.

3. الرسائل : مكتبة مخصصة وترويسات مُحكَمة

الدالة الأصلية mail() أَساسية وقليلة الموثوقية (قابلية التوصيل، السبام، إعداد الخادم) : للإرسال الجاد نستعمل مَكتبات مخصصة (PHPMailer وSymfony Mailer) تدير مصادقة SMTP والمرفقات وHTML وقابلية التوصيل — أو خدمات إرسال خارجية. ونقطة أَمان : لا تُدخِل أبدا بيانات مستخدم غير مراقبة في تَرويسات رسالة (ثغرة حقن الترويسات). فنشرة رياد تذهب إذن عبر مكتبة، بترويسات مبنية من قيم مراقبة. والمبدأ العابر للقسم : الاعتماد على الأَدوات المُجرَّبة (DateTime وfilter_var ومكتبات البريد) بدل ترقيع كل شيء يدويا.

خطأ شائع في الفهم: « تعبير مصنوع للعناوين أدق من filter_var ». لا، بل العكس : مواصفة العناوين الصالحة بالغة التعقيد، والتعابير المصنوعة دائما تقريبا إما صارمة جدا (ترفض عناوين صالحة) أو متساهلة جدا (تقبل أي شيء) — دون ذكر الحالات الحدية غير المختبرة أبدا. filter_var مع FILTER_VALIDATE_EMAIL يطبق تحققا مُجرَّبا ومُصانا. قاعدة رياد : حالة شائعة مغطاة بمرشح = filter_var دون نقاش ؛ والتعبير محفوظ للأنماط الخاصة بحاجته، مختبر ومُعلَّق.
التواريخ والأنماط والرسائل الأدوات المُجرَّبة الصحيحة DateTimeإنشاء وتنسيق و->diff ؛ والمنطقة + ISO+التعابير مقابل filter_varfilter_var للبريد/الرابط ؛ والتعابير = أنماط خاصة+الرسائلمكتبة مخصصة (لا mail()) الاعتماد على الأدوات المُجرَّبة بدل فعل كل شيء يدويا.
الأدوات المُجرَّبة الصحيحة
نص المخطط (SEO / قارئات الشاشة / الترجمة): 1) رياد يعالج التَواريخ بـ DateTime : إنشاء وتنسيق عند العرض وفروق بـ ->diff — والمنطقة مضبوطة والتخزين بـ ISO، ولا صيغة محلية في القاعدة أبدا. 2) للأَنماط، يتحقق من العناوين والروابط بـ filter_var (مُجرَّب) ويحتفظ بالتعابير المختبرة للصيغ الخاصة بالعمل. 3) يرسل رَسائله عبر مكتبة مخصصة (المصادقة وقابلية التوصيل)، دون بيان غير مراقب في الترويسات. الدرس : الأداة المُجرَّبة الصحيحة لكل حاجة، لا ترقيع منزلي.

هل تعلم ؟

رياد أضاع ظهيرة على ساعات مزاحة : منطقة الخادم لم تكن منطقة قسنطينة.
صحيح : منطقة غير مضبوطة تزيف كل التأريخات — الفخ رقم 1 للتواريخ.

سطر منطقة يساوي ظهيرة تصحيح.

🔎 مثال ملموس — 🔎 مثال ملموس — تسجيل رياد، مؤرَّخ ومتحقق

DateTime + filter_var، كما عند رياد :

$d = new DateTime('2026-07-25');
echo $d->format('d/m/Y');
// التخزين : صيغة ISO 2026-07-25
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
  echo htmlspecialchars($email, ENT_QUOTES, 'UTF-8');
}

القراءة : إنشاء التاريخ وتنسيقه، والتخزين بـ ISO، وتحقق موثوق دون تعبير مصنوع.

الدرس : اضبط المنطقة ؛ وخزن بـ ISO ونسق عند العرض.

مفردات القسم

التواريخ (DateTime)
PHP الحديث يعالج التواريخ بـ DateTime/DateTimeImmutable : إنشاء وتَنسيق للعرض (->format) وحساب الفروق (->diff) وإضافة/طرح.

مثال بسيط: رياد يؤرخ كل تسجيل بـ new DateTime().

ما ليس كذلك: حسابات المدد يدويا على الطوابع الزمنية.

رد فعل: معالجة تاريخ = DateTime.

المنطقة وصيغة التخزين
اضبط المَنطقة الزمنية (وإلا الساعات خاطئة) ؛ وخَزِّن بالصيغة المعيارية ISO (AAAA-MM-JJ) ونَسِّق عند العرض فحسب.

مثال بسيط: رياد يخزن 2026-07-25 ويعرض 25/07/2026.

ما ليس كذلك: تاريخ مُوطَّن مخزن كما هو في القاعدة.

رد فعل: خزن بـ ISO واعرض محليا.

التعابير النمطية (Regex)
لغة مصغرة تصف أنماطا في النص ؛ preg_match (هل يطابق ؟) وpreg_replace (الاستبدال) — قوية لكن صعبة.

مثال بسيط: رياد يراقب رقم العضو بتعبير مختبر.

ما ليس كذلك: تعبير مصنوع للتحقق من العناوين.

رد فعل: نمط خاص بالعمل = تعبير مختبر ومُعلَّق.

filter_var للتحقق
للتحققات الشائعة (البريد، الرابط…)، فضل filter_var (FILTER_VALIDATE_EMAIL…) على تعبير مصنوع — أكثر موثوقية.

مثال بسيط: كل بريد عضو يمر عبر FILTER_VALIDATE_EMAIL.

ما ليس كذلك: تعبير منسوخ دون اختبار للعناوين.

رد فعل: الحالة الشائعة = مرشح مُجرَّب.

إرسال الرسائل
الدالة الأصلية mail() أساسية وقليلة الموثوقية ؛ استعمل مكتبات مخصصة (PHPMailer وSymfony Mailer) — ولا بيانات غير مراقبة في الترويسات أبدا.

مثال بسيط: نشرة رياد تذهب عبر مكتبة بـ SMTP مُصادَق.

ما ليس كذلك: mail() حرفي لإرسالات جماعية.

رد فعل: بريد جاد = مكتبة مخصصة.

في التطبيق — تطبيقيا — التواريخ والتعابير والرسائل

  1. عالج التواريخ بـ DateTime : أنشئ ونسق للعرض (->format('d/m/Y')) واحسب فرقا (->diff) ؛ واضبط المنطقة الزمنية.
  2. تذكر : خزن التواريخ بالصيغة المعيارية (ISO) ونَسِّق عند العرض فحسب (لا تخزن صيغة مُوطَّنة أبدا).
  3. تحقق بـ filter_var (البريد، الرابط) بدل تعبير مصنوع ؛ واحتفظ بالتعابير (preg_match) للأنماط الخاصة.
  4. لإرسال رسالة بجدية، استعمل مكتبة مخصصة (PHPMailer / Symfony Mailer) بدل mail() ؛ ولا تحقن أبدا بيانات غير مراقبة في الترويسات.
تعالج التواريخ بـ DateTime (المنطقة وصيغة التخزين)، وتتحقق بـ filter_var (بدل التعابير المصنوعة) وترسل الرسائل عبر مكتبات مخصصة — بالاعتماد على الأدوات المُجرَّبة.

نص جاهز — الدفاع عن الأدوات المُجرَّبة في مراجعة الكود (30 ثانية)

« للتواريخ أستعمل DateTime والمنطقة مضبوطة، وأخزن بـ ISO وأنسق عند العرض — انتهت الساعات المزاحة. والعناوين تمر عبر filter_var لا بتعبير مصنوع. والإرسالات تذهب عبر مكتبة بـ SMTP مُصادَق لا بـ mail(). ثلاث أدوات مُجرَّبة، صفر ترقيع. »

يُقال مع عرض خطأ المنطقة المصحح وتعبير مصنوع مستبدَل بـ filter_var.

قالب للنسخ — تاريخ وفرق وتحقق من بريد

format('d/m/Y');
$aujourdhui = new DateTime();
$ecart = $inscription->diff($aujourdhui);
echo $ecart->format('%a jours d\u2019ancienneté');
// التخزين : $inscription->format('Y-m-d H:i:s')
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
  echo 'E-mail invalide.';
}

أقدمية عضو

رياد يحسب سنوات العضوية بـ ->diff : السنوات الكبيسة والشهور المتفاوتة مُدارة، دون حساب يدوي.

مرجع العمل

رقم العضو يتبع صيغة داخلية صارمة : تعبير مخصص مختبر على حالات حدية ومُعلَّق.

رسالة الترحيب

العنوان متحقق بـ filter_var، والإرسال عبر مكتبة SMTP : فالترحيب يصل بدل أن ينتهي في السبام.

كود إجرائي قديم

date() أو strtotime() يُصادَف في الصيانة : رياد يقرؤه ثم يهاجر إلى DateTime لكل معالجة.

حذر: لا تُدخِل أبدا بيان مستخدم غير مراقب في ترويسات رسالة : فمهاجم يحقن فيها ترويساته (مستلمون مخفيون، محتوى مُلفَّق) ويحرف خادمك للسبام. ابنِ الترويسات من قيم مراقبة ومرر عبر مكتبة تحميها. هذا الدليل يعطي المبدأ — اعرض كل إرسال حقيقي على تحقق قبل الإنتاج.

✓ ممارسات جيدة

  • استعمال DateTime/DateTimeImmutable ؛ وضبط المنطقة الزمنية.
  • تخزين التواريخ بـ ISO والتنسيق عند العرض فحسب.
  • التحقق من البريد/الرابط بـ filter_var ؛ وإرسال الرسائل عبر مكتبة مخصصة.

✗ أخطاء شائعة

  • المنطقة الزمنية غير المضبوطة (الساعات المزاحة) — الفخ رقم 1.
  • تخزين تاريخ بصيغة مُوطَّنة (ملتبس وغير قابل للترتيب).
  • كتابة تعبير مصنوع للتحقق من بريد (صعب وغير موثوق).

النقاط الأساسية

  • التَواريخ : PHP الحديث يستعمل صنف DateTime/DateTimeImmutable (إنشاء و->format للعرض و->diff للفروق). الحذر : المَنطقة الزمنية (وإلا الساعات خاطئة) وصيغة التَخزين (ISO AAAA-MM-JJ والتنسيق عند العرض فحسب).
  • التَعابير (preg_match وpreg_replace) = أنماط في النص، قوية لكن صعبة. للتحققات الشائِعة (البريد، الرابط)، فضل filter_var (FILTER_VALIDATE_EMAIL) على تعبير مصنوع.
  • الرَسائل : الدالة الأصلية mail() أساسية/قليلة الموثوقية ؛ استعمل مَكتبات مخصصة (PHPMailer وSymfony Mailer) للموثوقية وقابلية التوصيل.
  • المبدأ العابر : الاعتماد على الأَدوات المُجرَّبة (DateTime وfilter_var ومكتبات البريد) بدل فعل كل شيء يدويا. الأمان : لا بيانات غير مراقبة في ترويسات الرسائل.

تحدي 48 ساعة — طبق غدا

أرِّخ بيانا حقيقيا بـ DateTime (المنطقة مضبوطة والتخزين بـ ISO والعرض منسق و->diff حقيقي)، واستبدل تعبير بريد مصنوعا بـ filter_var، وحضر إرسالا عبر مكتبة بدل mail().

قائمة الخروج من القسم
  • أستطيع معالجة تاريخ (إنشاء وتنسيق وحساب فرق) دون خطأ منطقة.
  • أعرف متى أستعمل filter_var ومتى يكون التعبير مبررا.
  • حضرت إرسال رسالة عبر مكتبة بترويسات مُحكَمة.
تقييم ذاتي 1-5 : هل أخزن بـ ISO وأنسق عند العرض ؟هل أختار الأداة المُجرَّبة بدل الترقيع المنزلي ؟

أسئلة شائعة

ما الفخاخ الشائعة مع التواريخ في PHP، وكيف أتجنبها ؟

(1) المَنطقة الزمنية غير المضبوطة (الفخ رقم 1) : ساعات مزاحة وتأريخات خاطئة. اضبطها صراحة (date_default_timezone_set() أو date.timezone) ؛ وللدولي خزن بـ UTC وحول عند العرض. (2) الخلط بين التَخزين والعَرض : لا تخزن أبدا صيغة مُوطَّنة — خزن بـ ISO (AAAA-MM-JJ القابل للترتيب وغير الملتبس والمعياري في القاعدة) ونسق عند العرض فحسب (->format('d/m/Y')). (3) الدوال القديمة (date() وstrtotime()) : فضل DateTime/DateTimeImmutable للمعالجات. (4) الحسابات اليدوية (طوابع مطروحة) : خادعة (الكبيسة والشهور المتفاوتة) — استعمل ->diff(). (5) تغيير الساعة : DateTime بالمناطق الصحيحة يديره. (6) التحليل : DateTime::createFromFormat() بصيغة دقيقة ثم التحقق.

هل أتعلم التعابير النمطية، ومتى أستعملها (أو أتجنبها) ؟

نعم، الأَساسيات — ستصادفها في كل مكان — لكن دون هوس. تُتجنَّب في : (1) التحققات الشائِعة (البريد، الرابط، IP، العدد الصحيح) — استعمل filter_var (FILTER_VALIDATE_EMAIL…) : فالتحقق من بريد بتعبير صعب على نحو مدهش، والتعابير المصنوعة صارمة جدا أو متساهلة جدا ؛ (2) المعالجات البَسيطة — فضل دوال السلاسل (str_contains وstr_replace وexplode). تُبَرَّر في : الأنماط الخاصة غير المغطاة (الصيغة الداخلية، مرجع العمل، الاستخراج الدقيق) — مختبرة بعناية (الحالات الحدية) ومُعلَّقة (غير مقروءة وإلا). المطور الجيد يعرف متى يستعمل تعبيرا ومتى يفضل الأداة المخصصة — لا تعابير في كل مكان للتباهي.

تحقّق من فهمك

كيف أتحقق من بريد إلكتروني في PHP ؟

موارد إضافية (اختياري، للتعمّق أكثر)

اختبار المستوى 2أسئلة جديدة وأصعب للتحقق من مكتسباتك