Skip to content

Repository files navigation

Lasaas - Laravel 多租户 SaaS 平台

LaravelLivewireFilamentPHPLicenseTests

🔗 在线演示

演示地址https://lasaas.doulingvip.com/

⚠️项目目前处于早期开发阶段,生产环境请谨慎使用。 多租户是个深水区——数据库隔离、域名路由、资源调度、租户生命周期管理……每一个环节都有坑。这个系统要做扎实,还有大量工作要做。项目永久免费开源,欢迎大家在 Issues 提建议、报 Bug、一起完善。一个人的力量有限,社区的合力才是这个项目最大的护城河。


📖 项目简介

Lasaas 是一个基于 Laravel 生态构建的现代化多租户 SaaS 平台,采用独立数据库隔离方案,为每个租户提供完全独立的数据存储空间。项目整合了 Livewire、Filament、Spatie Permission 和 Stancl/Tenancy 等优秀组件,提供了完整的用户管理、团队协作、权限控制和多租户解决方案。


🏗️ 核心架构

 ┌──────────────────────────────────┐
│ 中央管理平台 │
│ {central-domain}/admin │
│ 用户 · 团队 · 租户 · 模块 │
│ 角色 · 权限 (RBAC) │
└────────────────┬─────────────────┘
│
┌────────────────────────────┼──────────────────────────────┐
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌───────────────┐
│ User │ 多对多 │ Team │ 一对多 │ Tenant │
│ 用户 │◄───────────► │ 团队 │────────────────►│ 租户(客户) │
└──────┬─────┘ └──────┬─────┘ └───────┬───────┘
│ │ │
│ │ ┌──────────┼──────────┐
│ │ │ │ │
│ ▼ ▼ ▼ ▼
│ ┌────────────────┐ ┌──────────┐ ┌──────────┐
│ │ 个人后台 │ │租户后台 1 │ │租户后台 N │
└─────────────────┤{team}/dashboard│ │t1.domain │ │tN.domain │
│ 管理团队下租户 │ │ /admin │ │ /admin │
└────────────────┘ │独立数据库 │ │独立数据库 │
│模块按需 │ │模块按需 │
└──────────┘ └──────────┘
关系类型说明
User ↔ Team多对多用户可加入多个团队,团队有多个成员
Team → Tenant一对多一个团队管理 N 个租户(客户),一个租户归属一个团队
中央 → 租户控制中央管理平台决定每个租户 App 可用的功能模块(按模块开关)

四套面板

面板路由谁用
中央管理平台{central-domain}/admin全局管控:用户、团队、租户、模块开关。基于 Filament Shield RBAC,可按角色细粒度控制资源、页面、小组件的权限
中央应用个人后台{central-domain}/{team}/dashboard团队成员:管理该团队下的租户及模块功能
租户应用管理后台{tenant-domain}/admin租户内部管理,同样支持 Filament Shield 细粒度 RBAC
租户应用个人后台{tenant-domain}/{team}/dashboard租户成员:管理该租户下的模块功能

🚀 应用场景

Lasaas 的核心竞争力就一句话:一套代码,无限可能

多租户 + 独立数据库 + 独立域名的架构,让你只需开发和维护一套代码,就能同时服务成百上千个独立站点。运维成本和开发成本断崖式下降。

📌 典型应用场景

场景说明收益
🕸️ 站群系统每个站点独立数据库、独立域名,统一后台管理,适用于 SEO 站群、行业门户矩阵几百个站点,一个 git pull 全部更新
🏢 企业官网平台给企业批量建站,每家拥有独立域名、独立数据和后台服务商模式:开发一次,卖给 N 个客户
🏪 多品牌电商同一集团旗下多个品牌,各自独立商城,统一管理品牌独立运营,数据安全隔离,后台集中管控
📱 SaaS 产品创业快速构建可商用的 SaaS 产品,按租户收费从 0 到上线只需几天,聚焦业务而非架构
🏬 加盟连锁门店每家门店独立管理后台、独立数据,总部统一管控门店之间数据隔离,总部一键查看全部门店
🏫 多校区/多机构管理教育集团、培训机构旗下多个校区,各自独立运营校区独立,集团统一,互不干扰
🏘️ 物业/园区管理多个小区或园区,各自管理住户、收费、报修一套系统管 N 个小区,物业公司的最爱
🕴️ 服务商/外包公司一个项目模板,交付 N 个客户,各自独立部署能力代码复用率 90%+,人均交付效率翻倍
📰 自媒体/内容矩阵多个内容站点,各自独立域名和内容体系一套 CMS 撑起整个内容帝国
🏛️ 政务/机构信息化下级单位各自独立站点,上级统一监管数据物理隔离,符合安全合规要求
🔧 行业软件定制CRM、ERP、进销存等行业软件,按客户分别部署高度定制化的同时保持代码统一维护

🤖 AI + 多租户的化学反应

多租户架构天然适合 AI 应用——每个租户的数据是私有的、敏感的、需要隔离的,而 AI 的能力又是通用的。两者结合,催生了大量高价值场景:

场景AI 能力为什么需要多租户
🧠 RAG 知识库平台企业上传私有文档,AI 基于文档问答每个企业的知识库绝对隔离,A 公司文档绝不让 B 公司 AI 看到
💬 AI 客服机器人每个租户训练自己的客服 Bot,基于自身产品知识不同企业的产品、FAQ、话术完全不同,数据相互保密
✍️ AI 内容工厂按品牌生成营销文案、社媒帖子、产品描述每个品牌有自己的 tone & voice、关键词库、合规要求
📊 AI 数据分析 SaaS租户上传数据,AI 自动生成洞察、报告、预测企业经营数据极度敏感,必须物理隔离
🎓 AI 教育/私教平台每个机构拥有 AI 导师,因材施教学生数据、课程体系、教学进度各校独立
⚖️ AI 法律/合同审查律所上传合同模板和案例,AI 辅助审查客户案件信息绝对机密,不容有失
🏥 AI 医疗辅助医院基于自身病例库进行 AI 辅助诊断建议患者隐私,法规强制要求数据隔离
💼 AI 招聘筛选每个企业的 JD、候选人库、筛选标准各自独立招聘数据涉及薪酬、竞争对手信息,高度敏感
🏪 AI 门店经营大脑每家门店获得 AI 销售预测、库存建议、客流分析门店经营数据是核心竞争力,不能共享
🔍 AI 内容审核每个平台配置自己的审核规则、敏感词库、AI 策略不同社区的内容红线完全不同
🌐 AI 翻译/本地化每个企业有自己的术语库、翻译记忆、品牌词典术语一致性是企业品牌资产,不可混用
💰 AI 智能记账每个企业的财务数据由 AI 自动分类、对账、预警财务数据是企业的命脉,隔离是基本要求
🤖 AI Agent 工作流每个租户编排自己的 Agent、工具链、自动化流程Agent 的配置和上下文是核心竞争力
🤝 AI 销售助手每个销售团队的客户跟进策略、话术库、AI 外呼客户资源是销售的生命线,绝不能泄露

总结:AI 提供能力,多租户提供信任。当你的 AI 产品需要处理客户的私有数据时,物理隔离的数据库架构不是加分项,而是准入门槛

💰 核心优势

  • 一套代码,全量服务 —— 几百个客户站点,只需维护一个 Git 仓库,一次更新全部生效
  • 数据库物理隔离 —— 每个租户独立数据库,数据安全性拉满,满足等保合规要求
  • 独立域名 —— 每个租户可配置自己的域名,完全白标,客户无感知
  • 极低成本 —— 一台服务器就能跑几百个租户,无需为每个客户单独部署
  • 快速交付 —— Filament 一行命令生成 CRUD,从需求到上线快到飞起

💡 为什么选择这套技术栈?

Lasaas 不仅是一个 SaaS 脚手架,更是一套 高效率开发范式。你完全可以按需裁剪,选择最适合你的开发方式:

不需要多租户?直接用中央应用就够了

多租户是可选的。如果项目不需要多租户,直接在中央应用中开发功能即可,无需触碰 Tenancy 相关配置。Lasaas 的核心能力不依赖多租户。

Livewire + Flux UI:单页面全栈开发,告别前后端分离

Livewire 让你不用写一行 JavaScript 就能构建动态交互界面。结合 Flux UI 组件库,表单、模态框、数据列表等常见 UI 都是现成的组件,直接拼装即可。一套 Blade 模板搞定前后端,开发效率提升数倍。

Filament:增删改查只需一个命令

php artisan make:filament-resource Post

一行命令生成完整的 CRUD 管理页面,包含列表、表单、筛选、导出等功能。无需手写 Controller、View、Route,Filament 全部自动化完成。

Filament Shield:权限管理零代码

Shield 会自动扫描你的资源(Resources)、页面(Pages)、组件(Widgets),并为它们生成细粒度权限。在后台点点鼠标就能完成角色和权限的分配,无需写一行权限代码

Laravel:AI 辅助开发的最佳框架

像 Claude Code、Cursor、GitHub Copilot 这样的 AI 编码 Agent 的兴起,彻底改变了开发方式——它们可以以前所未有的速度生成完整功能、调试复杂问题、重构代码。但它们的有效性在很大程度上取决于对代码库的理解程度。

Laravel 约定俗成的惯例和定义良好的结构使其成为 AI 辅助开发的理想框架

  • 当你要求 AI Agent 添加一个控制器时,它确切地知道该放在 app/Http/Controllers 目录
  • 当你需要一个新的迁移时,文件位置和命名约定是可预测的
  • Eloquent 关联、表单请求、中间件等功能遵循的模式是 Agent 可以可靠理解和复制的

这种一致性消除了那些在更灵活但更随意的框架中常常困扰 AI 工具的猜测工作。AI 生成的 Laravel 代码看起来就像是由经验丰富的 Laravel 开发人员编写的,而不是从通用的 PHP 代码片段拼凑而成的。

🚀 Laravel Boost:让 AI Agent 成为你的 Laravel 专家

Laravel Boost 是一个 MCP(模型上下文协议)服务器,弥合了 AI 编码 Agent 和你的 Laravel 应用之间的鸿沟。安装后,你的 AI Agent 将从通用代码助手转变为理解你特定应用的 Laravel 专家

Boost 提供超过 15 种专用工具:

能力说明
应用内省查询 PHP/Laravel 版本、已安装的包、配置和环境变量
数据库洞察检查数据库架构、执行只读查询,不离开对话就能理解数据结构
路由检查列出所有已注册路由及其中间件、控制器和参数
Artisan 命令发现可用命令及其参数,Agent 可为任务建议并执行正确命令
日志分析读取和分析应用日志,辅助调试
Tinker 集成在应用上下文中执行 PHP 代码,让 Agent 测试假设、验证行为
文档搜索搜索超过 17,000 条 Laravel 生态系统文档,版本精准匹配
composer require laravel/boost --dev
php artisan boost:install

AI 在 Laravel 中写代码,比你想象的更准确、更可靠。


✨ 功能介绍

🏢 多租户架构

  • 独立数据库隔离:每个租户拥有独立的数据库,确保数据安全和隐私
  • 独立域名支持:每个租户可配置专属域名访问(如 tenant.example.com)
  • 租户初始化:创建租户时自动执行数据库迁移(数据库需提前手动创建,并在 tenant_databases 表登记连接信息)
  • 资源隔离:缓存、文件系统、队列等资源按租户隔离
  • 租户状态管理:支持租户激活、过期、禁用等状态管理
  • 灵活的数据库驱动:支持 MySQL、PostgreSQL、SQLite 等多种数据库

👤 中央管理平台(Central App)

个人中心(Livewire + Flux UI)

  • 用户注册/登录(支持双因素认证、Passkeys 无密码登录)
  • 个人资料管理(头像、姓名、邮箱等)
  • 安全设置(密码修改、两步验证、会话管理)
  • 团队管理
    • 创建和管理多个团队
    • 邀请成员加入团队
    • 角色权限分配(Admin/Member)
    • 团队成员管理(移除、角色变更)
    • 团队切换功能
  • 外观偏好设置(主题、语言等)
  • 团队邀请链接接受

管理后台(Filament Admin Panel)

  • 用户管理

    • 查看所有注册用户列表
    • 用户状态管理(激活/禁用)
    • 用户详情查看与编辑
    • 用户角色分配
  • 租户管理

    • 创建新租户(自动生成数据库)
    • 租户列表查看与筛选
    • 租户域名配置与管理
    • 租户状态管理(激活/过期/禁用)
    • 租户数据统计
    • 租户信息维护(名称、联系方式等)
  • 团队管理

    • 全局团队视图
    • 团队数据统计
    • 团队成员查询
  • 权限管理(Filament Shield)

    • 角色定义与管理
    • 权限分配与控制
    • 访问控制策略
    • 细粒度权限管理

🏠 租户管理平台(Tenant App)

每个租户拥有独立的 Filament 管理后台,通过专属域名访问:

  • 用户管理

    • 租户内部用户 CRUD(创建、读取、更新、删除)
    • 用户角色分配与管理
    • 用户激活/禁用控制
    • 用户数据隔离
  • 团队管理

    • 团队信息维护
    • 团队成员管理
    • 团队权限配置
    • 团队邀请管理
  • 权限管理

    • 基于 Spatie Permission 的 RBAC(角色基于访问控制)
    • 细粒度权限控制
    • 角色继承与组合
    • 权限中间件保护
  • 可扩展性

    • 支持自定义业务模块
    • 租户级别的配置定制
    • 独立的数据库迁移

🛠️ 技术栈

后端框架

  • Laravel 13.x - PHP Web 应用框架
  • PHP 8.3+ - 编程语言

前端技术

  • Livewire 4.x - 全栈 Reactivity 框架,无需编写 JavaScript
  • Flux UI 2.x - 专业的 Livewire 组件库
  • Alpine.js - 轻量级 JavaScript 框架
  • Tailwind CSS 4.x - 实用优先的 CSS 框架
  • Vite 8.x - 现代前端构建工具

管理面板

  • Filament 5.x - Laravel 管理面板构建器
    • Forms - 强大的表单构建器
    • Tables - 数据表格展示与筛选
    • Notifications - 实时通知系统
    • Widgets - 数据可视化组件
    • Filament Shield - 权限管理集成

多租户

  • Stancl/Tenancy 3.x - Laravel 多租户解决方案
    • 数据库自动隔离
    • 域名路由识别
    • 资源自动隔离(缓存、文件系统、队列)
    • 租户生命周期管理

权限管理

  • Spatie Laravel Permission 7.x - 角色和权限管理
    • RBAC(角色基于访问控制)
    • 多模型权限支持
    • 权限缓存优化

认证授权

  • Laravel Fortify - 无头认证后端
    • 双因素认证(2FA)
    • Passkeys 无密码登录支持
    • 邮箱验证
    • 密码重置

国际化

  • Laravel Lang - 多语言支持
    • 中文(简体)
    • 英文
    • 易于扩展其他语言

开发工具

  • Pest 4.x - 优雅的 PHP 测试框架
  • Laravel Pint - 代码风格修复工具(PHP-CS-Fixer)
  • DDEV - 本地开发环境管理
  • Laravel Pail - 日志查看工具
  • Concurrently - 并行任务执行

📁 项目结构

lasaas/
├── app/
│ ├── Actions/ # 业务逻辑动作类(Fortify、Teams)
│ ├── Concerns/ # Traits(可复用特性)
│ ├── Enums/ # 枚举类(TeamRole、TeamPermission、TenantStatus)
│ ├── Filament/ # Filament 管理面板资源
│ │ ├── Resources/ # 资源管理(Users、Tenants、Teams、Roles)
│ │ ├── Pages/ # 自定义页面
│ │ └── Widgets/ # 数据小组件
│ ├── Http/ # HTTP 相关(Controllers、Middleware、Responses)
│ ├── Livewire/ # Livewire 组件
│ ├── Menu/ # 侧边栏菜单注册表(SidebarMenu、NavItem)
│ ├── Models/ # Eloquent 数据模型(User、Team、Tenant、Membership等)
│ ├── Module/ # 模块框架(ModuleServiceProvider、ModuleBootLoader、TenantRouteLoader等)
│ ├── Notifications/ # 通知类
│ ├── Policies/ # 授权策略类
│ ├── Providers/ # 服务提供者
│ ├── Rules/ # 自定义验证规则
│ └── Support/ # 辅助类
├── config/ # 配置文件(tenancy、fortify、filament、permission等)
├── database/
│ ├── migrations/ # 中央数据库迁移
│ │ └── tenant/ # 租户数据库迁移模板
│ ├── seeders/ # 数据填充器
│ └── factories/ # 模型工厂(测试用)
├── packages/ # 功能模块(lasaas-module)
│ ├── contrib/ # Composer 安装的第三方模块(.gitignore,不提交到 Git)
│ └── custom/ # 项目自定义模块(提交到 Git)
│ └── lasaas/
│ ├── demo-module/ # 示例模块
│ └── ... # 你的自定义模块
├── resources/
│ ├── views/ # Blade 视图模板
│ │ ├── components/ # Blade 组件
│ │ ├── layouts/ # 布局模板
│ │ │ ├── landing/ # Landing 页面布局(default / tenant)
│ │ │ ├── app/ # App 内页布局
│ │ │ └── auth/ # 认证页面布局
│ │ ├── pages/ # 中央应用页面(home、auth、teams、profile)
│ │ ├── tenant/ # 租户应用页面
│ │ └── flux/ # Flux UI 组件覆盖
│ ├── js/ # JavaScript 文件
│ └── css/ # CSS 样式文件
├── routes/ # 路由定义
│ ├── web.php # 中央应用路由
│ ├── tenant.php # 租户应用路由
│ ├── settings.php # 中央应用设置相关路由
│ ├── tenant-settings.php# 租户应用设置相关路由
│ └── console.php # Artisan 命令路由
├── tests/ # 测试文件
│ ├── Feature/ # 功能测试
│ └── Unit/ # 单元测试
├── public/ # 公共资源目录(入口文件、构建产物)
├── storage/ # 存储目录(app、framework、logs)
├── lang/ # 多语言文件(en、zh_CN)
├── .ddev/ # DDEV 开发环境配置
├── .env.example # 环境变量示例
├── composer.json # Composer 依赖配置(installer-paths 映射 lasaas-module)
├── package.json # NPM 依赖配置
├── vite.config.js # Vite 构建配置
└── artisan # Laravel Artisan 命令行工具

🚀 快速开始

环境要求

  • PHP 8.3+
  • Composer
  • Node.js & NPM
  • MySQL/MariaDB 或 PostgreSQL
  • DDEV(可选,推荐用于本地开发)

安装步骤

方式一:使用 DDEV(推荐)

  1. 克隆项目
git clone <repository-url> lasaas
cd lasaas
  1. 启动 DDEV 环境
ddev start
  1. 安装依赖并初始化
ddev composer install
ddev npm install
ddev artisan key:generate
ddev artisan migrate
ddev artisan livewire:publish --assets
ddev artisan shield:generate --all
ddev artisan db:seed
ddev npm run build
  1. 访问应用
  • 中央应用:https://lasaas.ddev.site
  • 租户应用:https://{tenant-id}.lasaas.ddev.site

方式二:手动安装

  1. 克隆项目并安装依赖
git clone <repository-url> lasaas
cd lasaas
composer install
npm install
  1. 配置环境变量
cp .env.example .env
php artisan key:generate

编辑 .env 文件,配置数据库连接:

DB_CONNECTION=mysqlDB_HOST=127.0.0.1DB_PORT=3306DB_DATABASE=lasaas_centralDB_USERNAME=rootDB_PASSWORD=
  1. 运行数据库迁移
php artisan migrate
php artisan livewire:publish --assets
php artisan shield:generate --all
php artisan db:seed
  1. 编译前端资源
npm run build
  1. 启动开发服务器
# 方式一:使用 Laravel 内置命令
php artisan serve
# 方式二:使用完整开发环境(推荐)
composer run dev

初始配置

  1. 创建第一个用户 访问注册页面创建管理员账户

  2. 创建第一个租户 先在数据库服务器上提前创建好物理数据库(SQLite 除外),再到中央管理后台「租户」页面创建租户,在"数据库连接"区块填写该租户的数据库连接信息。

    或通过代码创建:

php artisan tinker
>>> $tenant = \App\Models\Tenant::create(['id'=>'demo', 'name'=>'演示租户']);
>>> $tenant->setDatabaseConnection([
... 'connection'=>'mariadb',
... 'database'=>'tenant_demo',
... 'host'=>'127.0.0.1',
... 'username'=>'root',
... 'password'=>'',
... ]);
>>> \App\Models\Domain::create(['domain'=>'demo.lasaas.test', 'tenant_id'=>'demo']);
  1. 运行租户迁移
php artisan tenants:migrate
  1. 为租户生成 Shield 权限(否则租户后台看不到角色/权限菜单)
php artisan tenants:run shield:generate --option=panel=tenant-admin --option=all=1 --option=option=permissions
php artisan tenants:run permission:cache-reset
  1. 为租户超管分配 super_admin 角色(先在租户后台注册/创建用户,再替换 user_id
php artisan tenants:run shield:super-admin --option=user=<user_id> --option=panel=tenant-admin

📝 使用说明

中央应用功能

用户注册与登录

  • 访问首页进行用户注册
  • 支持邮箱验证
  • 支持双因素认证(2FA)
  • 支持 Passkeys 无密码登录

团队管理

  1. 创建团队

    • 点击团队切换器中的"创建团队"
    • 输入团队名称和 Slug
    • 系统自动生成唯一团队标识
  2. 邀请成员

    • 进入团队设置页面
    • 点击"邀请成员"
    • 输入邮箱地址选择角色
    • 发送邀请邮件
  3. 管理成员

    • 查看团队成员列表
    • 修改成员角色(Admin/Member)
    • 移除团队成员

管理后台

访问 /admin 进入 Filament 管理面板:

  • 管理所有用户
  • 创建和管理租户
  • 配置租户域名
  • 查看系统统计

租户应用功能

访问租户后台

通过配置的域名访问租户应用:

https://your-tenant-domain.com/admin

租户内部管理

  • 管理租户内部用户
  • 配置团队权限
  • 自定义业务逻辑

🔧 开发指南

添加新的租户资源

  1. 创建迁移文件
php artisan make:migration create_posts_table --path=database/migrations/tenant
  1. 创建模型
php artisan make:model Post
  1. 创建 Filament 资源
php artisan make:filament-resource Post --tenant
  1. 运行租户迁移
php artisan tenants:migrate
  1. 重新生成租户 Shield 权限(新资源会自动纳入权限体系)
php artisan tenants:run shield:generate --option=panel=tenant-admin --option=all=1 --option=option=permissions
php artisan tenants:run permission:cache-reset

自定义权限

  1. 定义角色和权限
// 在服务提供者中useSpatie\Permission\Models\Role;
useSpatie\Permission\Models\Permission;
$role = Role::create(['name' => 'manager']);
$permission = Permission::create(['name' => 'edit-posts']);
$role->givePermissionTo($permission);
  1. 在代码中使用
// 检查权限$user->can('edit-posts');
// 检查角色$user->hasRole('manager');

租户 Shield 权限(Filament Shield)

每个租户拥有独立的数据库和权限数据,Shield 的权限必须在租户上下文内生成

⚠️常见坑tenants:run shield:install 看起来能跑通,但 shield:install 内部通过 Process::run() 启动子进程执行 shield:generate,子进程没有初始化租户,会把权限写入中心数据库,导致租户后台看不到角色/权限菜单,同时中心库被写入多余的租户权限。

正确做法是使用 tenants:run 在租户上下文内直接执行生成命令:

# 1. 生成 tenant-admin 面板权限,并自动挂到 super_admin 角色
php artisan tenants:run shield:generate --option=panel=tenant-admin --option=all=1 --option=option=permissions
# 2. 重置权限缓存
php artisan tenants:run permission:cache-reset
# 3. 为租户超管分配 super_admin 角色
php artisan tenants:run shield:super-admin --option=user=<user_id> --option=panel=tenant-admin

要点:

  • 命令默认对所有租户执行,指定租户用 --tenants=<tenant_id>(支持逗号分隔)
  • tenants:run 传参必须是 key=value 形式,布尔开关要写成 --option=all=1
  • 权限生成使用 firstOrCreate,重复执行幂等、安全
  • --all 会扫描 tenant-admin 面板注册的所有资源、页面、小组件(DashboardAccountWidget 等已在 config/filament-shield.php 中排除),后续在 app/Filament/TenantAdmin/Resources 新增资源后重新执行即可自动纳入
  • 租户 Shield 初始化完整流程:tenants:migrate → 生成权限 → 重置缓存 → 分配角色

模块系统

Lasaas 采用与 Drupal 类似的模块系统:模块的存亡以文件系统为准,autoload 由构建步骤生成,不依赖运行时扫描。

目录结构

packages/
├── contrib/ # Composer 安装的第三方模块(.gitignore,提交到 Git)
│ ├── vendor-a/
│ │ └── module-x/ # contributor vendor-a/module-x
│ └── vendor-b/
│ └── module-y/ # contributor vendor-b/module-y
└── custom/ # 项目自定义模块(提交到 Git)
└── lasaas/
├── demo-module/ # 示例:lasaas/demo-module
└── blog/ # 示例:lasaas/blog

模块生命周期

操作命令说明
新增自定义模块复制到 packages/custom/{vendor}/{name}/手动放目录
删除自定义模块直接删除目录rm -rf packages/custom/{vendor}/{name}/
安装第三方模块composer require vendor/name自动安装到 packages/contrib/
卸载第三方模块composer remove vendor/name自动清理
启用 / 禁用模块php artisan module:enable {package} / module:disable {package}切换模块启用状态
卸载模块php artisan module:uninstall {package}卸载并清理模块数据
按租户启用/禁用/卸载module:tenant-enable / module:tenant-disable / module:tenant-uninstall {tenant} {package}单租户维度的模块开关
同步模块元数据composer dump-autoload自动触发 module:sync,更新数据库 + autoload 缓存

composer dump-autoloadpost-autoload-dump 钩子会自动执行 module:sync,实现:

  1. 扫描 packages/contrib/packages/custom/ 中的 lasaas-module 类型包
  2. 将模块元数据写入数据库(modules 表)
  3. 生成 autoload 缓存文件 bootstrap/cache/lasaas_modules_autoload.php
  4. 物理删除磁盘上已移除的模块记录

注意:新增或删除模块后,必须执行 composer dump-autoloadddev composer dump-autoload,让数据库和 autoload 与文件系统保持一致。

如何开发一个新模块

  1. packages/custom/lasaas/ 下创建模块目录:
packages/custom/lasaas/my-module/
├── composer.json # type 设为 "lasaas-module"
├── src/
│ └── MyModuleServiceProvider.php
├── routes/
│ └── web.php
├── database/
│ └── migrations/
└── resources/
└── views/
  1. composer.json 示例:
{
"name": "lasaas/my-module",
"type": "lasaas-module",
"autoload": {
"psr-4": {
"Lasaas\\MyModule\\": "src/"
}
},
"extra": {
"lasaas-module": {
"name": "我的模块",
"areas": ["tenant"],
"weight": 0
}
}
}
  1. 执行同步:
ddev composer dump-autoload
  1. 在 Filament 管理后台启用/禁用模块。

为模块添加前台侧边栏导航

前台个人后台(中央 {central_domain}/{team}/dashboard 与租户 {tenant_domain}/{team}/dashboard)的侧边栏由框架统一渲染,模块在 ModuleServiceProvider 中覆写 registerSidebarMenu() 钩子注入入口即可(框架在加载模块时自动调用,无需在 boot() 手动注册):

useApp\Enums\MenuPosition;
useApp\Menu\NavItem;
useApp\Menu\SidebarMenu;
useSpatie\Menu\Menu;
publicfunctionregisterSidebarMenu(SidebarMenu$nav): void
{
// 中央应用侧边栏$nav->register(MenuPosition::DashboardNav, function (Menu$menu): void {
$menu->add(NavItem::to(route('blog.index'), __('博客'))
->icon('document-text')
->group('内容')
->activeRoute('blog.*'));
});
// 租户应用侧边栏(仅在租户启用该模块后出现)$nav->register(MenuPosition::TenantNav, function (Menu$menu): void {
$menu->add(NavItem::to(route('tenant.blog.index'), __('博客'))
->icon('document-text')
->group('内容')
->activeRoute('tenant.blog.*'));
});
}
  • NavItem::group() 约定:'Team' 并入「团队」分组、'Personal' 并入「个人」分组、其他字符串为动态分组、省略则为无标题分组。
  • 租户上下文仅渲染当前租户已启用模块的入口(未启用的模块连其租户路由都未注册)。详见 packages/README.md 的「5.2 前台侧边栏导航菜单」。

命令参考

# 查看模块同步状态
ddev artisan module:sync --dry-run
# 强制执行同步
ddev artisan module:sync --force
# 删除模块但保留数据库记录(仅标记 inactive)
ddev artisan module:sync --soft
# 启用 / 禁用模块
ddev artisan module:enable {package}
ddev artisan module:disable {package}
# 卸载模块并清理数据
ddev artisan module:uninstall {package}
# 按租户启用 / 禁用 / 卸载模块
ddev artisan module:tenant-enable {tenant} {package}
ddev artisan module:tenant-disable {tenant} {package}
ddev artisan module:tenant-uninstall {tenant} {package}

测试

运行所有测试:

composer test

运行特定测试:

php artisan test --filter=TeamTest

📦 可用命令

Artisan 命令

租户管理

# 列出所有租户
php artisan tenants:list
# 为所有租户运行迁移
php artisan tenants:migrate
# 为特定租户运行迁移
php artisan tenants:migrate --tenants=demo,prod
# 填充租户数据
php artisan tenants:seed
# 在租户上下文执行任意命令(可指定租户,默认对所有租户)
php artisan tenants:run {command} --tenants=demo,prod
# 向租户上下文命令传递参数/选项(key=value 形式)
php artisan tenants:run shield:generate --option=panel=tenant-admin
# 删除租户记录(数据库不会自动删除,需手动清理物理数据库)
php artisan tinker
>>> \App\Models\Tenant::find('demo')?->delete();

说明:本项目不提供 tenants:create / tenants:delete 命令。租户创建请通过中央管理后台「租户」页面完成(会同时登记域名与 tenant_databases 连接信息),数据库需提前手动创建。

权限管理(Filament Shield)

# 中央管理平台:生成所有资源的权限
php artisan shield:generate --all
# 中央管理平台:生成特定资源的权限
php artisan shield:generate --resource=User
# 租户面板:为所有租户生成 tenant-admin 权限(在租户上下文内执行)
php artisan tenants:run shield:generate --option=panel=tenant-admin --option=all=1 --option=option=permissions
# 租户面板:重置权限缓存
php artisan tenants:run permission:cache-reset
# 租户面板:为租户超管分配 super_admin 角色
php artisan tenants:run shield:super-admin --option=user=1 --option=panel=tenant-admin
# 指定单个租户执行(默认对所有租户)
php artisan tenants:run shield:generate --option=panel=tenant-admin --option=all=1 --option=option=permissions --tenants=demo

⚠️不要对租户使用 tenants:run shield:installshield:install 内部通过子进程执行 shield:generate,子进程启动时丢失租户上下文,权限会被错误写入中心数据库,导致租户后台看不到角色/权限菜单。

常规命令

# 清除缓存
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear
# 缓存优化
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan optimize
# 模块同步
php artisan module:sync
php artisan module:sync --force
php artisan module:sync --dry-run
# 查看路由列表
php artisan route:list
# 数据库相关
php artisan migrate
php artisan migrate:rollback
php artisan db:seed
php artisan db:wipe
# 队列管理
php artisan queue:work
php artisan queue:restart
php artisan queue:flush

NPM 脚本

# 开发模式(带热重载)
npm run dev
# 生产构建
npm run build
# 预览生产构建
npm run preview

Composer 脚本

# 完整初始化项目
composer run setup
# 启动开发环境(服务器+队列+日志+Vite)
composer run dev
# 格式化代码
composer run lint
# 检查代码风格
composer run lint:check
# 运行测试
composer run test# CI 检查
composer run ci:check

DDEV 命令

# 启动环境
ddev start
# 停止环境
ddev stop
# 重启环境
ddev restart
# 删除环境(保留数据)
ddev delete
# 进入 Web 容器
ddev ssh
# 查看日志
ddev logs
# 访问数据库
ddev mysql
# 邮件预览
ddev mailhog
# 执行 Composer 命令
ddev composer install
# 执行 NPM 命令
ddev npm run dev
# 执行 Artisan 命令
ddev artisan migrate

🔐 安全考虑

Lasaas 采用了多层次的安全措施:

  • 数据隔离:每个租户独立数据库,数据完全隔离
  • 密码加密:使用 bcrypt 算法加密存储密码
  • 双因素认证:支持 TOTP 和 Passkeys
  • CSRF 保护:所有表单请求自动验证 CSRF token
  • XSS 防护:Blade 模板自动转义输出
  • SQL 注入防护:Eloquent ORM 使用参数化查询
  • RBAC 权限控制:基于角色的访问控制
  • 中间件保护:租户隔离验证、身份认证中间件
  • 邮箱验证:新用户必须验证邮箱
  • 会话管理:支持查看和管理活跃会话
  • 速率限制:防止暴力破解和 DDoS 攻击

安全最佳实践

  1. 生产环境配置

    APP_DEBUG=falseAPP_ENV=production
  2. 定期更新依赖

    composer update
    npm update
  3. 备份策略

    • 定期备份中央数据库
    • 定期备份所有租户数据库
    • 备份文件系统和用户上传内容
  4. 监控和日志

    • 启用错误监控(如 Sentry)
    • 定期审查日志文件
    • 设置异常报警

🤝 贡献指南

欢迎提交 Issue 和 Pull Request!

贡献流程

  1. Fork 本仓库 点击 GitHub 页面右上角的 Fork 按钮

  2. 创建特性分支

    git checkout -b feature/AmazingFeature
  3. 提交更改

    git commit -m 'Add some AmazingFeature'
  4. 推送到分支

    git push origin feature/AmazingFeature
  5. 开启 Pull Request 在 GitHub 上创建 Pull Request,描述您的更改

代码规范

  • 遵循 PSR-12 编码规范
  • 使用 Laravel Pint 格式化代码:composer run lint
  • 编写测试用例覆盖新功能
  • 更新相关文档

报告问题

如果您发现了 bug 或有功能建议:

  1. 搜索现有 Issues,避免重复报告
  2. 创建新的 Issue,详细描述问题
  3. 提供重现步骤(如适用)
  4. 包含环境信息(PHP 版本、数据库等)

📄 许可证

本项目采用 MIT 许可证 - 查看 LICENSE 文件了解详情。

🙏 致谢

❓ 常见问题(FAQ)

一般问题

Q: 如何创建第一个管理员账户?

A: 访问注册页面创建账户,然后使用 Tinker 分配角色:

php artisan tinker
>>> $user = \App\Models\User::find(1);
>>> $user->assignRole('super_admin');

Q: 如何重置密码?

A: 在登录页面点击“忘记密码”,输入邮箱地址接收重置链接。

Q: 支持哪些数据库?

A: 支持 MySQL 8.0+、MariaDB 10.5+、PostgreSQL 14+ 和 SQLite(开发环境)。

多租户相关

Q: 如何为新租户配置域名?

A: 在 Filament 管理后台的 Tenants 页面,编辑租户并添加域名。或者使用代码:

\App\Models\Domain::create([
'domain' => 'tenant.yourdomain.com',
'tenant_id' => $tenantId,
]);

Q: 租户数据库在哪里?

A: 每个租户有独立的数据库,名称在 tenant_databases 表的 database 字段中配置(通常为 tenant_{tenant_id}),连接信息(类型、主机、账号等)也登记在该表。中央数据库中可查看 tenants 表获取租户列表。

Q: 如何删除租户及其数据?

A: 本项目不提供删除命令,且删除租户记录不会自动删除物理数据库

php artisan tinker
>>> \App\Models\Tenant::find('demo')?->delete();

删除记录会一并清理其域名和 tenant_databases 配置,之后需手动到数据库服务器删除对应的物理数据库。

Q: 如何在中央应用和租户应用之间切换?

A:

  • 中央应用:访问主域名(如 lasaas.ddev.site)
  • 租户应用:访问租户专属域名(如 demo.lasaas.ddev.site)

开发相关

Q: 如何添加新的租户资源?

A: 参考“开发指南”部分的详细步骤:

  1. database/migrations/tenant/ 创建迁移
  2. 创建模型
  3. 创建 Filament 资源
  4. 运行 php artisan tenants:migrate

Q: DDEV 启动失败怎么办?

A: 尝试以下步骤:

# 停止并重新启动
ddev stop
ddev start
# 如果仍有问题,删除并重建
ddev delete
ddev start

Q: 前端资源更新后没有生效?

A: 清除浏览器缓存并重新构建:

npm run build
# 或开发模式
npm run dev

Q: 如何查看队列任务?

A: 检查 jobs 表或使用 Horizon(如果安装):

php artisan tinker
>>> \Illuminate\Support\Facades\DB::table('jobs')->count();

权限相关

Q: 如何为用户分配角色?

A: 在 Filament 后台的用户管理页面,编辑用户并分配角色。或使用代码:

$user->assignRole('admin');

Q: Filament Shield 是什么?

A: Filament Shield 是一个为 Filament 资源自动生成权限的包。它会根据资源生成相应的权限(view、create、update、delete 等)。

Q: 如何自定义权限?

A: 在服务提供者或 Seeder 中:

useSpatie\Permission\Models\Permission;
Permission::create(['name' => 'custom-permission']);

Q: 租户后台看不到角色/权限(Shield)菜单?

A: 说明租户的权限被写到了中心数据库。检查租户库(tenant_{id})的 permissions 表是否为空,若为空则按以下命令在租户上下文内重新生成:

php artisan tenants:run shield:generate --option=panel=tenant-admin --option=all=1 --option=option=permissions
php artisan tenants:run permission:cache-reset
php artisan tenants:run shield:super-admin --option=user=<user_id> --option=panel=tenant-admin

注意不要用 tenants:run shield:install(详见"开发指南 → 租户 Shield 权限"一节)。

性能相关

Q: 如何优化生产环境性能?

A:

  1. 启用缓存:php artisan optimize
  2. 使用 Redis 作为缓存驱动
  3. 配置队列 worker
  4. 启用 OPcache
  5. 使用 CDN 存储静态资源
  6. 数据库索引优化

Q: 如何处理大量租户?

A:

  • 使用连接池管理数据库连接
  • 实施租户分片策略
  • 定期清理不活跃租户
  • 监控服务器资源使用

故障排除

Q: 出现 "Class not found" 错误

A: 尝试重新生成自动加载文件:

composer dump-autoload

Q: 迁移失败怎么办?

A:

# 回滚迁移
php artisan migrate:rollback
# 清除迁移表
php artisan migrate:fresh
# 重新迁移
php artisan migrate

Q: 邮件发送失败

A: 检查 .env 中的邮件配置,查看日志文件:

tail -f storage/logs/laravel.log

Q: 如何调试租户相关问题?

A:

// 在当前请求中获取租户信息dump(tenant());
dump(tenant('id'));
// 检查是否在租户上下文中dump(tenancy()->initialized);

📞 联系方式

如有问题或建议,请提交 Issue 或通过以下方式联系:

📚 相关资源

学习资源

社区


Made with ❤️ using Laravel

About

Lasaas 是一个基于 Laravel 生态构建的现代化多租户 SaaS 平台,采用独立数据库隔离方案,为每个租户提供完全独立的数据存储空间。项目整合了 Livewire、Filament、Spatie Permission 和 Stancl/Tenancy 等优秀组件,提供了完整的用户管理、团队协作、权限控制和多租户解决方案。

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages