本文约 3,712 字,预计阅读 10 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:一百个结构相同的页面,难道要建一百次
做服务型站点时经常遇到这种情况:”同城上门维修”有 30 个城市页,每个页面结构完全一样,只换城市名、电话、几个参数;或者产品页有 50 个,字段、区块布局、图集结构一致,只换内容。
手工做法是复制粘贴 HTML,然后在古腾堡里一个块一个块改。用 ACF 的话更痛苦:几十个字段要重新填一遍。Yoast Duplicate Post 解决的正是这件事——它能把一篇文章(连同标题、正文、分类、标签、特色图、自定义字段、甚至子页面)完整复制成一份新的,之后只改差异部分。
插件由 Yoast 团队维护(原作者 Enrico Battocchi),免费版功能已经足够:复制成草稿、批量复制、”重写并重新发布”(Rewrite & Republish)、以及”模板”机制。
原理分析:复制到底复制了什么
复制一篇 WordPress 文章,技术上要处理五类数据:
| 数据 | 是否默认复制 | 说明 |
|---|---|---|
post_title / post_content / post_excerpt |
是 | 可在设置里关掉 |
post_status / post_date / post_name |
可配置 | 默认复制为草稿,slug 会加后缀 |
| 分类与标签 | 可配置 | 某些分类可排除 |
| 特色图与附件 | 可配置 | 注意只是”共用”同一个附件 ID |
| 自定义字段(postmeta) | 可配置 | 部分字段应排除(如浏览量) |
| 子页面(层级) | 可配置 | 适合页面树整体复制 |
这里有两个容易被忽视的细节:
一是”共用”而非”新建”。 复制过来的特色图指向的是同一个附件 ID,两篇文章共用一张图。如果在新文章里删掉特色图,通常不会影响原图(删的是关联关系),但如果你在媒体库里删除原附件,两篇都会没图。
二是有些字段不该被复制。 浏览量统计、表单提交数、_edit_lock、电商的销量数据、第三方插件写入的唯一 ID——复制过去会导致数据错乱。这就是 duplicate_post_blacklist_filter 这类钩子存在的意义。
保姆级实操
第一步:配置复制行为
后台「设置 → Duplicate Post」:
- What to copy:逐项勾选要复制的内容(标题、日期、状态、别名、摘要、正文、特色图、模板、文章形式、分类、附件、子页面);
- Permissions:哪些角色可以使用复制功能(默认管理员与编辑);
- Show links in:复制入口出现在哪里(文章列表行操作、编辑页、顶部工具栏、批量操作下拉);
- Taxonomies:如果只想复制部分分类法,在 Taxonomy 设置里排除;
- Advanced:可以设定复制后的默认状态(草稿 / 待审 / 私密)。
建议配置:状态固定复制为草稿,slug 不复制(避免 city-page-2 这种堆叠),特色图与自定义字段复制,分类复制。
第二步:三种复制方式
- Clone:列表页行操作里的「Clone」,直接生成一份草稿并跳到编辑页;
- New Draft:生成草稿但不跳转,适合批量操作;
- Rewrite & Republish:生成一个待审副本,审核通过后替换原文章(用于大改已发布内容,改动期间线上文章不受影响)。
Rewrite & Republish 是付费版功能,但对于”已收录页面要大幅改版”的场景非常实用:改完提交审核,通过后由编辑一键替换,中间不会出现半改状态。
第三步:排除不该复制的字段
// 复制时排除指定自定义字段(如浏览量、第三方 ID)
add_filter( 'duplicate_post_blacklist_filter', function ( $blacklist ) {
$blacklist[] = '_page_views';
$blacklist[] = '_external_ref_id';
$blacklist[] = '_edit_lock';
$blacklist[] = '_edit_last';
return $blacklist;
} );
// 复制时排除指定的分类法(如"置顶频道"这种手工维护的分类)
add_filter( 'duplicate_post_excludelist_filter', function ( $exclude ) {
$exclude[] = 'featured_channel';
return $exclude;
} );
第四步:控制复制入口的出现位置
// 只对指定文章类型显示复制入口
add_filter( 'duplicate_post_show_link', function ( $show, $post, $context ) {
if ( ! in_array( $post->post_type, array( 'post', 'page', 'city_page' ), true ) ) {
return false;
}
// 已发布的才允许复制重写
if ( 'rewrite_republish' === $context && 'publish' !== $post->post_status ) {
return false;
}
return $show;
}, 10, 3 );
// 顶部工具栏不显示,减少干扰
add_filter( 'duplicate_post_admin_bar', '__return_false' );
第五步:用”模板”批量生成页面
把一篇内容完整、结构标准的文章标记为模板后,就可以反复从它生成新页面,避免拿一篇真实文章当母版(容易误改)。做法是:先建一篇 模板-城市页 的草稿,把区块结构、ACF 字段默认值、图片占位都配好,之后每次新建城市页都从它克隆:
# 批量确认生成结果:列出所有从模板复制出的草稿
wp post list --post_type=city_page --post_status=draft --fields=ID,post_title,post_date --format=table
生成后按城市逐个改标题、正文与字段。如果字段很多,配合 ACF 字段组与前台调用 里的字段设计会更省力。
第六步:核对复制结果
复制完别急着改,先做三项检查:
- 检查 slug 是否重复或带后缀(后台快速编辑里看别名);
- 检查自定义字段是否都带过来了(尤其 ACF 的 Repeater);
- 检查特色图是否是同一张(如果是,决定要不要换)。
常见踩坑
- 复制后 slug 变成
-2-3,一大堆难看的地址。 在设置里关掉”复制别名”,让新文章发布时自动生成 slug。 - 把浏览量、销量这类统计字段也复制了,导致新页面一上线就显示”已有 3 万次浏览”。用黑名单钩子排除。
- 复制了
_edit_lock导致原文章被标记”正在编辑”。 同样应列入黑名单。 - 复制后的页面仍是
publish状态,直接出现在前台。 复制状态务必设为草稿,这是默认行为,别在设置里改回 publish。 - 删除复制页面的特色图,原文章的图也没了。 因为共用同一附件,删除操作要谨慎。
- Rewrite & Republish 副本未提交,长期堆积。 定期清理未提交的重写副本,否则后台一堆同名草稿。
- 案例: 某站用复制功能批量生成 40 个城市页,上线后 Google Search Console 报”重复的 title 与 description”,且部分页面互相 canonical 到同一地址。原因是复制时把 SEO 插件的标题、描述字段也一并复制了,40 个页面标题全叫”同城上门维修”。补救办法是在复制后逐页改写 SEO 标题与描述,并把 SEO 字段加入黑名单不再复制。教训:结构化复制能省的是”结构”,不是”内容”,凡是决定页面唯一性的字段(标题、描述、canonical、主图 alt)都必须逐页重写,否则批量生成的页面在搜索引擎眼里就是重复内容。
总结
Duplicate Post 的适用场景有三类:结构相同的内容批量生成(城市页、产品页、问答)、把已发布文章做一次大改(Rewrite & Republish)、把线上页面搬到测试环境做实验。
配置建议:复制状态固定为草稿、不复制 slug、把统计类与 SEO 唯一性字段列入黑名单、复制入口只保留列表行操作。生成后逐页改标题、SEO 描述与关键字段,别指望复制出来就能直接收录。字段结构的设计可以参考 ACF 字段组与前台调用,而如果复制的对象是自定义文章类型,先确认它已按 Custom Post Type UI 创建自定义文章类型 正确注册。
