بنية النظام
تُقدّم هذه الصفحة تعمّقًا في كيفية بناء FeedbackPulse SaaS. يساعدك فهم البنية على تصحيح الأخطاء وتوسيع المنصة واتخاذ قرارات نشر مدروسة.
مكدس التقنيات
| الطبقة | التقنية | الغرض |
|---|---|---|
| الخلفية | Laravel 12 (PHP 8.4+) | إطار التطبيق، والتوجيه، وORM، وقائمة الانتظار |
| قاعدة البيانات | MySQL 8.0+ / MariaDB 10.6+ | التخزين الدائم للبيانات |
| الواجهة الأمامية | Blade + Alpine.js + Tailwind CSS | واجهة مستخدم مُصيَّرة من الخادم مع مكونات تفاعلية |
| المدفوعات | Stripe PHP SDK + PayPal REST API | فوترة الاشتراكات |
| الذكاء الاصطناعي | OpenAI GPT API | تحليل المشاعر، الوسوم التلقائية، اقتراحات الردود |
| المصادقة | Laravel Socialite | Google & GitHub OAuth |
| البريد الإلكتروني | Laravel Mail (SMTP) | رسائل بريد تحويلية، ملخصات، تقارير |
| الوقت الفعلي | Server-Sent Events (SSE) | بث التقديمات الحية |
| جدولة المهام | Laravel Scheduler (cron) | الملخصات، انتهاء صلاحية التجربة، الاحتفاظ بالبيانات |
نموذج تعدد المستأجرين
يستخدم FeedbackPulse نموذج تعدد مستأجرين بـ قاعدة بيانات واحدة ومخطط مشترك. هذا يعني:
- قاعدة بيانات واحدة تخدم جميع المستأ جرين
- كل جدول خاص بالمستأجر لديه عمود
tenant_id - نطاق عام (
TenantScope) يُصفّي تلقائيًا جميع الاستعلامات للمستأجر الحالي - سمة (
BelongsToTenant) تملأtenant_idتلقائيًا عند الإنشاء وتُطبّق النطاق
كيف يعمل تحديد المستأجر
عند ورود طلب، يُحدّد برنامج الوسيط ResolveTenant المستأجر الحالي بهذا الترتيب:
- النطاق الفرعي —
acme.yourdomain.com← يبحث عن المستأجر بالنطاق الفرعي "acme" - النطاق المخصص —
feedback.acmecorp.com← يبحث عن نطاق موثَّق في جدولtenant_domains - المستخدم المصادق — يعود إلى
tenant_idالخاص بالمستخدم المسجّل دخوله
بالنسبة للصفحات العامة (مثل /wall/acme-corp)، يُحدَّد المستأجر من slug في URL مباشرةً في المتحكم (متجاوزًا برنامج الوسيط).
عزل البيانات
+------------------------------------------+
| قاعدة البيانات |
| |
| products (tenant_id = 1) -> بيانات Acme |
| products (tenant_id = 2) -> TechCorp |
| products (tenant_id = 3) -> E-Commerce |
| |
| يضمن TenantScope أن Acme يرى فقط |
| الصفوف التي tenant_id = 1 |
+------------------------------------------+
الأمان: تستخدم المتحكمات العامة
withoutGlobalScopes()لتجاوز ن طاق المستأجر، ثم تُصفّي يدويًا بمعرف المستأجر. هذا مقصود — تحتاج الصفحات العامة إلى إظهار البيانات دون جلسة مصادقة.
هيكل الدليل
feedbackpulse-saas/
+-- app/
| +-- Console/Commands/ # 7 أوامر artisan (ملخصات، الاحتفاظ، التنبيهات)
| +-- Http/
| | +-- Controllers/
| | | +-- Admin/ # متحكمات لوحة المشرف العام
| | | +-- Auth/ # تسجيل الدخول، التسجيل، 2FA، OAuth، انتحال الهوية
| | | +-- Customer/ # بوابة العملاء
| | | +-- Public/ # الصفحات العامة (wall، form، roadmap، changelog، hub)
| | | +-- Tenant/ # متحكمات لوحة تحكم المستأجر
| | | +-- Webhooks/ # معالجات Stripe وPayPal webhook
| | +-- Middleware/ # 15 برنامج وسيط مخصص
| +-- Mail/ # 7 فئات بريد قابلة للإرسال
| +-- Models/ # 28 نموذج Eloquent
| +-- Scopes/ # TenantScope (نطاق استعلام عام)
| +-- Services/ # منطق الأعمال (AI، مدفوعات، webhooks، إلخ)
| +-- Traits/ # سمة BelongsToTenant
| +-- Providers/ # مزودو الخدمة
+-- config/ # 11 ملف إعداد Laravel
+-- database/
| +-- migrations/ # 35+ ملف ترحيل
| +-- seeders/ # بذور البيانات التجريبية
+-- public/ # جذر الويب (index.php، الأصول، الرابط الرمزي للتخزين)
+-- resources/views/ # 86 قالب Blade
| +-- admin/ # عروض المشرف العام
| +-- auth/ # عروض المصادقة (تسجيل دخول، تسجيل، 2FA)
| +-- tenant/ # عروض لوحة تحكم المستأجر
| +-- public/ # عروض الصفحات العامة
| +-- emails/ # قوالب البريد الإلكتروني
| +-- layouts/ # قوالب التخطيط (admin، tenant، guest، install)
| +-- partials/ # المكونات المشتركة (nav، meta، لوحة الأوامر)
| +-- install/ # عروض مثبّت الويب
| +-- legal/ # صفحات الخصوصية والشروط وملفات تعريف الارتباط
| +-- errors/ # صفحات الأخطاء (403، 404، 419، 429، 500)
| +-- landing/ # أجزاء صفحة الهبوط
+-- routes/
| +-- web.php # 416 سطر من مسارات الويب
| +-- api.php # مسارات API v2
+-- storage/ # الرفعات، الذاكرة المؤقتة، الجلسات، السجلات
+-- bootstrap/ # ملفات تشغيل الإطار
أدوار المستخدمين
يمتلك FeedbackPulse أربعة أدوار للمستخدمين، مُخزَّنة في عمود users.role:
| الدور | الوصول | رابط تسجيل الدخول |
|---|---|---|
superadmin | تحكم كامل في المنصة (/admin/*) | /login |
tenant_admin | تحكم كامل في المستأجر (/dashboard، /settings/*) | /login |
tenant_staff | وصول محدود للمستأجر (بدون فوترة، بدون حذف) | /login |
customer | بوابة العميل فقط (/customer/dashboard) | /customer/login |
تسلسل الأدوار
superadmin
+-- يمكنه انتحال هوية أي tenant_admin
+-- tenant_admin
+-- يمكنه دعوة tenant_staff
+-- يمكنه إدارة الفوترة والإعدادات والفريق
+-- tenant_staff
+-- يمكنه إدارة التقديمات والحملات
+-- customer
+-- يمكنه عرض ملاحظاته الخاصة
دورة حياة الطلب
إليك ما يحدث عند وصول طلب إلى FeedbackPulse:
طلب المتصفح
|
v
public/index.php
|
v
Laravel Kernel (مكدس برامج الوسيط)
|
+-- EnsureInstalled -> إعادة التوجيه إلى /install إذا لم يُعدَّ
+-- SecurityHeaders -> إضافة HSTS وCSP وX-Frame-Options
+-- VerifyCsrfToken -> التحقق من رمز CSRF (ما عدا webhooks)
+-- ResolveTenant -> تحديد المستأجر الحالي
+-- Authenticate -> التحقق من تسجيل دخول المستخدم
+-- EnsureTenantAccess -> التحقق من انتماء المستخدم للمستأجر
+-- EnsureTwoFactorVerified -> التحقق من 2FA إذا كان مفعّلاً
+-- CheckPlanLimit -> تطبيق حدود ميزات الخطة
|
v
المتحكم (معالجة الطلب)
|
v
عرض Blade (تصيير HTML)
|
v
الاستجابة -> المتصفح
بنية قاعدة البيانات
الجداول الأساسية
| الجدول | الصفوف لكل | الغرض |
|---|---|---|
tenants | المنصة | حسابات متعددة المستأجرين |
users | المنصة | جميع حسابات المستخدمين (جميع الأدوار) |
plans | المنصة | خطط الاشتراك |
platform_settings | المنصة | إعداد مفتاح-قيمة عام |
products | المستأجر | منتجات التعليقات |
feedback_campaigns | المستأجر | إعدادات نماذج التعليقات |
feedback_submissions | المستأجر | إدخالات التعليقات الفردية |
feedback_tags | المستأجر | الوسوم (علاقة many-to-many مع التقديمات) |
roadmap_items | المستأجر | عناصر kanban خارطة الطريق |
roadmap_votes | المستأجر | الأصوات المجهولة على عناصر خارطة الطريق |
feature_requests | المستأجر | اقتراحات الميزات من المجتمع |
changelog_entries | المستأجر | ملاحظات إصدار المنتج |
team_members | المستأجر | سجلات أعضاء الفريق |
team_invitations | المستأجر | الدعوات المعلّقة |
api_keys | المستأجر | مفاتيح وصول API |
audit_logs | المنصة | مسار تدقيق الإجراءات |
notifications | المنصة | الإشعارات داخل التطبيق |
payment_events | المنصة | أحداث Stripe/PayPal webhook |
webhook_logs | المستأجر | سجلات تسليم webhook الصادرة |
data_deletion_requests | المستأجر | طلبات حذف بيانات GDPR |
landing_pages | المنصة | بيانات منشئ صفحة الهبوط |
tenant_domains | المستأجر | تعيينات النطاقات المخصصة |
referral_codes | المستأجر | رموز الإحالة |
referral_conversions | المنصة | تتبع تحويلات الإحالة |
cron_logs | المنصة | سجلات تنفيذ المهام المجدولة |
الفهارس الرئيسية
جميع الجداول ذات النطاق المحدد للمستأجر مُفهرسة على (tenant_id, created_at) لأداء استعلام مثالي. يمتلك جدول feedback_submissions فهارس إضافية على status وproduct_id وcampaign_id وsentiment_label.
بنية الأمان
| الطبقة | الحماية |
|---|---|
| النقل | فرض HTTPS، رؤوس HSTS |
| المصادقة | Bcrypt (12 جولة)، 2FA اختياري (TOTP) |
| التفويض | برامج وسيط مستندة إلى الأدوار + فئات السياسة |
| CSRF | رموز CSRF لـ Laravel على جميع النماذج |
| XSS | الإفلات التلقائي لـ Blade ({{ }}) |
| حقن SQL | استعلامات Eloquent ذات المعاملات |
| تحديد المعدل | تقييد لكل مسار (5-120 طلب/دقيقة) |
| أمان API | مفاتيح API مُشفَّرة بـ SHA256، حدود معدل لكل مستأجر |
| أمان Webhook | التحقق من توقيع HMAC (Stripe)، حماية SSRF |
| البيانات | الإعدادات الحساسة مُشفَّرة في مكان الراحة |
| الجلسات | مُشفَّرة، HTTP-only، كوكيز آمنة |
| الرؤوس | CSP، X-Frame-Options، X-Content-Type-Options |
الخطوات التالية
- قاموس المصطلحات — فهم المصطلحات
- دليل التثبيت — إعداد الخادم
- مخطط قاعدة البيانات — هياكل الجداول التفصيلية