From craft-workspace-webconsulting-skills
Applies TYPO3 Rector upgrade patterns for PHP migrations toward v14, including configuration, dry runs, rule sets, and manual deprecation checks.
How this skill is triggered — by the user, by Claude, or both
Slash command
/craft-workspace-webconsulting-skills:typo3-rectorThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Source: https://github.com/dirnbauer/webconsulting-skills
Compatibility: TYPO3 v14.x This skill covers patterns for writing code that works on TYPO3 v14.
TYPO3 API First: Always use TYPO3's built-in APIs, core features, and established conventions before creating custom implementations. Do not reinvent what TYPO3 already provides. Always verify that the APIs and methods you use exist and are not deprecated in TYPO3 v14 by checking the official TYPO3 documentation.
Rector is an automated refactoring tool that helps migrate TYPO3 PHP code between major versions. It applies predefined rules to update deprecated code patterns. For non-PHP migrations (FlexForms, TypoScript, Fluid, YAML), use Fractor -- see the typo3-fractor skill.
composer require --dev ssch/typo3-rector
# or with DDEV:
ddev composer require --dev ssch/typo3-rector
Important: Rector loads your project's autoloader. For TYPO3 v14 projects, Rector must run on PHP 8.2+ because TYPO3 v14 packages use
readonlyclasses and other PHP 8.2 syntax. If your local PHP is older, always use DDEV or a container:ddev exec vendor/bin/rector process --dry-run
Always run Rector, never skip it. Manual replacements (e.g.
strpos->str_starts_with) miss edge cases that Rector rules handle correctly. Rector also catches deprecated TYPO3 namespace changes and method signature updates that are hard to find manually.
Create rector.php in your project root:
<?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_82)
->withSets([
LevelSetList::UP_TO_PHP_82,
Typo3LevelSetList::UP_TO_TYPO3_14,
])
->withImportNames();
Incremental upgrades: On a very old codebase you may run
UP_TO_TYPO3_13in a dedicated step first, thenUP_TO_TYPO3_14. Published extensions should still declaretypo3/cms-core: ^14.0once you ship for v14.
# 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
For extensions targeting TYPO3 v14:
<?php
// ext_emconf.php
$EM_CONF[$_EXTKEY] = [
'title' => 'My Extension',
'version' => '2.0.0',
'state' => 'stable',
'constraints' => [
'depends' => [
'typo3' => '14.0.0-14.99.99',
'php' => '8.2.0-8.5.99',
],
'conflicts' => [],
'suggests' => [],
],
];
// composer.json
{
"require": {
"php": "^8.2",
"typo3/cms-core": "^14.0"
}
}
Add explicit v14 rules (in addition to or instead of the level set, depending on your Rector version):
<?php
declare(strict_types=1);
use Rector\Config\RectorConfig;
use Ssch\TYPO3Rector\Set\Typo3SetList;
return RectorConfig::configure()
->withPaths([__DIR__ . '/packages'])
->withSets([
Typo3SetList::TYPO3_14,
]);
The ViewFactory approach works on 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');
}
}
<?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 events work on TYPO3 v14. Use them instead of legacy 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);
}
}
<?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',
],
],
],
];
# Configuration/Services.yaml
services:
_defaults:
autowire: true
autoconfigure: true
public: false
Vendor\MyExtension\:
resource: '../Classes/*'
exclude:
- '../Classes/Domain/Model/*'
In v14, $GLOBALS['TCA'] becomes read-only after loading. Always use static TCA files:
<?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,
],
],
],
];
Read the full guide when the task needs detailed examples, long templates, troubleshooting matrices, appendices, or sections not included above. Keep this file unloaded for narrow tasks so the skill follows progressive disclosure.
npx claudepluginhub dirnbauer/webconsulting-skillsGuides TYPO3 v14 extension development and upgrades, covering version constraints, PHP 8.2+, controllers, ViewFactory, Fluid, events, backend modules, TCA, QueryBuilder, CLI commands, tests, and v14-only manual changes.
Analyzes, plans, and executes TYPO3 v13 to v14 upgrades in Composer-based projects: checks extension compatibility, deprecations, Rector/Fractor migrations, and system requirements.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.