1- نظرة عامة
في هذا الدرس التطبيقي، ستتعرَّف على بعض أساسيات Firebase لإنشاء تطبيقات ويب تفاعلية. ستُنشئ حدثًا للرد على الدعوة وتطبيق محادثة سجلّ الضيوف باستخدام العديد من منتجات Firebase.
المعلومات التي ستطّلع عليها
- يمكنك المصادقة على المستخدمين من خلال مصادقة Firebase وFirebaseUI.
- مزامنة البيانات باستخدام Cloud Firestore
- كتابة قواعد أمان Firebase لتأمين قاعدة بيانات
المتطلبات
- متصفّح من اختيارك، مثل Chrome
- الوصول إلى stackblitz.com (بدون الحاجة إلى حساب أو تسجيل الدخول)
- حساب Google، مثل حساب Gmail. ننصحك باستخدام حساب البريد الإلكتروني الذي تستخدمه حاليًا لحسابك على GitHub. يتيح لك هذا الإجراء استخدام ميزات متقدّمة في StackBlitz.
- تمثّل هذه السمة الرمز النموذجي الخاص بالدرس التطبيقي حول الترميز. اطّلِع على الخطوة التالية لمعرفة كيفية الحصول على الرمز.
2- الحصول على رمز البدء
في هذا الدرس التطبيقي، يمكنك إنشاء تطبيق باستخدام StackBlitz، وهو محرِّر على الإنترنت يحتوي على العديد من مهام سير العمل في Firebase. لا يتطلب Stackblitz تثبيت أي برامج أو استخدام حساب StackBlitz خاص.
يتيح لك StackBlitz مشاركة المشاريع مع الآخرين. يمكن للمستخدمين الآخرين الذين لديهم عنوان URL لمشروعك على StackBlitz الاطّلاع على الرمز البرمجي وإنشاء نسخة من مشروعك، ولكن لا يمكنهم تعديل مشروعك على StackBlitz.
- انتقِل إلى عنوان URL هذا للحصول على رمز البدء: https://stackblitz.com/edit/firebase-gtk-web-start
- في أعلى صفحة StackBlitz، انقر على Fork (نسخ):
أصبح لديك الآن نسخة من رمز البدء كمشروعك على StackBlitz، والذي يحمل اسمًا فريدًا إلى جانب عنوان URL فريد. يتم حفظ جميع ملفاتك وتغييراتك في مشروع StackBlitz هذا.
3- تعديل معلومات الحدث
توفّر مواد البدء لهذا الدرس التطبيقي حول الترميز بعض البنية لتطبيق الويب، بما في ذلك بعض أوراق الأنماط وحاويتَي HTML للتطبيق. وفي وقت لاحق من هذا الدرس التطبيقي، عليك ربط هذه الحاويات بمنصة Firebase.
للبدء، لنتعرّف أكثر على واجهة StackBlitz.
- في StackBlitz، افتح ملف
index.html
. - حدِّد موقع
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
- سجِّل الدخول إلى Firebase.
- في "وحدة تحكّم Firebase"، انقر على إضافة مشروع (أو إنشاء مشروع)، ثمّ أدخِل اسمًا لمشروعك على Firebase وهو Firebase-Web-Codelab.
- انقر على خيارات إنشاء المشروع. اقبل بنود Firebase إذا طُلب منك ذلك. على شاشة Google Analytics، انقر على "عدم تمكين"؛ لأنك لن تستخدم Analytics لهذا التطبيق.
لمزيد من المعلومات عن مشاريع Firebase، يُرجى الاطّلاع على مقالة فهم مشاريع Firebase.
تفعيل منتجات Firebase وإعدادها في وحدة التحكّم
يستخدم التطبيق الذي تنشئه العديد من منتجات Firebase المتاحة لتطبيقات الويب، وهي:
- Firebase Authentication وواجهة مستخدم Firebase للسماح للمستخدمين بتسجيل الدخول إلى تطبيقك بسهولة
- Cloud Firestore لحفظ البيانات المنظَّمة على السحابة الإلكترونية وتلقّي إشعارات فورية عند تغيير البيانات.
- قواعد أمان Firebase لتأمين قاعدة بياناتك
تحتاج بعض هذه المنتجات إلى إعدادات خاصة أو تفعيلها باستخدام وحدة تحكُّم Firebase.
تفعيل تسجيل الدخول باستخدام البريد الإلكتروني في ميزة "مصادقة Firebase"
للسماح للمستخدمين بتسجيل الدخول إلى تطبيق الويب، ستستخدم طريقة تسجيل الدخول باستخدام البريد الإلكتروني/كلمة المرور في هذا الدليل التعليمي للترميز:
- في اللوحة اليمنى من وحدة تحكّم Firebase، انقر على الإنشاء > المصادقة. بعد ذلك، انقر على البدء. أنت الآن في لوحة بيانات المصادقة، حيث يمكنك الاطّلاع على المستخدمين الذين اشتركوا، وضبط مقدمي خدمة تسجيل الدخول وإدارة الإعدادات.
- اختَر علامة التبويب طريقة تسجيل الدخول (أو انقر على هذا الرابط للانتقال مباشرةً إلى علامة التبويب).
- انقر على البريد الإلكتروني/كلمة المرور من خيارات موفّر الخدمة، وبدِّل المفتاح إلى تفعيل، ثم انقر على حفظ.
إعداد Cloud Firestore
يستخدم تطبيق الويب Cloud Firestore لحفظ رسائل المحادثة وتلقّي رسائل جديدة.
في ما يلي كيفية إعداد Cloud Firestore في مشروع Firebase:
- في اللوحة اليمنى من "وحدة تحكُّم Firebase"، وسِّع إنشاء، ثم اختَر قاعدة بيانات Firestore.
- انقر على إنشاء قاعدة بيانات.
- اترك معرّف قاعدة البيانات مضبوطًا على
(default)
. - اختَر موقعًا جغرافيًا لقاعدة بياناتك، ثم انقر على التالي.
إذا كان لديك تطبيق حقيقي، عليك اختيار موقع قريب من المستخدمين. - انقر على البدء في وضع الاختبار. يمكنك قراءة بيان إخلاء المسؤولية بشأن قواعد الأمان.
في وقت لاحق من هذا الدرس التطبيقي، عليك إضافة قواعد الأمان لتأمين بياناتك. لا توزِّع تطبيقًا علنًا أو تعرضه بدون إضافة قواعد أمان لقاعدة بياناتك. - انقر على إنشاء.
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
- في "وحدة تحكّم Firebase"، انتقِل إلى صفحة النظرة العامة على مشروعك بالنقر على نظرة عامة على المشروع في أعلى يمين الصفحة.
- في منتصف صفحة النظرة العامة على مشروعك، انقر على رمز الويب لإنشاء تطبيق ويب جديد على Firebase.
- سجِّل التطبيق باسمه المعرِّف تطبيق الويب.
- في هذا الدرس التطبيقي حول الترميز، لا تضع علامة في المربّع بجانب إعداد استضافة Firebase أيضًا لهذا التطبيق، بل سيتم استخدام جزء معاينة StackBlitz في الوقت الحالي.
- انقر على تسجيل التطبيق.
- انسخ كائن إعداد Firebase إلى الحافظة.
- انقر على متابعة إلى وحدة التحكّم.أضِف عنصر ضبط Firebase إلى تطبيقك:
- ارجع إلى StackBlitz، ثم انتقِل إلى ملف
index.js
. - حدِّد موقع سطر التعليق
Add Firebase project configuration object here
، ثم الصِق مقتطف الإعدادات أسفل التعليق مباشرةً. - أضِف طلب الدالة
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
- في StackBlitz، انتقِل إلى ملف
index.js
. - في أعلى الصفحة، حدِّد مكان عبارة الاستيراد
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';
- احفظ مرجعًا إلى عنصر المصادقة بعد
initializeApp
مباشرةً، كما يلي:initializeApp(firebaseConfig); auth = getAuth();
- يُرجى العلم أنّه سبق أن تم توفير إعدادات FirebaseUI في الرمز المبدئي. تم إعداده لاستخدام مقدّم خدمة مصادقة البريد الإلكتروني.
- في أسفل دالة
main()
فيindex.js
، أضِف بيان إعداد FirebaseUI على النحو التالي:async function main() { // ... // Initialize the FirebaseUI widget using Firebase const ui = new firebaseui.auth.AuthUI(auth); } main();
إضافة زر "الردّ على الدعوة" إلى ملف HTML
- في StackBlitz، انتقِل إلى ملف
index.html
. - أضف 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> <!-- ... -->
- ابدأ بإعداد مستمع على زر الرد على الدعوة واستدعِ وظيفة بدء FirebaseUI. يُعلم هذا الإجراء FirebaseUI بأنّك تريد عرض نافذة تسجيل الدخول.
أضِف الرمز التالي أسفل الدالةmain()
فيindex.js
:async function main() { // ... // Listen to RSVP button clicks startRsvpButton.addEventListener("click", () => { ui.start("#firebaseui-auth-container", uiConfig); }); } main();
اختبار تسجيل الدخول إلى التطبيق
- في نافذة معاينة StackBlitz، انقر على زر "الرد على الدعوة" لتسجيل الدخول إلى التطبيق.
- في هذا الدليل التعليمي حول رموز الترميز، يمكنك استخدام أي عنوان بريد إلكتروني، حتى عنوان بريد إلكتروني مزيّف، لأنّك لن تُعدّ خطوة إثبات ملكية عنوان البريد الإلكتروني في هذا الدليل التعليمي.
- إذا ظهرت لك رسالة خطأ تشير إلى
auth/operation-not-allowed
أوThe given sign-in provider is disabled for this Firebase project
، تأكَّد من تفعيل البريد الإلكتروني/كلمة المرور كمقدّم خدمة تسجيل الدخول في وحدة تحكّم Firebase.
- انتقِل إلى لوحة بيانات المصادقة في وحدة تحكُّم Firebase. في علامة التبويب المستخدمون، من المفترض أن تظهر لك معلومات الحساب التي أدخلتها لتسجيل الدخول إلى التطبيق.
إضافة حالة المصادقة إلى واجهة المستخدم
بعد ذلك، احرص على أن تعكس واجهة المستخدم أنّك سجّلت الدخول إلى حسابك.
ستستخدم دالة الاستدعاء الخاصة بمراقب حالة المصادقة في Firebase، والتي يتم إعلامها عند تغيير حالة تسجيل دخول المستخدم. إذا كان هناك مستخدم سجّل الدخول حاليًا، سيبدّل تطبيقك زر "تأكيد الحضور" إلى زر "تسجيل الخروج".
- في StackBlitz، انتقِل إلى ملف
index.js
. - في أعلى الصفحة، حدِّد مكان عبارة الاستيراد
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';
- أضِف الرمز التالي في أسفل دالة
main()
:async function main() { // ... // Listen to the current Auth state onAuthStateChanged(auth, user => { if (user) { startRsvpButton.textContent = 'LOGOUT'; } else { startRsvpButton.textContent = 'RSVP'; } }); } main();
- في أداة استماع الزر، تحقق مما إذا كان هناك مستخدم حالي وسجل الخروج. لإجراء ذلك، استبدِل
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
في هذا القسم، ستضيف وظيفة للمستخدمين لكتابة رسائل جديدة في قاعدة البيانات. أولاً، تضيف رمز HTML لعناصر واجهة المستخدم (حقل الرسالة وزر الإرسال). بعد ذلك، تضيف الرمز الذي يربط هذه العناصر بقاعدة البيانات.
لإضافة عناصر واجهة المستخدم لحقل الرسالة وزر الإرسال:
- في StackBlitz، انتقِل إلى ملف
index.html
. - حدِّد موضع
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
.
- في StackBlitz، انتقِل إلى ملف
index.js
. - في أعلى الصفحة، ابحث عن عبارة الاستيراد
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';
- سنحفظ الآن إشارة إلى كائن Firestore
db
بعدinitializeApp
مباشرةً:initializeApp(firebaseConfig); auth = getAuth(); db = getFirestore();
- في أسفل الدالة
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. (يتوفّر المزيد من المعلومات حول قواعد الأمان لاحقًا في الدرس التطبيقي حول الترميز).
- في StackBlitz، انتقِل إلى ملف
index.js
. - عدِّل مستمع
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'; } });
اختبار إرسال الرسائل
- تأكَّد من تسجيل الدخول إلى التطبيق.
- أدخِل رسالة، مثل "مرحبًا"، ثم انقر على إرسال.
يؤدي هذا الإجراء إلى كتابة الرسالة إلى قاعدة بيانات Cloud Firestore. لن تظهر لك الرسالة بعد في تطبيق الويب الفعلي لأنّك ما زلت بحاجة إلى تنفيذ عملية استرداد البيانات. ستفعل ذلك بعد ذلك.
ولكن يمكنك الاطّلاع على الرسالة التي تمت إضافتها حديثًا في وحدة تحكّم Firebase.
في وحدة تحكُّم Firebase، في لوحة بيانات Firestore Database، من المفترض أن تظهر لك المجموعة guestbook
مع رسالتك المضافة حديثًا. إذا واصلت إرسال الرسائل، ستتضمّن مجموعة دفتر الضيوف العديد من المستندات، مثل:
وحدة تحكُّم Firebase
8- قراءة الرسائل
مزامنة الرسائل
من الجيد أن يتمكن الضيوف من كتابة الرسائل إلى قاعدة البيانات، لكن لا يمكنهم رؤيتها في التطبيق بعد.
لعرض الرسائل، عليك إضافة أدوات استماع يتم تشغيلها عند تغيُّر البيانات، ثم إنشاء عنصر في واجهة المستخدم يعرض الرسائل الجديدة.
ستضيف رمزًا يستمع إلى الرسائل المُضافة حديثًا من التطبيق. أولاً، أضِف قسمًا في HTML لعرض الرسائل:
- في StackBlitz، انتقِل إلى ملف
index.html
. - في
guestbook-container
، أضِف قسمًا جديدًا برقم التعريفguestbook
.<!-- ... --> <section id="guestbook-container"> <h2>Discussion</h2> <form><!-- ... --></form> <section id="guestbook"></section> </section> <!-- ... -->
بعد ذلك، قم بتسجيل المستمع الذي يستمع إلى التغييرات التي يتم إجراؤها على البيانات:
- في StackBlitz، انتقِل إلى ملف
index.js
. - في أعلى الصفحة، حدِّد مكان عبارة الاستيراد
firebase/firestore
، ثم أضِفquery
وorderBy
وonSnapshot
، كما يلي:// ... import { getFirestore, addDoc, collection, query, orderBy, onSnapshot } from 'firebase/firestore';
- في أسفل دالة
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:
- في قسم الإنشاء في وحدة تحكّم Firebase، انقر على قاعدة بيانات Firestore، ثم اختَر علامة التبويب القواعد (أو انقر على هذا الرابط للانتقال مباشرةً إلى علامة التبويب القواعد).
- من المفترض أن تظهر لك قواعد الأمان التلقائية التالية، مع حدّ زمني للوصول العلني بعد أسبوعَين من اليوم.
تحديد المجموعات
أولاً، حدِّد المجموعات التي يكتب التطبيق البيانات فيها.
- احذف بند
match /{document=**}
الحالي لكي تظهر قواعدك على النحو التالي:rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { } }
- في
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 مطابق.
- أضِف قواعد القراءة والكتابة إلى مجموعة القواعد كما هو موضّح أدناه:
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; } } }
- انقر على نشر لنشر القواعد الجديدة.والآن، بالنسبة إلى دفتر الزوار، لا يمكن سوى للمستخدمين الذين سجّلوا الدخول قراءة الرسائل (أي رسالة)، ولكن لا يمكنك إنشاء رسالة إلا باستخدام رقم تعريف المستخدم. ولا نسمح أيضًا بتعديل الرسائل أو حذفها.
إضافة قواعد التحقّق
- أضِف عملية التحقّق من البيانات للتأكّد من توفّر جميع الحقول المتوقّعة في المستند:
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; } } }
- انقر على نشر لتفعيل القواعد الجديدة.
إعادة ضبط أدوات معالجة الأحداث
بما أنّ تطبيقك لا يسمح الآن إلا للمستخدمين الذين تمّت مصادقتهم بتسجيل الدخول، عليك نقل طلب البحث عن دفتر الضيوف firestore
داخل مستمع المصادقة. وإلّا، ستحدث أخطاء في الأذونات وسيتم إلغاء ربط التطبيق عندما يسجّل المستخدم خروجه.
- في StackBlitz، انتقِل إلى ملف
index.js
. - اسحب مستمع مجموعة دفتر الزوار
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); }); }); }
- أضِف دالة جديدة تحت الاسم
unsubscribeGuestbook
. تحقَّق ممّا إذا كان المتغيّرguestbookListener
غير فارغ، ثم استخدِم الدالة لإلغاء المستمع.// ... // Unsubscribe from guestbook updates function unsubscribeGuestbook() { if (guestbookListener != null) { guestbookListener(); guestbookListener = null; } }
أخيرًا، أضِف الدوالّ الجديدة إلى دالة الاستدعاء onAuthStateChanged
.
- أضِف
subscribeGuestbook()
في أسفلif (user)
. - يمكن إضافة السمة
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- خطوة إضافية: تطبيق ما تعلمته
تسجيل حالة الرد على دعوة الضيف
في الوقت الحالي، يسمح تطبيقك للمستخدمين ببدء المحادثة إذا كانوا مهتمين بالحدث. الطريقة الوحيدة لمعرفة حضور شخص ما هي أن ينشره في المحادثة. لننظم المعلومات ونتيح للأشخاص معرفة عدد الحاضرين.
ستضيف زرًا للتبديل لتسجيل الأشخاص الذين يريدون حضور الحدث، ثم تجمع عدد المشاركين.
- في StackBlitz، انتقِل إلى ملف
index.html
. - في "
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> <!-- ... -->
معاينة التطبيق
بعد ذلك، قم بتسجيل المستمع لنقرات الزر. إذا نقر المستخدم على نعم، استخدِم رقم تعريف المستخدم للمصادقة لحفظ الاستجابة في قاعدة البيانات.
- في StackBlitz، انتقِل إلى ملف
index.js
. - في أعلى الصفحة، ابحث عن عبارة الاستيراد
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';
- في أسفل الدالة
main()
، أضِف الرمز التالي للاستماع إلى حالة الرد على الدعوة:async function main() { // ... // Listen to RSVP responses rsvpYes.onclick = async () => { }; rsvpNo.onclick = async () => { }; } main();
- بعد ذلك، أنشئ مجموعة جديدة باسم
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
.
- بالنسبة إلى مجموعة
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; } } }
- انقر على نشر لنشر القواعد الجديدة.
إضافة قواعد التحقّق
- أضف بعض قواعد التحقق من صحة البيانات للتأكد من أن جميع الحقول المتوقعة موجودة في المستند:
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; } } }
- لا تنسَ النقر على نشر لنشر القواعد.
(اختياري) يمكنك الآن عرض نتائج النقر على الأزرار. انتقِل إلى لوحة بيانات Cloud Firestore في وحدة تحكُّم Firebase.
قراءة حالة الرد على الدعوة
بعد تسجيل الردود، لنلقِ نظرة على الحضور ونعرضه في واجهة المستخدم.
- في StackBlitz، انتقِل إلى ملف
index.html
. - في
description-container
، أضِف عنصرًا جديدًا برقم التعريفnumber-attending
.<!-- ... --> <section id="description-container"> <!-- ... --> <p id="number-attending"></p> </section> <!-- ... -->
بعد ذلك، سجِّل المستمع لمجموعة attendees
واحتسِب عدد الردود نعم:
- في StackBlitz، انتقِل إلى ملف
index.js
. - في أسفل دالة
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();
أخيرًا، لنبرز الزر المقابل للحالة الحالية.
- أنشِئ دالة تتحقّق مما إذا كان المعرِّف الفريد الحالي للمصادقة يتضمّن إدخالاً في مجموعة
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'; } } }); }
- أيضًا، لنُنشئ دالة لإلغاء الاشتراك. سيتم استخدام هذه الطريقة عندما يسجِّل المستخدم خروجه.
// ... function unsubscribeCurrentRSVP() { if (rsvpListener != null) { rsvpListener(); rsvpListener = null; } rsvpYes.className = ''; rsvpNo.className = ''; }
- استدعاء الدوالّ من مستمع المصادقة
// ... // 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(); } });
- حاوِل تسجيل الدخول بصفتك مستخدمين متعدّدين ولاحظ زيادة العدد مع كل نقرة إضافية على الزر نعم.
معاينة التطبيق
11- تهانينا!
لقد استخدمت Firebase لإنشاء تطبيق ويب تفاعلي في الوقت الفعلي.
المواضيع التي تناولناها
- مصادقة Firebase
- FirebaseUI
- Cloud Firestore
- قواعد أمان Firebase
الخطوات التالية
- هل تريد معرفة المزيد عن سير عمل المطوّرين في Firebase؟ اطّلِع على الدرس التطبيقي حول ترميز محاكي Firebase لمعرفة كيفية اختبار تطبيقك وتشغيله بالكامل على الجهاز.
- هل تريد معرفة المزيد من المعلومات عن منتجات Firebase الأخرى؟ هل تريد تخزين ملفات الصور التي يحمّلها المستخدمون؟ هل تريد إرسال إشعارات إلى المستخدمين؟ يمكنك الاطّلاع على الدرس التطبيقي حول ترميز الويب في Firebase للاطّلاع على درس تطبيقي حول الترميز يتضمّن معلومات أكثر تفصيلاً حول العديد من منتجات Firebase للويب.
- هل تريد معرفة مزيد من المعلومات حول Cloud Firestore؟ هل تريد الاطّلاع على معلومات عن المجموعات الفرعية والمعاملات؟ يمكنك الانتقال إلى الدرس التطبيقي حول ترميز الويب في Cloud Firestore للتعرّف على مزيد من التفاصيل حول الترميز في Cloud Firestore. يمكنك أيضًا الاطّلاع على سلسلة فيديوهات على YouTube للتعرّف على Cloud Firestore.
مزيد من المعلومات
- موقع Firebase الإلكتروني: firebase.google.com
- قناة Firebase على YouTube
كيف كانت النتيجة؟
يسرّنا تلقّي ملاحظاتك. يُرجى ملء نموذج قصير جدًا هنا.