باستخدام Cloud Functions، يمكنك التعامل مع الأحداث في
Firebase Realtime Database بدون الحاجة إلى تعديل رمز العميل.
يتيح لك Cloud Functions تشغيل عمليات Realtime Database باستخدام الإدارة الكاملة
وتضمن معالجة كل تغيير في Realtime Database.
كل على حدة. يمكنك إجراء Firebase Realtime Database تغييرات من خلال
DataSnapshot
أو من خلال SDK للمشرف.
في أي دورة حياة عادية، تقوم دالة Firebase Realtime Database بما يلي:
- بانتظار التغييرات في موقع جغرافي معيّن على "Realtime Database".
- يتم تشغيله عند وقوع حدث وتنفيذ مهامه (راجع ما الذي يمكنني فعله؟ مع "Cloud Functions"؟ للحصول على أمثلة على حالات الاستخدام).
- يتلقى كائن بيانات يحتوي على لقطة من البيانات المخزنة في المستند المحدد.
تشغيل دالة Realtime Database
إنشاء دوال جديدة لأحداث Realtime Database
مع functions.database
. إلى
التحكم في وقت تشغيل الدالة، وتحديد أحد معالِجات الأحداث،
تحديد مسار Realtime Database حيث سيتم الاستماع إلى الأحداث
ضبط معالِج الحدث
تتيح لك الدوال التعامل مع أحداث Realtime Database على مستويَين من الخصوصية. التي يمكنك الاستماع إليها تحديدًا للإنشاء والتحديث أو حذف الأحداث، أو يمكنك الاستماع إلى أي تغيير من أي نوع في المسار. يتوافق "Cloud Functions" مع معالِجات الأحداث التالية لـ "Realtime Database":
onWrite()
، الذي يتم تشغيله عند إنشاء بيانات أو تعديلها أو حذفها في Realtime Database.onCreate()
، الذي يتم تشغيله عند إنشاء بيانات جديدة في Realtime Database.onUpdate()
، الذي يتم تشغيله عند تعديل البيانات في Realtime DatabaseonDelete()
، الذي يتم تشغيله عند حذف البيانات من Realtime Database
تحديد المثيل والمسار
للتحكّم في وقت ومكان تشغيل الدالة، يمكنك طلب ref(path)
.
لتحديد مسار، ويمكنك اختياريًا تحديد مثيل Realtime Database
مع instance('INSTANCE_NAME')
. إذا لم
لتحديد مثيل، يتم نشر الدالة إلى مثيل Realtime Database التلقائي من أجل
مشروع Firebase على سبيل المثال:
- مثيل Realtime Database التلقائي:
functions.database.ref('/foo/bar')
- مثيل باسم "my-app-db-2":
functions.database.instance('my-app-db-2').ref('/foo/bar')
توجه هذه الطرق دالتك للتعامل مع عمليات الكتابة في مسار معين داخل
مثيل Realtime Database. تتطابق مواصفات المسار مع جميع النصوص التي تلمس مسارًا،
بما في ذلك الكتابة
تحدث في أي مكان تحتها. في حال تحديد المسار
لوظيفتك كـ /foo/bar
، فإنها تتطابق مع الأحداث في كلا الموقعين التاليين:
/foo/bar
/foo/bar/baz/really/deep/path
في كلتا الحالتين، يفسّر Firebase أن الحدث وقع في /foo/bar
،
وتشمل بيانات الحدث
البيانات القديمة والجديدة في /foo/bar
. إذا كانت بيانات الحدث كبيرة،
ننصحك باستخدام دوال متعددة في مسارات أكثر عمقًا بدلاً من دالة واحدة
تعمل بالقرب من جذر قاعدة البيانات الخاصة بك. للحصول على أفضل أداء، اطلب فقط
البيانات على أعمق مستوى ممكن.
يمكنك تحديد مكون مسار كحرف بدل من خلال إحاطته بحرف مجعد
الأقواس تتطابق ref('foo/{bar}')
مع أي عنصر ثانوي في /foo
. ولا تعتبر قيم هذه
تتوفر مكونات مسار حرف البدل ضمن
EventContext.params
كائن الدالة لديك. في هذا المثال، تتوفر القيمة على شكل
context.params.bar
يمكن أن تتطابق المسارات التي تتضمن أحرف البدل مع أحداث متعددة من عملية كتابة واحدة. إدراج
{
"foo": {
"hello": "world",
"firebase": "functions"
}
}
تتطابق مع المسار "/foo/{bar}"
مرتين: مرة مع "hello": "world"
ومرة أخرى باستخدام "firebase": "functions"
.
التعامل مع بيانات الأحداث
عند التعامل مع حدث Realtime Database، يكون عنصر البيانات المعروض هو
DataSnapshot
بالنسبة إلى onWrite
أو onUpdate
حدث، سيتم
المعلمة الأولى هي كائن Change
يحتوي على لقطتين
التي تمثل حالة البيانات قبل
وبعد الحدث التشغيلي. في onCreate
وonDelete
حدث
كائن البيانات المعروض هو لقطة من البيانات التي تم إنشاؤها أو حذفها.
في هذا المثال، تسترد الدالة لقطة المسار المحدد، يحول السلسلة في هذا الموقع إلى أحرف كبيرة، وتكتب هذه السلسلة المعدّلة في قاعدة البيانات:
// Listens for new messages added to /messages/:pushId/original and creates an // uppercase version of the message to /messages/:pushId/uppercase exports.makeUppercase = functions.database.ref('/messages/{pushId}/original') .onCreate((snapshot, context) => { // Grab the current value of what was written to the Realtime Database. const original = snapshot.val(); functions.logger.log('Uppercasing', context.params.pushId, original); const uppercase = original.toUpperCase(); // You must return a Promise when performing asynchronous tasks inside a Functions such as // writing to the Firebase Realtime Database. // Setting an "uppercase" sibling in the Realtime Database returns a Promise. return snapshot.ref.parent.child('uppercase').set(uppercase); });
الوصول إلى معلومات مصادقة المستخدم
من EventContext.auth
وEventContext.authType
،
يمكنك الوصول إلى
معلومات المستخدم، بما في ذلك الأذونات، للمستخدم الذي بدأ تشغيل
إحدى الدوال. ويمكن أن يفيد ذلك في فرض قواعد الأمان،
ما يسمح لوظيفتك بإكمال عمليات مختلفة بناءً على واجهة المستخدم
مستوى الأذونات:
const functions = require('firebase-functions/v1');
const admin = require('firebase-admin');
exports.simpleDbFunction = functions.database.ref('/path')
.onCreate((snap, context) => {
if (context.authType === 'ADMIN') {
// do something
} else if (context.authType === 'USER') {
console.log(snap.val(), 'written by', context.auth.uid);
}
});
يمكنك أيضًا الاستفادة من معلومات مصادقة المستخدم من أجل "انتحال الهوية" مستخدِم وتنفيذ عمليات الكتابة نيابةً عن المستخدم تأكد من حذف مثيل التطبيق كما هو موضّح أدناه لتجنُّب حدوث مشاكل في المزامنة:
exports.impersonateMakeUpperCase = functions.database.ref('/messages/{pushId}/original')
.onCreate((snap, context) => {
const appOptions = JSON.parse(process.env.FIREBASE_CONFIG);
appOptions.databaseAuthVariableOverride = context.auth;
const app = admin.initializeApp(appOptions, 'app');
const uppercase = snap.val().toUpperCase();
const ref = snap.ref.parent.child('uppercase');
const deleteApp = () => app.delete().catch(() => null);
return app.database().ref(ref).set(uppercase).then(res => {
// Deleting the app is necessary for preventing concurrency leaks
return deleteApp().then(() => res);
}).catch(err => {
return deleteApp().then(() => Promise.reject(err));
});
});
قراءة القيمة السابقة
يحتوي الكائن Change
على
before
تتيح لك فحص ما تم حفظه في Realtime Database قبل
فعالية. تعرض السمة before
علامة DataSnapshot
حيث تكون جميع
(على سبيل المثال،
val()
و
exists()
)
يشير إلى القيمة السابقة. يمكنك قراءة القيمة الجديدة مرة أخرى باستخدام
DataSnapshot
الأصلية أو قراءة
after
الموقع. هذه السمة على أي Change
هي سمة DataSnapshot
أخرى تمثّل
حالة البيانات بعد وقوع الحدث.
على سبيل المثال، يمكن استخدام السمة before
للتأكّد من أنّ الدالة فقط
كتابة النص بأحرف كبيرة عند إنشائه لأول مرة:
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
.onWrite((change, context) => {
// Only edit data when it is first created.
if (change.before.exists()) {
return null;
}
// Exit when the data is deleted.
if (!change.after.exists()) {
return null;
}
// Grab the current value of what was written to the Realtime Database.
const original = change.after.val();
console.log('Uppercasing', context.params.pushId, original);
const uppercase = original.toUpperCase();
// You must return a Promise when performing asynchronous tasks inside a Functions such as
// writing to the Firebase Realtime Database.
// Setting an "uppercase" sibling in the Realtime Database returns a Promise.
return change.after.ref.parent.child('uppercase').set(uppercase);
});