التعرُّف على 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.
  2. في "وحدة تحكّم Firebase"، انقر على إضافة مشروع (أو إنشاء مشروع)، ثمّ أدخِل اسمًا لمشروعك على Firebase وهو Firebase-Web-Codelab.

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

  3. انقر على خيارات إنشاء المشروع. اقبل بنود Firebase إذا طُلب منك ذلك. على شاشة Google Analytics، انقر على "عدم تمكين"؛ لأنك لن تستخدم Analytics لهذا التطبيق.

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

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

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

  • Firebase Authentication وواجهة مستخدم 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 و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 إلى التطبيق، يمكنك إعداد زرّ RSVP يُسجِّل المستخدمين باستخدام Firebase Authentication.

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

ستحتاج إلى زر "الردّ على الدعوة" يطلب من المستخدم تسجيل الدخول باستخدام عنوان بريده الإلكتروني. ويمكنك إجراء ذلك من خلال ربط FirebaseUI زر الرد على الدعوة.FirebaseUI هي مكتبة تمنحك واجهة مستخدم تم إنشاؤها مسبقًا فوق مصادقة Firebase.

تتطلّب FirebaseUI عملية ضبط (اطّلِع على الخيارات في المستندات) تؤدي إلى إجراء أمرَين:

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

أضِف الرمز لإعداد مصادقة FirebaseUI

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

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

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

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

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

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

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

  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 Database، من المفترض أن تظهر لك المجموعة 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.
      }
    }
    

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

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

  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>
    <!-- ... -->
    

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

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

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

  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()، أضِف الرمز التالي للاستماع إلى حالة RSVP واحتساب عدد النقرات على نعم.
    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. أنشِئ دالة تتحقّق مما إذا كان المعرِّف الفريد الحالي للمصادقة يتضمّن إدخالاً في مجموعة 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

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

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

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

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