TYPO3迁移至Drupal:内容、用户与URL完整保留
你的预发布服务器完成TYPO3缓存重建——一条内容变更需要四十三秒,而这个过程本应只需两秒。前端开发刷新浏览器,看到更新,然后低声嘟囔一些关于TypoScript的内容,这些话你大概不该在站会上重复。这幕戏每天都在欧洲各地的企业中上演,那些被TYPO3支撑了二十年的政府门户网站和公司网站。这个CMS在技术上仍在运行。但Drupal的组件优先架构、其无头工具包,以及十倍规模的贡献者基础使得迁移谈话变得不可避免。问题不在于是否要迁移——而在于如何迁移8000个页面、保留二十年的URL价值,并在过渡期间让你的内容编辑保持理智。在过去十八个月里,我们已经执行过这个计划六次,而干净迁移与灾难之间的差异取决于你在第一周做出的四个决策。
在过去几年里,我深入参与了几个TYPO3到Drupal的迁移项目,这是一段相当的旅程,需要解开现实中的内容模型。它们通常是一团乱麻。这份指南是我希望在第一次迁移前有人递给我的东西。我将涵盖所有细致的技术细节、规划必做项,以及那些令人讨厌的陷阱,如果你不小心应对,它们可能会摧毁你的时间表。
目录
- 为何组织离开TYPO3
- TYPO3与Drupal:诚实的比较
- 迁移前审计与规划
- 内容建模:TYPO3映射至Drupal
- 迁移工具与技术方法
- 处理TYPO3 TypoScript与扩展
- URL结构与SEO保留
- 迁移后走向无头架构
- 时间表、成本与人员估算
- 迁移后检查清单
- 常见问题

为何组织离开TYPO3
先说明白:TYPO3不是一个糟糕的CMS。它极其灵活,原生支持多站点和多语言设置,在DACH地区尤其拥有忠实的粉丝群体。那么为什么人们要跳船呢?
我听到的基本上都是同样的理由:
**开发者可用性。**在中欧之外,找TYPO3开发者就像大海捞针。另一方面,Drupal根据Drupal.org 2024年社区报告声称全球约有130万名开发者。TYPO3?远不如此。如果你的资深TYPO3开发者决定离职,填补这些空缺可能需要很久。
**生态系统势头。**随着2024年底Drupal 11的发布,在管理UI、新的recipes系统和强大的API优先功能上取得了巨大进展。当然,TYPO3 v13很扎实,但Drupal的创新速率,特别是在无头设置方面,明显更快。
**无头/解耦架构。**计划为一个漂亮的Next.js或Astro前端提供内容?Drupal的JSON:API和GraphQL插件经验丰富。TYPO3有自己的无头扩展,但它不那么成熟,支持者较少。
**总体拥有成本。**托管TYPO3通常花费更多。它的专业化基础设施意味着你最终可能要花更多钱。Drupal的内容可以在几乎任何地方运行,从Pantheon到Acquia,甚至基本的LAMP堆栈也能让它运行良好。
TYPO3与Drupal:诚实的比较
在匆忙迁移之前,确保Drupal真正会解决你的痛点。以下是2026年的情况:
| 功能 | TYPO3 v13 | Drupal 11 |
|---|---|---|
| 内容建模 | 灵活但依赖TCA | Entity/Field系统与字段管理UI |
| 多语言 | 卓越的原生支持 | 同样卓越的原生支持 |
| 多站点 | 标准多站点与内容树 | 可能,通常更适合Domain Access或独立安装 |
| 无头/API | 有无头扩展 | JSON:API核心,GraphQL贡献 |
| 模板 | Fluid模板+TypoScript | Twig模板 |
| 扩展/模块生态 | TER上约1,800个扩展 | Drupal.org上50,000+个模块 |
| 管理UI | 强大但陈旧(v13即将改进) | Drupal 11中光滑现代 |
| 开发者社区 | 约500名活跃贡献者 | 8,000+名活跃贡献者 |
| 托管选项 | 自托管或专业 | 自托管、Pantheon、Acquia、Platform.sh、Lagoon |
| PHP要求 | PHP 8.2+ | PHP 8.3+ |
| 典型代理费率 | €100-180/小时(DACH地区) | $80-200/小时(全球) |
TYPO3的页面树模型是一个罕见的瑰宝。习惯于在TYPO3中管理复杂页面层级的编辑可能会发现Drupal的方式——内容类型和分类的结合——需要一些调整。安排一些编辑培训来缓解这种过渡。
迁移前审计与规划
这个阶段决定了大多数迁移的命运。成功在于规划,而非技术时间。
内容清单
首先审计你的TYPO3设置中的所有内容:
- **页面:**拉出页面树,记录你正在使用的每个
doktype(页面类型)。 - **内容元素:**每个
CType(内容类型)都需要关注——无论是文本、带图像的文本、HTML还是通过mask或content_defender的自定义内容。 - **扩展:**记录你拥有的每个扩展。找出是否有Drupal等价物。
- **文件引用:**TYPO3的FAL(文件抽象层)处理媒体。将这些映射到Drupal的媒体位置。
- **后端用户和权限:**TYPO3的复杂后端用户组,带有页面和字段级别的访问权限,应该整齐地转换为Drupal角色和权限。
这是一个来自你的TYPO3数据库的内容元素摘要的便捷SQL查询:
SELECT CType, COUNT(*) as count
FROM tt_content
WHERE deleted = 0 AND hidden = 0
GROUP BY CType
ORDER BY count DESC;
通过这个,你可以快速了解你正在处理的内容类型。在一个案例中,我发现了一个TYPO3实例拥有40多个自定义内容元素类型,其中只有十几个被积极使用。不要拖累死重量。
保留什么,删除什么
这是你清理房间的机会。使用内容审计工具如Screaming Frog或Sitebulb来找出:
- 过去一年中没有流量的页面
- 重复或几乎相同的内容
- 破损的内部链接
- 孤立的媒体文件
通常,大型TYPO3迁移中有30-50%的内容被删除。更少的页面意味着更快的迁移。

内容建模:TYPO3映射至Drupal
卷起你的袖子。这是重型知识工作。TYPO3和Drupal处理内容的方式非常不同。
TYPO3的模型
TYPO3围绕页面展开。一切都塞进页面树中。内容元素(tt_content中的记录)插入页面的列中(colPos)。通过Extbase模型或TCA定义的自定义记录存在于单独的表中,但通常从页面链接。
Drupal的模型
Drupal全是关于实体。你创建内容类型(节点包),每个都有专用字段。页面只是许多内容类型中的一个。分类法、段落(使用段落模块),以及布局构建器主导结构化内容组合。
映射
这是我用作指南针的典型映射表:
| TYPO3概念 | Drupal等价物 |
|---|---|
| 页面(doktype:standard) | 节点(内容类型:Page) |
| 页面(doktype:shortcut) | URL重定向 |
| 页面(doktype:link) | 带链接字段的节点或重定向 |
| 内容元素(CType:text) | 段落类型或正文字段 |
| 内容元素(CType:image) | 媒体实体引用 |
| 内容元素(CType:textpic) | 带文本+媒体的段落类型 |
| 内容元素(CType:gridelements) | 布局构建器部分 |
| FAL文件引用 | 媒体实体 |
| sys_category | 分类法术语 |
| fe_users | Drupal用户实体 |
| be_users | 带管理员角色的Drupal用户实体 |
| TypoScript模板 | Twig模板 |
| Extbase插件 | 自定义Drupal模块 |
| Mask/DCE内容元素 | 段落类型 |
最大的转变?将内容元素移至段落。TYPO3在页面列中堆叠内容元素,这与Drupal的段落模块相映成趣。编辑从可重用段落类型中堆叠页面——这出人意料地无缝。
迁移工具与技术方法
Drupal的迁移API太棒了。但要注意,它缺乏本地TYPO3源插件。你将需要创建一些自定义源插件来从TYPO3的数据库中提取。
方法1:直接数据库迁移
将Drupal的迁移API直接插入你的TYPO3 MySQL/MariaDB数据库:
// TYPO3页面的迁移源插件示例
namespace Drupal\typo3_migrate\Plugin\migrate\source;
use Drupal\migrate\Plugin\migrate\source\SqlBase;
use Drupal\migrate\Row;
/**
* @MigrateSource(id = "typo3_pages")
*/
class Typo3Pages extends SqlBase {
public function query() {
return $this->select('pages', 'p')
->fields('p', ['uid', 'title', 'slug', 'abstract', 'doktype', 'crdate', 'tstamp'])
->condition('p.deleted', 0)
->condition('p.hidden', 0)
->condition('p.doktype', [1, 4], 'IN');
}
public function fields() {
return [
'uid' => $this->t('Page ID'),
'title' => $this->t('Page title'),
'slug' => $this->t('URL slug'),
'abstract' => $this->t('Abstract/summary'),
];
}
public function getIds() {
return ['uid' => ['type' => 'integer']];
}
public function prepareRow(Row $row) {
// 加载关联的内容元素
$pid = $row->getSourceProperty('uid');
$content = $this->select('tt_content', 'tt')
->fields('tt')
->condition('tt.pid', $pid)
->condition('tt.deleted', 0)
->orderBy('tt.sorting')
->execute()
->fetchAll();
$row->setSourceProperty('content_elements', $content);
return parent::prepareRow($row);
}
}
我喜欢这个方法。它是关于拥有完全控制权,让你在你的代码库中处理TYPO3的特殊性(如软删除和工作区覆盖)。
方法2:通过JSON或XML导出/导入
有些团队选择将TYPO3内容导出为结构化格式(比如通过自定义TYPO3扩展或CLI命令),然后将其导入到Drupal中。当然,这增加了一层,但当你对在迁移过程中维护直接数据库连接感到担忧时,它会派上用场。
方法3:混合与手动审查
有一个更小的网站(少于500页)?将结构化数据迁移自动执行,同时手工制作关键登陆页面可以很好地工作。这看起来可能很基础,但当内容与TYPO3特定的渲染逻辑交织时,自动化迁移通常会产生胡言乱语。
处理TYPO3 TypoScript与扩展
TypoScript
让我们直言不讳:TypoScript不会迁移。它是一种TYPO3特定的配置语言,在其他地方没有真正的对应物。你的工作是用外行术语记录每个TypoScript模板的用途,然后将其重建为Twig模板和Drupal配置。这很痛苦但必要。
扩展
这是常见TYPO3扩展及其Drupal对应物的便捷比较:
| TYPO3扩展 | Drupal等价物 |
|---|---|
| news | 核心内容类型+视图 |
| powermail | Webform模块 |
| solr (ext:solr) | 搜索API+Solr |
| realurl / routing | Pathauto+核心路由 |
| gridelements | 布局构建器或段落 |
| mask | 段落 |
| tt_address | 自定义内容类型或CiviCRM |
| ke_search | 搜索API |
| femanager | 用户模块+自定义 |
| cal/events | 自定义内容类型+视图 |
自定义Extbase扩展需要改写为Drupal模块。没有捷径——确保为其预算。
URL结构与SEO保留
搞砸这个,你会失去有机流量。我见过组织在迁移后由于处理不当的重定向而失去了高达40%的搜索流量。
步骤
- **从TYPO3导出所有URL。**使用CLI工具或爬虫获取每个索引URL。
- **将这些映射到Drupal URL。**使用Drupal的Pathauto生成URL别名,尽可能贴近现有URL。
- **为所有改变的内容创建重定向。**在Drupal中部署重定向模块。对于大量重定向,通过CSV导入。
- **处理语言前缀。**TYPO3使用
/de/、/en/、/fr/——确保Drupal的语言设置反映这一点。 - 立即向Google Search Console提交更新的站点地图。
# Drupal重定向模块的重定向导入CSV格式示例
source,redirect,status_code,language
/alte-seite,/new-page,301,de
/old-page/subpage,/new-page/subpage,301,en
/kontakt,/contact,301,de
专业提示:在迁移后最少保持旧TYPO3实例在线(尽管只读),保持三个月。你会发现遗漏的URL。
迁移后走向无头架构
Drupal在走向解耦前端的道路上闪闪发光。有了Drupal 11,JSON:API模块坚如磐石,无头Drupal生态系统蓬勃发展。
如果你正在考虑无头方法——而在2026年,对于大多数内容驱动的网站,这值得考虑——我们在/solutions/headless-cms-development上深入讨论过这个。
将流行的前端与Drupal配对:
- Next.js——领头羊。Chapter Three的
next-drupal让事情变得容易。我们在/capabilities/nextjs-development上广泛讨论了它。 - Astro——非常适合内容繁重且客户端不太复杂的网站。参见/capabilities/astro-development。
- Nuxt——如果Vue是你的游乐场。
首先迁移到Drupal的好处是使用Drupal的默认Twig前端启动。稍后,你可以切换到解耦的。不要同时尝试两个迁移——那是在要求项目混乱。
时间表、成本与人员估算
来自我参与过的项目或有准确数据的项目的真实数字(近年):
| 网站大小 | 页面 | 时间表 | 预算范围 | 团队 |
|---|---|---|---|---|
| 小 | <500页 | 2-3个月 | $30,000-60,000 | 2-3名开发者 |
| 中 | 500-5,000页 | 4-6个月 | $60,000-150,000 | 3-5名开发者 |
| 大 | 5,000-50,000页 | 6-12个月 | $150,000-400,000 | 5-8名开发者 |
| 企业 | 50,000+页 | 12-18个月 | $400,000-1,000,000+ | 8-15名开发者 |
这些包括从发现、内容建模、迁移、前端主题设计、QA和编辑培训的所有内容。持续维护不包括在内。
最大的成本因素不仅仅是页面数量——它是复杂性。一个有30个自定义内容类型和4种语言的2,000页网站成本将高于一个简单的10,000页网站。
迁移后检查清单
不要跳过这个清单。相信我。
- 验证所有重定向。确保它们是301。
- 用你的新站点地图更新Google Search Console。
- 测试所有表单:联系、新闻通讯、登录。
- 确保每种语言的多语言内容准确性。
- 准确迁移媒体文件,带有替代文本和元数据。
- 检查每个角色的编辑权限。
- 捕获性能指标(Core Web Vitals)。
- 验证分析跟踪(GA4事件、目标)。
- 配置并测试CDN/缓存。
- 启用安全标头(CSP、HSTS)。
- 测试备份和灾难恢复系统。
- 完成编辑培训并提供文档。
- 保持旧TYPO3实例处于只读模式可用。
常见问题
TYPO3到Drupal的迁移通常需要多长时间?
对于中等规模的网站(500-5,000页),从开始到启动大约需要4-6个月。第一个月?纯发现和内容建模。迁移脚本通常需要6-8周的工作。QA和编辑培训?再算上一个月。如果这是一个复杂的多语言、多站点设置,带有自定义扩展,你正在看9-12个月。
我可以自动迁移TYPO3内容,或者需要手动操作?
像页面、新闻记录或类别这样的结构化内容?绝对可以使用Drupal的迁移API自动完成。但TYPO3的复杂渲染逻辑内容可能需要一些手动护理。大多数迁移?大约70-80%自动,20-30%手动。
在迁移期间我会失去Google排名吗?
不会,如果你对重定向很小心。为任何URL更改设置301,尽可能坚持你的URL结构,立即提交更新的站点地图。你可能会看到下降,比如2-6周。但反弹是典型的——网站通常在4-8周内反弹回迁移前水平,三个月后经常看到由于更好性能而改进。
对于内容编辑来说,Drupal比TYPO3更难学吗?
不同,不是更难。那些习惯TYPO3页面树模型的人可能需要时间来适应Drupal的实体中心方法。段落模块确实提供了某种类似的内容构建体验。记住为编辑预算大约2-3天的培训,并为他们提供内容类型和工作流特定的文档。
迁移期间我的TYPO3扩展会发生什么?
每个扩展都值得个别评估。许多有直接的Drupal等价物(例如,powermail→Webform、ext:news→自定义内容类型+视图、ext:solr→搜索API+Solr)。自定义Extbase扩展?它们需要作为Drupal模块进行完全重写。没有转换器——你需要定制。
迁移TYPO3到Drupal时我应该走无头路线吗?
这取决于你的目标和时间表。如果你的迁移是由开发者或可维护性问题驱动的,从简单的Drupal Twig主题开始,稍后目标是无头。但如果你的前端团队热爱React或类似的设置,并且渴望现代交付架构,考虑从一开始就规划无头。只记住:同时进行两个迁移和前端变化?那是高风险领地。
我如何在迁移中处理多语言内容?
TYPO3的语言设置(sys_language_uid、l10n_parent)与Drupal的内容翻译模块很好地对齐。诀窍?在你的脚本中钉住语言到语言的映射,并确保回退匹配你的期望。谨慎对待部分翻译的内容——TYPO3的语言覆盖模式(自由、连接、严格)没有精确的Drupal对应物。对不完整翻译的编辑决定可能是必要的。
从TYPO3迁移到Drupal的ROI是什么?
ROI在哪里?主要来自削减开发支出和加快功能推出速度。从历史上看,我指导的团队在第一年看到了大约20-40%的开发成本削减,主要是由于更容易的人才招聘和拥有更大的模块池,减少了定制开发的需求。初始迁移成本可能很高,但大多数应该在18-24个月内收支平衡。