انتقل إلى محتوى الدرس
الدرس 92
دورة PHP

إرسال النماذج والتحقق التفاعلي واستطلاعات الرأي الحية عبر AJAX في PHPPHP AJAX Form Submission Validation and Live Polling

أرسل النماذج بدون تحديث الصفحة باستخدام FormData، وأرجع أخطاء التحقق لكل حقل من PHP، وابنِ نظام تصويت تفاعلي فوري.
أقسام الدرس
6
الأمثلة
6
اللغة
العربية
تاريخ النشر
غير محدد
المشاهدات
0
محتوى الدرس
في هذا الدرس 6تصفّح المواضيع

يتيح تمرير عنصر <form> إلى الكائن new FormData(form) في JavaScript تجميع كافة حقول النموذج تلقائياً وإرسالها بحيث تملأ مصفوفتي $_POST و$_FILES في PHP مباشرة!

  • استدعِ event.preventDefault() داخل مستمع الحدث submit لمنع المتصفح من إعادة تحميل الصفحة تقليدياً.
  • مرر body: new FormData(form) إلى دالة fetch(form.action, { method: "POST", body }).
  • عند إرسال كائن FormData، لا تضبط رأس الطلب Content-Type يدوياً؛ لأن المتصفح يضبطه تلقائياً مع رمز الفاصل boundary الصحيح.

لأن كائن FormData يستخدم ترميز النماذج القياسي، يقرأ ملف PHP الحقول مباشرة عبر $_POST["name"] و$_POST["subject"] دون تعقيد.

مخطط توضيحي: محاكي إرسال النماذج التفاعلية والتحقق واستطلاعات الرأي بـ AJAX في PHP
PHP
<?php
// PHP receives FormData fields directly inside $_POST
$_POST = [
    'name'    => 'Nadia',
    'subject' => 'AJAX Form Inquiry',
];
$name = trim((string) ($_POST['name'] ?? ''));
$subject = trim((string) ($_POST['subject'] ?? ''));
echo json_encode([
    'ok'       => true,
    'received' => "$name: $subject",
]) . "\n";

بدلاً من تحويل المسار عند فشل التحقق، يضبط معالج نماذج AJAX رمز الحالة http_response_code(422) ويُرجع مصفوفة أخطاء errors مفهرسة باسم كل حقل.

  • اجمع رسائل الخطأ لكل حقل في مصفوفة ترابطية مثل $errors["email"] = "البريد الإلكتروني غير صالح.".
  • إذا لم تكن مصفوفة $errors فارغة، أرسل رمز الحالة 422 مع كائن {"ok": false, "errors": $errors}.
  • تمر الواجهة الأمامية على مفاتيح data.errors، وتضبط الخاصية aria-invalid="true" لكل حقل خاطئ وتعرض رسالته تحته مباشرة.

يتيح إرجاع جميع أخطاء الحقول دفعة واحدة في استجابة 422 للمستخدم تصحيح كافة المدخلات دون فقدان ما كتبه في النموذج.

PHP
<?php
$_POST = ['email' => 'not-an-email', 'comment' => 'Hi'];
$errors = [];

if (!filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL)) {
    $errors['email'] = 'Please enter a valid email address.';
}
if (mb_strlen(trim((string) ($_POST['comment'] ?? ''))) < 10) {
    $errors['comment'] = 'Comment must be at least 10 characters.';
}

http_response_code(422);
echo json_encode(['ok' => false, 'errors' => $errors]) . "\n";

تشارك طلبات AJAX المرسلة بطرق POST وPUT وDELETE كوكيز جلسة المستخدم، ولذلك تتطلب التحقق من توكن CSRF تماماً كالنماذج التقليدية.

  • في نماذج FormData، يُرسل الحقل المخفي <input type="hidden" name="csrf_token"> تلقائياً ويُقرأ من $_POST["csrf_token"].
  • في طلبات JSON، اقرأ التوكن من وسم <meta name="csrf-token" content="..."> وأرسله في رأس الطلب X-CSRF-Token.
  • يحوّل PHP اسم الرأس X-CSRF-Token تلقائياً ليصبح متاحاً داخل المصفوفة $_SERVER["HTTP_X_CSRF_TOKEN"].

يتيح استخدام سلسلة دمج الفارغ $_POST["csrf_token"] ?? $_SERVER["HTTP_X_CSRF_TOKEN"] ?? "" دعم كل من نماذج FormData وطلبات JSON المرسلة برأس مخصص.

PHP
<?php
$_SESSION['csrf_token']       = '7f4e9a2c1b8d6035';
$_SERVER['HTTP_X_CSRF_TOKEN'] = '7f4e9a2c1b8d6035';

$candidate = (string) ($_POST['csrf_token'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '');
$sessToken = $_SESSION['csrf_token'] ?? '';

$valid = ($sessToken !== '') && hash_equals($sessToken, $candidate);
echo json_encode(['ok' => $valid, 'csrf_verified' => $valid]) . "\n";

من أشهر التطبيقات العملية لتكامل PHP و AJAX بناء نظام استطلاع رأي تفاعلي يصوت فيه المستخدم فتظهر له نسب التصويت المحدثة فوراً دون مغادرة الصفحة.

  • تحقق من أن معرف الخيار المرسل option_id عدد صحيح وموجود ضمن خيارات الاستطلاع المتاحة.
  • زِد عداد الأصوات في قاعدة البيانات باستعلام محضر ذري UPDATE poll_options SET votes = votes + 1 WHERE id = :id.
  • احسب النسبة المئوية لكل خيار عبر round(($votes / max(1, $total)) * 100, 1) وأرجع النتائج المحدثة بصيغة JSON.

يحمي استخدام max(1, $total) من خطأ القسمة على صفر، وتضمن array_values() إخراج مصفوفة JSON مرقمة بانتظام.

مخطط تدفق التنفيذ العملي لقسم بناء نظام استطلاع رأي وتصويت فوري بـ AJAX في لغة PHP
PHP
<?php
$options = [
    1 => ['label' => 'PHP 8.4', 'votes' => 78],
    2 => ['label' => 'TypeScript', 'votes' => 30],
];
$votedId = 1;
$options[$votedId]['votes']++;

$total = array_sum(array_column($options, 'votes'));
foreach ($options as &$opt) {
    $opt['percent'] = round(($opt['votes'] / max(1, $total)) * 100, 1);
}
echo json_encode(['ok' => true, 'total' => $total, 'options' => array_values($options)]) . "\n";

غالباً ما ينقر المستخدمون مرتين على زر الإرسال عند بطء الشبكة؛ لذا اجمع بين تعطيل الزر مؤقتاً في الواجهة وضوابط منع التكرار على الخادم.

  • عطّل زر الإرسال (submitBtn.disabled = true) فور بدء حدث submit، وأعد تفعيله داخل كتلة finally بعد اكتمال الطلب.
  • في PHP، حرر قفل ملف الجلسة مبكراً عبر session_write_close() إذا كان السكريبت ينفذ عمليات قراءة طويلة بعد التحقق من $_SESSION.
  • على مستوى قاعدة البيانات، اعتمد على التحديث الذري SET votes = votes + 1 وقيود UNIQUE بدلاً من القراءة ثم الجمع في PHP.

يؤدي حساب بصمة الإرسال ومقارنتها بآخر عملية مسجلة في الجلسة إلى منع النقرات المزدوجة الخاطئة وإرجاع الرمز 409 Conflict.

PHP
<?php
$_SESSION = ['last_submit_hash' => ''];
$payloadHash = hash('sha256', 'user_42:comment:Hello world');

if ($_SESSION['last_submit_hash'] === $payloadHash) {
    http_response_code(409);
    echo json_encode(['ok' => false, 'error' => 'Duplicate submission']) . "\n";
} else {
    $_SESSION['last_submit_hash'] = $payloadHash;
    echo json_encode(['ok' => true, 'hash' => substr($payloadHash, 0, 12)]) . "\n";
}

اختر بين النماذج التقليدية بنمط PRG ونماذج AJAX التفاعلية بناءً على طبيعة تجربة المستخدم في كل شاشة.

  • استخدم نماذج PRG التقليدية عندما يؤدي إرسال النموذج للانتقال إلى صفحة جديدة كلياً (مثل تسجيل الدخول أو الخروج).
  • استخدم نماذج AJAX عندما يبقى المستخدم في نفس الشاشة (مثل التصويت الفوري، أو التعليقات، أو النوافذ المنبثقة، أو حفظ الإعدادات).
  • يتطلب كلا الأسلوبين نفس ضوابط التحقق على الخادم واستعلامات PDO المحضرة وفحص توكن CSRF دون أي استثناء!

يتيح فحص الرأس HTTP_ACCEPT لنفس ملف PHP إرجاع استجابة JSON لطلبات AJAX أو التحويل بنمط PRG للنماذج العادية.

وجه المقارنةالنموذج التقليدي POST + PRGنموذج AJAX عبر FormData + fetch()
Page ReloadFull browser navigation (303 Redirect)Zero reload (in-place DOM update)
Validation ErrorsStored in session flash + redirect backReturned immediately as HTTP 422 JSON
CSRF Token CarrierHidden <input name="csrf_token">Hidden input in FormData or X-CSRF-Token header
Success FeedbackSession flash banner on next pageLive toast / progress bar update
Server Security RulesFull validation + PDO + CSRFFull validation + PDO + CSRF
PHP
<?php
function wantsJson(array $server): bool {
    $accept = $server['HTTP_ACCEPT'] ?? '';
    $xhr    = $server['HTTP_X_REQUESTED_WITH'] ?? '';
    return str_contains($accept, 'application/json')
        || strtolower($xhr) === 'xmlhttprequest';
}

$simServer = ['HTTP_ACCEPT' => 'application/json, text/plain'];
echo "Client expects JSON? " . (wantsJson($simServer) ? "Yes" : "No") . "\n";
خلاصة المعرفة ومحطة الانتقال

ملخص الدرس

حصاد الدرس

مراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي

ماذا تعلّمت في هذا الدرس؟

اختر بين النماذج التقليدية بنمط PRG ونماذج AJAX التفاعلية بناءً على طبيعة تجربة المستخدم في كل شاشة. استخدم نماذج PRG التقليدية عندما يؤدي إرسال النموذج للانتقال إلى صفحة جديدة كلياً (مثل تسجيل الدخول أو الخروج). استخدم نماذج AJAX عندما يبقى المستخدم في نفس الشاشة (مثل التصويت الفوري، أو التعليقات، أو النوافذ المنبثقة، أو حفظ الإعدادات). يتطلب كلا الأسلوبين نفس ضوابط التحقق على الخادم واستعلامات PDO المحضرة وفحص توكن CSRF دون أي استثناء!

مشاركة

هل كان هذا الدرس مفيدًا؟

جارٍ تحميل الآراء…

ابنِ لغتك البرمجية

المصطلحات4

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 4 مفهومةأول بطاقة، أول خطوة
01 AJAX Forms & Poll نماذج واستطلاعات AJAX
أرسل النماذج بدون تحديث الصفحة باستخدام FormData، وأرجع أخطاء التحقق لكل حقل من PHP، وابنِ نظام تصويت تفاعلي فوري.
للمراجعة
02 Submitting Forms with FormData and fetch إرسال النماذج غير المتزامن عبر الكائن FormData
المفهوم الأساسي لقسم إرسال النماذج غير المتزامن عبر الكائن FormData في لغة PHP الحديثة.
للمراجعة
03 Returning Field Validation Errors as JSON إرجاع أخطاء التحقق لكل حقل بصيغة JSON (422)
الصياغة البرمجية والتطبيق العملي المباشر لقسم إرجاع أخطاء التحقق لكل حقل بصيغة JSON (422).
للمراجعة
04 Verifying CSRF Tokens in AJAX Requests التحقق من توكن CSRF في طلبات AJAX
قواعد التحقق وأفضل الممارسات القياسية الخاصة بقسم التحقق من توكن CSRF في طلبات AJAX.
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

حروف قليلة. معنى كامل.

الاختصارات4

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 4 مفهومةأول بطاقة، أول خطوة
01 PHP PHP
PHP: Hypertext Preprocessor
لغة البرمجة النصية على جانب الخادم لبناء تطبيقات الويب الديناميكية وواجهات البرمجة.
للمراجعة
02 CLI CLI
Command-Line Interface
واجهة سطر الأوامر التي تتيح تشغيل ملفات PHP مباشرة عبر الطرفية.
للمراجعة
03 FPM FPM
FastCGI Process Manager
مدير عمليات FastCGI عالي الأداء لمعالجة طلبات خادم الويب في PHP.
للمراجعة
04 HTML HTML
HyperText Markup Language
لغة الترميز القياسية التي يولدها محرك PHP ويرسلها إلى متصفح العميل بعد التنفيذ.
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

من الفهم للتطبيق

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

خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.

0/2مهام منجزة
  1. أنشئ ملف PHP محلياً ونفّذ المثال البرمجي المشروح في قسم إرسال النماذج غير المتزامن عبر الكائن FormData للتحقق من المخرجات.

  2. بدّل بين الحالات الثلاث في المحاكي التفاعلي ضمن قسم إرجاع أخطاء التحقق لكل حقل بصيغة JSON (422) وقارن مخرجات التنفيذ.

تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.

مساحة التحدي

اختبر فهمك.
ووصلها للإتقان.

كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.

8أسئلة 1أنواع تحديات 100%هدف الإتقان
تصحيح تلقائي. فرص بلا حدود.

أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.

الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.

لمحة عن التحدي8 أسئلة تنتظرك
01

ماذا يحدث في PHP عندما ترسل نموذج HTML بشكل غير متزامن باستخدام body: new FormData(formEl) في دالة fetch()؟

يرسل الكائن FormData البيانات بترميز multipart/form-data فيقرأها PHP مباشرة في $_POST و $_FILES.

02

لماذا يجب عدم ضبط رأس الطلب "Content-Type": "multipart/form-data" يدوياً عند تمرير كائن FormData إلى دالة fetch()؟

بدون معامل boundary الذي يولده المتصفح لا يستطيع PHP فصل الحقول فتصل $_POST فارغة.

03

كيف يتيح PHP قراءة رأس الطلب المخصص المرسل من دالة fetch() باسم "X-CSRF-Token"؟

يحول PHP اسم الرأس إلى أحرف كبيرة ويستبدل الشرطات بشرطات سفلية ويضيف البادئة HTTP_.

04

ما النمط القياسي لإرجاع أخطاء التحقق الخاصة بالحقول من معالج نماذج AJAX في PHP؟

فهرسة الأخطاء باسم الحقل تتيح لـ JavaScript تمييز كل حقل وعرض رسالته الخاصة بدقة.

05

كيف يجب أن يزيد ملف التصويت في PHP عداد الأصوات في قاعدة البيانات لتجنب تعارض الطلبات المتزامنة في نفس اللحظة؟

الجمع الذري داخل محرك قاعدة البيانات يمنع ضياع الأصوات المتزامنة.

06

كيف تمنع خطأ القسمة على صفر (DivisionByZeroError) في PHP عند حساب النسب المئوية لخيارات الاستطلاع؟

القسمة على صفر في PHP 8 تطلق DivisionByZeroError؛ واستخدام max(1, $total) يضمن مقسوماً عليه آمناً.

07

ماذا يجب أن يفعل كود JavaScript فور بدء إرسال نموذج AJAX، وماذا يفعل في كتلة finally؟

تعطيل الزر أثناء الطلب يمنع إرسال النموذج مرتين عن طريق الخطأ.

08

هل يسمح استخدام نماذج AJAX بتخطي التحقق من المدخلات أو فحص توكن CSRF على خادم PHP؟

يمكن دائماً تجاوز الواجهة الأمامية بطلبات مباشرة، لذا يجب أن يفرض خادم PHP كافة الفحوصات الأمنية.