كيفية استخدام Firebase API: دليل التكامل الكامل (2026)

Ashley Innocent

Ashley Innocent

23 مارس 2026

كيفية استخدام Firebase API: دليل التكامل الكامل (2026)

enterprise.banner.title

enterprise.banner.feature1

enterprise.banner.feature2

enterprise.banner.feature3

enterprise.banner.ctaB

أنت تبني تطبيقًا. يحتاج المستخدمون إلى تسجيل الدخول. يجب مزامنة البيانات في الوقت الفعلي. تحتاج الملفات إلى التخزين. يمكنك إطلاق خوادم، وتكوين قواعد بيانات، وإدارة البنية التحتية لأسابيع. أو يمكنك استخدام Firebase.

تدعم Firebase أكثر من 1.5 مليون تطبيق، بما في ذلك The New York Times، وDuolingo، وعلي بابا. يختارها المطورون لأنها تزيل تعقيد الواجهة الخلفية. أنت تركز على الميزات، وليس صيانة الخادم. ولكن واجهة برمجة تطبيقات Firebase لها بعض الغرابة. تدفقات المصادقة تربك المبتدئين. قواعد البيانات تربك المطورين ذوي الخبرة. تبدو وظائف Cloud Functions سحرية حتى تفهم المشغلات.

لقد قمت بدمج Firebase في تطبيقات إنتاج تخدم ملايين المستخدمين. لقد ارتكبت كل الأخطاء الممكنة: مفاتيح حساب الخدمة المكشوفة، استعلامات غير فعالة، وظائف معطلة. هذا الدليل يستخلص تلك الدروس.

ستتعلم المصادقة، وعمليات قواعد البيانات، ووظائف Cloud Functions، والتخزين. سترى كودًا عمليًا، وليس مجرد نظرية. ستتجنب المزالق التي تسبب مشكلات في الإنتاج.

💡
يصبح اختبار واجهات برمجة تطبيقات Firebase أسهل باستخدام أدوات عميل API المناسبة. يتيح لك Apidog تنظيم نقاط النهاية، واختبار تدفقات المصادقة، ومشاركة المجموعات مع فريقك. سنوضح أين يتناسب ذلك بشكل طبيعي في سير العمل.
زر

ما هي واجهة برمجة تطبيقات Firebase ولماذا هي مهمة؟

Firebase ليست واجهة برمجة تطبيقات واحدة. إنها مجموعة من خدمات الواجهة الخلفية التي يتم الوصول إليها من خلال مجموعات SDKs موحدة ونقاط نهاية REST.

خدمات Firebase الأساسية

الخدمة الغرض نوع واجهة برمجة التطبيقات (API)
المصادقة تسجيل دخول المستخدم والهوية SDK + REST
قاعدة بيانات Firestore قاعدة بيانات مستندات NoSQL SDK + REST
قاعدة بيانات Realtime مزامنة JSON في الوقت الفعلي SDK + REST
التخزين السحابي (Cloud Storage) تخزين الملفات وCDN SDK + REST
وظائف Cloud Functions الحوسبة بلا خادم (Serverless) واجهة سطر الأوامر (Deployment CLI)
الاستضافة (Hosting) استضافة الويب الثابتة واجهة سطر الأوامر (Deployment CLI)
الرسائل السحابية (Cloud Messaging) إشعارات الدفع (Push notifications) HTTP v1 API

متى يكون Firebase خيارًا منطقيًا

يحل Firebase مشاكل محددة بكفاءة:

استخدم Firebase عندما:

تجنب Firebase عندما:

هندسة واجهة برمجة تطبيقات Firebase

تستخدم Firebase نهجًا هجينًا:

┌─────────────────────────────────────────────────────────┐
│                    تطبيقك                                 │
├─────────────────────────────────────────────────────────┤
│  Firebase SDK (العميل)                                   │
│  - يعالج رموز المصادقة تلقائيًا                           │
│  - يدير التخزين المؤقت في وضع عدم الاتصال             │
│  - مستمعو الوقت الفعلي                                  │
└─────────────────────────────────────────────────────────┘
                          │
                          │ HTTPS + WebSocket
                          ▼
┌─────────────────────────────────────────────────────────┐
│                   واجهة Firebase الخلفية                 │
├──────────────┬──────────────┬──────────────┬────────────┤
│   خدمة        │  قاعدة بيانات│   خدمة        │  بيئة تشغيل│
│  المصادقة     │  Firestore   │   التخزين     │  الوظائف   │
└──────────────┴──────────────┴──────────────┴────────────┘

تعمل مجموعات SDKs للعميل على تجريد طبقة HTTP. تحت الغطاء، تُترجم كل عملية إلى استدعاءات REST API مع مصادقة JWT.

مصادقة Firebase: إعداد كامل

المصادقة هي أول عملية دمج لك مع Firebase. إذا أخطأت في هذا، فكل شيء آخر سيفشل.

الخطوة 1: إنشاء مشروع Firebase

  1. اذهب إلى وحدة تحكم Firebase

انقر على "إضافة مشروع" وأدخل اسم المشروع (بدون مسافات)

تفعيل Google Analytics (اختياري لكن موصى به)

انقر على "إنشاء مشروع"

انتظر 30 ثانية للتزويد. ستظهر لك لوحة تحكم المشروع.

الخطوة 2: تسجيل تطبيقك

لتطبيقات الويب:

// في Firebase Console > Project Settings > General
// انقر على "إضافة تطبيق" > أيقونة الويب

// تسجيل تطبيق الويب
const firebaseConfig = {
  apiKey: "AIzaSyDxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  authDomain: "your-app.firebaseapp.com",
  projectId: "your-app",
  storageBucket: "your-app.appspot.com",
  messagingSenderId: "123456789012",
  appId: "1:123456789012:web:abc123def456"
};

// تهيئة Firebase
import { initializeApp } from 'firebase/app';
const app = initializeApp(firebaseConfig);

لتطبيقات iOS:

قم بتنزيل GoogleService-Info.plist وأضفه إلى مشروع Xcode. تأكد من أن "Target Membership" يتضمن تطبيقك.

لتطبيقات Android:

قم بتنزيل google-services.json وضعه في مجلد app/. أضفه إلى build.gradle:

// Project-level build.gradle
buildscript {
    dependencies {
        classpath 'com.google.gms:google-services:4.4.0'
    }
}

// App-level build.gradle
plugins {
    id 'com.google.gms.google-services'
}

الخطوة 3: تمكين طرق المصادقة

في وحدة تحكم Firebase > المصادقة > طريقة تسجيل الدخول:

  1. البريد الإلكتروني/كلمة المرور: قم بتمكينها للتسجيل التقليدي
  2. Google: أضف بصمة شهادة SHA-1 الخاصة بك (Android) أو معرّف الحزمة (bundle ID) الخاص بك (iOS)
  3. Apple: مطلوب لتطبيقات iOS إذا قمت بتمكين أي تسجيل دخول اجتماعي
  4. الهاتف: قم بتمكينه للمصادقة عبر الرسائل القصيرة (يتطلب فاتورة)

الخطوة 4: تنفيذ تدفق المصادقة

التسجيل بالبريد الإلكتروني/كلمة المرور:

import {
  createUserWithEmailAndPassword,
  getAuth,
  updateProfile
} from 'firebase/auth';

const auth = getAuth(app);

async function signUp(email, password, displayName) {
  try {
    const userCredential = await createUserWithEmailAndPassword(
      auth,
      email,
      password
    );

    // تعيين اسم العرض
    await updateProfile(userCredential.user, {
      displayName: displayName
    });

    console.log('تم إنشاء المستخدم:', userCredential.user.uid);
    return userCredential.user;
  } catch (error) {
    // التعامل مع رموز الأخطاء المحددة
    switch (error.code) {
      case 'auth/email-already-in-use':
        throw new Error('هذا البريد الإلكتروني مسجل بالفعل');
      case 'auth/weak-password':
        throw new Error('يجب أن تتكون كلمة المرور من 6 أحرف على الأقل');
      case 'auth/invalid-email':
        throw new Error('عنوان بريد إلكتروني غير صالح');
      default:
        throw new Error('فشل التسجيل: ' + error.message);
    }
  }
}

تسجيل الدخول بالبريد الإلكتروني/كلمة المرور:

import {
  signInWithEmailAndPassword,
  signOut
} from 'firebase/auth';

async function signIn(email, password) {
  try {
    const userCredential = await signInWithEmailAndPassword(
      auth,
      email,
      password
    );

    const user = userCredential.user;

    // الحصول على رمز الهوية لمكالمات API
    const idToken = await user.getIdToken();
    console.log('رمز المصادقة:', idToken);

    return user;
  } catch (error) {
    switch (error.code) {
      case 'auth/user-not-found':
        throw new Error('لا يوجد حساب بهذا البريد الإلكتروني');
      case 'auth/wrong-password':
        throw new Error('كلمة مرور غير صحيحة');
      case 'auth/too-many-requests':
        throw new Error('محاولات كثيرة جدًا. حاول مرة أخرى لاحقًا');
      default:
        throw new Error('فشل تسجيل الدخول');
    }
  }
}

async function logOut() {
  await signOut(auth);
  console.log('تم تسجيل خروج المستخدم');
}

تسجيل الدخول عبر Google (الويب):

import {
  GoogleAuthProvider,
  signInWithPopup
} from 'firebase/auth';

async function signInWithGoogle() {
  const provider = new GoogleAuthProvider();

  // طلب نطاقات إضافية
  provider.addScope('email');
  provider.addScope('profile');

  try {
    const result = await signInWithPopup(auth, provider);
    const user = result.user;

    // الوصول إلى رمز OAuth من Google
    const credential = GoogleAuthProvider.credentialFromResult(result);
    const googleAccessToken = credential.accessToken;

    return user;
  } catch (error) {
    if (error.code === 'auth/popup-closed-by-user') {
      throw new Error('تم إلغاء تسجيل الدخول');
    }
    throw new Error('فشل تسجيل الدخول عبر Google');
  }
}

الخطوة 5: حماية المسارات بحالة المصادقة

import { onAuthStateChanged } from 'firebase/auth';

// الاشتراك في تغييرات حالة المصادقة
onAuthStateChanged(auth, (user) => {
  if (user) {
    // المستخدم مسجل الدخول
    console.log('المستخدم:', user.email);
    // إعادة التوجيه إلى لوحة التحكم
    window.location.href = '/dashboard';
  } else {
    // المستخدم غير مسجل الدخول
    console.log('لا يوجد مستخدم');
    // إعادة التوجيه إلى صفحة تسجيل الدخول
    window.location.href = '/login';
  }
});

أخطاء المصادقة الشائعة

الخطأ 1: عدم التعامل مع تحديث الرمز المميز (token refresh)

يقوم Firebase SDK بتحديث الرموز المميزة تلقائيًا. ولكن إذا قمت بتخزين الرموز المميزة مؤقتًا في جانب الخادم، فإنها تنتهي صلاحيتها بعد ساعة واحدة. قم دائمًا بالتحقق من الرموز المميزة في كل طلب أو قم بتنفيذ منطق التحديث.

الخطأ 2: كشف بيانات اعتماد المشرف في كود العميل

لا تستخدم أبدًا مفاتيح حساب الخدمة في تطبيقات العميل. تتجاوز حسابات الخدمة قواعد الأمان. استخدمها فقط في بيئات الخادم الموثوقة.

الخطأ 3: تخطي التحقق من البريد الإلكتروني

import { sendEmailVerification } from 'firebase/auth';

async function sendVerificationEmail(user) {
  await sendEmailVerification(user);
  console.log('تم إرسال بريد التحقق');
}

// التحقق من حالة التحقق
if (!auth.currentUser.emailVerified) {
  console.log('البريد الإلكتروني غير متحقق');
  // تقييد الوصول
}

قاعدة بيانات Firestore: العمليات والاستعلامات

Firestore هي قاعدة بيانات NoSQL من Firebase. تُنظّم المستندات في مجموعات. تتوسع الاستعلامات تلقائيًا.

هيكل البيانات

your-project (الجذر)
└── users (مجموعة)
    ├── userId123 (مستند)
    │   ├── name: "John"
    │   ├── email: "john@example.com"
    │   └── posts (مجموعة فرعية)
    │       ├── postId1 (مستند)
    │       └── postId2 (مستند)
    └── userId456 (مستند)

تهيئة Firestore

import { getFirestore } from 'firebase/firestore';

const db = getFirestore(app);

إنشاء المستندات

import {
  collection,
  addDoc,
  setDoc,
  doc
} from 'firebase/firestore';

// الخيار 1: معرف يتم إنشاؤه تلقائيًا
async function createUser(userData) {
  const docRef = await addDoc(collection(db, 'users'), userData);
  console.log('تم كتابة المستند بالمعرف:', docRef.id);
  return docRef.id;
}

// الخيار 2: معرف مخصص
async function createUserWithId(userId, userData) {
  await setDoc(doc(db, 'users', userId), userData);
  console.log('تم كتابة المستند بمعرف مخصص:', userId);
}

// الاستخدام
const userId = await createUser({
  name: 'Alice',
  email: 'alice@example.com',
  createdAt: new Date(),
  role: 'user'
});

قراءة المستندات

import {
  getDoc,
  getDocs,
  query,
  where,
  orderBy,
  limit
} from 'firebase/firestore';

// الحصول على مستند واحد
async function getUser(userId) {
  const docRef = doc(db, 'users', userId);
  const docSnap = await getDoc(docRef);

  if (docSnap.exists()) {
    return docSnap.data();
  } else {
    throw new Error('المستخدم غير موجود');
  }
}

// استعلام مع الفلاتر
async function getUsersByRole(role) {
  const q = query(
    collection(db, 'users'),
    where('role', '==', role),
    orderBy('createdAt', 'desc'),
    limit(10)
  );

  const querySnapshot = await getDocs(q);
  const users = [];

  querySnapshot.forEach((doc) => {
    users.push({ id: doc.id, ...doc.data() });
  });

  return users;
}

// الاستخدام
const adminUsers = await getUsersByRole('admin');
console.log('المستخدمون المشرفون:', adminUsers);

تحديث المستندات

import {
  updateDoc,
  increment,
  arrayUnion,
  arrayRemove
} from 'firebase/firestore';

async function updateUser(userId, updates) {
  const userRef = doc(db, 'users', userId);
  await updateDoc(userRef, updates);
}

// العمليات الذرية
await updateUser('userId123', {
  loginCount: increment(1),
  tags: arrayUnion('premium', 'beta-tester'),
  lastLogin: new Date()
});

// إزالة من المصفوفة
await updateUser('userId123', {
  tags: arrayRemove('beta-tester')
});

حذف المستندات

import { deleteDoc } from 'firebase/firestore';

async function deleteUser(userId) {
  await deleteDoc(doc(db, 'users', userId));
  console.log('تم حذف المستخدم');
}

مستمعو الوقت الفعلي

import { onSnapshot } from 'firebase/firestore';

// الاستماع إلى مستند واحد
const unsubscribe = onSnapshot(
  doc(db, 'users', userId),
  (doc) => {
    console.log('تم تحديث المستخدم:', doc.data());
  },
  (error) => {
    console.error('خطأ في الاستماع:', error);
  }
);

// الاستماع إلى نتائج الاستعلام
const q = query(collection(db, 'posts'), where('published', '==', true));

const unsubscribeQuery = onSnapshot(q, (snapshot) => {
  const posts = snapshot.docs.map(doc => ({
    id: doc.id,
    ...doc.data()
  }));
  console.log('المنشورات المنشورة:', posts);
});

// إيقاف الاستماع
unsubscribe();
unsubscribeQuery();

قواعد أمان Firestore

بدون قواعد مناسبة، يمكن لأي شخص قراءة بياناتك. قم بتعيين القواعد في Firebase Console > Firestore > Rules:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    // دالة مساعدة
    function isAuthenticated() {
      return request.auth != null;
    }

    function isOwner(userId) {
      return request.auth.uid == userId;
    }

    // مجموعة المستخدمين
    match /users/{userId} {
      allow read: if isAuthenticated();
      allow create: if isAuthenticated() && isOwner(userId);
      allow update, delete: if isOwner(userId);
    }

    // مجموعة المنشورات
    match /posts/{postId} {
      allow read: if true; // قراءة عامة
      allow create: if isAuthenticated();
      allow update, delete: if resource.data.authorId == request.auth.uid;
    }

    // مجموعة فرعية خاصة
    match /users/{userId}/private/{document} {
      allow read, write: if isOwner(userId);
    }
  }
}

قيود الاستعلام

Firestore لديه قيود:

حل بديل لاستعلامات OR:

// بدلاً من: where('status', '==', 'active') OR where('status', '==', 'pending')

const activeQuery = query(
  collection(db, 'tasks'),
  where('status', '==', 'active')
);

const pendingQuery = query(
  collection(db, 'tasks'),
  where('status', '==', 'pending')
);

const [activeSnap, pendingSnap] = await Promise.all([
  getDocs(activeQuery),
  getDocs(pendingQuery)
]);

// دمج النتائج في العميل

وظائف Cloud Functions: منطق الواجهة الخلفية بلا خادم

تُشغل وظائف Cloud Functions كود الواجهة الخلفية دون إدارة الخوادم. يتم تشغيلها بناءً على تغييرات قاعدة البيانات، طلبات HTTP، أو الأحداث المجدولة.

الإعداد

# تثبيت Firebase CLI
npm install -g firebase-tools

# تسجيل الدخول
firebase login

# تهيئة الوظائف في مشروعك
firebase init functions

# اختر: JavaScript, ESLint نعم, Express.js لا

وظائف HTTP (نقاط نهاية API)

// functions/index.js
const { onRequest } = require('firebase-functions/v2/https');
const admin = require('firebase-admin');

admin.initializeApp();
const db = admin.firestore();

// نقطة نهاية عامة
exports.getPublicData = onRequest(async (req, res) => {
  res.set('Access-Control-Allow-Origin', '*');

  try {
    const snapshot = await db.collection('public').get();
    const data = snapshot.docs.map(doc => doc.data());
    res.json({ success: true, data });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// نقطة نهاية محمية (التحقق من رمز المصادقة)
exports.getUserProfile = onRequest(async (req, res) => {
  res.set('Access-Control-Allow-Origin', '*');

  // الحصول على الرمز المميز من رأس Authorization
  const authHeader = req.headers.authorization || '';
  const token = authHeader.split('Bearer ')[1];

  if (!token) {
    return res.status(401).json({ error: 'غير مصرح به' });
  }

  try {
    // التحقق من الرمز المميز
    const decodedToken = await admin.auth().verifyIdToken(token);
    const userId = decodedToken.uid;

    // الحصول على بيانات المستخدم
    const userDoc = await db.collection('users').doc(userId).get();

    if (!userDoc.exists) {
      return res.status(404).json({ error: 'المستخدم غير موجود' });
    }

    res.json({
      success: true,
      data: { id: userId, ...userDoc.data() }
    });
  } catch (error) {
    res.status(401).json({ error: 'رمز مميز غير صالح' });
  }
});

النشر:

firebase deploy --only functions:getUserProfile

الاستدعاء من العميل:

async function getUserProfile(token) {
  const response = await fetch(
    'https://us-central1-your-app.cloudfunctions.net/getUserProfile',
    {
      headers: {
        'Authorization': `Bearer ${token}`
      }
    }
  );

  const data = await response.json();
  return data;
}

مشغلات قاعدة البيانات

const { onDocumentWritten } = require('firebase-functions/v2/firestore');

// التشغيل عند تغيير مستند المستخدم
exports.onUserUpdate = onDocumentWritten(
  'users/{userId}',
  async (event) => {
    const userId = event.params.userId;
    const before = event.data?.before?.data();
    const after = event.data?.after?.data();

    // التحقق مما إذا كان البريد الإلكتروني قد تغير
    if (before?.email !== after?.email) {
      console.log(`تم تغيير بريد المستخدم ${userId}: ${before?.email} ← ${after?.email}`);

      // إرسال بريد إلكتروني للإشعار
      await admin.auth().getUser(userId);
      // أضف منطق بريدك الإلكتروني هنا
    }
  }
);

// التشغيل عند إنشاء منشور جديد
exports.onNewPost = onDocumentWritten(
  'posts/{postId}',
  async (event) => {
    const post = event.data?.after?.data();

    if (!post) return; // تم حذف المستند

    // التحقق مما إذا كان هذا مستندًا جديدًا
    if (!event.data?.before?.exists) {
      console.log('تم إنشاء منشور جديد:', post.title);

      // إشعار المتابعين
      const followersSnap = await admin.firestore()
        .collection('users')
        .where('following', 'array-contains', post.authorId)
        .get();

      const notifications = followersSnap.docs.map(doc => ({
        userId: doc.id,
        postId: event.params.postId,
        type: 'new_post',
        createdAt: admin.firestore.FieldValue.serverTimestamp()
      }));

      const batch = admin.firestore().batch();
      notifications.forEach(notif => {
        const ref = admin.firestore().collection('notifications').doc();
        batch.set(ref, notif);
      });

      await batch.commit();
    }
  }
);

الوظائف المجدولة (مهام Cron)

const { onSchedule } = require('firebase-functions/v2/scheduler');

// تشغيل كل يوم عند منتصف الليل بالتوقيت العالمي المنسق (UTC)
exports.dailyCleanup = onSchedule('every 24 hours', async (event) => {
  console.log('تشغيل عملية التنظيف اليومية');

  // حذف الإشعارات القديمة (أكثر من 30 يومًا)
  const thirtyDaysAgo = new Date();
  thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);

  const oldNotifs = await admin.firestore()
    .collection('notifications')
    .where('createdAt', '<', thirtyDaysAgo)
    .get();

  const batch = admin.firestore().batch();
  oldNotifs.forEach(doc => batch.delete(doc.ref));
  await batch.commit();

  console.log(`تم حذف ${oldNotifs.size} إشعارات قديمة`);
});

تهيئة البيئة

# تعيين متغيرات البيئة
firebase functions:config:set \
  stripe.secret="sk_test_xxx" \
  email.api_key="key_xxx"

# الوصول في الوظائف
const config = require('firebase-functions/config');
const stripe = require('stripe')(config.stripe.secret);

التخزين السحابي: تحميل الملفات وإدارتها

قم بتخزين ملفات المستخدمين المحملة والصور والملفات مع التوزيع التلقائي عبر شبكة CDN.

إعداد قواعد التخزين

// Firebase Console > Storage > Rules
rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {

    // مجلد تحميلات المستخدم
    match /users/{userId}/{allPaths=**} {
      allow read: if true; // قراءة عامة
      allow write: if request.auth.uid == userId;
      allow delete: if request.auth.uid == userId;
    }

    // أصول عامة
    match /public/{allPaths=**} {
      allow read: if true;
      allow write: if false; // للمشرفين فقط عبر Firebase Console
    }
  }
}

تحميل الملفات (العميل)

import {
  getStorage,
  ref,
  uploadBytesResumable,
  getDownloadURL
} from 'firebase/storage';

const storage = getStorage(app);

async function uploadProfileImage(userId, file) {
  // إنشاء مرجع التخزين
  const storageRef = ref(storage, `users/${userId}/profile/${file.name}`);

  // تحميل الملف
  const uploadTask = uploadBytesResumable(storageRef, file);

  return new Promise((resolve, reject) => {
    uploadTask.on(
      'state_changed',
      (snapshot) => {
        // تتبع التقدم
        const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
        console.log(`التحميل: ${progress.toFixed(0)}%`);
      },
      (error) => {
        // معالجة الأخطاء
        switch (error.code) {
          case 'storage/unauthorized':
            reject(new Error('ليس لديك إذن'));
            break;
          case 'storage/canceled':
            reject(new Error('تم إلغاء التحميل'));
            break;
          default:
            reject(new Error('فشل التحميل'));
        }
      },
      async () => {
        // اكتمل التحميل
        const downloadURL = await getDownloadURL(uploadTask.snapshot.ref);
        console.log('الملف متاح على:', downloadURL);
        resolve(downloadURL);
      }
    );
  });
}

// الاستخدام
const fileInput = document.querySelector('input[type="file"]');
const file = fileInput.files[0];

if (file) {
  const imageUrl = await uploadProfileImage(auth.currentUser.uid, file);

  // حفظ الرابط إلى Firestore
  await updateDoc(doc(db, 'users', auth.currentUser.uid), {
    profileImage: imageUrl
  });
}

تنزيل الملفات

import { getDownloadURL } from 'firebase/storage';

async function getProfileImage(userId) {
  const imageRef = ref(storage, `users/${userId}/profile/avatar.png`);

  try {
    const url = await getDownloadURL(imageRef);
    return url;
  } catch (error) {
    if (error.code === 'storage/object-not-found') {
      return null; // لا توجد صورة ملف شخصي
    }
    throw error;
  }
}

حذف الملفات

import { deleteObject } from 'firebase/storage';

async function deleteProfileImage(userId) {
  const imageRef = ref(storage, `users/${userId}/profile/avatar.png`);
  await deleteObject(imageRef);
  console.log('تم حذف صورة الملف الشخصي');
}

اختبار واجهات برمجة تطبيقات Firebase باستخدام Apidog

توفر Firebase واجهات برمجة تطبيقات REST لجميع الخدمات. يساعد اختبارها مباشرة في تصحيح الأخطاء وفهم الطلبات الأساسية.

استيراد Firebase REST API

  1. افتح Apidog
  2. أنشئ مشروعًا جديدًا: "Firebase API"
  3. استورد مواصفات OpenAPI من وثائق Firebase
  4. أو أضف نقاط النهاية يدويًا:

نقطة نهاية Firestore REST:

POST https://firestore.googleapis.com/v1/projects/{projectId}/databases/(default)/documents
Authorization: Bearer {oauth2_token}
Content-Type: application/json

{
  "fields": {
    "name": { "stringValue": "John" },
    "email": { "stringValue": "john@example.com" },
    "age": { "integerValue": 30 }
  }
}

نقطة نهاية المصادقة:

POST https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key={api_key}
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "secret123",
  "returnSecureToken": true
}

اختبار تدفق المصادقة

  1. أنشئ طلبًا: "تسجيل الدخول"
  2. عيّن الطريقة: POST
  3. أضف البريد الإلكتروني/كلمة المرور في الجسم
  4. احفظ رمز الاستجابة كمتغير بيئة
  5. استخدم {{token}} في الطلبات اللاحقة

تصحيح أخطاء قواعد الأمان

استخدم Firebase Emulator Suite للاختبار المحلي:

# تشغيل المحاكي
firebase emulators:start

# الاختبار مقابل Firestore المحلي
# http://localhost:8080

أفضل ممارسات الإنتاج

1. تنفيذ معالجة الأخطاء المناسبة

// منطق إعادة المحاولة للأعطال العابرة
async function firestoreWithRetry(operation, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await operation();
    } catch (error) {
      if (
        error.code === 'unavailable' ||
        error.code === 'deadline-exceeded'
      ) {
        const delay = Math.pow(2, i) * 1000; // تراجع أسي
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }
      throw error;
    }
  }
}

2. تحسين أداء الاستعلام

أضف فهارس مركبة للاستعلامات متعددة الحقول:

// هذا الاستعلام يحتاج إلى فهرس مركب
const q = query(
  collection(db, 'posts'),
  where('category', '==', 'tech'),
  where('views', '>', 1000),
  orderBy('views', 'desc')
);

تطلب منك Firestore إنشاء الفهرس مع رابط مباشر عند تشغيل هذا الاستعلام.

3. عمليات الدفعة (Batch Operations)

import { writeBatch } from 'firebase/firestore';

async function bulkUpdate(userIds, updates) {
  const batch = writeBatch(db);

  userIds.forEach(id => {
    const ref = doc(db, 'users', id);
    batch.update(ref, updates);
  });

  await batch.commit();
  console.log(`تم تحديث ${userIds.length} مستخدمًا`);
}

// الحد الأقصى 500 عملية في الدفعة الواحدة

4. مراقبة التكاليف

تسعير Firebase:

الخدمة الفئة المجانية المدفوعة
Firestore 50 ألف قراءة/يوم 0.036 دولار/100 ألف قراءة
التخزين 5 جيجابايت 0.023 دولار/جيجابايت
الوظائف 2 مليون استدعاء 0.40 دولار/مليون
المصادقة 10 آلاف/شهر 0.0055 دولار/100 ألف

عيّن تنبيهات الميزانية في Google Cloud Console.

5. تأمين حسابات الخدمة

// خطأ: لا تفعل هذا أبدًا في كود العميل
admin.initializeApp({
  credential: admin.credential.cert(require('./serviceAccountKey.json'))
});

// صحيح: استخدم في بيئة الخادم فقط
const serviceAccount = JSON.parse(process.env.FIREBASE_SERVICE_ACCOUNT);
admin.initializeApp({
  credential: admin.credential.cert(serviceAccount)
});

6. التعامل مع سيناريوهات عدم الاتصال

// تمكين استمرارية وضع عدم الاتصال (الويب)
import { enableMultiTabIndexedDbPersistence } from 'firebase/firestore';

enableMultiTabIndexedDbPersistence(db)
  .catch((err) => {
    if (err.code === 'failed-precondition') {
      // علامات تبويب متعددة مفتوحة
    } else if (err.code === 'unimplemented') {
      // المتصفح لا يدعم
    }
  });

// الاستماع إلى الاتصال بالشبكة
import { onSnapshot } from 'firebase/firestore';

onSnapshot(doc(db, 'status', 'online'), (doc) => {
  if (!doc.exists()) {
    console.log('أنت غير متصل بالإنترنت');
    // عرض واجهة المستخدم لعدم الاتصال
  }
});

مشكلات وحلول واجهة برمجة تطبيقات Firebase الشائعة

المشكلة 1: أخطاء رفض الإذن

العرض: Error: 7 PERMISSION_DENIED

السبب: قواعد الأمان تمنع العملية

الحل:

  1. تحقق من القواعد في Firebase Console
  2. تحقق مما إذا كان request.auth.uid يطابق المستخدم المتوقع
  3. اختبر القواعد باستخدام Rules Playground

المشكلة 2: انتهاء صلاحية الرمز المميز

العرض: Error: ID token expired

الحل:

// فرض تحديث الرمز المميز
const user = auth.currentUser;
if (user) {
  await user.getIdToken(true); // فرض التحديث
}

المشكلة 3: تأخر بدء التشغيل البارد

العرض: تستغرق وظائف Cloud Functions من 2 إلى 5 ثوانٍ في أول استدعاء

الحل:

// حافظ على دفء الوظائف باستخدام عمليات ping المجدولة
exports.keepWarm = onSchedule('every 60 seconds', async () => {
  await fetch('https://your-function.cloudfunctions.net/health');
});

المشكلة 4: الاستعلام يعيد نتائج فارغة

العرض: يجب أن يعيد الاستعلام بيانات ولكنه يعيد مصفوفة فارغة

السبب: فهرس مفقود أو ترتيب حقول خاطئ

الحل: تحقق من Firebase Console > Indexes بحثًا عن الفهارس المركبة المطلوبة.

حالات الاستخدام الواقعية

تطبيق التكنولوجيا المالية: تحديثات المعاملات في الوقت الفعلي

استخدمت شركة ناشئة في مجال المدفوعات Firebase Firestore لإنشاء إشعارات المعاملات في الوقت الفعلي. عندما تتم معالجة الدفعة، تقوم Cloud Functions بتشغيل تحديثات لجميع لوحات تحكم المشرفين المتصلة في غضون 200 مللي ثانية. النتيجة: انخفاض بنسبة 40٪ في تذاكر الدعم المتعلقة بالمعاملات "المعلقة".

التجارة الإلكترونية: مزامنة المخزون

يقوم بائع تجزئة عبر الإنترنت بمزامنة المخزون عبر الويب و iOS و Android باستخدام مستمعي Firestore. عندما يتغير المخزون، يتم تحديث جميع العملاء تلقائيًا. تضمن استمرارية وضع عدم الاتصال أن يتمكن عمال المستودعات من مسح العناصر ضوئيًا دون اتصال، مع المزامنة التلقائية عند إعادة الاتصال.

SaaS: مصادقة متعددة المستأجرين

تستخدم منصة B2B مصادقة Firebase مع مطالبات مخصصة للوصول المستند إلى الأدوار. يحصل المستخدمون المسؤولون على أذونات مرتفعة عبر Cloud Functions التي تتحقق من صحة تكوينات المستأجرين في Firestore. قاعدة بيانات واحدة تخدم أكثر من 500 مؤسسة ببيانات معزولة.

الخاتمة

يتضمن دمج Firebase API أربع خدمات أساسية:

لقد تعلمت تدفقات المصادقة، وعمليات قواعد البيانات، ونشر الوظائف، وإدارة الملفات. لقد رأيت أنماط الإنتاج: معالجة الأخطاء، المعالجة الدفعية، دعم عدم الاتصال، والأمان.

زر

الأسئلة الشائعة

هل Firebase مجاني للاستخدام؟

نعم، لدى Firebase طبقة مجانية سخية (خطة Spark) تتضمن 5 جيجابايت من التخزين، 50 ألف قراءة يوميًا من Firestore، 2 مليون استدعاء لوظائف Cloud Functions، و 10 آلاف مستخدم للمصادقة شهريًا. تستخدم الخطط المدفوعة (Blaze) تسعير الدفع حسب الاستخدام.

هل يمكنني استخدام Firebase مع قواعد البيانات الموجودة؟

نعم. استخدم Firebase Extensions للمزامنة مع PostgreSQL، MySQL، أو MongoDB. أو قم باستدعاء واجهات برمجة تطبيقات خارجية من Cloud Functions للدمج مع الأنظمة الموجودة.

كيف يمكنني الترحيل من Firebase إلى منصة أخرى؟

قم بتصدير البيانات باستخدام وظائف تصدير Firestore أو Firebase CLI. لمجموعات البيانات الكبيرة، استخدم مسار تصدير Dataflow. تعتمد تعقيد عملية الترحيل على هيكل بياناتك.

هل Firebase يدعم GraphQL؟

ليس بشكل أساسي. استخدم حلولًا خارجية مثل firestore-graphql أو قم ببناء طبقة GraphQL باستخدام Cloud Functions و Apollo Server.

هل يمكنني استخدام Firebase محليًا؟

لا. Firebase يعمل فقط على Google Cloud. للبدائل المستضافة ذاتيًا، فكر في Appwrite، Supabase، أو Nhost.

كيف أتعامل مع تحميل الملفات التي يزيد حجمها عن 100 ميجابايت؟

استخدم التحميلات القابلة للاستئناف مع التقطيع. يتعامل Firebase SDK مع هذا تلقائيًا. للملفات الكبيرة جدًا، استخدم Google Cloud Storage مباشرة مع عناوين URL الموقعة.

ماذا يحدث إذا تجاوزت حدود استعلام Firestore؟

تفشل الاستعلامات بخطأ FAILED_PRECONDITION. أضف الفهارس المطلوبة أو أعد هيكلة الاستعلامات. توفر Firestore روابط مباشرة لإنشاء الفهارس المفقودة في رسالة الخطأ.

هل Firebase متوافق مع اللائحة العامة لحماية البيانات (GDPR)؟

نعم، تقدم Firebase معالجة بيانات متوافقة مع اللائحة العامة لحماية البيانات (GDPR). قم بتمكين مكان إقامة البيانات في مناطق محددة، وقم بتنفيذ تصدير/حذف بيانات المستخدم، ووقع على تعديل معالجة البيانات من Google.

ممارسة تصميم API في Apidog

اكتشف طريقة أسهل لبناء واستخدام واجهات برمجة التطبيقات