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

بنية النظام

تُقدّم هذه الصفحة تعمّقًا في كيفية بناء 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

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