Chuyển tới nội dung chính

🏢 Kiến trúc Multi-tenant SaaS & Cô lập Dữ liệu

LMS hoạt động theo mô hình Multi-tenant SaaS với ranh giới phân tách dữ liệu 2 cấp độ: Organization (Tổ chức)Center (Chi nhánh / Cơ sở).


1. Mô hình Phân cấp Thực thể & Ràng buộc Khóa

Ràng buộc Khóa & Định danh

  • Ràng buộc định danh người dùng: UNIQUE(organization_id, username). Email là tùy chọn (nullable) và không bắt buộc duy nhất toàn cục.
  • Subdomain Routing: Tên miền con của request (ví dụ: abc.localhost:8085 hoặc abc.cerylms.com) sẽ tự động được phân giải thành Organization ID = abc.

2. Cơ chế Cô lập Dữ liệu trên Backend

2.1. TenantManager Static Service

Service quản lý Context của request hiện tại (Modules/Core/App/Services/TenantManager.php):

  • TenantManager::getOrganizationId()
  • TenantManager::getCenterId()
  • TenantManager::setCenterId($centerId)

2.2. Trait HasTenantScope

Mọi Model nghiệp vụ (Lớp học, Học viên, Hóa đơn, Giao dịch) BẮT BUỘC sử dụng trait HasTenantScope:

namespace Modules\Academic\App\Models;

use Illuminate\Database\Eloquent\Model;
use Modules\Core\App\Traits\HasTenantScope;
use Modules\Core\App\Traits\Auditable;

class AcademicClass extends Model
{
use HasTenantScope, Auditable;

protected $fillable = [
'organization_id',
'center_id',
'name',
'code',
'status',
];
}

Tác dụng của HasTenantScope:

  • Tự động thêm điều kiện WHERE center_id = TenantManager::getCenterId() vào mọi câu lệnh SELECT, UPDATE, DELETE.
  • Tự động điền center_idorganization_id khi gọi phương thức Model::create().

3. Kiến trúc Dual-Surface Routing qua Nginx Gateway

Nginx traffic routing (:8085):
/admin/*, /portal/* → Vite Dev Server (React SPA)
/api/*, /sanctum/* → Laravel PHP-FPM (RESTful API)
/* (Fallback) → Laravel Blade Engine (Landing Page công khai tối ưu SEO)
  • Quy tắc: Tuyệt đối không thêm các trang HTML công khai (Landing Page, bài viết tin tức) vào React SPA. Mọi trang public cần SEO đều do Laravel Blade Engine kết hợp middleware LpHostRouterMiddleware xử lý.

🔗 Xem thêm