Files
2026-10-11 19:06:33 +08:00

15 KiB
Raw Permalink Blame History

4.9 数据库设计

:::tip 概述 项目支持 MySQL、PostgreSQL、SQL Server、Oracle、SQLite 五种数据库,通过 .env 的 DB_CONNECTION 一键切换,document/ 下提供五套初始化脚本。所有数据库共用同一套代码,无需修改业务逻辑。本章涵盖命名规范、表结构设计、字段说明、索引策略和多数据库适配。 :::

命名规范

对象 规范 示例
表名 不含前缀的业务名 + DB_PREFIX(默认 laravel_) laravel_user、laravel_article
模型 $table 不含前缀 protected $table = 'user'
字段名 小写下划线 create_time、user_name
主键 统一 id,INT 自增 id INT PRIMARY KEY
外键 表名_id user_id、role_id
索引 idx_字段名 idx_status、idx_tenant_id
唯一索引 uk_含义(常含 is_delete 协同) uk_tenant_username

公共字段

所有业务表必须包含以下公共字段,由模型 Trait 自动维护:

-- MySQL 格式
id              INT PRIMARY KEY AUTO_INCREMENT  COMMENT '主键',
is_delete       TINYINT(1) DEFAULT 0            COMMENT '软删除 0=正常 1=已删除',
create_user     VARCHAR(50) DEFAULT ''           COMMENT '创建人',
create_time     DATETIME                         COMMENT '创建时间',
update_user     VARCHAR(50) DEFAULT ''           COMMENT '更新人',
update_time     DATETIME                         COMMENT '更新时间'
字段 自动维护方 说明
is_delete SoftDeletesByFlag softDelete() 设置为 1,SoftDeleteFlagScope 全局过滤
create_user HasAuditColumns creating 事件 取 Auth::username(),已传入则不覆盖
create_time HasAuditColumns creating 事件 取 now(),已传入则不覆盖
update_user HasAuditColumns updating 事件 取 Auth::username()
update_time HasAuditColumns updating 事件 始终覆盖为当前时间

核心表清单(25 张)

用户与权限(5 张)

表名 说明 Service 基类
laravel_user 用户表 BaseTenantService
laravel_user_role 用户角色关联表(N:N 中间表) —
laravel_role 角色表 BaseTenantService
laravel_role_menu 角色菜单关联表(N:N 中间表) —
laravel_menu 菜单/权限表(菜单即权限) BaseService

关联关系:

laravel_user ──┐
               │ N:N (laravel_user_role)
laravel_role ──┤
               │ N:N (laravel_role_menu)
laravel_menu ──┘

laravel_dept   ←── laravel_user.dept_id
laravel_tenant ←── laravel_user.tenant_id

组织架构(3 张)

表名 说明 Service 基类
laravel_dept 部门表(树形,parent_id) BaseTenantService
laravel_position 岗位表 BaseTenantService
laravel_level 职级表 BaseTenantService

租户(1 张)

表名 说明 Service 基类
laravel_tenant 租户表(状态、过期时间、用户数限制) BaseService

系统配置(5 张)

表名 说明 Service 基类
laravel_dict 字典表 BaseService
laravel_dict_item 字典项表 BaseService
laravel_config 配置组表 BaseService
laravel_config_item 配置项表 BaseService
laravel_param 系统参数表 BaseService

关联关系:

laravel_dict   ←── laravel_dict_item.dict_id
laravel_config ←── laravel_config_item.config_id

内容管理(4 张)

表名 说明 Service 基类
laravel_article 文章表 BaseTenantService
laravel_category 文章分类表(树形) BaseTenantService
laravel_link 友情链接表 BaseTenantService
laravel_notice 通知公告表 BaseTenantService

日志审计(2 张)

表名 说明 Service 基类
laravel_login_log 登录日志表 BaseService
laravel_operation_log 操作日志表 BaseService

定时任务(2 张)

表名 说明 Service 基类
laravel_job 定时任务表 BaseService
laravel_job_log 定时任务执行日志表 BaseService

关联关系:

laravel_job ←── laravel_job_log.job_id

基础数据(3 张)

表名 说明 Service 基类
laravel_city 城市行政区划表(树形) BaseService
laravel_file_template 文件模板表 BaseService
laravel_example 案例演示表(生成器参考模板) BaseService

:::tip 租户隔离范围 继承 BaseTenantService 的 9 个服务:User / Role / Dept / Position / Level / Article / Category / Notice / Link——业务数据按租户隔离;系统共享数据(字典、配置、菜单、日志等)继承 BaseService 不隔离。 :::

关键表字段说明

laravel_user(用户表)

字段 类型 说明
id INT 主键
tenant_id INT 租户 ID(0=平台用户)
code VARCHAR(100) 用户编码
username VARCHAR(30) 用户名(登录账号)
password VARCHAR(255) 密码(bcrypt 加密)
salt VARCHAR(30) 加密盐(外部盐,与 password 分离存储)
realname VARCHAR(150) 用户姓名
gender INT 性别:1-男 2-女 3-保密
mobile / email VARCHAR(30) 手机号 / 邮箱
avatar VARCHAR(255) 用户头像
status INT 状态:1-正常 2-禁用
dept_id / level_id / position_id INT 部门 / 职级 / 岗位 ID
province_code / city_code / district_code / street_code VARCHAR(30) 省市县街道编码
city_info VARCHAR(255) 省市区信息拼接
address VARCHAR(255) 详细地址
intro / note VARCHAR(255) 个人简介 / 备注
sort INT 排序
is_delete + 四个审计字段 公共字段

唯一索引(与软删除协同):

UNIQUE INDEX uk_tenant_username (tenant_id, username, is_delete)
UNIQUE INDEX uk_tenant_mobile   (tenant_id, mobile,   is_delete)
UNIQUE INDEX uk_tenant_code     (tenant_id, code,     is_delete)

:::tip 为什么唯一索引含 is_delete? 软删除的用户 is_delete=1 仍占唯一索引——把 is_delete 纳入联合唯一后,同名账号删除后可重新注册(新记录 is_delete=0 不与已删记录冲突),同时保证同租户内未删数据用户名唯一。业务层的 uniqueFields 校验与数据库索引双保险。 :::

laravel_role(角色表)

字段 类型 说明
id INT 主键
name VARCHAR(50) 角色名称
code VARCHAR(50) 角色编码
tenant_id INT 租户 ID(角色按租户隔离)
status TINYINT 状态
remark / sort 备注 / 排序

laravel_menu(菜单/权限表)

字段 类型 说明
id INT 主键
parent_id INT 父级 ID(0=顶级)
name VARCHAR(50) 菜单名称
permission VARCHAR(100) 权限标识(如 sys:user:add,菜单即权限)
type TINYINT 类型:0=菜单/目录(可导航) 1=权限节点
path VARCHAR(200) 路由路径
icon VARCHAR(100) 图标
sort / status / remark 排序 / 状态 / 备注

laravel_tenant(租户表)

字段 类型 说明
id INT 主键
name VARCHAR(100) 租户名称
code VARCHAR(50) 租户编码(系统自动生成)
status TINYINT 状态(字典 tenant_status):0=禁用 1=启用
expire_time DATETIME 过期时间(ResolveTenant 中间件校验)
max_user_num INT 最大用户数限制
contact_name / contact_phone 联系人 / 联系电话

laravel_article(文章表)

字段 类型 说明
id INT 主键
title VARCHAR(200) 标题
category_id INT 分类 ID
cover VARCHAR(500) 封面图路径
content TEXT 内容(富文本,含 [IMG_URL] 占位符)
author VARCHAR(50) 作者
status TINYINT 状态(字典 article_status)
sort INT 排序
tenant_id INT 租户 ID

索引策略

推荐索引

-- 用户表:高频查询字段(联合唯一索引见上文)
ALTER TABLE laravel_user ADD INDEX idx_tenant_id (tenant_id);
ALTER TABLE laravel_user ADD INDEX idx_dept_id (dept_id);
ALTER TABLE laravel_user ADD INDEX idx_status (status);

-- 角色关联表:外键索引
ALTER TABLE laravel_user_role ADD INDEX idx_user_id (user_id);
ALTER TABLE laravel_user_role ADD INDEX idx_role_id (role_id);
ALTER TABLE laravel_role_menu ADD INDEX idx_role_id (role_id);
ALTER TABLE laravel_role_menu ADD INDEX idx_menu_id (menu_id);

-- 文章表:常用过滤字段
ALTER TABLE laravel_article ADD INDEX idx_category_id (category_id);
ALTER TABLE laravel_article ADD INDEX idx_status (status);
ALTER TABLE laravel_article ADD INDEX idx_tenant_id (tenant_id);

-- 日志表:按时间查询
ALTER TABLE laravel_login_log ADD INDEX idx_create_time (create_time);
ALTER TABLE laravel_operation_log ADD INDEX idx_create_time (create_time);
ALTER TABLE laravel_job_log ADD INDEX idx_job_id (job_id);

-- 菜单表:树形查询
ALTER TABLE laravel_menu ADD INDEX idx_parent_id (parent_id);

-- 字典项表:按字典 ID 查询
ALTER TABLE laravel_dict_item ADD INDEX idx_dict_id (dict_id);
ALTER TABLE laravel_config_item ADD INDEX idx_config_id (config_id);

-- 城市表:按编码查询
ALTER TABLE laravel_city ADD INDEX idx_area_code (area_code);
ALTER TABLE laravel_city ADD INDEX idx_parent_code (parent_code);

索引设计原则

原则 说明
外键必加 所有 _id 外键字段都应加索引
过滤字段 pageEqFields 中配置的精确匹配字段应加索引
模糊搜索 pageLikeFields 中的字段可考虑全文索引,但 LIKE '%xx%' 无法用普通索引
排序字段 pageOrderBy 中的默认排序字段可加索引
时间字段 日志表的 create_time 必加索引(按时间范围查询)
联合唯一 软删除表的唯一约束必须含 is_delete(见上文)

多数据库支持

支持的数据库

数据库 DB_CONNECTION 值 默认端口 PHP 扩展
MySQL mysql 3306 pdo_mysql
PostgreSQL pgsql 5432 pdo_pgsql
SQL Server sqlsrv 1433 pdo_sqlsrv
Oracle oracle 1521 pdo_oci(自定义 oci 驱动接入)
SQLite sqlite - pdo_sqlite

切换数据库

只需修改 .env 文件,无需改动任何代码:

::: code-group

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=rxthinkcmf.laravel13.naivevue
DB_USERNAME=root
DB_PASSWORD=root
DB_PREFIX=laravel_
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=rxthinkcmf.laravel13.naivevue
DB_USERNAME=postgres
DB_PASSWORD=root
DB_PREFIX=laravel_
DB_CONNECTION=sqlsrv
DB_HOST=127.0.0.1
DB_PORT=1433
DB_DATABASE=rxthinkcmf.laravel13.naivevue
DB_USERNAME=sa
DB_PASSWORD=root
DB_PREFIX=laravel_
DB_CONNECTION=oracle
DB_HOST=127.0.0.1
DB_PORT=1521
DB_DATABASE=rxthinkcmf.laravel13.naivevue
DB_USERNAME=root
DB_PASSWORD=root
DB_PREFIX=laravel_
DB_CONNECTION=sqlite
# DB_DATABASE 指向 database/database.sqlite(默认值)
DB_PREFIX=laravel_

:::

配置文件结构

// config/database.php
return [
    'default' => env('DB_CONNECTION', 'mysql'),
    'connections' => [
        'sqlite'  => [...],
        'mysql'   => [...],
        'pgsql'   => [...],
        'sqlsrv'  => [...],
        'oracle'  => [...],   // 自定义 oci 驱动(AppServiceProvider 注册 DB::extend)
    ],
];

:::tip Oracle 接入说明 Laravel 核心不内置 Oracle 连接器,项目通过 AppServiceProvider 中 DB::extend('oci', ...) 注册自定义驱动,配套 App\Support\Database\{OracleConnection, OracleGrammar, OracleProcessor} 完成分页语法与自增主键回填适配。切换前需安装 pdo_oci 扩展(见 2.1 开发环境准备)。 :::

字段类型映射

通用类型 MySQL PostgreSQL SQL Server Oracle SQLite
自增主键 INT AUTO_INCREMENT SERIAL INT IDENTITY NUMBER + 序列/触发器 INTEGER PRIMARY KEY
字符串 VARCHAR(n) VARCHAR(n) NVARCHAR(n) VARCHAR2(n) TEXT
文本 TEXT TEXT NVARCHAR(MAX) CLOB TEXT
布尔 TINYINT(1) BOOLEAN BIT NUMBER(1) INTEGER
日期时间 DATETIME TIMESTAMP DATETIME2 TIMESTAMP TEXT
小数 DECIMAL(m,n) NUMERIC(m,n) DECIMAL(m,n) NUMBER(m,n) REAL

:::tip 业务代码零修改 Eloquent 的方言层自动处理大部分 SQL 差异,切换数据库只需修改 .env 中的 DB_CONNECTION,业务代码无需任何修改。跨库 DDL 由 DbSchemaBuilder 按驱动生成(Oracle 自增序列与触发器自动创建)。 :::

各数据库安装

数据库的安装与初始化步骤已在 2.1 开发环境准备(含四平台安装命令、扩展启用、Oracle Instant Client)与 2.5 数据库初始化(建库、脚本导入、.env 配置)中完整说明,此处不再重复。

SQL 脚本

项目为每种数据库提供了独立的 SQL 脚本,存放在 document/ 目录下按数据库类型分组:

document/
├── mysql/
│   └── rxthinkcmf.laravel13.naivevue.sql      # MySQL 版本
├── postgresql/
│   └── rxthinkcmf.laravel13.naivevue.sql      # PostgreSQL 版本
├── sqlserver/
│   └── rxthinkcmf.laravel13.naivevue.sql      # SQL Server 版本
├── oracle/
│   └── rxthinkcmf.laravel13.naivevue.sql      # Oracle 版本
└── sqlite/
    └── rxthinkcmf.laravel13.naivevue.sql      # SQLite 版本

各数据库脚本包含完整的表结构定义和初始数据(用户、角色、菜单、字典、城市行政区划等),已针对各数据库的 SQL 语法做了适配,可直接导入使用。

:::warning 本项目 database/migrations/ 为空,建表以 SQL 脚本为准,php artisan migrate 不会创建业务表。导入方法详见 2.5 数据库初始化。 :::

慢查询排查

# MySQL my.cnf / my.ini
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2

:::warning 注意 项目所有查询都通过 Eloquent 查询构建器构建(参数绑定),不会出现原生 SQL 注入。如需排查慢查询,建议开启数据库慢查询日志,而非在代码层面埋点;同时核对 索引策略 中的推荐索引是否缺失。 :::