TYPO3 到 Drupal 迁移:实用开发者指南

如果你曾经盯着 TYPO3 后台想过"肯定有更好的办法",相信我,你绝不是唯一一个。TYPO3 确实很强大——我不否认这一点。它在众多欧洲企业和政府网站中担任 CMS 中坚二十多年了。但说实话,开发者生态已经发生了巨大变化。许多组织发现 Drupal 提供了更现代的设置、更强大的社区和更便捷的无头/解耦架构路径。

过去几年里,我深入参与了几个 TYPO3 到 Drupal 的迁移项目,这是一段令人难忘的旅程,需要解开现实世界中复杂的内容模型。它们通常是一团乱麻。本指南就是我希望在第一次迁移前有人交给我的东西。我将涵盖所有技术细节、规划要点,以及那些容易让你的时间表脱轨的陷阱。

目录

TYPO3 到 Drupal 迁移:实用开发者指南

为什么组织离开 TYPO3

坦白说:TYPO3 并不是一个糟糕的 CMS。它极其灵活,本身支持多站点和多语言设置,在 DACH 地区有着忠实的粉丝基础。那么为什么有人要跳槽呢?

我几乎每次都听到同样的原因:

开发者可用性。 在中欧以外,找到 TYPO3 开发者就像大海捞针。另一方面,Drupal 根据 Drupal.org 的 2024 年社区报告声称拥有约 130 万名全球开发者。TYPO3?远不如此。如果你的资深 TYPO3 开发者决定打包离开,填补那些职位可能需要很长时间。

生态系统动力。 随着 2024 年底 Drupal 11 的发布,管理 UI、新的菜谱系统和强大的 API 优先能力取得了巨大进展。当然,TYPO3 v13 很坚实,但 Drupal 的创新速度,尤其是在无头设置方面,明显更快。

无头/解耦架构。 计划将内容提供给时髦的 Next.js 或 Astro 前端?Drupal 的 JSON:API 和 GraphQL 插件都是经验丰富的老手。TYPO3 有自己的无头扩展,但它不太成熟且支持较少。

总拥有成本。 TYPO3 的托管通常会消耗更多资金。其专业化的基础设施意味着你最终可能会花费更多。Drupal 在从 Pantheon 到 Acquia 的任何地方都能运行良好,甚至基本的 LAMP 栈也能让它顺利运行。

TYPO3 vs Drupal:坦白的比较

在贸然迁移之前,确保 Drupal 真正能解决你的痛点。以下是 2025 年的情况:

功能 TYPO3 v13 Drupal 11
内容建模 灵活但倾向于 TCA 实体/字段系统,有字段管理 UI
多语言 原生支持优秀 同样优秀的原生支持
多站点 标准的多站点和内容树 可能,通常用 Domain Access 或单独安装更好
无头/API 有无头扩展 核心 JSON:API,GraphQL contrib
模板引擎 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 或通过 maskcontent_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 和 Drupal 处理内容的方式截然不同。

TYPO3 的模型

TYPO3 围绕页面。一切都嵌入在页面树中。内容元素(tt_content 中的记录)插入页面的列中(colPos)。通过 Extbase 模型或 TCA 定义的自定义记录位于单独的表中,但通常从页面链接。

Drupal 的模型

Drupal 完全基于实体。你设计内容类型(节点包),每个都有专用字段。页面只是众多内容类型之一。分类法、段落(使用段落模块)和布局生成器掌握着结构化内容组合。

映射

以下是我用作指南针的典型映射表:

TYPO3 概念 Drupal 等价物
页面(doktype: 标准) 节点(内容类型:页面)
页面(doktype: 快捷方式) URL 重定向
页面(doktype: 链接) 带链接字段或重定向的节点
内容元素(CType: 文本) 段落类型或正文字段
内容元素(CType: 图片) 媒体实体引用
内容元素(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('页面 ID'),
      'title' => $this->t('页面标题'),
      'slug' => $this->t('URL 段'),
      'abstract' => $this->t('摘要/总结'),
    ];
  }

  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% 的搜索流量。

步骤

  1. 从 TYPO3 导出所有 URL。 使用 CLI 工具或爬虫为每个已索引的 URL。
  2. 将这些映射到 Drupal URL。 使用 Drupal 的 Pathauto 生成 URL 别名,尽可能接近现有 URL。
  3. 为所有改变的内容创建重定向。 在 Drupal 中部署重定向模块。对于大量重定向,通过 CSV 导入。
  4. 处理语言前缀。 TYPO3 使用 /de//en//fr/ - 确保 Drupal 的语言设置镜像这个。
  5. 立即向 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 生态系统蓬勃发展。

如果你在考虑无头方法——2025 年,对于大多数内容驱动的网站,这值得考虑——我们在 /solutions/headless-cms-development 已经详尽地讨论了这一点。

与 Drupal 配对流行前端的方式:

首先迁移到 Drupal 然后使用 Drupal 的默认 Twig 前端启动的好处是,之后你可以切换到解耦的。不要同时尝试两种移动——那是在要求项目混乱。

时间表、成本和人员配置估计

来自我参与过的项目的真实数字,或者有准确数据的(2024-2025):

网站规模 页数 时间表 预算范围 团队
小型 <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 和编辑培训的所有内容。此处不包括持续维护。

大成本因素不仅仅是页数——它是复杂性。一个 2,000 页的网站,有 30 个自定义内容类型和 4 种语言,将比一个简单的 10,000 页网站成本更高。

考虑你的具体情况?查看 /pricing直接联系

迁移后检查清单

不要跳过这个清单。相信我。

  • 验证所有重定向。确保它们是 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 的投资回报率是什么?
投资回报率在哪?主要来自削减开发者成本和加快功能推出。从历史上看,我指导的团队在第一年看到约 20-40% 的开发成本削减,这主要是因为更容易的人才招聘和有一个更大的模块池,减少了对自定义开发的需求。初始迁移成本可能很高,但大多数应该在 18-24 个月内收支平衡。