تخطَّ إلى المحتوى

📱 شرح Flutter

Firebase وFirestore

الدرس 26 من 28· ⏱ 2 دقائق قراءة

لماذا Firebase؟

بناء خادم خلفي (Backend) كامل يستهلك وقتًا كبيرًا. Firebase (من Google) يوفّر خدمات جاهزة: مصادقة مستخدمين، قاعدة بيانات سحابية فورية (Firestore)، تخزين ملفات، وإشعارات — كلها بدون كتابة سطر خادم واحد.

الإعداد الأساسي

flutter pub add firebase_core cloud_firestore firebase_auth
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart'; // يُولَّد تلقائيًا بأداة flutterfire configure

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  runApp(MyApp());
}

Firestore — قاعدة بيانات NoSQL فورية

Firestore تخزّن البيانات كـ مستندات (Documents) داخل مجموعات (Collections) — شبيهة بمجلدات وملفات JSON. أهم ميزة: التحديثات فورية (Real-time) بدون تحديث الصفحة يدويًا.

إضافة مستند:

import 'package:cloud_firestore/cloud_firestore.dart';

Future<void> addTask(String title) async {
  await FirebaseFirestore.instance.collection('tasks').add({
    'title': title,
    'done': false,
    'createdAt': FieldValue.serverTimestamp(),
  });
}

قراءة فورية (Stream) — أهم فرق عن قاعدة بيانات تقليدية:

StreamBuilder<QuerySnapshot>(
  stream: FirebaseFirestore.instance
      .collection('tasks')
      .orderBy('createdAt', descending: true)
      .snapshots(), // .snapshots() تدفّق مستمر، لا get() لمرة واحدة
  builder: (context, snapshot) {
    if (!snapshot.hasData) return CircularProgressIndicator();

    final docs = snapshot.data!.docs;
    return ListView.builder(
      itemCount: docs.length,
      itemBuilder: (context, i) {
        final data = docs[i].data() as Map<String, dynamic>;
        return CheckboxListTile(
          title: Text(data['title']),
          value: data['done'],
          onChanged: (v) => docs[i].reference.update({'done': v}),
        );
      },
    );
  },
)

كل تغيير بقاعدة البيانات (من أي جهاز) ينعكس فورًا بكل الشاشات المفتوحة — StreamBuilder يعيد البناء تلقائيًا عند وصول بيانات جديدة.

Firebase Authentication

import 'package:firebase_auth/firebase_auth.dart';

Future<User?> signUp(String email, String password) async {
  try {
    final credential = await FirebaseAuth.instance
        .createUserWithEmailAndPassword(email: email, password: password);
    return credential.user;
  } on FirebaseAuthException catch (e) {
    print('خطأ تسجيل: ${e.message}');
    return null;
  }
}

// مراقبة حالة تسجيل الدخول بأي وقت
StreamBuilder<User?>(
  stream: FirebaseAuth.instance.authStateChanges(),
  builder: (context, snapshot) {
    if (snapshot.hasData) return HomeScreen();
    return LoginScreen();
  },
)

عمليات CRUD الأساسية

final tasksRef = FirebaseFirestore.instance.collection('tasks');

await tasksRef.add({'title': 'مهمة جديدة'});           // إنشاء
await tasksRef.doc(id).update({'done': true});          // تعديل
await tasksRef.doc(id).delete();                        // حذف
final snapshot = await tasksRef.doc(id).get();           // قراءة مرة واحدة

جدول سريع

المفهومالغرض
Collectionمجموعة مستندات (شبيه بجدول)
Documentسجل بيانات واحد (شبيه بصف/JSON)
.snapshots()تدفّق فوري يُحدَّث تلقائيًا عند تغيّر البيانات
.get()قراءة لمرة واحدة، بلا تحديث فوري لاحق
StreamBuilderويدجت Flutter يعيد البناء تلقائيًا عند وصول بيانات جديدة

أخطاء شائعة

  • استخدام .get() بدل .snapshots() بشاشة تحتاج تحديثًا فوريًا — تحصل على بيانات لحظة الطلب فقط، لا تحديثات لاحقة.
  • نسيان قواعد أمان Firestore (Security Rules) وترك القاعدة مفتوحة للجميع — ثغرة أمنية خطيرة بالتطبيقات الحقيقية.
  • عدم التعامل مع حالة !snapshot.hasData بـ StreamBuilder — يسبب أخطاء عند محاولة قراءة بيانات لم تصل بعد.

🎯 التالي: نمط BLoC — إدارة حالة احترافية وقابلة للاختبار لتطبيقات كبيرة.

شرح Firebase وFirestore — Flutter بالعربي
Firebase وFirestoreFlutter بالعربي · The Code Fix

📚 لمزيد من التعمّق في Flutter، راجِع التوثيق الرسمي لـ Flutter.

هل كان هذا الدرس مفيدًا؟