Cockpit 核心概念精讲:Collections、Singletons 与 Trees 到底该怎么选?
【免费下载链接】CockpitCockpit Core - Content Platform项目地址: https://gitcode.com/gh_mirrors/cockp/Cockpit
Cockpit CMS 是一款开源的 headless 内容平台,它最迷人的地方在于:你不需要写一行后端代码,就能通过动态内容模型快速搭建出网站、API 甚至整个应用的数据层。而这一切的起点,就是创建内容模型时首先要面对的选择题——Collections(集合)、Singletons(单例)与 Trees(树),三种类型分别对应什么样的内容结构?新手很容易在这第一步就卡住。这篇文章用最通俗的语言,帮你一次搞清楚三者的区别与适用场景,从此建模型不再纠结。
一、先搞懂一个前提:什么是内容模型?
在 Cockpit 中,内容模型(Model)是一套字段定义的模板,相当于"数据结构的说明书"。你在后台创建一个模型后,Cockpit 会自动帮你生成对应的存储结构、管理界面以及 REST / GraphQL 查询接口。
在后台点击"创建模型"时,你首先要选的,就是这个模型的type(类型):collection、singleton还是tree。选择不同,后续的内容管理方式和 API 查询方式完全不同。
小提示:模型定义的源码位于
modules/Content/Helper/Model.php,其中create()方法会校验模型类型并写入配置,默认类型就是collection。
二、Collections:适合"成批出现"的同类内容
Collections(集合)是最常用、也最直观的类型。它适合承载"同一种结构、有多条记录"的内容,比如:
- 📝 博客文章列表
- 🛍️ 商品目录
- 📰 新闻动态
- 👥 团队成员介绍
集合的特点是一张"表"里有很多条记录(items),每条记录结构相同但内容不同。Cockpit 为集合提供了最完整的能力:
- 批量管理:支持批量修改、批量发布、克隆(clone)等操作,对应源码
modules/Content/Controller/Collection.php中的batchUpdate()、updateState()等接口; - 灵活的列表视图:可以保存多种筛选视图,方便运营人员切换视角;
- 强大的查询:支持 MongoDB 查询语法,可过滤、排序、分页、字段投影,还能通过
populate自动填充关联内容。
典型场景举例
一个电商网站的商品模型,用 Collection 再合适不过:
| 场景 | 说明 |
|---|---|
| 商品列表页 | 分页加载、按价格/上架时间排序 |
| 分类筛选 | 用$gte/$lte做价格区间查询 |
| 搜索 | 用$regex做模糊匹配 |
三、Singletons:只为"全站仅一份"的内容而生
Singletons(单例)天生只有一条记录,没有列表的概念。它适合承载那些"一个站点只有一份"的全局内容,比如:
- 🏠 首页配置(轮播图、主打文案、SEO 信息)
- ⚙️ 网站全局设置(联系方式、社交链接)
- 📄 关于我们、联系我们等单页内容
从源码modules/Content/Controller/Singleton.php可以看到,整个控制器里几乎只有一个item()方法——因为它不需要列表、不需要批量操作,打开就是直接编辑唯一的那条数据。后台界面也因此更简洁,编辑人员不用面对"列表页再点进去"的繁琐流程。
为什么不用 Collection 代替?
你当然可以用一个只允许添加一条数据的 Collection 来模拟,但 Singleton 的价值在于:
- 后台体验更好:打开即编辑,少一层跳转;
- API 更简单:直接
GET /api/content/item/homepage就能取到内容,不需要传 id 或 filter。
四、Trees:天生适合"有层级"的内容
Trees(树)用于承载带有父子层级关系的内容,比如:
- 🗂️ 商品分类(父分类 → 子分类 → 孙分类)
- 🧭 导航菜单
- 📚 文档目录 / FAQ 分组
树的结构在底层通过_pid(父节点 ID)和_o(同级排序)两个字段来维护,对应源码modules/Content/Controller/Tree.php。这套实现带来了两个非常实用的特性:
- 拖拽排序:后台可以直接拖拽调整顺序与层级,通过
updateOrder()保存; - 递归删除:删除一个父节点时,Cockpit 会通过
_remove()递归删除其下所有子节点,不会留下"孤儿数据"。
典型场景举例
比如一个"帮助中心",文档可以这样组织:
帮助中心(根) ├── 账户管理 │ ├── 注册与登录 │ └── 找回密码 ├── 订单相关 │ ├── 下单流程 │ └── 退款规则这样的层级结构用 Tree 表达,前台导航和面包屑都能轻松生成。
五、一张表看懂三者的核心区别
| 对比维度 | Collections 集合 | Singletons 单例 | Trees 树 |
|---|---|---|---|
| 数据量 | 多条记录 | 仅一条记录 | 多条记录 |
| 层级关系 | ❌ 无 | ❌ 无 | ✅ 有父子层级 |
| 后台交互 | 列表 + 详情 | 直接编辑 | 树形拖拽 |
| 排序方式 | 按字段排序 | 不适用 | 同级手动排序 |
| 典型用途 | 文章、商品、成员 | 首页、站点设置 | 分类、导航、目录 |
| 控制器示例 | Collection.php | Singleton.php | Tree.php |
六、三分钟判断法:到底该选哪个?
面对新需求时,按下面三个问题快速决策:
- 这个内容在站点上是否只出现一份?是 → 选Singleton。
- 这些内容之间是否存在父子层级关系?是 → 选Tree。
- 以上都不是,就是一批结构相同的记录?→ 选Collection。
再补充两个进阶判断技巧:
- 内容之间有关联怎么办?三种类型都支持
contentItemLink字段进行内容关联,配合populate参数可以自动把关联内容展开,无需升级类型; - 混合需求怎么办?一个站点可以同时存在多种模型,例如"商品"用 Collection、"商品分类"用 Tree、"站点配置"用 Singleton,三者各司其职,互不冲突。
七、小实践:在 Cockpit 里搭建一个内容结构
假设你要做一个"极简博客",只需三步:
- 文章模型→ 选 Collection,字段加
title(text)、content(wysiwyg)、published(boolean)、tags(tags); - 分类模型→ 选 Tree,字段加
name(text)、slug(text); - 站点设置模型→ 选 Singleton,字段加
site_name(text)、logo(asset)。
创建完成后,Cockpit 会自动为每个模型生成 REST API 和 GraphQL 接口。比如文章列表的 REST 请求就是:
GET /api/content/items/blog?filter={"published":true}相关的接口定义可以在modules/Content/api.php中查看,内容增删改查的核心逻辑则封装在modules/Content/Helper/Content.php中。
八、总结:选择没有对错,只有合不合适
Collections、Singletons 与 Trees 是 Cockpit CMS 内容管理的三大基石,它们各自擅长处理"列表型、单体型、层级型"三种不同的内容结构。只要记住一句话——"成批的用 Collection,单份的用 Singleton,有层级的用 Tree"——绝大多数场景都能轻松对号入座。
选对了类型,不仅后台操作更顺手,前台的查询接口也会更简洁高效。如果你正在评估或刚刚上手 Cockpit,不妨现在就打开后台,用这三种类型各建一个模型试试,感受一下它们的不同手感,很快你就能形成自己的判断直觉了。
【免费下载链接】CockpitCockpit Core - Content Platform项目地址: https://gitcode.com/gh_mirrors/cockp/Cockpit
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考