1. قبل البدء
في هذا الدرس التطبيقي حول الترميز، ستتعلّم كيفية دمج Firebase مع تطبيق ويب Next.js يُسمى Friendly Eats، وهو موقع إلكتروني يعرض مراجعات للمطاعم.
يوفّر تطبيق الويب المكتمل ميزات مفيدة توضّح كيف يمكن أن تساعدك Firebase في إنشاء تطبيقات Next.js. تشمل هذه الميزات ما يلي:
- الإنشاء والنشر التلقائيان: يستخدم برنامج التدريب العملي هذا خدمة استضافة التطبيقات من Firebase لإنشاء رمز Next.js ونشره تلقائيًا في كل مرة يتم فيها إرسال الرمز إلى فرع تم إعداده.
- تسجيل الدخول والخروج: يتيح لك تطبيق الويب المكتمل تسجيل الدخول باستخدام حساب Google والخروج منه. تتم إدارة تسجيل دخول المستخدمين واستمرارهم في تسجيل الدخول بالكامل من خلال Firebase Authentication.
- الصور: يتيح تطبيق الويب المكتمل للمستخدمين الذين سجّلوا الدخول تحميل صور المطاعم. يتم تخزين مواد عرض الصور في Cloud Storage for Firebase. توفّر حزمة تطوير البرامج (SDK) في JavaScript من Firebase عنوان URL عامًا للصور التي تم تحميلها. يتم بعد ذلك تخزين عنوان URL العام هذا في مستند المطعم ذي الصلة في Cloud Firestore.
- المراجعات: يتيح تطبيق الويب المكتمل للمستخدمين الذين سجّلوا الدخول نشر مراجعات للمطاعم تتضمّن تقييمًا بالنجوم ورسالة نصية. يتم تخزين معلومات المراجعات في Cloud Firestore.
- الفلاتر: يتيح تطبيق الويب المكتمل للمستخدمين الذين سجّلوا الدخول فلترة قائمة المطاعم استنادًا إلى الفئة والموقع الجغرافي والسعر. يمكنك أيضًا تخصيص طريقة الترتيب المستخدَمة. يتم الوصول إلى البيانات من Cloud Firestore، ويتم تطبيق طلبات بحث Firestore استنادًا إلى الفلاتر المستخدَمة.
المتطلبات الأساسية
- حساب على GitHub
- معرفة Next.js وJavaScript
أهداف الدورة التعليمية
- كيفية استخدام Firebase مع ميزة "موجّه التطبيق" والعرض على جهة الخادم في Next.js
- كيفية الاحتفاظ بالصور في "مساحة تخزين Cloud Storage لخدمة Firebase"
- كيفية قراءة البيانات وكتابتها في قاعدة بيانات Cloud Firestore
- كيفية استخدام ميزة "تسجيل الدخول باستخدام حساب Google" مع حزمة تطوير البرامج (SDK) لمنصة Firebase JavaScript
المتطلبات
- Git
- إصدار ثابت حديث من Node.js
- متصفّح من اختيارك، مثل Google Chrome
- بيئة تطوير تتضمّن أداة تعديل الرموز البرمجية ونافذة طرفية
- حساب Google لإنشاء مشروعك على Firebase وإدارته
- إمكانية ترقية مشروعك على Firebase إلى خطة أسعار "الفئة المَرِنة"
2. إعداد بيئة التطوير ومستودع GitHub
يوفّر هذا الدرس التطبيقي حول الترميز قاعدة الرموز البرمجية الأولية للتطبيق ويعتمد على واجهة سطر الأوامر (CLI) في Firebase.
إنشاء مستودع GitHub
يمكن العثور على رمز مصدر الدرس العملي على الرابط https://github.com/firebase/friendlyeats-web. يحتوي المستودع على نماذج مشاريع لمنصات متعددة. ومع ذلك، لا يستخدم برنامج التدريب العملي هذا سوى الدليل nextjs-start
. يُرجى الانتباه إلى الدلائل التالية:
* `nextjs-start`: contains the starter code upon which you build.
* `nextjs-end`: contains the solution code for the finished web app.
انسخ المجلد nextjs-start
إلى المستودع الخاص بك:
- باستخدام نافذة طرفية، أنشئ مجلدًا جديدًا على جهاز الكمبيوتر وانتقِل إلى الدليل الجديد:
mkdir codelab-friendlyeats-web cd codelab-friendlyeats-web
- استخدِم حزمة npm giget لجلب المجلد
nextjs-start
فقط:npx giget@latest gh:firebase/friendlyeats-web/nextjs-start#master . --install
- تتبُّع التغييرات محليًا باستخدام git:
git init git add . git commit -m "codelab starting point" git branch -M main
- أنشئ مستودع GitHub جديدًا: https://github.com/new. يمكنك تسميته بأي اسم تريده.
- انسخ عنوان URL الجديد الذي ينشئه GitHub لك. سيبدو أحد الخيارَين التاليَين:
https://github.com/<USER_NAME>/<REPOSITORY_NAME>.git
أوgit@github.com:<USER_NAME>/<REPOSITORY_NAME>.git
- ادفع التغييرات المحلية إلى مستودع GitHub الجديد عن طريق تشغيل الأمر التالي. استبدِل العنصر النائب
<REPOSITORY_URL>
بعنوان URL الفعلي للمستودع.git remote add origin <REPOSITORY_URL> git push -u origin main
- من المفترض أن يظهر الرمز الأولي الآن في مستودعك على GitHub.
تثبيت واجهة سطر الأوامر (CLI) في Firebase أو تحديثها
نفِّذ الأمر التالي للتحقّق من تثبيت واجهة Firebase CLI ومن أنّ إصدارها هو 14.1.0 أو إصدار أحدث:
firebase --version
إذا ظهر لك إصدار أقدم أو لم يكن لديك Firebase CLI مثبّتًا، شغِّل أمر التثبيت:
npm install -g firebase-tools@latest
إذا تعذّر عليك تثبيت واجهة سطر الأوامر (CLI) في Firebase بسبب أخطاء في الأذونات، راجِع مستندات npm أو استخدِم خيار تثبيت آخر.
تسجيل الدخول إلى Firebase
- نفِّذ الأمر التالي لتسجيل الدخول إلى واجهة سطر الأوامر في Firebase:
firebase login
- استنادًا إلى ما إذا كنت تريد أن يجمع Firebase البيانات، أدخِل
Y
أوN
. - في المتصفّح، اختَر حسابك على Google، ثم انقر على السماح.
3- إعداد مشروعك على Firebase
في هذا القسم، عليك إعداد مشروع على Firebase وربط تطبيق ويب على Firebase به. ستعمل أيضًا على إعداد خدمات Firebase التي يستخدمها تطبيق الويب النموذجي.
إنشاء مشروع Firebase
- سجِّل الدخول إلى وحدة تحكّم Firebase باستخدام حساب Google نفسه الذي استخدمته في الخطوة السابقة.
- انقر على الزر لإنشاء مشروع جديد، ثم أدخِل اسم المشروع (على سبيل المثال،
FriendlyEats Codelab
).
- انقر على متابعة.
- إذا طُلب منك ذلك، راجِع بنود Firebase واقبلها، ثم انقر على متابعة.
- (اختياري) فعِّل ميزة "المساعدة المستندة إلى الذكاء الاصطناعي" في وحدة تحكّم Firebase (المعروفة باسم "Gemini في Firebase").
- في هذا الدرس العملي، لا تحتاج إلى "إحصاءات Google"، لذا أوقِف خيار "إحصاءات Google".
- انقر على إنشاء مشروع، وانتظِر إلى أن يتم توفير مشروعك، ثم انقر على متابعة.
ترقية خطة أسعار Firebase
لاستخدام خدمة "استضافة التطبيقات" في Firebase و"مساحة التخزين السحابي في Firebase"، يجب أن يكون مشروعك على Firebase ضمن خطة الأسعار "الدفع حسب الاستخدام" (Blaze)، ما يعني أنّه مرتبط بحساب Cloud Billing.
- يتطلّب حساب الفوترة في Cloud طريقة دفع، مثل بطاقة الائتمان.
- إذا كنت حديث العهد باستخدام Firebase وGoogle Cloud، تحقَّق ممّا إذا كنت مؤهَّلاً للحصول على رصيد بقيمة 300 دولار أمريكي وحساب فوترة على Cloud في الفترة التجريبية المجانية.
- إذا كنت تجري هذا الدرس العملي المبرمَج كجزء من حدث، اسأل المنظِّم عمّا إذا كانت هناك أي أرصدة في السحابة الإلكترونية متاحة.
لترقية مشروعك إلى خطة Blaze، اتّبِع الخطوات التالية:
- في "وحدة تحكّم Firebase"، اختَر ترقية خطتك.
- اختَر خطة Blaze. اتّبِع التعليمات الظاهرة على الشاشة لربط حساب فوترة على Cloud بمشروعك.
إذا احتجت إلى إنشاء حساب فوترة على Cloud كجزء من عملية الترقية هذه، قد تحتاج إلى الرجوع إلى مسار الترقية في وحدة تحكّم Firebase لإكمال عملية الترقية.
إضافة تطبيق ويب إلى مشروع Firebase
- انتقِل إلى نظرة عامة على المشروع في مشروعك على Firebase، ثم انقر على
الويب.
إذا كانت لديك تطبيقات مسجّلة في مشروعك، انقر على إضافة تطبيق لعرض رمز الويب. - في مربّع النص اسم التطبيق، أدخِل اسمًا مميزًا للتطبيق، مثل
My Next.js app
. - لا تضع علامة في مربّع الاختيار إعداد ميزة "استضافة Firebase" لهذا التطبيق أيضًا.
- انقر على تسجيل التطبيق > الانتقال إلى Play Console.
إعداد خدمات Firebase في وحدة تحكّم Firebase
إعداد المصادقة
- في وحدة تحكّم Firebase، انتقِل إلى المصادقة.
- انقر على البدء.
- في عمود موفّرو خدمات إضافيون، انقر على Google > تفعيل.
- في مربّع النص الاسم المعروض للجمهور للمشروع، أدخِل اسمًا يسهل تذكّره، مثل
My Next.js app
. - من القائمة المنسدلة عنوان البريد الإلكتروني المخصّص للدعم في المشروع، اختَر عنوان بريدك الإلكتروني.
- انقر على حفظ.
إعداد Cloud Firestore
- في اللوحة اليمنى من "وحدة تحكّم Firebase"، وسِّع إنشاء، ثم اختَر قاعدة بيانات Firestore.
- انقر على إنشاء قاعدة بيانات.
- اترك معرّف قاعدة البيانات مضبوطًا على
(default)
. - اختَر موقعًا لقاعدة البيانات، ثم انقر على التالي.
بالنسبة إلى تطبيق حقيقي، عليك اختيار موقع جغرافي قريب من المستخدمين. - انقر على البدء في وضع الاختبار. اقرأ بيان إخلاء المسؤولية عن قواعد الأمان.
في وقت لاحق من هذا الدرس العملي، ستضيف قواعد الأمان لتأمين بياناتك. لا توزِّع تطبيقًا أو تعرضه بشكل علني بدون إضافة "قواعد الأمان" لقاعدة البيانات. - انقر على إنشاء.
إعداد "مساحة تخزين سحابية لـ Firebase"
- في اللوحة اليمنى من وحدة تحكّم Firebase، وسِّع إنشاء، ثم اختَر مساحة التخزين.
- انقر على البدء.
- اختَر موقعًا جغرافيًا لحزمة Storage التلقائية.
يمكن للحِزم فيUS-WEST1
وUS-CENTRAL1
وUS-EAST1
الاستفادة من الفئة"دائمًا مجانية" في Google Cloud Storage. تخضع الحِزم في جميع المواقع الجغرافية الأخرى لأسعار واستخدام Google Cloud Storage. - انقر على البدء في وضع الاختبار. اقرأ بيان إخلاء المسؤولية عن قواعد الأمان.
في وقت لاحق من هذا الدرس العملي، ستضيف قواعد أمان لحماية بياناتك. لا توزّع تطبيقًا أو تعرضه للجميع بدون إضافة "قواعد الأمان" لحزمة Cloud Storage. - انقر على إنشاء.
نشر قواعد الأمان
يتضمّن الرمز مجموعات من قواعد الأمان لكلّ من Firestore وCloud Storage for Firebase. بعد نشر "قواعد الأمان"، تتم حماية البيانات في قاعدة البيانات والحزمة بشكل أفضل من إساءة الاستخدام.
- في نافذة الأوامر، اضبط واجهة سطر الأوامر لاستخدام مشروع Firebase الذي أنشأته سابقًا:
عندما يُطلب منك إدخال اسم مستعار، أدخِلfirebase use --add
friendlyeats-codelab
. - لنشر قواعد الأمان هذه (بالإضافة إلى الفهارس التي ستكون مطلوبة لاحقًا)، شغِّل الأمر التالي في الوحدة الطرفية:
firebase deploy --only firestore,storage
- إذا طُرح عليك السؤال:
"Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?"
، اضغط علىEnter
لاختيار نعم.
4. مراجعة قاعدة الرموز البرمجية الأولية
في هذا القسم، ستراجع بعض أقسام قاعدة الرموز البرمجية الأولية للتطبيق التي ستضيف إليها وظائف في هذا الدرس العملي.
بنية المجلدات والملفات
يحتوي الجدول التالي على نظرة عامة على بنية المجلدات والملفات في التطبيق:
المجلدات والملفات | الوصف |
| مكوّنات React للفلاتر والعناوين وتفاصيل المطاعم والمراجعات |
| الدوال المساعدة التي لا تكون مرتبطة بالضرورة بـ React أو Next.js |
| رمز Firebase وإعدادات Firebase |
| مواد العرض الثابتة في تطبيق الويب، مثل الرموز |
| التوجيه باستخدام App Router في Next.js |
| تبعيات المشروع باستخدام npm |
| إعدادات خاصة بمنصة Next.js (يجب أن تكون "إجراءات الخادم" مفعّلة) |
| إعدادات خدمة لغة JavaScript |
مكوّنات الخادم والعميل
التطبيق هو تطبيق ويب Next.js يستخدم App Router. يتم استخدام العرض على جهة الخادم في جميع أنحاء التطبيق. على سبيل المثال، ملف src/app/page.js
هو مكوّن خادم مسؤول عن الصفحة الرئيسية. الملف src/components/RestaurantListings.jsx
هو أحد مكونات العميل ويتم تحديده بواسطة التوجيه "use client"
في بداية الملف.
عبارات الاستيراد
قد تلاحظ عبارات استيراد مثل ما يلي:
import RatingPicker from "@/src/components/RatingPicker.jsx";
يستخدم التطبيق الرمز @
لتجنُّب مسارات الاستيراد النسبية المعقّدة، ويتم ذلك من خلال أسماء المسارات المستعارة.
واجهات برمجة التطبيقات الخاصة بمنصة Firebase
يتم تضمين جميع رموز Firebase API في الدليل src/lib/firebase
. بعد ذلك، تستورد مكوّنات React الفردية الدوال المغلفة من الدليل src/lib/firebase
، بدلاً من استيراد دوال Firebase مباشرةً.
بيانات تجريبية
يحتوي الملف src/lib/randomData.js
على بيانات وهمية خاصة بالمطاعم والمراجعات. يتم تجميع البيانات من هذا الملف في الرمز البرمجي في الملف src/lib/fakeRestaurants.js
.
5- إنشاء خلفية لاستضافة التطبيقات
في هذا القسم، ستُعدّ خادمًا خلفيًا لاستضافة التطبيقات لمراقبة فرع في مستودع git.
في نهاية هذا القسم، سيكون لديك خلفية App Hosting مرتبطة بمستودعك في GitHub، وسيتم تلقائيًا إعادة إنشاء إصدار جديد من تطبيقك وطرحه كلما أرسلت عملية تثبيت جديدة إلى فرع main
.
إنشاء خادم خلفي
- انتقِل إلى صفحة "استضافة التطبيقات" في وحدة تحكّم Firebase:
- انقر على "البدء" لبدء عملية إنشاء الخلفية. اضبط الخلفية على النحو التالي:
- اختر منطقة. بالنسبة إلى تطبيق حقيقي، عليك اختيار المنطقة الأقرب إلى المستخدمين.
- اتّبِع التعليمات في خطوة "استيراد مستودع GitHub" لربط مستودع GitHub الذي أنشأته سابقًا.
- اضبط إعدادات النشر:
- الاحتفاظ بالدليل الجذر على النحو
/
- ضبط الفرع المباشر على
main
- تفعيل عمليات الطرح التلقائي
- الاحتفاظ بالدليل الجذر على النحو
- أدخِل اسمًا لخادمك الخلفي
friendlyeats-codelab
. - في قسم "ربط تطبيق ويب على Firebase"، انقر على "إنشاء تطبيق ويب جديد على Firebase".
- انقر على "إنهاء ونشر". بعد لحظات، سيتم نقلك إلى صفحة جديدة يمكنك فيها الاطّلاع على حالة الخلفية الجديدة لميزة "استضافة التطبيقات".
- بعد اكتمال عملية الطرح، انقر على نطاقك المجاني ضمن "النطاقات". قد يستغرق بدء عملها بضع دقائق بسبب نشر نظام أسماء النطاقات.
- عفوًا عند تحميل الصفحة، ستظهر لك رسالة خطأ تفيد بحدوث استثناء من جهة الخادم (يمكنك الاطّلاع على سجلات الخادم للحصول على مزيد من المعلومات).
- في وحدة تحكّم Firebase، اطّلِع على علامة التبويب "السجلات" في الخلفية الخاصة بخدمة "استضافة التطبيقات". سيظهر لك سجلّ "الخطأ: لم يتم التنفيذ". سنحلّ هذه المشكلة في الخطوة التالية عند إضافة المصادقة.
لقد نشرت تطبيق الويب الأوّلي. في كل مرة ترسل فيها عملية تثبيت جديدة إلى فرع main
في مستودع GitHub، سيظهر لك إصدار جديد ويبدأ طرحه في وحدة تحكّم Firebase، وسيتم تعديل موقعك الإلكتروني تلقائيًا بعد اكتمال عملية الطرح.
6. إضافة مصادقة إلى تطبيق الويب
في هذا القسم، ستضيف مصادقة إلى تطبيق الويب لتتمكّن من تسجيل الدخول إليه.
إضافة نطاق معتمَد
لن تقبل خدمة Firebase Authentication طلبات تسجيل الدخول إلا من النطاقات التي تسمح بها. سنضيف هنا نطاق الخلفية المستخدَمة في App Hosting إلى قائمة النطاقات الموافَق عليها في مشروعك.
- انسخ نطاق الخلفية في App Hosting من صفحة "نظرة عامة" في App Hosting.
- انتقِل إلى علامة التبويب إعدادات المصادقة واختَر النطاقات المعتمَدة.
- انقر على الزر إضافة نطاق.
- أدخِل نطاق الخلفية في App Hosting.
- انقر على إضافة.
تنفيذ وظائف تسجيل الدخول وتسجيل الخروج
- في الملف
src/lib/firebase/auth.js
، استبدِل الدوالonAuthStateChanged
وonIdTokenChanged
وsignInWithGoogle
وsignOut
بالرمز التالي:
export function onAuthStateChanged(cb) {
return _onAuthStateChanged(auth, cb);
}
export function onIdTokenChanged(cb) {
return _onIdTokenChanged(auth, cb);
}
export async function signInWithGoogle() {
const provider = new GoogleAuthProvider();
try {
await signInWithPopup(auth, provider);
} catch (error) {
console.error("Error signing in with Google", error);
}
}
export async function signOut() {
try {
return auth.signOut();
} catch (error) {
console.error("Error signing out with Google", error);
}
}
يستخدم هذا الرمز واجهات برمجة تطبيقات Firebase التالية:
Firebase API | الوصف |
تضيف هذه الطريقة مراقبًا للتغييرات التي تطرأ على حالة تسجيل الدخول للمستخدم. | |
تضيف هذه الدالة مراقبًا للتغييرات التي تطرأ على الرمز المميّز للمستخدم. | |
تنشئ هذه الدالة مثيلاً لموفّر مصادقة Google. | |
يبدأ مسار المصادقة المستند إلى مربّع الحوار. | |
تسجيل خروج المستخدم |
في الملف src/components/Header.jsx
، تستدعي التعليمة البرمجية الدالتَين signInWithGoogle
وsignOut
.
إرسال حالة المصادقة إلى الخادم
من أجل تمرير حالة المصادقة إلى الخادم، سنستخدم ملفات تعريف الارتباط. عندما تتغيّر حالة المصادقة في العميل، سنعدّل ملف تعريف الارتباط __session
.
في src/components/Header.jsx
، استبدِل الدالة useUserSession
بالرمز التالي:
function useUserSession(initialUser) {
useEffect(() => {
return onIdTokenChanged(async (user) => {
if (user) {
const idToken = await user.getIdToken();
await setCookie("__session", idToken);
} else {
await deleteCookie("__session");
}
if (initialUser?.uid === user?.uid) {
return;
}
window.location.reload();
});
}, [initialUser]);
return initialUser;
}
قراءة حالة المصادقة على الخادم
سنستخدم FirebaseServerApp لعكس حالة مصادقة العميل على الخادم.
افتح src/lib/firebase/serverApp.js
، واستبدِل الدالة getAuthenticatedAppForUser
بما يلي:
export async function getAuthenticatedAppForUser() {
const authIdToken = (await cookies()).get("__session")?.value;
// Firebase Server App is a new feature in the JS SDK that allows you to
// instantiate the SDK with credentials retrieved from the client & has
// other affordances for use in server environments.
const firebaseServerApp = initializeServerApp(
// https://github.com/firebase/firebase-js-sdk/issues/8863#issuecomment-2751401913
initializeApp(),
{
authIdToken,
}
);
const auth = getAuth(firebaseServerApp);
await auth.authStateReady();
return { firebaseServerApp, currentUser: auth.currentUser };
}
التحقّق من التغييرات
يعرض تنسيق الجذر في الملف src/app/layout.js
العنوان ويُدخل المستخدم، إذا كان متاحًا، كخاصية.
<Header initialUser={currentUser?.toJSON()} />
وهذا يعني أنّ مكوّن <Header>
يعرض بيانات المستخدم، إذا كانت متاحة، أثناء وقت تشغيل الخادم. إذا كانت هناك أي تعديلات على المصادقة خلال مراحل نشاط الصفحة بعد تحميل الصفحة الأولي، سيتولّى المعالج onAuthStateChanged
التعامل معها.
حان الوقت الآن لطرح إصدار جديد والتحقّق من صحة ما أنشأته.
- أنشئ عملية إيداع مع رسالة الإيداع "إضافة مصادقة" وادفعها إلى مستودع GitHub.
- افتح صفحة "استضافة التطبيقات" في وحدة تحكّم Firebase وانتظِر إلى أن يكتمل طرح الإصدار الجديد.
- تحقَّق من سلوك المصادقة الجديد:
- في المتصفّح، أعِد تحميل تطبيق الويب. سيظهر اسمك المعروض في العنوان.
- سجِّل الخروج ثم سجِّل الدخول مرة أخرى. يمكنك تكرار هذه الخطوة مع مستخدمين مختلفين.
- اختياري: انقر بزر الماوس الأيمن على تطبيق الويب، واختَر عرض مصدر الصفحة، وابحث عن الاسم المعروض. يظهر في مصدر HTML الأولي الذي يعرضه الخادم.
7. عرض معلومات المطعم
يتضمّن تطبيق الويب بيانات تجريبية للمطاعم والمراجعات.
إضافة مطعم واحد أو أكثر
لإدراج بيانات مطاعم وهمية في قاعدة بيانات Cloud Firestore المحلية، اتّبِع الخطوات التالية:
- سجِّل الدخول إلى تطبيق الويب إذا لم يسبق لك إجراء ذلك. بعد ذلك، انقر على
> إضافة مطاعم نموذجية.
- في صفحة قاعدة بيانات Firestore ضِمن وحدة تحكّم Firebase، اختَر restaurants. يمكنك الاطّلاع على المستندات ذات المستوى الأعلى في مجموعة المطاعم، ويمثّل كل مستند مطعمًا.
- انقر على بعض المستندات لاستكشاف خصائص مستند خاص بمطعم.
عرض قائمة المطاعم
يتضمّن الآن تطبيق الويب Next.js قاعدة بيانات Cloud Firestore التي يمكنه عرضها.
لتحديد رمز استرجاع البيانات، اتّبِع الخطوات التالية:
- في الملف
src/app/page.js
، ابحث عن مكوّن الخادم<Home />
، وراجِع استدعاء الدالةgetRestaurants
التي تسترد قائمة بالمطاعم في وقت تشغيل الخادم. يمكنك تنفيذ الدالةgetRestaurants
باتّباع الخطوات التالية. - في الملف
src/lib/firebase/firestore.js
، استبدِل الدالتَينapplyQueryFilters
وgetRestaurants
بالرمز البرمجي التالي:
function applyQueryFilters(q, { category, city, price, sort }) {
if (category) {
q = query(q, where("category", "==", category));
}
if (city) {
q = query(q, where("city", "==", city));
}
if (price) {
q = query(q, where("price", "==", price.length));
}
if (sort === "Rating" || !sort) {
q = query(q, orderBy("avgRating", "desc"));
} else if (sort === "Review") {
q = query(q, orderBy("numRatings", "desc"));
}
return q;
}
export async function getRestaurants(db = db, filters = {}) {
let q = query(collection(db, "restaurants"));
q = applyQueryFilters(q, filters);
const results = await getDocs(q);
return results.docs.map((doc) => {
return {
id: doc.id,
...doc.data(),
// Only plain objects can be passed to Client Components from Server Components
timestamp: doc.data().timestamp.toDate(),
};
});
}
- أنشئ عملية تأكيد مع رسالة التأكيد "قراءة قائمة المطاعم من Firestore" وادفعها إلى مستودع GitHub.
- افتح صفحة "استضافة التطبيقات" في وحدة تحكّم Firebase وانتظِر إلى أن يكتمل طرح الإصدار الجديد.
- في تطبيق الويب، أعِد تحميل الصفحة. تظهر صور المطاعم على شكل مربّعات في الصفحة.
التأكّد من تحميل بيانات المطاعم في وقت تشغيل الخادم
باستخدام إطار عمل Next.js، قد لا يكون من الواضح متى يتم تحميل البيانات في وقت تشغيل الخادم أو وقت تشغيل العميل.
للتأكّد من تحميل بيانات المطاعم في وقت تشغيل الخادم، اتّبِع الخطوات التالية:
- في تطبيق الويب، افتح "أدوات مطوّري البرامج" وأوقِف JavaScript.
- أعِد تحميل تطبيق الويب، وستظل بيانات المطاعم تظهر. يتم عرض معلومات المطعم في ردّ الخادم. عند تفعيل JavaScript، يتم ترطيب معلومات المطعم من خلال رمز JavaScript من جهة العميل.
- في "أدوات مطوّري البرامج"، أعِد تفعيل JavaScript.
الاستماع إلى إشعارات المطاعم باستخدام أدوات الاستماع إلى اللقطات في Cloud Firestore
في القسم السابق، رأيت كيف تم تحميل المجموعة الأولية من المطاعم من ملف src/app/page.js
. ملف src/app/page.js
هو أحد مكونات الخادم ويتم عرضه على الخادم، بما في ذلك رمز جلب البيانات من Firebase.
الملف src/components/RestaurantListings.jsx
هو أحد مكوّنات العميل ويمكن ضبطه لترطيب الترميز الذي يتم عرضه من جهة الخادم.
لضبط ملف src/components/RestaurantListings.jsx
من أجل تفعيل ميزة "الترطيب" لترميز يتم عرضه من جهة الخادم، اتّبِع الخطوات التالية:
- في ملف
src/components/RestaurantListings.jsx
، لاحظ الرمز البرمجي التالي الذي تمّت كتابته لك مسبقًا:
useEffect(() => {
return getRestaurantsSnapshot((data) => {
setRestaurants(data);
}, filters);
}, [filters]);
يستدعي هذا الرمز الدالة getRestaurantsSnapshot()
، وهي تشبه الدالة getRestaurants()
التي نفّذتها في خطوة سابقة. ومع ذلك، توفّر وظيفة اللقطة هذه آلية ردّ اتصال يتم استدعاؤها في كل مرة يتم فيها إجراء تغيير على مجموعة المطاعم.
- في الملف
src/lib/firebase/firestore.js
، استبدِل الدالةgetRestaurantsSnapshot()
بالرمز التالي:
export function getRestaurantsSnapshot(cb, filters = {}) {
if (typeof cb !== "function") {
console.log("Error: The callback parameter is not a function");
return;
}
let q = query(collection(db, "restaurants"));
q = applyQueryFilters(q, filters);
return onSnapshot(q, (querySnapshot) => {
const results = querySnapshot.docs.map((doc) => {
return {
id: doc.id,
...doc.data(),
// Only plain objects can be passed to Client Components from Server Components
timestamp: doc.data().timestamp.toDate(),
};
});
cb(results);
});
}
تظهر الآن التغييرات التي يتم إجراؤها من خلال صفحة قاعدة بيانات Firestore في تطبيق الويب في الوقت الفعلي.
- أنشئ عملية حفظ مع رسالة عملية الحفظ "الاستماع إلى آخر الأخبار في المطاعم" وادفعها إلى مستودع GitHub.
- افتح صفحة "استضافة التطبيقات" في وحدة تحكّم Firebase وانتظِر إلى أن يكتمل طرح الإصدار الجديد.
- في تطبيق الويب، انقر على
> إضافة مطاعم نموذجية. إذا تم تنفيذ وظيفة اللقطة بشكلٍ صحيح، ستظهر المطاعم في الوقت الفعلي بدون إعادة تحميل الصفحة.
8. حفظ المراجعات التي أرسلها المستخدمون من تطبيق الويب
- في الملف
src/lib/firebase/firestore.js
، استبدِل الدالةupdateWithRating()
بالرمز التالي:
const updateWithRating = async (
transaction,
docRef,
newRatingDocument,
review
) => {
const restaurant = await transaction.get(docRef);
const data = restaurant.data();
const newNumRatings = data?.numRatings ? data.numRatings + 1 : 1;
const newSumRating = (data?.sumRating || 0) + Number(review.rating);
const newAverage = newSumRating / newNumRatings;
transaction.update(docRef, {
numRatings: newNumRatings,
sumRating: newSumRating,
avgRating: newAverage,
});
transaction.set(newRatingDocument, {
...review,
timestamp: Timestamp.fromDate(new Date()),
});
};
يُدرِج هذا الرمز مستند Firestore جديدًا يمثّل المراجعة الجديدة. تعدّل التعليمة البرمجية أيضًا مستند Firestore الحالي الذي يمثّل المطعم بأرقام معدَّلة لعدد التقييمات ومتوسط التقييم المحسوب.
- استبدِل الدالة
addReviewToRestaurant()
بالرمز التالي:
export async function addReviewToRestaurant(db, restaurantId, review) {
if (!restaurantId) {
throw new Error("No restaurant ID has been provided.");
}
if (!review) {
throw new Error("A valid review has not been provided.");
}
try {
const docRef = doc(collection(db, "restaurants"), restaurantId);
const newRatingDocument = doc(
collection(db, `restaurants/${restaurantId}/ratings`)
);
// corrected line
await runTransaction(db, transaction =>
updateWithRating(transaction, docRef, newRatingDocument, review)
);
} catch (error) {
console.error(
"There was an error adding the rating to the restaurant",
error
);
throw error;
}
}
تنفيذ إجراء خادم Next.js
توفّر "إجراءات الخادم" في Next.js واجهة برمجة تطبيقات ملائمة للوصول إلى بيانات النموذج، مثل data.get("text")
للحصول على قيمة النص من حمولة إرسال النموذج.
لاستخدام إجراء خادم Next.js لمعالجة نموذج إرسال المراجعة، اتّبِع الخطوات التالية:
- في ملف
src/components/ReviewDialog.jsx
، ابحث عن السمةaction
في العنصر<form>
.
<form action={handleReviewFormSubmission}>
تشير قيمة السمة action
إلى دالة عليك تنفيذها في الخطوة التالية.
- في الملف
src/app/actions.js
، استبدِل الدالةhandleReviewFormSubmission()
بالرمز التالي:
// This is a next.js server action, which is an alpha feature, so
// use with caution.
// https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions
export async function handleReviewFormSubmission(data) {
const { app } = await getAuthenticatedAppForUser();
const db = getFirestore(app);
await addReviewToRestaurant(db, data.get("restaurantId"), {
text: data.get("text"),
rating: data.get("rating"),
// This came from a hidden form field.
userId: data.get("userId"),
});
}
إضافة مراجعات لمطعم
لقد نفّذت إمكانية إرسال المراجعات، لذا يمكنك الآن التأكّد من إدراج مراجعاتك في Cloud Firestore بشكل صحيح.
لإضافة مراجعة والتأكّد من إدراجها في Cloud Firestore، اتّبِع الخطوات التالية:
- أنشئ عملية إيداع مع رسالة الإيداع "السماح للمستخدمين بإرسال مراجعات للمطاعم" وادفعها إلى مستودع GitHub.
- افتح صفحة "استضافة التطبيقات" في وحدة تحكّم Firebase وانتظِر إلى أن يكتمل طرح الإصدار الجديد.
- أعِد تحميل تطبيق الويب، واختَر مطعمًا من الصفحة الرئيسية.
- في صفحة المطعم، انقر على
.
- اختَر تقييمًا بالنجوم.
- كتابة مراجعة
- انقر على إرسال. تظهر مراجعتك في أعلى قائمة المراجعات.
- في Cloud Firestore، ابحث في لوحة إضافة مستند عن مستند المطعم الذي راجعته واختَره.
- في جزء بدء جمع البيانات، اختَر التقييمات.
- في لوحة إضافة مستند، ابحث عن المستند الذي تريد مراجعته للتأكّد من أنّه تم إدراجه على النحو المتوقّع.
9. حفظ الملفات التي حمّلها المستخدمون من تطبيق الويب
في هذا القسم، ستضيف وظيفة تتيح لك استبدال الصورة المرتبطة بمطعم معيّن عندما تكون مسجّلاً الدخول. تحمّل الصورة إلى Firebase Storage، وتعدّل عنوان URL الخاص بالصورة في مستند Cloud Firestore الذي يمثّل المطعم.
لحفظ الملفات التي حمّلها المستخدمون من تطبيق الويب، اتّبِع الخطوات التالية:
- في ملف
src/components/Restaurant.jsx
، راقِب الرمز الذي يتم تنفيذه عندما يحمّل المستخدم ملفًا:
async function handleRestaurantImage(target) {
const image = target.files ? target.files[0] : null;
if (!image) {
return;
}
const imageURL = await updateRestaurantImage(id, image);
setRestaurantDetails({ ...restaurantDetails, photo: imageURL });
}
لا يلزم إجراء أي تغييرات على هذه الدالة، ولكن يمكنك تنفيذ سلوك الدالة updateRestaurantImage()
في الخطوات التالية.
- في الملف
src/lib/firebase/storage.js
، استبدِل الدالتَينupdateRestaurantImage()
وuploadImage()
بالرمز البرمجي التالي:
export async function updateRestaurantImage(restaurantId, image) {
try {
if (!restaurantId) {
throw new Error("No restaurant ID has been provided.");
}
if (!image || !image.name) {
throw new Error("A valid image has not been provided.");
}
const publicImageUrl = await uploadImage(restaurantId, image);
await updateRestaurantImageReference(restaurantId, publicImageUrl);
return publicImageUrl;
} catch (error) {
console.error("Error processing request:", error);
}
}
async function uploadImage(restaurantId, image) {
const filePath = `images/${restaurantId}/${image.name}`;
const newImageRef = ref(storage, filePath);
await uploadBytesResumable(newImageRef, image);
return await getDownloadURL(newImageRef);
}
تمّ تنفيذ الدالة updateRestaurantImageReference()
لك من قبل. تعدّل هذه الدالة مستند مطعم حالي في Cloud Firestore باستخدام عنوان URL معدَّل للصورة.
التحقّق من وظيفة تحميل الصور
للتأكّد من أنّ عملية تحميل الصورة تتم على النحو المتوقّع، اتّبِع الخطوات التالية:
- أنشئ عملية دمج مع رسالة عملية الدمج "السماح للمستخدمين بتغيير صورة كل مطعم" وادفعها إلى مستودع GitHub.
- افتح صفحة "استضافة التطبيقات" في وحدة تحكّم Firebase وانتظِر إلى أن يكتمل طرح الإصدار الجديد.
- في تطبيق الويب، تأكَّد من تسجيل الدخول واختَر مطعمًا.
- انقر على
وحمِّل صورة من نظام الملفات. تتم مغادرة صورتك لبيئتك المحلية وتحميلها إلى Cloud Storage. تظهر الصورة فور تحميلها.
- انتقِل إلى Cloud Storage لبرنامج Firebase.
- انتقِل إلى المجلد الذي يمثّل المطعم. تتضمّن الصورة التي حمّلتها المجلد.
10. تلخيص مراجعات المطاعم باستخدام الذكاء الاصطناعي التوليدي
في هذا القسم، ستضيف ميزة "ملخّص المراجعات" ليتمكّن المستخدم من معرفة آراء الجميع حول أحد المطاعم بسرعة بدون الحاجة إلى قراءة كل مراجعة.
تخزين مفتاح Gemini API في Cloud Secret Manager
- لاستخدام Gemini API، ستحتاج إلى مفتاح واجهة برمجة التطبيقات. انتقِل إلى Google AI Studio وانقر على "إنشاء مفتاح API".
- في حقل الإدخال "البحث عن مشاريع Google Cloud"، اختَر مشروعك على Firebase. يستند كل مشروع على Firebase إلى مشروع على Google Cloud.
- تتكامل خدمة App Hosting مع Cloud Secret Manager لتتيح لك تخزين القيم الحسّاسة، مثل مفاتيح واجهة برمجة التطبيقات، بشكل آمن:
- في الوحدة الطرفية، شغِّل الأمر لإنشاء سر جديد:
firebase apphosting:secrets:set GEMINI_API_KEY
- عندما يُطلب منك إدخال القيمة السرية، انسخ مفتاح Gemini API والصِقه من Google AI Studio.
- عندما يُطلب منك تحديد ما إذا كان السر الجديد مخصّصًا للإصدار العلني أو الاختبار المحلي، اختَر "الإصدار العلني".
- عندما يُطلب منك تحديد ما إذا كنت تريد منح إذن الوصول إلى حساب الخدمة في الخلفية كي يتمكّن من الوصول إلى كلمة المرور، اختَر "نعم".
- عندما يُطلب منك تحديد ما إذا كان يجب إضافة السر الجديد إلى
apphosting.yaml
، أدخِلY
للموافقة.
يتم الآن تخزين مفتاح Gemini API بشكل آمن في Cloud Secret Manager، ويمكن الوصول إليه من خلفية App Hosting.
تنفيذ مكوّن ملخّص المراجعات
- في
src/components/Reviews/ReviewSummary.jsx
، استبدِل الدالةGeminiSummary
بالرمز التالي:export async function GeminiSummary({ restaurantId }) { const { firebaseServerApp } = await getAuthenticatedAppForUser(); const reviews = await getReviewsByRestaurantId( getFirestore(firebaseServerApp), restaurantId ); const reviewSeparator = "@"; const prompt = ` Based on the following restaurant reviews, where each review is separated by a '${reviewSeparator}' character, create a one-sentence summary of what people think of the restaurant. Here are the reviews: ${reviews.map((review) => review.text).join(reviewSeparator)} `; try { if (!process.env.GEMINI_API_KEY) { // Make sure GEMINI_API_KEY environment variable is set: // https://firebase.google.com/docs/genkit/get-started throw new Error( 'GEMINI_API_KEY not set. Set it with "firebase apphosting:secrets:set GEMINI_API_KEY"' ); } // Configure a Genkit instance. const ai = genkit({ plugins: [googleAI()], model: gemini20Flash, // set default model }); const { text } = await ai.generate(prompt); return ( <div className="restaurant__review_summary"> <p>{text}</p> <p>✨ Summarized with Gemini</p> </div> ); } catch (e) { console.error(e); return <p>Error summarizing reviews.</p>; } }
- أنشئ عملية دمج مع رسالة الدمج "استخدام الذكاء الاصطناعي لتلخيص المراجعات" وادفعها إلى مستودع GitHub.
- افتح صفحة "استضافة التطبيقات" في وحدة تحكّم Firebase وانتظِر إلى أن يكتمل طرح الإصدار الجديد.
- افتح صفحة خاصة بمطعم. في أعلى الصفحة، من المفترض أن يظهر ملخّص من جملة واحدة لجميع المراجعات في الصفحة.
- أضِف مراجعة جديدة وأعِد تحميل الصفحة. من المفترض أن يظهر لك التغيير في الملخّص.
11. الخاتمة
تهانينا! تعرّفت على كيفية استخدام Firebase لإضافة ميزات ووظائف إلى تطبيق Next.js، وتحديدًا استخدمت ما يلي:
- Firebase App Hosting لإنشاء رمز Next.js ونشره تلقائيًا في كل مرة يتم فيها إرسال الرمز إلى فرع تم إعداده
- مصادقة Firebase لتفعيل وظيفة تسجيل الدخول وتسجيل الخروج
- Cloud Firestore لبيانات المطاعم وبيانات مراجعات المطاعم
- مساحة تخزين سحابية لـ Firebase لتخزين صور المطاعم