本文约 4,138 字,预计阅读 11 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:列表页看不出”这个月发几篇”
WordPress 的文章列表页是按发布时间倒序的,适合找文章,不适合做计划。内容团队真正想看的是:这个月总共安排了几篇、哪天空着、哪天挤了三篇、哪篇还停在草稿没定时间。
于是很多团队用 Excel 或飞书表格排期,然后再回到后台一篇篇设日期——两套数据,必然不同步。Editorial Calendar 这个插件解决的就是”可视化排期”:它在后台提供一个月视图日历,文章以色块形式排在上面,直接拖动就能改发布日期,也能从日历上新建”未排期”的草稿,拖进某天即完成排期。
需要说明的是,这个插件原作者把它交给了 PublishPress 团队维护,功能也基本被 PublishPress 的 Calendar 模块吸收(见 PublishPress 内容审核流程)。如果你已经装了 PublishPress,不必再装它;如果只想要一个轻量排期视图,Editorial Calendar 依然够用。
原理分析:日历只是”改 post_date”的一层皮
理解它的原理,就能预判它能做什么、不能做什么:
- 日历上的每个色块对应一篇文章,位置由
post_date决定,颜色由post_status决定(草稿、待审、定时、已发布各一色); - 拖动色块 = 修改
post_date与post_date_gmt,若日期在未来,post_status会被置为future; - “未排期”区域 =
post_date为默认(草稿通常等于创建时间)或状态为 draft 的文章; - 到了时间点,文章由
future变publish,这个动作由 WP-Cron 执行,钩子是publish_future_post。
所以日历能解决”计划可视化”,解决不了”按时发布”。后者依赖定时任务机制——这是绝大多数”排期没生效”问题的真正原因。
| 现象 | 真正原因 | 解决方向 |
|---|---|---|
| 日历上拖了日期,到点没发 | WP-Cron 没被触发 | 改用系统 crontab |
| 文章显示”错过计划” | 到期时刻无人访问,任务延后跑 | 同上 |
| 拖动后日期跳回原处 | 保存失败/权限不足 | 检查 edit_others_posts |
| 日历只显示部分文章 | 默认筛选了状态或作者 | 调整日历顶部筛选器 |
| 时间差 8 小时 | 时区与 post_date_gmt 不一致 |
检查站点时区设置 |
保姆级实操
第一步:安装与基本视图
后台「Posts → Calendar」(或独立菜单「日历」),默认是月视图,可以切 1 周 / 4 周。顶部有几个筛选器:按状态、按作者、按分类。第一次进去看不到文章时,先确认筛选器是不是卡在某个作者上。
第二步:排一篇新文章
日历右上角「Add Post」(或点某天的空白处)→ 填标题 → 回车,就生成一篇该日期的草稿。再点开它可以补全正文、分类、作者。这样”先排期后写”的流程就成立了:主编先把坑占好,写手再填。
第三步:拖动改期
鼠标按住色块拖到目标日期即可。拖动后注意两件事:
- 状态会随日期变化——拖到未来会变成”已定时”;拖回过去不会自动发布,仍是草稿;
- 日期变了,固定链接里的日期结构(若用
/%year%/%monthnum%/%postname%/)也会变,已经收录的旧链接会 404,需要按 批量替换与跳转处理 的思路补 301。
第四步:批量改期(脚本版)
如果要整体延后一周,一个个拖太慢,用 WP-CLI 或脚本:
# 先看清有哪些待发布内容
wp post list --post_status=future --fields=ID,post_title,post_date --format=table
# 单篇改期
wp post update 123 --post_date="2026-10-20 09:00:00" --post_status=future
代码版(注意同时写 post_date 与 post_date_gmt,否则时区会错):
$ids = array( 101, 102, 103 );
$shift = 7 * DAY_IN_SECONDS; // 整体延后 7 天
foreach ( $ids as $id ) {
$post = get_post( $id );
if ( ! $post ) {
continue;
}
$new_date = gmdate( 'Y-m-d H:i:s', strtotime( $post->post_date_gmt ) + $shift );
$new_date_gmt = get_gmt_from_date( $new_date );
wp_update_post( array(
'ID' => $id,
'post_date' => $new_date,
'post_date_gmt' => $new_date_gmt,
'post_status' => 'future',
'edit_date' => true,
) );
}
第五步:处理”错过计划”的漏发文章
add_action( 'init', function () {
// cron 自己触发时不参与,避免递归
if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
return;
}
// 每分钟级别的兜底:只处理已经到点的 future 文章
$ids = get_posts( array(
'post_type' => 'post',
'post_status' => 'future',
'posts_per_page' => 20,
'fields' => 'ids',
'date_query' => array(
array( 'column' => 'post_date_gmt', 'before' => current_time( 'mysql', true ) ),
),
) );
foreach ( $ids as $id ) {
wp_publish_post( $id );
}
} );
这段代码只是兜底,根本解法仍是把 WP-Cron 交给系统 crontab(见 WP-Cron 与系统 cron 配合配置)。兜底逻辑建议加上限流,避免每次请求都查库。
第六步:让日历只显示”我的”
多人协作时,日历默认显示所有人的文章,会显得很挤。用筛选器选作者,或在代码层面限制编辑只能看到自己的:
add_action( 'pre_get_posts', function ( $query ) {
if ( ! is_admin() || ! $query->is_main_query() ) {
return;
}
if ( 'edit.php' !== ( get_current_screen()->base ?? '' ) ) {
return;
}
if ( current_user_can( 'manage_options' ) ) {
return;
}
$query->set( 'author', get_current_user_id() );
} );
常见踩坑
- 拖了日期但没发布,误以为是插件坏了。 排期 ≠ 发布,后者靠 cron。
- 时区错了 8 小时。 只改
post_date不改post_date_gmt,前台显示的发布时间会与预期不符。用get_gmt_from_date()转换。 - 改期后旧链接 404。 日期型固定链接结构下改发布日期等于换 URL,必须补跳转。
- 日历里看不到自定义文章类型。 默认只显示文章(
post),产品、案例等类型需要插件支持或在 PublishPress 的日历里配置。 - 大量
future文章堆积拖慢后台。 部分列表查询会带上日期条件,建议定期清理过期未发的草稿。 - 拖到过去的日期期望”补发”。 WordPress 不会把草稿自动变已发布,补发要手动改状态。
- 案例: 某内容站一次性排了 30 篇稿子到未来两个月,日历上看得很整齐。三个月后运营发现有一半没发,状态卡在”已定时”并显示”错过计划”。排查发现站点上了全页缓存,访客请求不进 PHP,WP-Cron 从未被触发过。改成系统 crontab 后正常,但已经错过的 30 篇需要逐个确认是否还有效再手动发布。教训:排期工具的可靠性完全建立在定时任务之上,上线日历前先验证一篇定时文章能否准时发布。
总结
Editorial Calendar 的价值在于把”发布计划”从表格搬回后台,让排期、改期、补坑都在一个视图里完成,避免两套数据不同步。它适合 1–5 人的内容团队;团队再大、需要状态流转和审批时,就该上 PublishPress 的完整方案。
上线前的验收清单:定时一篇文章到 5 分钟后,确认它真的自动发布了(这一条同时验证了 cron);确认时区与后台「设置 → 常规」里的时区一致;确认改期后旧链接有 301;确认自定义文章类型是否需要出现在日历上。流程化协作(状态流转、通知、分工)需要另配专门的工作流插件。
