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

بناء البحث الفوري المباشر AJAX Live Search المتصل بـ PDO في PHPPHP AJAX Live Database Search with PDO

ابنِ محرك بحث فوري الإكمال التلقائي باستخدام PHP 8 واستعلامات PDO المحضرة بـ LIKE واستجابات JSON وتأخير الإدخال Debounce.
أقسام الدرس
6
الأمثلة
6
اللغة
العربية
تاريخ النشر
غير محدد
المشاهدات
0
محتوى الدرس
في هذا الدرس 6تصفّح المواضيع

بدون تقنية التأخير الذكي (Debounce)، فإن كتابة كلمة من 10 أحرف تطلق 10 طلبات HTTP منفصلة إلى خادم PHP خلال ثانية واحدة، مما يرهق قاعدة البيانات ويسبب تداخل النتائج.

  • تعتمد تقنية Debounce على إعادة ضبط مؤقت زمني (عادةً من 250 إلى 300 مللي ثانية) مع كل ضغطة زر، فلا يُرسل الطلب إلا بعد توقف المستخدم عن الكتابة.
  • اربط تقنية Debounce بكائن AbortController في JavaScript لإلغاء أي طلب سابق لم يكتمل بعد عند بدء بحث جديد.
  • حتى مع وجود Debounce في الواجهة، احرص دائماً على إبقاء استعلام PHP سريعاً ومقيداً بسقف LIMIT.

يقلص استخدام Debounce عدد الطلبات من 14 ضغطة مفتاح متتالية إلى طلبين فقط لخادم PHP، مما يوفر 86% من الحمل على قاعدة البيانات.

PHP
<?php
// Comparing server load with and without 280ms input debouncing
$typedWord = "authentication";
$rawKeystrokes = strlen($typedWord);
$debouncedRequests = 2; // User paused once mid-word and once at the end

$savedPercent = round((1 - ($debouncedRequests / $rawKeystrokes)) * 100);
echo "Raw requests       : $rawKeystrokes\n";
echo "Debounced requests : $debouncedRequests ($savedPercent% load reduction)\n";

داخل ملف البحث في PHP، ادمج علامتي النسبة المئوية % داخل قيمة المتغير في PHP ثم اربطه كمعامل محضر في PDO، ولا تدمج $_GET["q"] داخل نص SQL أبداً!

  • اكتب المعامل المحضر في SQL بالصورة WHERE title LIKE :term، وليس داخل علامات تنصيص '%:term%'.
  • هرّب الرمزين % و_ داخل كلمة البحث عبر addcslashes($q, "%_\\") لمنع المستخدم من إدخال أنماط بحث شاملة تبطئ الخادم.
  • اجلب الأعمدة اللازمة فقط للقائمة المنسدلة (مثل id, title, slug) بدلاً من جلب كامل الصفوف بـ SELECT *.

يحضر المثال استعلام LIKE :q عبر PDO، ويربط القيمة "%Password%" بأمان، ثم يعيد الصف المطابق بصيغة JSON.

PHP
<?php
$pdo = new PDO('sqlite::memory:');
$pdo->exec("CREATE TABLE lessons (id INT, title TEXT, slug TEXT)");
$pdo->exec("INSERT INTO lessons VALUES (85, 'PHP Password Hashing', 'php-password-hashing')");
$pdo->exec("INSERT INTO lessons VALUES (86, 'PHP CSRF Protection', 'php-csrf-protection')");

$rawQ = "Password";
$escaped = addcslashes($rawQ, '%_\\');
$stmt = $pdo->prepare("SELECT id, title, slug FROM lessons WHERE title LIKE :q LIMIT 8");
$stmt->execute([':q' => '%' . $escaped . '%']);
echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC)) . "\n";

لا ينبغي لقائمة الإكمال التلقائي أن تُرجع آلاف السجلات؛ لذا قيّد استعلام البحث الفوري دائماً بـ LIMIT 8 أو LIMIT 10 ونسّق عناصر المصفوفة.

  • قيّد الحد الأقصى لطول نص البحث (مثلاً mb_substr($q, 0, 60)) قبل تمريره للاستعلام.
  • حوّل صفوف قاعدة البيانات إلى مصفوفة نظيفة تضم المفاتيح المطلوبة فقط للعرض مثل id وtitle وurl.
  • أرفق مفتاح العدد count ومصفوفة النتائج results في كائن JSON النهائي.

تحول دالة array_map() صفوف قاعدة البيانات الخام إلى كائنات جاهزة للاستخدام المباشر في الواجهة مع بناء مسار الرابط url.

مخطط تدفق التنفيذ العملي لقسم تحديد سقف النتائج وتنسيق مخرجات JSON في لغة PHP
PHP
<?php
$rows = [
    ['id' => 89, 'title' => 'PHP AJAX Intro', 'slug' => 'php-ajax-introduction'],
    ['id' => 91, 'title' => 'AJAX Live Search', 'slug' => 'php-ajax-live-search'],
];

$formatted = array_map(fn(array $r): array => [
    'id'    => (int) $r['id'],
    'title' => $r['title'],
    'url'   => '/tutorials/php/' . $r['slug'],
], $rows);

echo json_encode(['ok' => true, 'count' => count($formatted), 'results' => $formatted]) . "\n";

عند عرض نتائج البحث الفوري في المتصفح، أنشئ عناصر القائمة عبر document.createElement() وأسند العناوين عبر خاصية textContent الآمنة.

  • لا تقم أبداً ببناء عناصر القائمة المنسدلة بدمج النصوص مباشرة داخل resultsBox.innerHTML += "...".
  • استخدم document.createElement("a")، واضبط الرابط a.href = item.url، والعنوان a.textContent = item.title.
  • اعرض رسالة واضحة للمستخدم عند عدم وجود نتائج متطابقة (عندما يكون data.results.length === 0).

يضمن تنظيف المعرف النصي على الخادم أن يكون item.url مساراً نسبياً آمناً دائماً، بينما تتكفل textContent في المتصفح بعرض العنوان بأمان.

PHP
<?php
// Server-side validation of generated result URLs before JSON output
function buildSafeSearchResult(int $id, string $title, string $slug): array {
    $cleanSlug = preg_replace('/[^a-z0-9-]/', '', strtolower($slug));
    return [
        'id'    => $id,
        'title' => $title,
        'url'   => '/tutorials/php/' . $cleanSlug,
    ];
}

$item = buildSafeSearchResult(91, 'Live Search <PDO>', 'php-ajax-live-search');
echo json_encode($item) . "\n";

اجمع بين ضوابط الواجهة الأمامية والخادم التالية لضمان بقاء نظام البحث الفوري سريعاً وآمناً تماماً ضد الهجمات.

  • طبّق تأخير الكتابة Debounce (من 250 إلى 300 مللي ثانية) وألغِ الطلبات السابقة عبر AbortController.
  • افرض حداً أدنى لطول النص (حرفان فأكثر) وحداً أقصى (60 محرفاً) داخل كود PHP.
  • استخدم استعلامات PDO المحضرة مع تهريب رموز LIKE وتقييد النتائج بـ LIMIT 8.

تزيل دالة normalizeSearchTerm() المسافات الزائدة، وتفحص حدود الطول بترميز UTF-8، وتهرّب الشرطة السفلية، وتحيط النص بعلامتي %.

معيار الأداء / الأمانمكان التطبيقالأهمية العملية
Input Debounce (280ms)Frontend JSCuts HTTP request volume by 80%+
AbortControllerFrontend JSPrevents stale responses overwriting newer ones
mb_strlen($q) >= 2Both JS & PHPBlocks expensive 1-letter table scans
PDO Prepared LIKE :qBackend PHPEliminates SQL Injection completely
LIMIT 8 + Specific ColumnsBackend SQLCaps memory & network payload size
textContent RenderingFrontend DOMEliminates DOM-based XSS in dropdown
PHP
<?php
function normalizeSearchTerm(string $raw): ?string {
    $trimmed = trim($raw);
    $len = mb_strlen($trimmed, 'UTF-8');
    if ($len < 2 || $len > 60) {
        return null;
    }
    return '%' . addcslashes($trimmed, '%_\\') . '%';
}
echo (normalizeSearchTerm("  pdo_8  ") ?? "SKIP") . "\n";
خلاصة المعرفة ومحطة الانتقال

ملخص الدرس

حصاد الدرس

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

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

اجمع بين ضوابط الواجهة الأمامية والخادم التالية لضمان بقاء نظام البحث الفوري سريعاً وآمناً تماماً ضد الهجمات. طبّق تأخير الكتابة Debounce (من 250 إلى 300 مللي ثانية) وألغِ الطلبات السابقة عبر AbortController. افرض حداً أدنى لطول النص (حرفان فأكثر) وحداً أقصى (60 محرفاً) داخل كود PHP. استخدم استعلامات PDO المحضرة مع تهريب رموز LIKE وتقييد النتائج بـ LIMIT 8.

مشاركة

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

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

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

المصطلحات4

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

0 / 4 مفهومةأول بطاقة، أول خطوة
01 AJAX Live Search البحث الفوري Live Search
ابنِ محرك بحث فوري الإكمال التلقائي باستخدام PHP 8 واستعلامات PDO المحضرة بـ LIKE واستجابات JSON وتأخير الإدخال Debounce.
للمراجعة
02 Architecture of AJAX Live Search معمارية نظام البحث الفوري المباشر Live Search
المفهوم الأساسي لقسم معمارية نظام البحث الفوري المباشر Live Search في لغة PHP الحديثة.
للمراجعة
03 Debouncing Keystrokes on the Frontend تقليل طلبات الخادم بتقنية Debounce عند الكتابة
الصياغة البرمجية والتطبيق العملي المباشر لقسم تقليل طلبات الخادم بتقنية Debounce عند الكتابة.
للمراجعة
04 Building the PDO LIKE Search Endpoint بناء نقطة نهاية البحث الآمنة بـ PDO و LIKE
قواعد التحقق وأفضل الممارسات القياسية الخاصة بقسم بناء نقطة نهاية البحث الآمنة بـ PDO و LIKE.
للمراجعة

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

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

الاختصارات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 محلياً ونفّذ المثال البرمجي المشروح في قسم معمارية نظام البحث الفوري المباشر Live Search للتحقق من المخرجات.

  2. بدّل بين الحالات الثلاث في المحاكي التفاعلي ضمن قسم تقليل طلبات الخادم بتقنية Debounce عند الكتابة وقارن مخرجات التنفيذ.

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

مساحة التحدي

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

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

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

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

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

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

لماذا تُعد تقنية تأخير الإدخال (Debouncing) ضرورية في الواجهة الأمامية لحقل البحث الفوري AJAX؟

تمنع إطلاق استعلام قاعدة بيانات منفصل مع كل ضغطة مفتاح.

02

كيف يجب ربط معامل البحث الجزئي LIKE المحتوي على علامة % في استعلام PDO محضر؟

توضع علامتا % داخل قيمة المتغير في PHP عند الربط، وليس حول اسم المعامل في نص SQL.

03

لماذا يجب أن يفحص ملف البحث الفوري في PHP الشرط if (mb_strlen($q, "UTF-8") < 2) قبل استعلام قاعدة البيانات؟

البحث بحرف واحد يطابق معظم السجلات ويستهلك موارد قاعدة البيانات دون فائدة.

04

ما فائدة استخدام addcslashes($q, "%_\\") قبل إحاطة كلمة بحث المستخدم بعلامتي "%"؟

في معامل LIKE، يطابق الرمز % أي نص ويطابق _ أي حرف مفرد ما لم يتم تهريبهما.

05

لماذا يجب أن يتضمن استعلام SQL الخاص بالإكمال التلقائي دائماً شرطاً مثل LIMIT 8؟

يحتاج المستخدم لرؤية أول 5 إلى 10 اقتراحات فقط، وإرجاع آلاف الصفوف يبطئ النظام.

06

ما المشكلة التي يحلها كائن AbortController في JavaScript داخل نظام البحث الفوري؟

إلغاء الطلبات المتجاوزة يمنع تعارض التوقيت بين استجابات الشبكة.

07

لماذا يجب استخدام mb_strlen($q, "UTF-8") بدلاً من strlen($q) عند فحص طول كلمة بحث باللغة العربية؟

الحرف العربي الواحد يشغل بايتين في UTF-8، فترجع strlen("م") الرقم 2 بينما ترجع mb_strlen الرقم 1 بدقة.

08

كيف يجب أن يعرض المتصفح كل عنصر مطابق عائد من نقطة نهاية البحث الفوري بصيغة JSON؟

استخدام createElement() مع textContent يمنع ثغرات XSS حتى لو احتوى العنوان على أقواس زاوية.