文档目录
文章表结构

简介

本文面向内容管理系统开发者,系统化梳理 DouPHP 文章管理模块的数据库表结构设计,重点围绕文章主表与文章分类表的字段设计、状态与时间字段、层级与唯一标识机制、SEO 与统计字段、以及常见 CRUD 查询与优化策略。文档同时给出模型层对表结构的映射与使用方式,帮助读者从“表—模型—查询”全链路理解文章模块的数据设计与实现。

项目结构

文章模块在前后端分别提供模型:

  • 后台模型:用于管理界面数据读写、过滤、排序等。
  • 前台模型:用于列表展示、详情读取、多语言、附件 URL 预热、SEO 字段输出等。
graph TB
subgraph "后台"
A["后台文章模型<br/>admin/model/article/Article.php"]
B["后台分类模型<br/>admin/model/article/ArticleCategory.php"]
end
subgraph "前台"
C["前台文章模型<br/>front/model/article/Article.php"]
D["前台分类模型<br/>front/model/article/ArticleCategory.php"]
end
subgraph "数据库"
T1["dou_article"]
T2["dou_article_category"]
end
A --> T1
B --> T2
C --> T1
D --> T2

核心组件

  • 文章主表(dou_article):承载文章标题、内容、SEO 字段、点击统计、排序、主图、创建时间等核心信息。
  • 文章分类表(dou_article_category):承载分类名称、父级关系、排序、是否同步导航等,支持树形结构与关联业务记录计数。

架构总览

文章模块采用“表—模型—查询构造器”的分层设计:

  • 表层:定义 dou_article 与 dou_article_category 的字段、索引与约束。
  • 模型层:通过 ORM Model 声明表名、可写字段白名单、类型转换、关联关系、默认排序与筛选作用域。
  • 查询层:基于 Scope 与 Prefetcher 组合出高效列表与详情查询,并附带多语言、附件 URL 预热。
classDiagram
class Article_Admin {
+string table = "article"
+array fillable
+array casts
+category()
+scopeFilterByKeyword(query, keyword)
+scopeApplyDefaultOrder(query)
}
class Article_Front {
+string table = "article"
+array casts
+array translatable
+array prefetchers
+category()
+scopePublished(query)
+scopeFilterByArchive(query, archive)
+scopeImageNotEmpty(query)
+scopeApplyDefaultOrder(query)
}
class Category_Admin {
+string table = "article_category"
+array fillable
}
class Category_Front {
+string table = "article_category"
+array translatable
+array prefetchers
}
Article_Admin --> Category_Admin : "belongsTo(category_id)"
Article_Front --> Category_Front : "belongsTo(category_id)"

详细组件分析

文章主表(dou_article)设计

  • 标题与内容
    • 标题:用于列表展示与搜索;支持按标题关键字模糊筛选。
    • 内容:富文本或结构化内容;前台模型支持导出与列表摘要字段。
  • SEO 优化字段
    • keywords、description:用于详情页 SEO 元信息;前台模型将 keywords 纳入多语言覆写范围。
  • 点击统计
    • click:整型计数器,用于统计文章被访问次数。
  • 排序与可见性
    • sort:用于自定义排序;默认列表按 sort ASC、id DESC。
    • status:状态位,前台仅展示已发布(status=1)。
  • 时间与主图
    • created_at:统一时间字段(DATETIME),用于归档筛选与列表展示。
    • image:主图附件,列表时通过附件服务生成 URL。
  • 其他字段
    • category_id:关联分类。
    • slug:URL 友好标识(由升级脚本可见新增与建索引)。
    • defined:键值对扩展字段。
    • operator_type/operator_id:操作者信息(后台写入)。

文章分类表(dou_article_category)设计

  • 层级关系
    • parent_id:自引用父级 ID,形成树形分类结构。
    • 通过 HasCategoryTree trait 提供树形遍历能力。
  • 唯一标识与别名
    • slug:分类的 URL 友好标识(结合升级脚本可知存在索引)。
  • SEO 与展示
    • name:分类名称,支持多语言覆写。
    • keywords、description:分类级 SEO 元信息。
  • 功能开关与排序
    • sync_to_nav:是否同步到导航。
    • icon:分类图标。
    • sort:分类排序。
  • 关联业务记录
    • recordsTable 指向 article,便于统计分类下文章数量。

字段设计说明(聚焦 SEO、统计、排序、时间)

  • SEO 字段
    • 文章:keywords、description 在前台模型中参与多语言与导出,用于详情页 SEO。
    • 分类:name、keywords、description 支持多语言与列表预热。
  • 点击统计
    • click 为整型计数器,适合简单访问量统计场景。
  • 排序
    • 文章:默认 sort ASC、id DESC;后台可通过配置切换排序行为。
    • 分类:sort 控制分类显示顺序。
  • 时间字段
    • created_at:统一 DATETIME 格式,支持归档筛选与格式化输出。
    • 历史兼容:部分旧表曾使用 add_time(UNIX 时间戳),并通过升级脚本迁移至 created_at。

文章状态管理与发布时间

  • 状态管理
    • status:前台通过 scopePublished 限定 status=1 的文章。
    • 后台列表通过 casts 将 status 转换为语言三元组字符串,便于 UI 展示。
  • 发布时间
    • created_at:统一时间字段,支持归档筛选与格式化输出。
    • 历史字段 add_time:在部分旧表中存在,已通过升级脚本迁移至 created_at。

文章分类层级与唯一标识

  • 层级关系
    • parent_id:自引用父级 ID,构建分类树。
    • 通过 HasCategoryTree 提供树形遍历与子节点获取。
  • 唯一标识
    • slug:分类的 URL 友好标识,配合索引提升路由匹配效率。

文章 CRUD 查询示例与优化策略

  • 列表查询
    • 仅已发布:使用 published 作用域过滤 status=1。
    • 关键词筛选:使用 filterByKeyword 按标题模糊匹配。
    • 归档筛选:使用 filterByArchive 按 created_at 时间窗筛选。
    • 默认排序:应用 applyDefaultOrder 保证 sort 与 id 的优先级。
  • 详情查询
    • 通过 findPublishedById 获取单条已发布文章。
  • 图片与多语言预热
    • 使用 prefetchers 批量预热附件 URL 与多语言字段,减少 N+1 查询。
  • 分类关联
    • with('category') 批量加载分类,避免多次 JOIN。
  • 索引建议
    • 对 category_id、created_at、slug 建立合适索引以提升筛选与排序性能。
    • 对 click 字段一般无需索引,除非有高频按点击量排序的场景。
sequenceDiagram
participant Client as "客户端"
participant FrontModel as "前台文章模型"
participant DB as "数据库"
Client->>FrontModel : "请求文章列表"
FrontModel->>FrontModel : "scopePublished()"
FrontModel->>FrontModel : "scopeFilterByKeyword()/scopeFilterByArchive()"
FrontModel->>FrontModel : "scopeApplyDefaultOrder()"
FrontModel->>DB : "SELECT ... WHERE status=1 AND ..."
DB-->>FrontModel : "文章集合"
FrontModel->>FrontModel : "with('category') 批量加载分类"
FrontModel->>FrontModel : "prefetchers 预热 url/语言/附件"
FrontModel-->>Client : "返回文章列表"

依赖关系分析

  • 模型间依赖
    • 文章模型依赖分类模型进行 belongsTo 关联。
    • 分类模型通过 traits 提供树形与关联业务记录能力。
  • 表间依赖
    • dou_article.category_id → dou_article_category.id。
  • 外部依赖
    • 多语言与附件服务通过 prefetechers 与 casts 接入。
graph LR
A["dou_article"] -- "category_id" --> B["dou_article_category"]
A -. "belongs to" .-> B
B -. "HasCategoryTree" .-> B

性能考虑

  • 列表优化
    • 使用 with('category') 批量加载分类,避免 N+1。
    • 使用 prefetchers 预热附件 URL 与多语言字段。
    • 合理使用 scope 组合条件,减少无效扫描。
  • 索引优化
    • 对 category_id、created_at、slug 建立索引。
    • 对频繁排序字段(如 sort)考虑复合索引(如 (sort, id))。
  • 缓存策略
    • 对热门文章列表与分类树结果进行缓存。
    • 对 SEO 元信息(keywords、description)可缓存以减少重复计算。

故障排查指南

  • 列表为空
    • 检查 status 是否为已发布(1)。
    • 检查关键词与归档时间窗是否正确。
  • 分类树异常
    • 检查 parent_id 是否存在环或非法值。
    • 确认 HasCategoryTree 的使用与数据完整性。
  • 多语言未生效
    • 确认 translatable 字段配置与语言预热。
  • 附件 URL 缺失
    • 检查 image 字段是否为空,确认附件服务可用。

结论

DouPHP 文章模块通过清晰的分层设计与合理的字段规划,实现了高效的列表与详情查询、完善的 SEO 支持、灵活的分类层级与排序机制。借助 ORM 的作用域、类型转换与预热机制,开发者可以快速构建高性能的内容页面。建议在大数据量场景下重点关注索引与缓存策略,确保系统的可扩展性与稳定性。

附录

表结构参考(ER 图)

erDiagram
DOU_ARTICLE {
int id PK
int category_id FK
varchar title
text content
varchar keywords
text description
int click
int sort
tinyint status
datetime created_at
varchar image
varchar slug
text defined
varchar operator_type
int operator_id
}
DOU_ARTICLE_CATEGORY {
int id PK
int parent_id FK
varchar name
varchar slug
varchar icon
varchar keywords
text description
tinyint sync_to_nav
int sort
}
DOU_ARTICLE_CATEGORY ||--o{ DOU_ARTICLE : "包含"
添加日期:2026-10-05