study-api-v2/docs/模型配置总结.md

247 lines
6.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 模型配置总结
## 系统字段维护配置状态
### 已启用系统字段维护的模型
#### 学校相关模型
-**School** (`app/Models/Schools/School.php`)
- `$enableSystemFields = true`
- `$enableTenantScope = true`
- 原因:主要业务表,需要完整的审计功能
-**SchoolCampus** (`app/Models/Schools/SchoolCampus.php`)
- `$enableSystemFields = true`
- `$enableTenantScope = true`
- 原因:主要业务表,需要租户隔离
-**SchoolClass** (`app/Models/Schools/SchoolClass.php`)
- `$enableSystemFields = true`
- `$enableTenantScope = true`
- 原因:主要业务表,需要租户隔离
### 关闭系统字段维护的模型
#### 学生相关模型
-**Student** (`app/Models/Students/Student.php`)
- 继承 `Authenticatable`,不是 `BaseModel`
- 使用自己的时间戳字段和认证机制
-**StudentClass** (`app/Models/Students/StudentClass.php`)
- `$enableSystemFields = false` (默认)
- `$enableTenantScope = false` (默认)
- 原因:关联表,不需要系统字段维护
#### 老师相关模型
-**TeacherClass** (`app/Models/Teachers/TeacherClass.php`)
- `$enableSystemFields = false` (默认)
- `$enableTenantScope = false` (默认)
- 原因:关联表,不需要系统字段维护
#### 系统相关模型
-**SystemUserSchoolCampus** (`app/Models/System/SystemUserSchoolCampus.php`)
- `$enableSystemFields = false` (默认)
- `$enableTenantScope = false` (默认)
- 原因:关联表,不需要系统字段维护
-**SystemUserRole** (`app/Models/System/SystemUserRole.php`)
- 已有完整的系统字段注释
- 原因:系统核心表,已有自己的字段管理
-**SystemRole** (`app/Models/System/SystemRole.php`)
- 已有完整的系统字段注释
- 原因:系统核心表,已有自己的字段管理
-**SystemMenu** (`app/Models/System/SystemMenu.php`)
- 已有完整的系统字段注释
- 原因:系统核心表,已有自己的字段管理
-**SystemRoleMenu** (`app/Models/System/SystemRoleMenu.php`)
- 已有完整的系统字段注释
- 原因:关联表,不需要系统字段维护
-**User** (`app/Models/User.php`)
- 继承 `Authenticatable`,不是 `BaseModel`
- 使用自己的时间戳字段和认证机制
## 配置原则
### 启用系统字段维护 (`$enableSystemFields = true`)
**适用场景:**
1. 主要业务实体表
2. 需要审计功能的表
3. 需要软删除的表
4. 需要跟踪创建者和更新者的表
**必要条件:**
- 表中必须包含系统字段:`tenant_id``creator``create_time``updater``update_time``deleted`
- 继承 `BaseModel`
### 启用租户隔离 (`$enableTenantScope = true`)
**适用场景:**
1. 多租户系统的业务表
2. 需要按租户隔离数据的表
3. 用户相关的数据表
**必要条件:**
- 表中必须包含 `tenant_id` 字段
- 继承 `BaseModel`
### 关闭配置 (默认状态)
**适用场景:**
1. 关联表(如用户角色关联、学生班级关联)
2. 日志表(有自己的时间戳管理)
3. 全局共享的配置表
4. 临时表或缓存表
5.`BaseModel` 的认证表
## 数据库字段要求
### 启用系统字段维护需要的字段
```sql
-- 租户ID
tenant_id INT DEFAULT 0 COMMENT '租户ID',
-- 创建信息
creator INT DEFAULT 0 COMMENT '创建者',
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
-- 更新信息
updater INT DEFAULT 0 COMMENT '更新者',
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
-- 软删除
deleted TINYINT DEFAULT 0 COMMENT '删除标识',
-- 推荐的索引
INDEX idx_tenant_id (tenant_id),
INDEX idx_deleted (deleted),
INDEX idx_create_time (create_time),
INDEX idx_update_time (update_time)
```
### 启用租户隔离需要的字段
```sql
-- 租户ID必须
tenant_id INT DEFAULT 0 COMMENT '租户ID',
-- 推荐的索引
INDEX idx_tenant_id (tenant_id)
```
## 使用建议
### 开发新模型时
1. **分析表的性质**
- 是否为主要业务表?
- 是否需要审计功能?
- 是否需要租户隔离?
2. **设置合适的配置**
```php
// 主要业务表
protected $enableSystemFields = true;
protected $enableTenantScope = true;
// 关联表
// 保持默认关闭,不需要显式设置
```
3. **确保数据库结构匹配**
- 添加必要的系统字段
- 创建合适的索引
### 升级现有项目
1. **检查现有模型**
- 确定哪些模型需要启用配置
- 检查数据库字段是否完整
2. **逐步启用**
- 先启用主要业务表
- 测试功能是否正常
- 逐步扩展到其他表
3. **数据迁移**
- 为缺少系统字段的表添加字段
- 填充历史数据的系统字段
## 性能考虑
### 查询性能
1. **为系统字段添加索引**
```sql
ALTER TABLE table_name ADD INDEX idx_tenant_id (tenant_id);
ALTER TABLE table_name ADD INDEX idx_deleted (deleted);
```
2. **合理使用全局作用域**
- 启用租户隔离会在所有查询中添加 `tenant_id` 过滤
- 启用系统字段维护会在所有查询中添加 `deleted = 0` 过滤
### 写入性能
1. **每次保存都会更新系统字段**
- 创建时设置:`creator`、`create_time`、`tenant_id`、`deleted`
- 更新时设置:`updater`、`update_time`
2. **批量操作优化**
- 使用 `DB::table()` 进行批量操作时,系统字段不会自动设置
- 需要手动设置系统字段值
## 常见问题
### Q1: 如何临时跳过系统字段维护?
```php
// 方法1使用 DB::table() 直接操作
DB::table('schools')->where('id', 1)->update(['name' => 'New Name']);
// 方法2临时禁用钩子不推荐
School::withoutEvents(function () {
School::where('id', 1)->update(['name' => 'New Name']);
});
```
### Q2: 如何批量设置系统字段?
```php
// 使用模型的批量操作
$userId = auth()->id();
$tenantId = auth()->user()->tenant_id;
$now = now();
School::whereIn('id', $ids)->update([
'updater' => $userId,
'update_time' => $now,
'tenant_id' => $tenantId,
]);
```
### Q3: 关联表是否需要 tenant_id
关联表通常不需要直接的 tenant_id因为
- 通过关联的主表来控制访问权限
- 查询时通过关联关系自动过滤
- 减少数据冗余
但在某些情况下,为了性能考虑,可能需要添加 tenant_id 字段。
## 总结
通过合理配置BaseModel的系统字段维护功能可以实现
1. **灵活的字段管理** - 根据表的特点选择性启用功能
2. **统一的开发体验** - 所有表遵循相同的配置规则
3. **高效的数据维护** - 自动处理常见的系统字段
4. **安全的数据隔离** - 租户隔离确保数据安全
建议在项目开始时就制定好配置策略,确保系统的一致性和可维护性。