التعرُّف على 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 وواجهة مستخدم Firebase للسماح للمستخدمين بتسجيل الدخول إلى تطبيقك بسهولة.
  • Cloud Firestore لحفظ البيانات المنظَّمة على السحابة الإلكترونية وتلقّي إشعارات فورية عند تغيير البيانات.
  • قواعد أمان Firebase لتأمين قاعدة البيانات.

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

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

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

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

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

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

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

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

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

إعداد Cloud Firestore

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

إليك كيفية إعداد Cloud Firestore:

  1. في اللوحة الجانبية اليمنى من "وحدة تحكُّم Firebase"، انقر على إنشاء >. قاعدة بيانات Firestore. بعد ذلك، انقر على إنشاء قاعدة بيانات.
  2. انقر على إنشاء قاعدة بيانات.

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

  3. حدِّد الخيار البدء في وضع الاختبار. اقرأ بيان إخلاء المسؤولية بشأن قواعد الأمان. يضمن وضع الاختبار إمكانية الكتابة بحرية في قاعدة البيانات أثناء التطوير. انقر على Next (التالي).

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

  4. حدد موقع قاعدة البيانات الخاصة بك (يمكنك استخدام الإعداد الافتراضي فقط). لكن، لا يمكن تغيير هذا الموقع الجغرافي في وقت لاحق.

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

  5. انقر على تم.

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.appspot.com",
      messagingSenderId: "random-unique-string",
      appId: "random-unique-string",
    };
    
    // Initialize Firebase
    initializeApp(firebaseConfig);
    

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

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

مصادقة المستخدمين باستخدام ميزة "تسجيل الدخول باستخدام البريد الإلكتروني" و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.
      }
    }
    

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

نظرًا لأنك استخدمت معرف المستخدم الفريد (UID) للمصادقة كحقل في كل مستند دفتر زوار، يمكنك الحصول على المعرف الفريد للمصادقة والتحقق من أن أي شخص يحاول الكتابة إلى المستند لديه معرف 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.

    يعرض مستمع Firestore onSnapshot وظيفة إلغاء الاشتراك يمكنك استخدامها لإلغاء قارئ اللقطات لاحقًا.
    // ...
    // 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 واحتسِب عدد الردود بـ Yes:

  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
  • واجهة مستخدم Firebase
  • Cloud Firestore
  • قواعد أمان Firebase

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

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

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

كيف تم الأمر؟

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