mcpField
T
typo3-rector

typo3-rector

github.com/dirnbauer开发3377 次安装13 周前更新
代码仓库

关于 typo3-rector

面向 TYPO3 开发者的技能,介绍如何使用 Rector 将 PHP 代码迁移至 TYPO3 v14。内容涵盖配置、变更预览、应用自动化规则及常见迁移模式,并区分 PHP 与 Fractor 负责的非 PHP 迁移。

主要功能

  1. 01TYPO3 v14 的 Rector 配置指引
  2. 02PHP 自动迁移模式
  3. 03预览与应用迁移流程
  4. 04TYPO3 API 与约定指引
  5. 05常见 v14 代码示例

适用场景

  1. 01为 TYPO3 PHP 项目准备 v14 升级
  2. 02应用迁移前预览代码变更
  3. 03使用 Rector 规则更新扩展代码

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dirnbauer/webconsulting-skills --skill typo3-rector

安装后在 Claude Code 中输入/typo3-rector确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
06-typo3-v14-platform-snapshot.md
07-step-by-step-migration-process.md
08-troubleshooting.md
09-common-rector-rules.md
10-resources.md
credits-and-attribution.md
full-guide.md
v14-only-rector-targets.md

详细介绍

TYPO3 Rector 升级模式

来源:https://github.com/dirnbauer/webconsulting-skills

兼容性: TYPO3 v14.x 此技能涵盖适用于 TYPO3 v14 的代码编写模式。

优先使用 TYPO3 API: 创建自定义实现之前,始终优先使用 TYPO3 内置的 API、核心功能和既定约定。不要重复实现 TYPO3 已经提供的功能。始终查阅 TYPO3 官方文档,确认所用的 API 和方法在 TYPO3 v14 中存在且未被弃用。

1. TYPO3 Rector 简介

Rector 是一款自动化重构工具,可帮助在不同主版本之间迁移 TYPO3 PHP 代码。它会应用预定义规则,更新已弃用的代码模式。对于非 PHP 迁移(FlexForms、TypoScript、Fluid、YAML),请使用 Fractor —— 参见 typo3-fractor 技能。

安装
composer require --dev ssch/typo3-rector
# or with DDEV:
ddev composer require --dev ssch/typo3-rector

重要提示: Rector 会加载项目的自动加载器。对于 TYPO3 v14 项目,Rector 必须在 PHP 8.2 或更高版本上运行,因为 TYPO3 v14 软件包使用了 readonly 类和其他 PHP 8.2 语法;而且 webconsulting 项目的目标 PHP 版本为 8.4 或更高,因此请使用项目所需的相同 PHP 版本运行 Rector。如果本地 PHP 版本较旧,请务必使用 DDEV 或容器:ddev exec vendor/bin/rector process --dry-run

务必运行 Rector,切勿跳过。 手动替换(例如 strpos -> str_starts_with) 会遗漏 Rector 规则能够正确处理的边缘情况。Rector 还会发现已弃用的 TYPO3 命名空间变更和方法签名更新,这些问题很难通过手动方式找到。

基本配置(目标为 TYPO3 v14)

在项目根目录中创建 rector.php:

<?php
declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\ValueObject\PhpVersion;
use Ssch\TYPO3Rector\Set\Typo3LevelSetList;

return RectorConfig::configure()
    ->withPaths([
        __DIR__ . '/packages',
        __DIR__ . '/public/typo3conf/ext',
    ])
    ->withSkip([
        __DIR__ . '/public/typo3conf/ext/*/Resources/',
        __DIR__ . '/public/typo3conf/ext/*/Tests/',
    ])
    ->withPhpVersion(PhpVersion::PHP_84)
    ->withSets([
        LevelSetList::UP_TO_PHP_84,
        Typo3LevelSetList::UP_TO_TYPO3_14,
    ])
    ->withImportNames();

渐进式升级: 对于非常旧的代码库,可以先在专门的步骤中运行 UP_TO_TYPO3_13,然后再运行 UP_TO_TYPO3_14。发布的扩展在面向 v14 发布时应声明 typo3/cms-core: ^14.3 —— 14.0 至 14.2 已不再接收安全更新。

当前状态(typo3-rector v3.14,2026 年年中)

typo3-rector 3.14 基于 Rector 2.5 运行,由 Simon Schaufelberger 维护,部分资金来自 TYPO3 社区预算。每次迁移前运行 composer update ssch/typo3-rector,以应用最新的 v14 规则。3.14 的显著变化:

  • 将 TYPO3 内置的 Fluid 类名迁移为独立的 Fluid;TYPO3 v14 使用独立的 Fluid
  • 迁移 makeCategorizable() 注册
  • 扩大 $GLOBALS['TSFE']->fe_user 迁移覆盖范围
  • 加强 HashService 和 MailMessage::send() 迁移

2. 运行 Rector

试运行(预览变更)
# Show what would be changed
ddev exec vendor/bin/rector process --dry-run

# For specific extension
ddev exec vendor/bin/rector process packages/my_extension --dry-run
应用变更
# Apply all changes
ddev exec vendor/bin/rector process

# Apply to specific path
ddev exec vendor/bin/rector process packages/my_extension
之后清除缓存
ddev typo3 cache:flush
ddev composer dump-autoload

3. 版本约束和额外的 Rector 规则集

版本约束

对于面向 TYPO3 v14 的扩展:

<?php
// ext_emconf.php
$EM_CONF[$_EXTKEY] = [
    'title' => 'My Extension',
    'version' => '2.0.0',
    'state' => 'stable',
    'constraints' => [
        'depends' => [
            'typo3' => '14.3.0-14.99.99',
            'php' => '8.4.0-8.5.99',
        ],
        'conflicts' => [],
        'suggests' => [],
    ],
];
// composer.json
{
    "require": {
        "php": "^8.4",
        "typo3/cms-core": "^14.3"
    }
}
可选:仅使用 TYPO3 v14 规则集

添加显式的 v14 规则(根据 Rector 版本,可与级别规则集一并使用或替代它):

<?php
declare(strict_types=1);

use Rector\Config\RectorConfig;
use Ssch\TYPO3Rector\Set\Typo3SetList;

return RectorConfig::configure()
    ->withPaths([__DIR__ . '/packages'])
    ->withSets([
        Typo3SetList::TYPO3_14,
    ]);

4. 关键迁移模式(TYPO3 v14)

Fluid ViewFactory(替代 StandaloneView)

ViewFactory 方案适用于 TYPO3 v14:

<?php
declare(strict_types=1);

namespace Vendor\Extension\Service;

use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\View\ViewFactoryData;
use TYPO3\CMS\Core\View\ViewFactoryInterface;

final class RenderingService
{
    public function __construct(
        private readonly ViewFactoryInterface $viewFactory,
    ) {}

    public function render(ServerRequestInterface $request): string
    {
        $viewFactoryData = new ViewFactoryData(
            templateRootPaths: ['EXT:my_extension/Resources/Private/Templates'],
            partialRootPaths: ['EXT:my_extension/Resources/Private/Partials'],
            layoutRootPaths: ['EXT:my_extension/Resources/Private/Layouts'],
            request: $request,
        );
        
        $view = $this->viewFactory->create($viewFactoryData);
        $view->assign('data', ['key' => 'value']);
        $view->assignMultiple([
            'items' => [],
            'settings' => [],
        ]);
        
        return $view->render('MyTemplate');
    }
}
Extbase 控制器响应(TYPO3 v14)
<?php
declare(strict_types=1);

namespace Vendor\Extension\Controller;

use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

final class ItemController extends ActionController
{
    // ✅ Correct: Return ResponseInterface (required in TYPO3 v14)
    public function listAction(): ResponseInterface
    {
        $items = $this->itemRepository->findAll();
        $this->view->assign('items', $items);
        return $this->htmlResponse();
    }

    // ✅ Correct: JSON response
    public function apiAction(): ResponseInterface
    {
        $data = ['success' => true];
        return $this->jsonResponse(json_encode($data));
    }

    // ✅ Correct: Redirect
    public function createAction(Item $item): ResponseInterface
    {
        $this->itemRepository->add($item);
        return $this->redirect('list');
    }
}
PSR-14 事件(优先于 Hooks)

PSR-14 事件适用于 TYPO3 v14。请使用这些事件替代旧版 Hooks:

<?php
declare(strict_types=1);

namespace Vendor\Extension\EventListener;

use TYPO3\CMS\Core\Attribute\AsEventListener;
use TYPO3\CMS\Frontend\Event\ModifyPageLinkConfigurationEvent;

#[AsEventListener(identifier: 'vendor-extension/modify-pagelink')]
final class ModifyPageLinkListener
{
    public function __invoke(ModifyPageLinkConfigurationEvent $event): void
    {
        $configuration = $event->getConfiguration();
        // Modify link configuration
        $event->setConfiguration($configuration);
    }
}
后端模块注册(TYPO3 v14)
<?php
// Configuration/Backend/Modules.php
return [
    'web_myextension_mymodule' => [
        'parent' => 'content',
        'position' => ['after' => 'records'],
        'access' => 'user,group',
        'iconIdentifier' => 'myextension-module',
        'path' => '/module/content/myextension',
        'labels' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang_mod.xlf',
        'extensionName' => 'MyExtension',
        'controllerActions' => [
            \Vendor\MyExtension\Controller\ModuleController::class => [
                'index',
                'edit',
            ],
        ],
    ],
];
服务配置(Services.yaml)
# Configuration/Services.yaml
services:
  _defaults:
    autowire: true
    autoconfigure: true
    public: false

  Vendor\MyExtension\:
    resource: '../Classes/*'
    exclude:
      - '../Classes/Domain/Model/*'

5. TCA 最佳实践(TYPO3 v14)

仅使用静态 TCA

在 v14 中,加载后 $GLOBALS['TCA'] 将变为只读。务必使用静态 TCA 文件:

<?php
// Configuration/TCA/Overrides/tt_content.php
defined('TYPO3') or die();

// ✅ Correct: Static TCA configuration
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem(
    'tt_content',
    'CType',
    [
        'label' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:mytype.title',
        'value' => 'myextension_mytype',
        'icon' => 'content-text',
        'group' => 'default',
    ]
);

$GLOBALS['TCA']['tt_content']['types']['myextension_mytype'] = [
    'showitem' => '
        --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general,
            --palette--;;general,
            header;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:header_formlabel,
            bodytext,
        --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access,
            --palette--;;hidden,
            --palette--;;access,
    ',
    'columnsOverrides' => [
        'bodytext' => [
            'config' => [
                'enableRichtext' => true,
            ],
        ],
    ],
];

详细参考

如果任务需要详细示例、较长的模板、故障排查矩阵、附录或上文未包含的章节,请阅读完整指南。对于范围较窄的任务,请勿加载此文件,以便技能遵循渐进式披露。

评论

支持 Markdown