إنتقل إلى المحتوى الرئيسي

بنية النظام

تُقدّم هذه الصفحة تعمّقًا في كيفية بناء 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 SocialiteGoogle & GitHub OAuth
البريد الإلكترونيLaravel Mail (SMTP)رسائل بريد تحويلية، ملخصات، تقارير
الوقت الفعليServer-Sent Events (SSE)بث التقديمات الحية
جدولة المهامLaravel Scheduler (cron)الملخصات، انتهاء صلاحية التجربة، الاحتفاظ بالبيانات

نموذج تعدد المستأجرين

يستخدم FeedbackPulse نموذج تعدد مستأجرين بـ قاعدة بيانات واحدة ومخطط مشترك. هذا يعني:

  • قاعدة بيانات واحدة تخدم جميع المستأجرين
  • كل جدول خاص بالمستأجر لديه عمود tenant_id
  • نطاق عام (TenantScope) يُصفّي تلقائيًا جميع الاستعلامات للمستأجر الحالي
  • سمة (BelongsToTenant) تملأ tenant_id تلقائيًا عند الإنشاء وتُطبّق النطاق

كيف يعمل تحديد المستأجر

عند ورود طلب، يُحدّد برنامج الوسيط ResolveTenant المستأجر الحالي بهذا الترتيب:

  1. النطاق الفرعيacme.yourdomain.com ← يبحث عن المستأجر بالنطاق الفرعي "acme"
  2. النطاق المخصصfeedback.acmecorp.com ← يبحث عن نطاق موثَّق في جدول tenant_domains
  3. المستخدم المصادق — يعود إلى 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

الخطوات التالية