التعرُّف على Firebase للويب

1. نظرة عامة

في هذا الدرس العملي، ستتعرّف على بعض أساسيات Firebase لإنشاء تطبيقات ويب تفاعلية. ستنشئ تطبيقًا للدردشة في سجلّ الزوّار ولتأكيد حضور الأحداث باستخدام العديد من منتجات Firebase.

لقطة شاشة لهذه الخطوة

ما ستتعلمه

  • مصادقة المستخدمين باستخدام "مصادقة Firebase" وFirebaseUI
  • مزامنة البيانات باستخدام Cloud Firestore
  • اكتب "قواعد أمان Firebase" لتأمين قاعدة بيانات.

المتطلبات

  • متصفّح من اختيارك، مثل Chrome
  • الوصول إلى stackblitz.com (لا يلزم إنشاء حساب أو تسجيل الدخول)
  • حساب Google، مثل حساب Gmail ننصحك باستخدام حساب البريد الإلكتروني الذي تستخدمه حاليًا لحسابك على GitHub. يتيح لك ذلك استخدام ميزات متقدّمة في StackBlitz.
  • الرمز النموذجي الخاص بالتجربة العملية راجِع الخطوة التالية لمعرفة كيفية الحصول على الرمز.

2. الحصول على الرمز الأولي

في هذا الدرس التطبيقي حول الترميز، ستنشئ تطبيقًا باستخدام StackBlitz، وهو محرّر على الإنترنت يتضمّن العديد من مهام سير عمل Firebase. لا يتطلّب Stackblitz تثبيت أي برامج أو إنشاء حساب خاص على Stackblitz.

يتيح لك StackBlitz مشاركة المشاريع مع الآخرين. يمكن للمستخدمين الآخرين الذين لديهم عنوان URL الخاص بمشروعك على StackBlitz الاطّلاع على الرمز البرمجي وإنشاء نسخة من مشروعك، ولكن لا يمكنهم تعديل مشروعك على StackBlitz.

  1. انتقِل إلى عنوان URL هذا للحصول على الرمز الأولي: https://stackblitz.com/edit/firebase-gtk-web-start
  2. في أعلى صفحة StackBlitz، انقر على Fork:

لقطة شاشة لهذه الخطوة

أصبحت لديك الآن نسخة من رمز البداية كمشروع StackBlitz خاص بك، وله اسم فريد، بالإضافة إلى عنوان URL فريد. يتم حفظ جميع ملفاتك وتغييراتك في مشروع StackBlitz هذا.

3- تعديل معلومات الحدث

توفّر المواد الأولية لهذا الدرس التطبيقي حول الترميز بعض البنية لتطبيق الويب، بما في ذلك بعض أوراق الأنماط وحاويتان بتنسيق HTML للتطبيق. وفي وقت لاحق من هذا الدرس التطبيقي حول الترميز، ستربط هاتين الحاويتين بمنصة Firebase.

للبدء، دعنا نتعرّف أكثر على واجهة StackBlitz.

  1. في StackBlitz، افتح الملف index.html.
  2. ابحث عن event-details-container وdescription-container، ثم جرِّب تعديل بعض تفاصيل الحدث.

أثناء تعديل النص، ستعرض عملية إعادة تحميل الصفحة التلقائية في StackBlitz تفاصيل الحدث الجديدة. رائع، أليس كذلك؟

<!-- ... -->

<div id="app">
  <img src="..." />

  <section id="event-details-container">
     <h1>Firebase Meetup</h1>

     <p><i class="material-icons">calendar_today</i> October 30</p>
     <p><i class="material-icons">location_city</i> San Francisco</p>

  </section>

  <hr>

  <section id="firebaseui-auth-container"></section>

  <section id="description-container">
     <h2>What we'll be doing</h2>
     <p>Join us for a day full of Firebase Workshops and Pizza!</p>
  </section>
</div>

<!-- ... -->

يجب أن تبدو معاينة تطبيقك على النحو التالي:

معاينة التطبيق

لقطة شاشة لهذه الخطوة

4. إنشاء مشروع Firebase وإعداده

يُعدّ عرض معلومات الحدث أمرًا رائعًا للضيوف، ولكن مجرد عرض الأحداث ليس مفيدًا لأي شخص. لنضِف بعض الوظائف الديناميكية إلى هذا التطبيق. ولإجراء ذلك، عليك ربط Firebase بتطبيقك. للبدء في استخدام Firebase، عليك إنشاء مشروع على Firebase وإعداده.

إنشاء مشروع على Firebase

  1. سجِّل الدخول إلى وحدة تحكّم Firebase باستخدام حسابك على Google.
  2. انقر على الزر لإنشاء مشروع جديد، ثم أدخِل اسم المشروع (على سبيل المثال، Firebase-Web-Codelab).
  3. انقر على متابعة.
  4. إذا طُلب منك ذلك، راجِع بنود Firebase واقبلها، ثم انقر على متابعة.
  5. (اختياري) فعِّل ميزة "المساعدة المستندة إلى الذكاء الاصطناعي" في وحدة تحكّم Firebase (المعروفة باسم "Gemini في Firebase").
  6. في هذا الدرس العملي، لا تحتاج إلى "إحصاءات Google"، لذا أوقِف خيار "إحصاءات Google".
  7. انقر على إنشاء مشروع، وانتظِر إلى أن يتم توفير مشروعك، ثم انقر على متابعة.

لمزيد من المعلومات عن مشاريع Firebase، اطّلِع على مقالة التعرّف على مشاريع Firebase.

تفعيل منتجات Firebase وإعدادها في وحدة التحكّم

يستخدم التطبيق الذي تنشئه العديد من منتجات Firebase المتاحة لتطبيقات الويب:

  • مصادقة Firebase وواجهة مستخدم Firebase للسماح للمستخدمين بتسجيل الدخول إلى تطبيقك بسهولة
  • ‫Cloud Firestore لحفظ البيانات المنظَّمة على السحابة الإلكترونية وتلقّي إشعار فوري عند تغيُّر البيانات
  • قواعد الأمان في Firebase لتأمين قاعدة البيانات

تتطلّب بعض هذه المنتجات إعدادًا خاصًا أو يجب تفعيلها باستخدام وحدة تحكّم Firebase.

تفعيل تسجيل الدخول باستخدام البريد الإلكتروني في "مصادقة Firebase"

للسماح للمستخدمين بتسجيل الدخول إلى تطبيق الويب، ستستخدم طريقة تسجيل الدخول البريد الإلكتروني/كلمة المرور في هذا الدرس العملي:

  1. في اللوحة الجانبية اليمنى من وحدة تحكّم Firebase، انقر على إنشاء > المصادقة. بعد ذلك، انقر على البدء. أنت الآن في لوحة بيانات "المصادقة"، حيث يمكنك الاطّلاع على المستخدمين الذين اشتركوا، وإعداد موفّري خدمة تسجيل الدخول، وإدارة الإعدادات.

    لقطة شاشة لهذه الخطوة

  2. انقر على علامة التبويب طريقة تسجيل الدخول (أو انقر هنا للانتقال مباشرةً إلى علامة التبويب).

    لقطة شاشة لهذه الخطوة

  3. انقر على البريد الإلكتروني/كلمة المرور من خيارات موفّر الخدمة، ثم فعِّل الخيار تفعيل، وانقر على حفظ.

    لقطة شاشة لهذه الخطوة

إعداد Cloud Firestore

يستخدم تطبيق الويب Cloud Firestore لحفظ رسائل المحادثات وتلقّي رسائل المحادثات الجديدة.

في ما يلي كيفية إعداد Cloud Firestore في مشروعك على Firebase:

  1. في اللوحة اليمنى من "وحدة تحكّم Firebase"، وسِّع إنشاء، ثم اختَر قاعدة بيانات Firestore.
  2. انقر على إنشاء قاعدة بيانات.
  3. اترك معرّف قاعدة البيانات مضبوطًا على (default).
  4. اختَر موقعًا لقاعدة البيانات، ثم انقر على التالي.
    بالنسبة إلى تطبيق حقيقي، عليك اختيار موقع جغرافي قريب من المستخدمين.
  5. انقر على البدء في وضع الاختبار. اقرأ بيان إخلاء المسؤولية عن قواعد الأمان.
    في وقت لاحق من هذا الدرس العملي، ستضيف قواعد الأمان لتأمين بياناتك. لا توزِّع تطبيقًا أو تعرضه بشكل علني بدون إضافة "قواعد الأمان" لقاعدة البيانات.
  6. انقر على إنشاء.

5- إضافة Firebase وضبطها

بعد إنشاء مشروعك على Firebase وتفعيل بعض الخدمات، عليك إخبار الرمز البرمجي بأنّك تريد استخدام Firebase، بالإضافة إلى تحديد مشروع Firebase الذي تريد استخدامه.

إضافة مكتبات Firebase

لكي يتمكّن تطبيقك من استخدام Firebase، عليك إضافة مكتبات Firebase إلى التطبيق. وهناك طرق متعدّدة لإجراء ذلك، كما هو موضّح في مستندات Firebase. على سبيل المثال، يمكنك إضافة المكتبات من شبكة توصيل المحتوى (CDN) من Google، أو يمكنك تثبيتها محليًا باستخدام npm ثم تجميعها في تطبيقك إذا كنت تستخدم Browserify.

توفّر منصة StackBlitz تجميعًا تلقائيًا، لذا يمكنك إضافة مكتبات Firebase باستخدام عبارات الاستيراد. ستستخدم الإصدارات النموذجية (الإصدار 9) من المكتبات، ما يساعد في تقليل الحجم الإجمالي لصفحة الويب من خلال عملية تُعرف باسم "استبعاد الرموز غير المستخدَمة". يمكنك الاطّلاع على مزيد من المعلومات حول حِزم تطوير البرامج (SDK) النموذجية في المستندات.

لإنشاء هذا التطبيق، يمكنك استخدام مكتبات Firebase Authentication وFirebaseUI وCloud Firestore. في هذا الدرس البرمجي، تمّ تضمين عبارات الاستيراد التالية في أعلى ملف index.js، وسنستورد المزيد من الطرق من كل مكتبة من مكتبات Firebase أثناء تقدّمنا:

// Import stylesheets
import './style.css';

// Firebase App (the core Firebase SDK) is always required
import { initializeApp } from 'firebase/app';

// Add the Firebase products and methods that you want to use
import {} from 'firebase/auth';
import {} from 'firebase/firestore';

import * as firebaseui from 'firebaseui';

إضافة تطبيق ويب على Firebase إلى مشروعك على Firebase

  1. ارجع إلى "وحدة تحكّم Firebase"، وانتقِل إلى صفحة النظرة العامة على مشروعك من خلال النقر على نظرة عامة على المشروع في أعلى يمين الصفحة.
  2. في وسط صفحة النظرة العامة على مشروعك، انقر على رمز الويب رمز تطبيق الويبلإنشاء تطبيق ويب جديد على Firebase.

    لقطة شاشة لهذه الخطوة

  3. سجِّل التطبيق بالاسم المستعار تطبيق الويب.
  4. في هذا الدرس العملي، لا تضع علامة في المربّع بجانب إعداد ميزة "استضافة Firebase" لهذا التطبيق أيضًا. ستستخدم جزء المعاينة في StackBlitz في الوقت الحالي.
  5. انقر على تسجيل التطبيق.

    لقطة شاشة لهذه الخطوة

  6. انسخ عنصر إعدادات Firebase إلى الحافظة.

    لقطة شاشة لهذه الخطوة

  7. انقر على متابعة إلى وحدة التحكّم.أضِف عنصر إعداد Firebase إلى تطبيقك:
  8. في StackBlitz، انتقِل إلى الملف index.js.
  9. ابحث عن سطر التعليق Add Firebase project configuration object here، ثم الصِق مقتطف الإعداد أسفل التعليق مباشرةً.
  10. أضِف استدعاء الدالة initializeApp لإعداد Firebase باستخدام إعدادات مشروع Firebase الفريدة.
    // ...
    // Add Firebase project configuration object here
    const firebaseConfig = {
      apiKey: "random-unique-string",
      authDomain: "your-projectId.firebaseapp.com",
      databaseURL: "https://your-projectId.firebaseio.com",
      projectId: "your-projectId",
      storageBucket: "your-projectId.firebasestorage.app",
      messagingSenderId: "random-unique-string",
      appId: "random-unique-string",
    };
    
    // Initialize Firebase
    initializeApp(firebaseConfig);
    

6. إضافة ميزة تسجيل دخول المستخدم (الرد على الدعوة)

بعد إضافة Firebase إلى التطبيق، يمكنك إعداد زر تأكيد الحضور الذي يسجّل المستخدمين باستخدام Firebase Authentication.

مصادقة المستخدمين باستخدام ميزة "تسجيل الدخول باستخدام البريد الإلكتروني" وFirebaseUI

ستحتاج إلى زر ردّ على الدعوة يطلب من المستخدم تسجيل الدخول باستخدام عنوان بريده الإلكتروني. يمكنك إجراء ذلك من خلال ربط FirebaseUI بزر تأكيد الحضور.‏FirebaseUI هي مكتبة تتيح لك واجهة مستخدم مُعدّة مسبقًا تستند إلى Firebase Auth.

يتطلّب FirebaseUI إعدادًا (راجِع الخيارات في المستندات) يؤدي وظيفتَين:

  • يُعلم FirebaseUI أنّك تريد استخدام طريقة تسجيل الدخول البريد الإلكتروني/كلمة المرور.
  • تعالج هذه الدالة رد الاتصال لعملية تسجيل دخول ناجحة وتعرض القيمة false لتجنُّب إعادة التوجيه. لا تريد إعادة تحميل الصفحة لأنّك بصدد إنشاء تطبيق ويب من صفحة واحدة.

إضافة الرمز لتهيئة FirebaseUI Auth

  1. في StackBlitz، انتقِل إلى الملف index.js.
  2. في أعلى الصفحة، ابحث عن عبارة الاستيراد firebase/auth، ثم أضِف getAuth وEmailAuthProvider، كما يلي:
    // ...
    // Add the Firebase products and methods that you want to use
    import { getAuth, EmailAuthProvider } from 'firebase/auth';
    
    import {} from 'firebase/firestore';
    
  3. احفظ مرجعًا إلى عنصر المصادقة مباشرةً بعد initializeApp، كما يلي:
    initializeApp(firebaseConfig);
    auth = getAuth();
    
  4. لاحظ أنّه تم توفير إعدادات FirebaseUI في الرمز الأوّلي. تم إعدادها مسبقًا لاستخدام موفّر مصادقة البريد الإلكتروني.
  5. في أسفل الدالة main() في index.js، أضِف عبارة إعداد FirebaseUI على النحو التالي:
    async function main() {
      // ...
    
      // Initialize the FirebaseUI widget using Firebase
      const ui = new firebaseui.auth.AuthUI(auth);
    }
    main();
    
    

إضافة زر الرد على الدعوة إلى رمز HTML

  1. في StackBlitz، انتقِل إلى الملف index.html.
  2. أضِف رمز HTML لزر الرد على الدعوة داخل event-details-container كما هو موضّح في المثال أدناه.

    احرص على استخدام قيم id نفسها الموضّحة أدناه، لأنّه في هذا الدرس العملي، تتوفّر خطافات لهذه المعرّفات المحدّدة في ملف index.js.

    يُرجى العِلم أنّه في الملف index.html، هناك حاوية تحمل رقم التعريف firebaseui-auth-container. هذا هو المعرّف الذي ستمرّره إلى FirebaseUI للاحتفاظ بتفاصيل تسجيل الدخول.
    <!-- ... -->
    
    <section id="event-details-container">
        <!-- ... -->
        <!-- ADD THE RSVP BUTTON HERE -->
        <button id="startRsvp">RSVP</button>
    </section>
    <hr>
    <section id="firebaseui-auth-container"></section>
    <!-- ... -->
    
    معاينة التطبيق

    لقطة شاشة لهذه الخطوة

  3. اضبط أداة معالجة على زر الردّ على الدعوة واستدعِ دالة بدء FirebaseUI. يُعلم هذا الرمز FirebaseUI بأنّك تريد عرض نافذة تسجيل الدخول.

    أضِف الرمز التالي إلى أسفل الدالة main() في index.js:
    async function main() {
      // ...
    
      // Listen to RSVP button clicks
      startRsvpButton.addEventListener("click",
       () => {
            ui.start("#firebaseui-auth-container", uiConfig);
      });
    }
    main();
    

اختبار تسجيل الدخول إلى التطبيق

  1. في نافذة المعاينة في StackBlitz، انقر على زر RSVP لتسجيل الدخول إلى التطبيق.
    • في هذا الدرس العملي، يمكنك استخدام أي عنوان بريد إلكتروني، حتى عنوان بريد إلكتروني مزيف، لأنّك لن تُعدّ خطوة لإثبات ملكية عنوان البريد الإلكتروني في هذا الدرس العملي.
    • إذا ظهرت لك رسالة خطأ تفيد auth/operation-not-allowed أو The given sign-in provider is disabled for this Firebase project، تأكَّد من أنّك فعّلت البريد الإلكتروني/كلمة المرور كمقدّم خدمة تسجيل الدخول في وحدة تحكّم Firebase.
    معاينة التطبيق

    لقطة شاشة لهذه الخطوة

  2. انتقِل إلى لوحة بيانات المصادقة في وحدة تحكّم Firebase. في علامة التبويب المستخدمون، من المفترض أن تظهر معلومات الحساب التي أدخلتها لتسجيل الدخول إلى التطبيق.

    لقطة شاشة لهذه الخطوة

إضافة حالة المصادقة إلى واجهة المستخدم

بعد ذلك، تأكَّد من أنّ واجهة المستخدم تشير إلى أنّك سجّلت الدخول.

ستستخدم دالة معاودة الاتصال الخاصة بمستمع حالة Firebase Authentication، والتي يتم إعلامها كلما تغيّرت حالة تسجيل الدخول للمستخدم. إذا كان هناك مستخدم مسجّل الدخول حاليًا، سيغيّر تطبيقك الزر "تأكيد الحضور" إلى زر "تسجيل الخروج".

  1. في StackBlitz، انتقِل إلى الملف index.js.
  2. في أعلى الصفحة، ابحث عن عبارة الاستيراد firebase/auth، ثم أضِف signOut وonAuthStateChanged، كما يلي:
    // ...
    // Add the Firebase products and methods that you want to use
    import {
      getAuth,
      EmailAuthProvider,
      signOut,
      onAuthStateChanged
    } from 'firebase/auth';
    
    import {} from 'firebase/firestore';
    
  3. أضِف الرمز التالي في أسفل الدالة main():
    async function main() {
      // ...
    
      // Listen to the current Auth state
      onAuthStateChanged(auth, user => {
        if (user) {
          startRsvpButton.textContent = 'LOGOUT';
        } else {
          startRsvpButton.textContent = 'RSVP';
        }
      });
    }
    main();
    
  4. في أداة معالجة أحداث الزر، تحقَّق ممّا إذا كان هناك مستخدم حالي وسجِّل خروجه. لإجراء ذلك، استبدِل startRsvpButton.addEventListener الحالي بما يلي:
    // ...
    // Called when the user clicks the RSVP button
    startRsvpButton.addEventListener('click', () => {
      if (auth.currentUser) {
        // User is signed in; allows user to sign out
        signOut(auth);
      } else {
        // No user is signed in; allows user to sign in
        ui.start('#firebaseui-auth-container', uiConfig);
      }
    });
    

من المفترض أن يعرض الزر في تطبيقك الآن تسجيل الخروج، وأن يعود إلى تأكيد الحضور عند النقر عليه.

معاينة التطبيق

لقطة شاشة لهذه الخطوة

7. كتابة الرسائل إلى Cloud Firestore

من الرائع معرفة أنّ هناك مستخدمين سيأتون إلى تطبيقك، ولكن لنقدّم للضيوف شيئًا آخر يمكنهم فعله في التطبيق، مثل ترك رسائل في دفتر الضيوف. يمكنهم مشاركة سبب حماسهم للمشاركة أو الأشخاص الذين يأملون مقابلتهم.

لتخزين رسائل المحادثة التي يكتبها المستخدمون في التطبيق، عليك استخدام Cloud Firestore.

نموذج البيانات

‫Cloud Firestore هي قاعدة بيانات NoSQL، ويتم تقسيم البيانات المخزّنة في قاعدة البيانات إلى مجموعات ومستندات وحقول ومجموعات فرعية. سيتم تخزين كل رسالة من المحادثة كمستند في مجموعة ذات مستوى أعلى تُسمى guestbook.

رسم بياني لنموذج بيانات Firestore يعرض مجموعة دفتر الضيوف التي تحتوي على مستندات رسائل متعددة

إضافة رسائل إلى Firestore

في هذا القسم، ستضيف وظيفة تتيح للمستخدمين كتابة رسائل جديدة في قاعدة البيانات. أولاً، عليك إضافة رمز HTML لعناصر واجهة المستخدم (حقل الرسالة وزر الإرسال). بعد ذلك، أضِف الرمز الذي يربط هذه العناصر بقاعدة البيانات.

لإضافة عناصر واجهة المستخدم الخاصة بحقل الرسالة وزر الإرسال، اتّبِع الخطوات التالية:

  1. في StackBlitz، انتقِل إلى الملف index.html.
  2. ابحث عن guestbook-container، ثم أضِف رمز HTML التالي لإنشاء نموذج يتضمّن حقل إدخال الرسالة وزر الإرسال.
    <!-- ... -->
    
     <section id="guestbook-container">
       <h2>Discussion</h2>
    
       <form id="leave-message">
         <label>Leave a message: </label>
         <input type="text" id="message">
         <button type="submit">
           <i class="material-icons">send</i>
           <span>SEND</span>
         </button>
       </form>
    
     </section>
    
    <!-- ... -->
    

معاينة التطبيق

لقطة شاشة لهذه الخطوة

سيؤدي النقر على الزر إرسال إلى تشغيل مقتطف الرمز البرمجي أدناه. يضيف هذا الرمز محتوى حقل إدخال الرسالة إلى مجموعة guestbook في قاعدة البيانات. على وجه التحديد، تضيف طريقة addDoc محتوى الرسالة إلى مستند جديد (مع معرّف تم إنشاؤه تلقائيًا) إلى المجموعة guestbook.

  1. في StackBlitz، انتقِل إلى الملف index.js.
  2. في أعلى الصفحة، ابحث عن عبارة الاستيراد firebase/firestore، ثم أضِف getFirestore وaddDoc وcollection، كما يلي:
    // ...
    
    // Add the Firebase products and methods that you want to use
    import {
      getAuth,
      EmailAuthProvider,
      signOut,
      onAuthStateChanged
    } from 'firebase/auth';
    
    import {
      getFirestore,
      addDoc,
      collection
    } from 'firebase/firestore';
    
  3. سنحفظ الآن مرجعًا إلى عنصر Firestore db مباشرةً بعد initializeApp:
    initializeApp(firebaseConfig);
    auth = getAuth();
    db = getFirestore();
    
  4. في أسفل الدالة main()، أضِف الرمز التالي.

    يُرجى العِلم أنّ auth.currentUser.uid هو إشارة إلى المعرّف الفريد الذي يتم إنشاؤه تلقائيًا والذي توفّره خدمة "المصادقة في Firebase" لجميع المستخدمين الذين سجّلوا الدخول.
    async function main() {
      // ...
    
      // Listen to the form submission
      form.addEventListener('submit', async e => {
        // Prevent the default form redirect
        e.preventDefault();
        // Write a new message to the database collection "guestbook"
        addDoc(collection(db, 'guestbook'), {
          text: input.value,
          timestamp: Date.now(),
          name: auth.currentUser.displayName,
          userId: auth.currentUser.uid
        });
        // clear message input field
        input.value = '';
        // Return false to avoid redirect
        return false;
      });
    }
    main();
    

عرض دفتر الضيوف للمستخدمين الذين سجّلوا الدخول فقط

لا تريد أن يرى أي شخص محادثة الضيوف. يمكنك اتّخاذ إجراء واحد لتأمين المحادثة، وهو السماح للمستخدمين الذين سجّلوا الدخول فقط بعرض دفتر الضيوف. مع ذلك، بالنسبة إلى تطبيقاتك، عليك أيضًا تأمين قاعدة البيانات باستخدام قواعد الأمان في Firebase. (ستجد المزيد من المعلومات عن قواعد الأمان في وقت لاحق من هذا الدرس العملي).

  1. في StackBlitz، انتقِل إلى الملف index.js.
  2. عدِّل أداة معالجة الأحداث onAuthStateChanged لإخفاء دفتر الضيوف وإظهاره.
    // ...
    
    // Listen to the current Auth state
    onAuthStateChanged(auth, user => {
      if (user) {
        startRsvpButton.textContent = 'LOGOUT';
        // Show guestbook to logged-in users
        guestbookContainer.style.display = 'block';
      } else {
        startRsvpButton.textContent = 'RSVP';
        // Hide guestbook for non-logged-in users
        guestbookContainer.style.display = 'none';
      }
    });
    

اختبار إرسال الرسائل

  1. تأكَّد من تسجيل الدخول إلى التطبيق.
  2. أدخِل رسالة مثل "مرحبًا"، ثم انقر على إرسال.

يؤدي هذا الإجراء إلى كتابة الرسالة في قاعدة بيانات Cloud Firestore. ومع ذلك، لن تظهر لك الرسالة بعد في تطبيق الويب الفعلي لأنّه لا يزال عليك تنفيذ عملية استرداد البيانات. ستنفّذ هذه الخطوة في الصفحة التالية.

ولكن يمكنك الاطّلاع على الرسالة المُضافة حديثًا في وحدة تحكّم Firebase.

في وحدة تحكّم Firebase، ضِمن لوحة بيانات Firestore، من المفترض أن ترى المجموعة guestbook التي تتضمّن الرسالة التي أضفتها مؤخرًا. إذا واصلت إرسال الرسائل، ستتضمّن مجموعة سجلّ الزوّار العديد من المستندات، مثل ما يلي:

وحدة تحكُّم Firebase

لقطة شاشة لهذه الخطوة

8. قراءة الرسائل

مزامنة الرسائل

يسرّنا أن يتمكّن الضيوف من كتابة رسائل في قاعدة البيانات، ولكن لا يمكنهم الاطّلاع عليها في التطبيق بعد.

لعرض الرسائل، عليك إضافة أدوات معالجة يتم تشغيلها عند تغيير البيانات، ثم إنشاء عنصر واجهة مستخدم يعرض الرسائل الجديدة.

ستضيف رمزًا برمجيًا يتلقّى الرسائل المضافة حديثًا من التطبيق. أولاً، أضِف قسمًا في HTML لعرض الرسائل:

  1. في StackBlitz، انتقِل إلى الملف index.html.
  2. في guestbook-container، أضِف قسمًا جديدًا بالمعرّف guestbook.
    <!-- ... -->
    
      <section id="guestbook-container">
       <h2>Discussion</h2>
    
       <form><!-- ... --></form>
    
       <section id="guestbook"></section>
    
     </section>
    
    <!-- ... -->
    

بعد ذلك، سجِّل أداة معالجة الأحداث التي تستمع إلى التغييرات التي تم إجراؤها على البيانات:

  1. في StackBlitz، انتقِل إلى الملف index.js.
  2. في أعلى الصفحة، ابحث عن عبارة الاستيراد firebase/firestore، ثم أضِف query وorderBy وonSnapshot، كما يلي:
    // ...
    import {
      getFirestore,
      addDoc,
      collection,
      query,
      orderBy,
      onSnapshot
    } from 'firebase/firestore';
    
  3. في أسفل الدالة main()، أضِف الرمز التالي لتكرار جميع المستندات (رسائل دفتر الضيوف) في قاعدة البيانات. لمزيد من المعلومات حول ما يحدث في هذا الرمز، اطّلِع على المعلومات الواردة أسفل المقتطف.
    async function main() {
      // ...
    
      // Create query for messages
      const q = query(collection(db, 'guestbook'), orderBy('timestamp', 'desc'));
      onSnapshot(q, snaps => {
        // Reset page
        guestbook.innerHTML = '';
        // Loop through documents in database
        snaps.forEach(doc => {
          // Create an HTML entry for each document and add it to the chat
          const entry = document.createElement('p');
          entry.textContent = doc.data().name + ': ' + doc.data().text;
          guestbook.appendChild(entry);
        });
      });
    }
    main();
    

للاستماع إلى الرسائل في قاعدة البيانات، أنشأت طلب بحث في مجموعة معيّنة باستخدام الدالة collection. يستمع الرمز البرمجي أعلاه إلى التغييرات في المجموعة guestbook، حيث يتم تخزين رسائل المحادثة. يتم أيضًا ترتيب الرسائل حسب التاريخ، باستخدام orderBy('timestamp', 'desc') لعرض أحدث الرسائل في أعلى الصفحة.

تتلقّى الدالة onSnapshot مَعلمتَين: طلب البحث الذي سيتم استخدامه ودالة ردّ الاتصال. يتم تشغيل دالة ردّ الاتصال عند حدوث أي تغييرات في المستندات التي تتطابق مع طلب البحث. قد يحدث ذلك إذا تم حذف رسالة أو تعديلها أو إضافتها. لمزيد من المعلومات، راجِع مستندات Cloud Firestore.

اختبار مزامنة الرسائل

تتم مزامنة البيانات تلقائيًا وفوريًا مع العملاء المشتركين في قاعدة البيانات على Cloud Firestore.

  • يجب أن تظهر الرسائل التي أنشأتها سابقًا في قاعدة البيانات في التطبيق. يمكنك كتابة رسائل جديدة، ومن المفترض أن تظهر على الفور.
  • إذا فتحت مساحة عملك في نوافذ أو علامات تبويب متعددة، ستتم مزامنة الرسائل في الوقت الفعلي على جميع علامات التبويب.
  • (اختياري) يمكنك محاولة حذف الرسائل أو تعديلها أو إضافة رسائل جديدة يدويًا مباشرةً في قسم قاعدة البيانات في وحدة تحكّم Firebase، ومن المفترض أن تظهر أي تغييرات في واجهة المستخدم.

تهانينا! أنت تقرأ مستندات Cloud Firestore في تطبيقك.

معاينة التطبيق

لقطة شاشة لهذه الخطوة

9. إعداد قواعد الأمان الأساسية

لقد أعددت Cloud Firestore في البداية لاستخدام وضع الاختبار، ما يعني أنّ قاعدة البيانات مفتوحة للقراءة والكتابة. ومع ذلك، يجب استخدام وضع الاختبار خلال المراحل المبكرة جدًا من عملية التطوير فقط. وفقًا لأفضل الممارسات، عليك إعداد قواعد الأمان لقاعدة البيانات أثناء تطوير تطبيقك، لأنّ الأمان يجب أن يكون جزءًا لا يتجزأ من بنية تطبيقك وسلوكه.

تتيح لك "قواعد الأمان" التحكّم في الوصول إلى المستندات والمجموعات في قاعدة البيانات. يتيح لك بناء الجملة المرن للقواعد إنشاء قواعد تتطابق مع أي شيء، بدءًا من جميع عمليات الكتابة إلى قاعدة البيانات بأكملها وصولاً إلى العمليات على مستند معيّن.

يمكنك كتابة قواعد الأمان في Cloud Firestore من خلال وحدة تحكّم Firebase باتّباع الخطوات التالية:

  1. في قسم الإنشاء في وحدة تحكّم Firebase، انقر على قاعدة بيانات Firestore، ثم اختَر علامة التبويب القواعد (أو انقر هنا للانتقال مباشرةً إلى علامة التبويب القواعد).
  2. من المفترض أن تظهر لك قواعد الأمان التلقائية التالية، مع حدّ زمني للوصول العام يبلغ أسبوعَين من تاريخ اليوم.

لقطة شاشة لهذه الخطوة

تحديد المجموعات

أولاً، حدِّد المجموعات التي يكتب التطبيق البيانات فيها.

  1. احذف عبارة match /{document=**} الحالية، لكي تبدو قواعدك على النحو التالي:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
      }
    }
    
  2. في match /databases/{database}/documents، حدِّد المجموعة التي تريد تأمينها:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /guestbook/{entry} {
         // You'll add rules here in the next step.
      }
    }
    

إضافة قواعد الأمان

بما أنّك استخدمت المعرّف الفريد للمصادقة كحقل في كل مستند من مستندات دفتر الضيوف، يمكنك الحصول على المعرّف الفريد للمصادقة والتحقّق من أنّ أي شخص يحاول الكتابة في المستند لديه معرّف فريد مطابق للمصادقة.

  1. أضِف قواعد القراءة والكتابة إلى مجموعة القواعد كما هو موضّح أدناه:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /guestbook/{entry} {
          allow read: if request.auth.uid != null;
          allow create:
            if request.auth.uid == request.resource.data.userId;
        }
      }
    }
    
  2. انقر على نشر لتفعيل القواعد الجديدة.الآن، في دفتر الضيوف، يمكن للمستخدمين الذين سجّلوا الدخول فقط قراءة الرسائل (أي رسالة)، ولكن يمكنك إنشاء رسالة باستخدام معرّف المستخدم فقط. ولا نسمح أيضًا بتعديل الرسائل أو حذفها.

إضافة قواعد التحقّق

  1. أضِف ميزة التحقّق من صحة البيانات للتأكّد من توفّر جميع الحقول المتوقّعة في المستند:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /guestbook/{entry} {
          allow read: if request.auth.uid != null;
          allow create:
          if request.auth.uid == request.resource.data.userId
              && "name" in request.resource.data
              && "text" in request.resource.data
              && "timestamp" in request.resource.data;
        }
      }
    }
    
  2. انقر على نشر لنشر القواعد الجديدة.

إعادة ضبط المتتبّعين

بما أنّ تطبيقك لا يسمح الآن إلا للمستخدمين الذين تمّت المصادقة عليهم بتسجيل الدخول، عليك نقل طلب البحث firestore الخاص بدفتر الضيوف إلى داخل أداة معالجة المصادقة. وإلا، ستحدث أخطاء في الأذونات وسيتم قطع اتصال التطبيق عند تسجيل خروج المستخدم.

  1. في StackBlitz، انتقِل إلى الملف index.js.
  2. اسحب أداة معالجة مجموعة سجل الزوار onSnapshot إلى دالة جديدة باسم subscribeGuestbook. عيِّن أيضًا نتائج الدالة onSnapshot إلى المتغير guestbookListener.

    onSnapshot المستمع يُرجع في Firestore دالة إلغاء اشتراك يمكنك استخدامها لإلغاء مستمع اللقطة لاحقًا.
    // ...
    // Listen to guestbook updates
    function subscribeGuestbook() {
      const q = query(collection(db, 'guestbook'), orderBy('timestamp', 'desc'));
      guestbookListener = onSnapshot(q, snaps => {
        // Reset page
        guestbook.innerHTML = '';
        // Loop through documents in database
        snaps.forEach(doc => {
          // Create an HTML entry for each document and add it to the chat
          const entry = document.createElement('p');
          entry.textContent = doc.data().name + ': ' + doc.data().text;
          guestbook.appendChild(entry);
        });
      });
    }
    
  3. أضِف دالة جديدة أدناه باسم unsubscribeGuestbook. تحقَّق ممّا إذا كان المتغيّر guestbookListener ليس فارغًا، ثم استدعِ الدالة لإلغاء أداة معالجة الأحداث.
    // ...
    // Unsubscribe from guestbook updates
    function unsubscribeGuestbook() {
      if (guestbookListener != null) {
        guestbookListener();
        guestbookListener = null;
      }
    }
    

وأخيرًا، أضِف الدوال الجديدة إلى عملية الاسترجاع onAuthStateChanged.

  1. أضِف subscribeGuestbook() في أسفل if (user).
  2. أضِف unsubscribeGuestbook() في أسفل عبارة else.
    // ...
    // Listen to the current Auth state
    onAuthStateChanged(auth, user => {
      if (user) {
        startRsvpButton.textContent = 'LOGOUT';
        // Show guestbook to logged-in users
        guestbookContainer.style.display = 'block';
        // Subscribe to the guestbook collection
        subscribeGuestbook();
      } else {
        startRsvpButton.textContent = 'RSVP';
        // Hide guestbook for non-logged-in users
        guestbookContainer.style.display = 'none';
        // Unsubscribe from the guestbook collection
        unsubscribeGuestbook();
      }
    });
    

10. خطوة إضافية: ممارسة ما تعلّمته

تسجيل حالة ردّ الضيف على الدعوة

في الوقت الحالي، يتيح تطبيقك للمستخدمين بدء محادثة إذا كانوا مهتمين بالحدث. بالإضافة إلى ذلك، الطريقة الوحيدة لمعرفة ما إذا كان أحد المستخدمين سيشارك في المحادثة هي إذا نشر ذلك في المحادثة. لننظّم الأمور ونُعلم الآخرين بعدد الأشخاص الذين سيحضرون.

ستضيف زر تبديل لتسجيل الأشخاص الذين يريدون حضور الحدث، ثم ستجمع عدد الأشخاص الذين سيحضرون.

  1. في StackBlitz، انتقِل إلى الملف index.html.
  2. في guestbook-container، أضِف مجموعة من أزرار نعم ولا، على النحو التالي:
    <!-- ... -->
      <section id="guestbook-container">
       <h2>Are you attending?</h2>
         <button id="rsvp-yes">YES</button>
         <button id="rsvp-no">NO</button>
    
       <h2>Discussion</h2>
    
       <!-- ... -->
    
     </section>
    <!-- ... -->
    

معاينة التطبيق

لقطة شاشة لهذه الخطوة

بعد ذلك، سجِّل أداة معالجة نقرات الأزرار. إذا نقر المستخدم على نعم، استخدِم معرّف UID للمصادقة لحفظ الردّ في قاعدة البيانات.

  1. في StackBlitz، انتقِل إلى الملف index.js.
  2. في أعلى الصفحة، ابحث عن عبارة الاستيراد firebase/firestore، ثم أضِف doc وsetDoc وwhere، كما يلي:
    // ...
    // Add the Firebase products and methods that you want to use
    import {
      getFirestore,
      addDoc,
      collection,
      query,
      orderBy,
      onSnapshot,
      doc,
      setDoc,
      where
    } from 'firebase/firestore';
    
  3. في أسفل الدالة main()، أضِف الرمز التالي للاستماع إلى حالة الردّ على الدعوة:
    async function main() {
      // ...
    
      // Listen to RSVP responses
      rsvpYes.onclick = async () => {
      };
      rsvpNo.onclick = async () => {
      };
    }
    main();
    
    
  4. بعد ذلك، أنشئ مجموعة جديدة باسم attendees، ثم سجِّل مرجع مستند إذا تم النقر على أي من زرَّي الرد على الدعوة. اضبط قيمة المرجع على true أو false استنادًا إلى الزر الذي تم النقر عليه.

    أولاً، بالنسبة إلى rsvpYes:
    // ...
    // Listen to RSVP responses
    rsvpYes.onclick = async () => {
      // Get a reference to the user's document in the attendees collection
      const userRef = doc(db, 'attendees', auth.currentUser.uid);
    
      // If they RSVP'd yes, save a document with attendi()ng: true
      try {
        await setDoc(userRef, {
          attending: true
        });
      } catch (e) {
        console.error(e);
      }
    };
    
    ثم، يتم تكرار العملية نفسها مع rsvpNo، ولكن بالقيمة false:
    rsvpNo.onclick = async () => {
      // Get a reference to the user's document in the attendees collection
      const userRef = doc(db, 'attendees', auth.currentUser.uid);
    
      // If they RSVP'd yes, save a document with attending: true
      try {
        await setDoc(userRef, {
          attending: false
        });
      } catch (e) {
        console.error(e);
      }
    };
    

تعديل قواعد الأمان

بما أنّك أعددت بعض القواعد سابقًا، سيتم رفض البيانات الجديدة التي تضيفها باستخدام الأزرار.

السماح بإضافة محتوى إلى مجموعة attendees

عليك تعديل القواعد للسماح بإضافة المحتوى إلى مجموعة attendees.

  1. بالنسبة إلى attendees المجموعة، بما أنّك استخدمت المعرّف الفريد للمصادقة كاسم للمستند، يمكنك الحصول عليه والتأكّد من أنّ uid الخاص بالمرسِل هو نفسه المستند الذي يكتبه. ستسمح للجميع بقراءة قائمة الضيوف (لأنّها لا تتضمّن أي بيانات خاصة)، ولكن يجب أن يكون بإمكان المنشئ فقط تعديلها.
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        // ... //
        match /attendees/{userId} {
          allow read: if true;
          allow write: if request.auth.uid == userId;
        }
      }
    }
    
  2. انقر على نشر لنشر القواعد الجديدة.

إضافة قواعد التحقّق

  1. أضِف بعض قواعد التحقّق من صحة البيانات للتأكّد من أنّ جميع الحقول المتوقّعة متوفّرة في المستند:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        // ... //
        match /attendees/{userId} {
          allow read: if true;
          allow write: if request.auth.uid == userId
              && "attending" in request.resource.data;
    
        }
      }
    }
    
  2. لا تنسَ النقر على نشر لتفعيل قواعدك.

(اختياري) يمكنك الآن الاطّلاع على نتائج النقر على الأزرار. انتقِل إلى لوحة بيانات Cloud Firestore في وحدة تحكّم Firebase.

قراءة حالة الردّ على الدعوة

بعد تسجيل الردود، لنطّلِع على الضيوف الذين سيحضرون ونعرض ذلك في واجهة المستخدم.

  1. في StackBlitz، انتقِل إلى الملف index.html.
  2. في description-container، أضِف عنصرًا جديدًا بالمعرّف number-attending.
    <!-- ... -->
    
     <section id="description-container">
         <!-- ... -->
         <p id="number-attending"></p>
     </section>
    
    <!-- ... -->
    

بعد ذلك، سجِّل أداة معالجة الأحداث لمجموعة attendees واحتسِب عدد الردود نعم:

  1. في StackBlitz، انتقِل إلى الملف index.js.
  2. في أسفل الدالة main()، أضِف الرمز التالي للاستماع إلى حالة الرد على الدعوة واحتساب عدد النقرات على نعم.
    async function main() {
      // ...
    
      // Listen for attendee list
      const attendingQuery = query(
        collection(db, 'attendees'),
        where('attending', '==', true)
      );
      const unsubscribe = onSnapshot(attendingQuery, snap => {
        const newAttendeeCount = snap.docs.length;
        numberAttending.innerHTML = newAttendeeCount + ' people going';
      });
    }
    main();
    

أخيرًا، لنبرز الزر الذي يتوافق مع الحالة الحالية.

  1. أنشئ دالة تتحقّق ممّا إذا كان معرّف UID الحالي للمصادقة يتضمّن إدخالاً في المجموعة attendees، ثم اضبط فئة الزر على clicked.
    // ...
    // Listen for attendee list
    function subscribeCurrentRSVP(user) {
      const ref = doc(db, 'attendees', user.uid);
      rsvpListener = onSnapshot(ref, doc => {
        if (doc && doc.data()) {
          const attendingResponse = doc.data().attending;
    
          // Update css classes for buttons
          if (attendingResponse) {
            rsvpYes.className = 'clicked';
            rsvpNo.className = '';
          } else {
            rsvpYes.className = '';
            rsvpNo.className = 'clicked';
          }
        }
      });
    }
    
  2. لننشئ أيضًا دالة لإلغاء الاشتراك. سيتم استخدام هذا المعرّف عندما يسجّل المستخدم الخروج.
    // ...
    function unsubscribeCurrentRSVP() {
      if (rsvpListener != null) {
        rsvpListener();
        rsvpListener = null;
      }
      rsvpYes.className = '';
      rsvpNo.className = '';
    }
    
  3. استدعِ الدوال من أداة معالجة المصادقة.
    // ...
    // Listen to the current Auth state
      // Listen to the current Auth state
      onAuthStateChanged(auth, user => {
        if (user) {
          startRsvpButton.textContent = 'LOGOUT';
          // Show guestbook to logged-in users
          guestbookContainer.style.display = 'block';
    
          // Subscribe to the guestbook collection
          subscribeGuestbook();
          // Subscribe to the user's RSVP
          subscribeCurrentRSVP(user);
        } else {
          startRsvpButton.textContent = 'RSVP';
          // Hide guestbook for non-logged-in users
          guestbookContainer.style.display = 'none'
          ;
          // Unsubscribe from the guestbook collection
          unsubscribeGuestbook();
          // Unsubscribe from the guestbook collection
          unsubscribeCurrentRSVP();
        }
      });
    
  4. جرِّب تسجيل الدخول بصفتك عدة مستخدمين ولاحظ زيادة العدد مع كل نقرة إضافية على الزر نعم.

معاينة التطبيق

لقطة شاشة لهذه الخطوة

11. تهانينا!

لقد استخدمت Firebase لإنشاء تطبيق ويب تفاعلي في الوقت الفعلي.

المواضيع التي تناولناها

  • مصادقة Firebase
  • FirebaseUI
  • Cloud Firestore
  • قواعد الأمان في Firebase

الخطوات التالية

مزيد من المعلومات

كيف كانت النتيجة؟

يسرّنا تلقّي ملاحظاتك. يُرجى ملء نموذج (مختصر جدًا) هنا.