目标:不是重新罗列 20 个实验,而是建立一张可以长期记忆的 WordPress Classic Theme / WP_Query 总体地图。
这 20 章最终可以归纳为一句话:WordPress 先理解请求与数据,再构造查询条件,最后控制结果的顺序、分页与输出。
flowchart LR
R["URL / Request\n浏览器请求"] --> MQ["主查询 Main Query\nadv-02 Default Query"]
MQ --> TH["模板选择\nadv-01 Template Hierarchy"]
TH --> LOOP["主 Loop / 页面输出"]
DATA["数据模型\nadv-03 Post / Meta / Term / Attachment"] --> API["数据读取 API\nadv-04 Functions"]
API --> CQ["自定义查询\nadv-05 WP_Query Basics"]
MQ -.理解主查询与自定义查询的区别.-> CQ
CQ --> G1["身份与分类"]
CQ --> G2["内容与对象"]
CQ --> G3["状态与互动"]
CQ --> G4["时间 / Meta / 媒体"]
G1 --> A6["06 Author"]
G1 --> A7["07 Category"]
G1 --> A8["08 Tag"]
G1 --> A9["09 Tax Query"]
G2 --> A10["10 Search"]
G2 --> A11["11 Post / Page"]
G2 --> A12["12 Password"]
G2 --> A13["13 Post Type"]
G3 --> A14["14 Post Status"]
G3 --> A15["15 Comment Count"]
G4 --> A16["16 Date Query"]
G4 --> A17["17 Meta Query"]
G4 --> A18["18 MIME / Attachment"]
A6 --> SORT["结果排序\nadv-19 Order / Orderby"]
A7 --> SORT
A8 --> SORT
A9 --> SORT
A10 --> SORT
A11 --> SORT
A12 --> SORT
A13 --> SORT
A14 --> SORT
A15 --> SORT
A16 --> SORT
A17 --> SORT
A18 --> SORT
SORT --> PAGE["结果分页\nadv-20 Pagination / Offset"]
PAGE --> OUT["Loop / Pagination UI / 最终输出"]
请求
↓
Main Query
↓
Template Hierarchy
↓
Loop
同时,在页面内部需要额外数据时:
数据模型
↓
WordPress API
↓
WP_Query
↓
查询条件
↓
Order / Orderby
↓
Pagination
↓
Loop / 页面输出
课程为了便于理解,先学习:
adv-01 Template Hierarchy
↓
adv-02 Default Query
但 WordPress 实际处理请求时,更接近:
URL / Request
↓
解析请求
↓
建立 Main Query / query_vars
↓
确定页面状态与 Queried Object
↓
Template Hierarchy 选择模板
↓
模板中的 Loop 输出内容
因此:
adv-01告诉我们 “WordPress 最终选哪个 PHP 模板”。adv-02告诉我们 “WordPress 为什么知道当前是什么页面”。
二者合起来,才是 Classic Theme 最基础的运行模型。
| 章节 | 核心问题 | 需要形成的认识 |
|---|---|---|
adv-01 Template Hierarchy |
WordPress 为什么加载这个模板? | URL 对应页面类型,页面类型决定模板候选顺序 |
adv-02 Default Query |
WordPress 怎么知道“当前是什么页面”? | Main Query、query_vars、Conditional Tags、Queried Object |
这一层解决的是:
页面从哪里来?WordPress 为什么选择当前模板?
| 章节 | 核心问题 | 核心对象 / API |
|---|---|---|
adv-03 Data |
WordPress 的内容到底存成什么? | Post、Post Meta、Term、Term Meta、Attachment |
adv-04 Functions |
已经知道数据在哪里,如何读取? | get_post_meta()、get_term_by()、get_terms()、Attachment API 等 |
这一层解决的是:
WordPress 有哪些数据对象,以及如何直接读取这些对象。
需要建立的数据关系:
Post
├─ Post Meta
├─ Author
├─ Post Type
├─ Post Status
├─ Taxonomy / Term
├─ Comments
└─ Attachment(Attachment 本身也是一种 Post)
| 章节 | 核心问题 | 核心知识 |
|---|---|---|
adv-05 WP_Query Basics |
页面还需要另一组文章怎么办? | new WP_Query()、have_posts()、the_post()、wp_reset_postdata() |
这一章是后面所有 Query 章节的总入口。
最重要的区别:
Main Query
→ WordPress 根据当前 URL 自动创建
Custom WP_Query
→ 开发者在模板中主动创建
后面的 adv-06 ~ adv-20,本质上都在回答:
WP_Query 的
$args到底还能写什么?
从 adv-06 开始,不要把每一个参数看成孤立知识,而应该按照“我要按什么维度筛选内容”来记忆。
author
author_name
author__in
author__not_in
核心问题:
按作者身份筛选 Post。
cat
category_name
category__in
category__and
category__not_in
tag
tag_id
tag__in
tag__and
tag__not_in
tag_slug__in
tag_slug__and
tax_query
├─ taxonomy
├─ field
├─ terms
├─ operator
├─ include_children
└─ relation
三章关系:
Category
Tag
↓
都是 Taxonomy 的具体形式
↓
复杂、多个、自定义 Taxonomy 查询
↓
tax_query
长期最重要的结论:
Category / Tag 是方便参数,
tax_query才是通用 Taxonomy 查询模型。
s
search_columns
回答:
内容中有没有某个搜索词?
p
name
page_id
pagename
post_parent
post__in
post__not_in
post_name__in
回答:
我要的是哪一个 / 哪几个具体对象?
其中 Page 层级要特别记住完整 Path:
page-parent/page-child/page-grandchild
has_password
post_password
回答:
内容是否受密码保护?
post_type
回答:
我要查询 Post、Page、Product 还是 Attachment?
publish
draft
pending
future
private
inherit
trash
any
核心关系:
post_type
→ 这是什么对象
post_status
→ 这个对象现在处于什么生命周期状态
例如:
Attachment
post_type = attachment
post_status = inherit
comment_count
value
compare
回答:
哪些文章的已批准评论数量满足某个条件?
这一章还建立了:
WP_Query
→ 查询 Post
WP_Comment_Query / get_comments()
→ 查询 Comment
不要混淆查询对象。
简单日期:
year
monthnum
day
复杂日期:
date_query
├─ year / month / day
├─ after / before
├─ inclusive
├─ compare
├─ column
└─ relation
核心认识:
简单条件使用顶层日期参数;复杂范围和组合使用
date_query。
meta_query
├─ key
├─ value
├─ compare
├─ type
└─ relation
这是主题 / 插件开发非常重要的一章。
核心判断:
分类、标签、产品类别
→ Taxonomy / tax_query
价格、评分、型号、自定义开关
→ Post Meta / meta_query
数字比较尤其注意:
type = NUMERIC
post_type = attachment
post_status = inherit
post_mime_type = image/jpeg
三个概念必须分开:
attachment
→ Post Type
inherit
→ Post Status
image/jpeg
→ MIME Type
这章实际上把前面的 Post Type + Post Status + Attachment 数据模型重新串联了一次。
查询条件回答的是:
“哪些内容符合条件?”
但得到结果以后,还要解决:
以什么顺序显示?
一页显示多少?
当前是第几页?
这就是最后两章。
orderby
→ 按什么字段排序
order
→ 按什么方向排序
常见:
date
ID
name
comment_count
meta_value
meta_value_num
post__in
rand
最重要的两个区别:
ASC = 升序
DESC = 降序
以及:
文本型 Meta
→ meta_value
数字型 Meta
→ meta_value_num
底层分页参数:
posts_per_page
paged
offset
found_posts
post_count
max_num_pages
上层分页 UI:
主查询
→ the_posts_pagination()
自定义 WP_Query
→ paginate_links()
简单前后翻页
→ previous_posts_link()
→ next_posts_link()
→ posts_nav_link()
不要混淆:
wp_link_pages()
→ 单篇文章正文分页
paginate_comments_links()
→ 评论列表分页
最重要的风险:
固定
offset不要直接和正常paged分页混用。
| # | 实验主题 | 一句话记忆 |
|---|---|---|
| 01 | Template Hierarchy | 当前请求最终使用哪个模板 |
| 02 | Default Query | WordPress 如何建立当前页面状态 |
| 03 | Data | Post / Meta / Term / Attachment 数据模型 |
| 04 | Functions | 使用核心 API 读取 WordPress 数据 |
| 05 | WP_Query Basics | 建立自定义查询并正确恢复全局 Post |
| 06 | Author | 按作者查询 |
| 07 | Category | 按分类查询 |
| 08 | Tag | 按标签查询 |
| 09 | Tax Query | 通用、多条件 Taxonomy 查询 |
| 10 | Search | 按关键词查询 |
| 11 | Post / Page | 按具体 Post / Page / 层级关系查询 |
| 12 | Password | 按密码保护状态查询 |
| 13 | Post Type | 按内容类型查询 |
| 14 | Post Status | 按生命周期状态查询 |
| 15 | Comment Count | 按已批准评论数查询 |
| 16 | Date Query | 按日期、范围与日期组合查询 |
| 17 | Meta Query | 按自定义字段查询 |
| 18 | MIME / Attachment | 按附件 MIME 查询 |
| 19 | Order / Orderby | 控制查询结果排序 |
| 20 | Pagination | 控制分页、Offset 与分页 UI |
如果以后忘记某个参数,不需要先想“第几章”,而应该问下面 6 个问题:
Default Query
Conditional Tags
Queried Object
Template Hierarchy
Post
Page
Product
Attachment
Term
Post Meta
Comment
已有对象直接读取
→ WordPress Data Functions
需要筛选一组 Post
→ WP_Query
作者
分类 / 标签 / Taxonomy
搜索词
具体 Post / Page
密码
Post Type
Post Status
评论数量
日期
Meta
MIME
orderby
order
posts_per_page
paged
max_num_pages
paginate_links()
这 6 个问题,比死记几十个参数更重要。
可复用的分类关系
→ Taxonomy
属于某一篇 Post 的额外属性
→ Meta
例如:
产品类别 = 手机
→ product_cat / Taxonomy
产品评分 = 95
→ Post Meta
Main Query
→ WordPress 根据 URL 自动产生
→ 决定页面状态
→ 参与模板选择
Custom WP_Query
→ 模板执行过程中主动创建
→ 用于额外内容区域
→ 完成后 wp_reset_postdata()
筛选
→ 哪些 Post 可以进入结果集
排序
→ 结果集内部先显示谁
分页
→ 当前只取结果集中的哪一段
不要把三者写成一个模糊的“查询”。
完成全部实验后,应该已经能够独立解释下面这段 WordPress 主题开发流程:
用户访问一个 URL
↓
WordPress 解析请求并创建 Main Query
↓
通过 query_vars / Conditional Tags 得知当前页面类型
↓
Template Hierarchy 选择模板
↓
模板读取主查询数据
↓
需要其他数据时创建 Custom WP_Query
↓
使用 Author / Tax / Search / Type / Status / Date / Meta 等参数筛选
↓
使用 Order / Orderby 控制顺序
↓
使用 Pagination 控制当前数据区间
↓
Loop 输出结果
↓
wp_reset_postdata() 恢复模板环境
如果这一条链能够解释清楚,就说明这 20 个主题不再是 20 份零散代码,而已经组成了一套完整的知识体系。
20 个最小实验已经完成,下一阶段不应该继续无边界增加 WP_Query 参数。
建议按下面顺序继续:
20 章知识地图
✓ 当前完成
↓
统一整理 20 章知识卡片
↓
生成 HTML WordPress 知识库
↓
最后再做 adv-21-theme-project
把分散知识应用到一个完整 Classic Theme
这样可以保持:
先把知识体系固定下来,再用完整项目验证体系。
WordPress Theme Development
│
├─ ① 请求与模板
│ ├─ Default Query
│ └─ Template Hierarchy
│
├─ ② 数据模型
│ ├─ Post
│ ├─ Meta
│ ├─ Term
│ └─ Attachment
│
├─ ③ 数据读取
│ ├─ Core Functions
│ └─ WP_Query
│
├─ ④ 查询条件
│ ├─ Author
│ ├─ Taxonomy
│ ├─ Search
│ ├─ Post / Page
│ ├─ Password
│ ├─ Post Type
│ ├─ Post Status
│ ├─ Comment Count
│ ├─ Date
│ ├─ Meta
│ └─ MIME
│
├─ ⑤ 结果控制
│ ├─ Order / Orderby
│ └─ Pagination / Offset
│
└─ ⑥ 输出
├─ Loop
├─ Pagination UI
└─ Reset Post Data
这就是 adv-01 ~ adv-20 的核心知识骨架。