适用版本:EspoCRM 9.2.2+
你以为多对多必须建中间表?在 EspoCRM 里,手写 SQL 往往是你自己给自己埋雷。
TL;DR
entityDefs.links+relationName决定关系与中间表scopes决定实体能不能被管理与配置clientDefs + layouts决定用户界面”看不看得到、用不用得起来”rebuild是让系统把元数据变成真实结构的开关
1. 场景:什么时候需要多对多
很多 CRM 场景都需要多对多关系:
- 一个记录关联多个标签、多个分类
- 一个项目关联多个联系人、多个资源
- 一个工单关联多个参与人、多个附件
很多人第一反应是:建中间表、写迁移 SQL。这在 EspoCRM 里往往是最差的选择——你会绕过系统的元数据机制,升级时痛苦指数爆炸。
我们推荐的路线:只写配置 → rebuild → EspoCRM 自动创建表结构。
2. 目标:用一套最小配置打通”能看见、能选择、能保存”
多对多不是”数据能存进去”就完事了。真正能交付给业务用,至少要满足:
- 关系在实体定义里存在(后端能存)
- 关系在界面上可见(前端能选)
- 权限与作用域可控(ACL 不出事)
- rebuild 后自动生成/更新结构(可升级)
3. 关键机制:relationName 决定中间表
你可以把 EspoCRM 的自动建表理解为:
entityDefs 里声明了关系 → rebuild 生成实际表结构。
flowchart TD A[entityDefs: fields + links] --> B[rebuild] B --> C[(主表自动创建/更新)] B --> D[(中间表按 relationName 自动创建)] B --> E[前端元数据缓存更新]
在 links 中给同一段关系设置同一个 relationName,就是告诉系统:
- 这是同一个关联(正反两侧一致)
- 中间表应按这个名字生成(内部映射)
4. 配置最小闭环(示例:EntityA ↔ EntityB)
用中性实体名演示:
CItem:条目CTag:标签
4.1 定义实体(entityDefs)
1 | { |
另一侧:
1 | { |
4.2 定义作用域(scopes)
如果 scopes 不完整,菜单不显示、权限无法配置、布局无法编辑。
1 | { |
4.3 让关系在 UI 可见(clientDefs + layouts)
只写 entityDefs,用户会说”加了关系,但页面上看不到”。需要两层:
clientDefs:关系面板声明(relationshipPanels)layouts:字段/面板落位(edit/detail)
1 | { |
布局示例:
1 | [ |
5. rebuild 之后会发生什么
- 系统为
cItemTag自动生成中间表 - 两侧实体的关联可在 UI 面板中维护
- ACL 生效:不同角色看到的范围可控
6. 部署与验证
1 | # 逐文件复制 |
验证清单:
- 后台能看到两个实体的菜单入口
- 编辑页面能选择关联记录
- 保存后关系面板能看到关联列表
- 不同角色下 ACL 表现符合预期
7. 常见坑
- scopes 配置缺失导致”菜单不显示/权限不可配”
- layouts 没放字段导致”后端有关系,前端看不到”
- 忘记 rebuild 导致”改了配置不生效”