跳到主内容

WordPress Playground 导入内容:WXR、runPHP、ZIP 快照三种方式实测对比

100%
WordPress Playground 导入内容:WXR、runPHP、ZIP 快照三种方式实测对比

用 WordPress Playground 做演示站、主题预览或测试夹具时,内容从哪来?官方 Playground Handbook 2026 年 9 月 30 日那篇指南给了三条路:WXR XML 导入(importWxr)、 PHP 代码生成(runPHP)、 ZIP 快照恢复(importWordPressFiles)。官方在 Apple M4 Pro 上用 100 篇文章实测过一轮,ZIP 恢复中位数 320 毫秒,WXR 导入 2.21 秒,PHP 生成 2.78 秒——最快和最慢之间差了近 9 倍。但选哪个不取决于速度,取决于你要搬的是内容、数据还是整个站点。

测试数据来自官方 Handbook(2026-07-13 于 Apple M4 Pro / 24GB 内存 / Node 22.16 / WordPress 7.0 / PHP 8.3 / 100 篇文章 / 每方法 5 轮全新站点)。这是单机参考值,不是通用排名。

三种方式速查

方法最适合实际搬运的东西
importWxr站点间共享可移植内容,且不想覆盖目标站已有内容文章、页面、自定义文章类型、分类标签、作者、评论、附件引用
runPHP小而确定的测试夹具,或内容需要自定义逻辑生成PHP 代码通过 WordPress API 创建的任何东西
importWordPressFiles完整还原一个 Playground 演示站数据库 + ZIP 里存在的 WordPress 文件(插件、主题、 uploads)

选择逻辑其实一句话就能说完:只要文章和标签 → WXR;内容是生成出来的或依赖安装配置 → PHP;数据库、媒体、插件、主题、设置必须一起恢复 → ZIP 快照。

方式一:WXR XML 导入

WXR 就是 WordPress 自带的「工具 → 导出」生成的 XML 格式。把它放到 blueprint.json 同目录,然后在 blueprint 里引用:

{
    "$schema": "https://playground.wordpress.net/blueprint-schema.json",
    "landingPage": "/wp-admin/edit.php",
    "preferredVersions": { "php": "8.3", "wp": "latest" },
    "login": true,
    "steps": [
        {
            "step": "importWxr",
            "file": { "resource": "bundled", "path": "/content.xml" },
            "fetchAttachments": false,
            "rewriteUrls": true,
            "importComments": false,
            "authorsMode": "default-author",
            "defaultAuthorUsername": "admin"
        }
    ]
}

几个关键参数值得单独说:

  • fetchAttachments 设为 true 时会下载 WXR 引用的媒体文件。网络传输往往主导总耗时,所以官方基准测试里把它关掉了。
  • authorsMode 可以把导入的作者映射到本地已有用户、或者创建新用户。
  • rewriteUrls 用于把旧站点的 URL 批量替换成新站点地址——从别的域名搬内容时必开。

如果 XML 放在线上而不是随包分发,把 bundled 换成 url 资源引用即可。

优点与代价

优点很实在:用的是 WordPress 官方标准交换格式,文章类型、分类、 post meta 、作者、评论和内容关系都能保住;可以拉附件、重写旧 URL;内容与目标站的核心、插件、主题、设置是分离的;源文件是纯文本 XML,任何编辑器里都能看、能进版本控制、能手工改。

代价集中在五点:

  • 它不是整站克隆。插件、主题、插件自定义表、 options,以及 WXR 表达不了的文件,都得另配 blueprint 步骤。
  • 附件导入要联网,且依赖旧媒体 URL 仍然可访问。
  • 大 XML 的解析时间和内存开销都高于直接恢复一个现成的 SQLite 数据库。
  • 重复导入是「累加」不是「同步」。导入器只创建找不到的分类标签,从不删除已有内容;只有当标题、作者、日期三项都匹配时才会跳过某篇文章。这意味着跑第二遍会得到重复内容。
  • blueprint 会自动安装 WordPress Importer 依赖,在 WXR 导入开始前就多出一段安装时间。
「累加不是同步」这一条最容易踩坑。调试 blueprint 时反复导入同一份 XML,结果数据看起来翻倍了——很多人会以为是导入器有 bug,其实是语义如此。要可重复的夹具,就得用 runPHP 并在代码里先查存在再建。

方式二:用 runPHP 生成内容

runPHP 直接调 WordPress API 。关键是必须先加载 /wordpress/wp-load.php,否则 wp_insert_post() 之类的函数根本不存在。官方基准里生成 100 篇文章的完整代码长这样:

{
    "step": "runPHP",
    "code": "<?php\nrequire_once '/wordpress/wp-load.php';\n\nfor ( $index = 1; $index <= 100; $index++ ) {\n\t$result = wp_insert_post(\n\t\tarray(\n\t\t\t'post_title'   => 'Benchmark post ' . $index,\n\t\t\t'post_content' => '<!-- wp:paragraph --><p>Blueprint import benchmark content.</p><!-- /wp:paragraph -->',\n\t\t\t'post_status'  => 'publish',\n\t\t\t'post_type'    => 'post',\n\t\t),\n\t\ttrue\n\t);\n\tif ( is_wp_error( $result ) ) {\n\t\tthrow new RuntimeException( $result->get_error_message() );\n\t}\n}"
}

代码量最大的真实例子就是官方这段——把 JSON 里的 PHP 写成单行转义字符串,可读性基本为零。官方的建议是:程序大一点就把代码放进一个小插件里,或者拆成多个聚焦的步骤,别在 blueprint 里维护一条几千字符的长字符串。

什么时候值得

runPHP 的真正价值不是「快」或「慢」,而是它能表达另外两种方式表达不了的东西:

  • 完全控制生成的数据及其相互关系(标签层级、菜单结构、指定作者、指定时间序列);
  • 不需要内容文件,不需要联网;
  • 可以在同一次操作里配置 options 、 post meta 、用户、分类法乃至插件专属数据;
  • 写成代码就能做幂等——插入前先查一遍。

但它也有清晰的代价:blueprint 是受信任输入,只跑你信任来源的 PHP;脚本得自己处理报错、重跑、依赖和部分失败;代码可能和某个插件的 API 、数据库模型耦合;逐条创建记录会触发 WordPress hooks 和数据库写入,数据量大时性能会线性下降;比起「导出现有编辑内容」,写自定义 PHP 啰嗦得多。

用 WP API 而不是直接写数据库表

官方明确建议用 WordPress API,而不是直接操作数据库表——这样 hooks 、缓存和数据校验才照常运行。这个建议在 Playground 里尤其重要:很多人在本地用 wpdb 硬插数据觉得快,结果 hook 不触发、缓存不刷新、元数据不自增,排查时间比老老实实用 wp_insert_post() 长得多。

另一个容易被忽略的边界:runPHP 能做的远不止「造内容」。它可以覆盖 options 、可以改数据库、可以装东西。把它当「内容生成器」用很安全,当「任意代码执行器」用就要格外小心来源。

方式三:ZIP 快照恢复

这一步不是「导入内容」,而是整站恢复。它从 ZIP 里解出顶层 WordPress 文件,替换新实例里对应的路径。用 Playground 的「 Download as zip 」导出的文件,包含 wp-content、 SQLite 数据库、 uploads,以及一份用于调整 Playground scope URL 的 manifest 。

{
    "$schema": "https://playground.wordpress.net/blueprint-schema.json",
    "landingPage": "/",
    "preferredVersions": { "php": "8.3", "wp": "latest" },
    "login": true,
    "steps": [
        {
            "step": "importWordPressFiles",
            "wordPressFilesZip": { "resource": "bundled", "path": "/site.zip" }
        }
    ]
}

ZIP 里可以只有 wp-content、可以是一个完整的 WordPress 目录、也可以是套了一层外壳的目录。归档里有多个站点时,或者自动探测根目录不够用,用 pathInZip 显式指定。

它快的原因是显而易见的——没有逐条导入,只是把一份准备好的 SQLite 数据库放回去。 50.5 KiB 的输入换来 320 毫秒中位耗时,对比 WXR 的 106.0 KiB / 2.21 秒。


  1. 版本对齐。确认源和目标实例的 WordPress 、 PHP 、主题、插件版本兼容。这一步会升级导入的数据库并调整 Playground scope URL,但它不是面向任意生产环境迁移的通用工具。

  2. 只信自己的快照。ZIP 里可能含可执行 PHP 和整个数据库。只从可信来源恢复,别从别人分享的 demo 快照直接跑起来。

  3. 记住它是覆盖不是合并。ZIP 里存在的顶层路径会被替换,可能覆盖你已有的站点状态,而不是合并进去。

  4. 别指望挑着导入。它不适合往已有站点里挑几篇文章塞进去——要这个效果请用 WXR 。

  5. 附件多时优先 ZIP 。基准里 WXR 关掉了附件下载,所以 2.21 秒这个数字不含媒体传输成本。如果你的内容依赖大量附件,自包含的 ZIP 才是实际最快的选择。

官方基准数据怎么看

方法输入体积中位数最小最大相对最快
ZIP / importWordPressFiles50.5 KiB320 ms318 ms322 ms1.00x
XML / importWxr106.0 KiB2.21 s2.16 s2.25 s6.90x
PHP / runPHP生成代码2.78 s2.76 s2.80 s8.68x

官方对这组数字的免责声明写得很实在:把它当单台机器上的参考,不要当通用排名。数据形态很关键——附件多的场景偏向自包含 ZIP,WordPress hooks 复杂的项目会拖慢 runPHP,而 WXR 的可移植性可能比绝对速度更值钱。

其他内容来源

Blueprint 还能用两条路拿到内容:importThemeStarterContent 导入主题注册的 starter content,wp-cli 步骤执行 wp post generate 这类命令。当主题自身的 starter content 或 WP-CLI 命令就是演示数据的权威来源时,这两条比三种导入方式都更直接。

相关阅读


只想导入 10 篇文章做主题演示,选哪种?
WXR 。从现有站点「工具 → 导出」全站导出,导出后再手动删到只剩 10 篇,或者用一个干净的测试站导出这 10 篇。 ZIP 需要你先有一个完整 Playground 快照,对新场景来说准备成本反而更高。

为什么我重复导入 WXR,文章数量翻倍了?
这是预期行为,不是 bug 。 WXR 导入是累加式的:它只创建找不到的分类标签,从不删除内容;只有标题、作者、日期三项全匹配才跳过某篇。需要可重复的夹具就改用 runPHP,在代码里先查后建实现幂等。

runPHP 报「 undefined function wp_insert_post 」怎么办?
忘了加载 /wordpress/wp-load.php。runPHP 不会自动加载 WordPress 核心,第一行必须是 require_once '/wordpress/wp-load.php';,然后才能调 wp_insert_post() 这类函数。

ZIP 恢复能把内容导入到已有的 Playground 实例吗?
不建议。importWordPressFiles 会替换 ZIP 里存在的顶层路径,是覆盖语义不是合并。而且它会把快照和当时的 WordPress 、 PHP 、主题、插件、数据库版本绑得更死。要往已有站点加内容,请用 WXR 。

”跑

这篇有帮助吗?
云上的幻象
云上的幻象查看主页

七彩云博客,分享 WordPress 建站实战与 AI 工具测评,覆盖服务器运维、站长工具、软件资源与电商运营干货,专注原创实用的主题插件、网站加速与安全优化教程。

906文章4评论

相关文章

评论 (0)

欢迎你,新朋友,感谢参与互动!文明发言,理性交流 · 首次评论将在审核后展示