typo3-simplify

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

TYPO3 Code Simplifier

TYPO3代码简化工具

Adapted from Boris Cherny's (Anthropic) code-simplifier agent for TYPO3 contexts. Target: TYPO3 v14 (primary), v13, v12.4 LTS (fallbacks noted).
Simplify and refine recently changed TYPO3 code. Preserve all functionality. Focus on clarity over cleverness, TYPO3 API usage over custom implementations, and v14 patterns over deprecated approaches.
改编自Boris Cherny(Anthropic)为TYPO3场景打造的代码简化Agent。 目标版本: TYPO3 v14(优先)、v13、v12.4 LTS(标注兼容回退方案)。
在保留所有功能的前提下,简化和优化近期修改的TYPO3代码。优先考虑代码清晰度而非技巧性,优先使用TYPO3 API而非自定义实现,优先采用v14模式而非已废弃的方案。

Process

流程

  1. Identify recently modified files (use
    git diff --name-only HEAD~1
    or staged changes)
  2. Run three parallel review passes: Reuse, Quality, Efficiency
  3. Aggregate findings, deduplicate, sort by impact
  4. Apply fixes, verify no behavior change
  1. 识别近期修改的文件(使用
    git diff --name-only HEAD~1
    或暂存区变更)
  2. 并行执行三轮审核:复用性代码质量执行效率
  3. 汇总发现的问题,去重后按影响程度排序
  4. 应用修复,验证功能无变化

Pass 1: TYPO3 API Reuse

第一轮:TYPO3 API复用

Find custom implementations that duplicate what TYPO3 already provides.
找出重复实现TYPO3已有功能的自定义代码。

Replace Custom Code with Core APIs

用核心API替换自定义代码

Custom PatternTYPO3 API Replacement
Manual DB queries (
$connection->executeQuery(...)
)
QueryBuilder
with named parameters
$GLOBALS['TYPO3_REQUEST']
Inject
ServerRequestInterface
via middleware/controller
new FlashMessage(...)
+ manual queue
FlashMessageService
via DI
Manual JSON response construction
JsonResponse
from PSR-7
GeneralUtility::makeInstance()
Constructor injection via
Services.yaml
$GLOBALS['TSFE']->id
$request->getAttribute('routing')->getPageId()
$GLOBALS['BE_USER']
Inject
Context
or
BackendUserAuthentication
ObjectManager::get()
Constructor DI
Manual file path resolution
PathUtility
,
Environment::getPublicPath()
Custom caching with globals
CacheManager
via DI with cache configuration
BackendUtility::getRecord()
for single field
QueryBuilder
selecting only needed columns
Manual page tree traversal
RootlineUtility
or
PageRepository
GeneralUtility::_GP()
/
_POST()
/
_GET()
$request->getQueryParams()
/
getParsedBody()
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']
writes
PSR-14 events or
ExtensionConfiguration
Manual link generation
UriBuilder
(backend) or
ContentObjectRenderer::typoLink()
自定义模式TYPO3 API替代方案
手动数据库查询(
$connection->executeQuery(...)
带命名参数的
QueryBuilder
$GLOBALS['TYPO3_REQUEST']
通过中间件/控制器注入
ServerRequestInterface
new FlashMessage(...)
+ 手动入队
通过依赖注入使用
FlashMessageService
手动构造JSON响应使用PSR-7的
JsonResponse
GeneralUtility::makeInstance()
通过
Services.yaml
实现构造函数注入
$GLOBALS['TSFE']->id
$request->getAttribute('routing')->getPageId()
$GLOBALS['BE_USER']
注入
Context
BackendUserAuthentication
ObjectManager::get()
构造函数依赖注入
手动解析文件路径
PathUtility
Environment::getPublicPath()
使用全局变量的自定义缓存通过依赖注入配合缓存配置使用
CacheManager
使用
BackendUtility::getRecord()
获取单个字段
使用
QueryBuilder
仅选择所需列
手动遍历页面树
RootlineUtility
PageRepository
GeneralUtility::_GP()
/
_POST()
/
_GET()
$request->getQueryParams()
/
getParsedBody()
写入
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']
PSR-14事件或
ExtensionConfiguration
手动生成链接
UriBuilder
(后端)或
ContentObjectRenderer::typoLink()

Replace Deprecated Patterns (v14)

替换已废弃的模式(v14)

Deprecatedv14 Replacement
ext_localconf.php
hook arrays
#[AsEventListener]
on PSR-14 events
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']
hooks
PSR-14 events
ext_tables.php
module registration
Configuration/Backend/Modules.php
XCLASS
PSR-14 events or DI decoration
switchableControllerActions
Separate plugins per action
$querySettings->setRespectStoragePage(false)
in repo
Set in controller, not repository
Signal/SlotPSR-14 events
AbstractPlugin
(pi_base)
Extbase controller or middleware
TCA
eval
for
required
,
trim
,
null
Dedicated TCA keys:
required
,
nullable
renderType => 'inputDateTime'
'type' => 'datetime'
'type' => 'input', 'eval' => 'int'
'type' => 'number'
items
with numeric array keys
items
with
label
/
value
keys
已废弃模式v14替代方案
ext_localconf.php
中的钩子数组
在PSR-14事件上使用
#[AsEventListener]
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']
钩子
PSR-14事件
ext_tables.php
中的模块注册
Configuration/Backend/Modules.php
XCLASS
PSR-14事件或依赖注入装饰器
switchableControllerActions
每个动作对应独立插件
在仓库中调用
$querySettings->setRespectStoragePage(false)
在控制器中设置,而非仓库
Signal/SlotPSR-14事件
AbstractPlugin
(pi_base)
Extbase控制器或中间件
TCA中用
eval
设置
required
trim
null
使用专用TCA键:
required
nullable
renderType => 'inputDateTime'
'type' => 'datetime'
'type' => 'input', 'eval' => 'int'
'type' => 'number'
带数字数组键的
items
label
/
value
键的
items

Pass 2: Code Quality

第二轮:代码质量

PHP Classes

PHP类

  • One class per file, PSR-4 autoloading
  • declare(strict_types=1)
    on every PHP file
  • final
    on classes not designed for inheritance
  • readonly
    on immutable properties
  • Constructor promotion for DI dependencies
  • Explicit return types on all methods
  • No unused
    use
    imports
  • No suppressed errors (
    @
    )
  • Guard clauses over deep nesting (early returns)
  • No mixed types where specific types exist
  • Replace
    array
    typehints with typed arrays or DTOs
php
// Before
class MyService
{
    private ConnectionPool $connectionPool;
    private Context $context;

    public function __construct(ConnectionPool $connectionPool, Context $context)
    {
        $this->connectionPool = $connectionPool;
        $this->context = $context;
    }

    public function getData($id)
    {
        // ...
    }
}

// After
final class MyService
{
    public function __construct(
        private readonly ConnectionPool $connectionPool,
        private readonly Context $context,
    ) {}

    public function getData(int $id): array
    {
        // ...
    }
}
  • 一个文件对应一个类,遵循PSR-4自动加载规范
  • 每个PHP文件开头添加
    declare(strict_types=1)
  • 非为继承设计的类添加
    final
    修饰符
  • 不可变属性添加
    readonly
    修饰符
  • 依赖注入的参数使用构造函数提升
  • 所有方法添加显式返回类型
  • 移除未使用的
    use
    导入
  • 禁止使用错误抑制符(
    @
  • 使用卫语句替代深层嵌套(提前返回)
  • 已有特定类型时禁止使用
    mixed
    类型
  • 用类型化数组或DTO替换
    array
    类型提示
php
// Before
class MyService
{
    private ConnectionPool $connectionPool;
    private Context $context;

    public function __construct(ConnectionPool $connectionPool, Context $context)
    {
        $this->connectionPool = $connectionPool;
        $this->context = $context;
    }

    public function getData($id)
    {
        // ...
    }
}

// After
final class MyService
{
    public function __construct(
        private readonly ConnectionPool $connectionPool,
        private readonly Context $context,
    ) {}

    public function getData(int $id): array
    {
        // ...
    }
}

Fluid Templates

Fluid模板

  • No inline PHP or complex ViewHelper chains
  • Use
    <f:translate>
    instead of hardcoded strings
  • Use
    <f:link.page>
    /
    <f:link.typolink>
    instead of manual
    <a href>
  • Use
    <f:image>
    instead of manual
    <img>
    tags
  • Partials for repeated markup (DRY)
  • Sections for layout slots, not for reuse (use Partials)
  • No
    {variable -> f:format.raw()}
    unless absolutely necessary (XSS risk)
  • Variables use camelCase
  • Remove empty
    <f:section>
    blocks
  • Simplify nested
    <f:if>
    to
    <f:switch>
    or ternary where clearer
  • 禁止内联PHP或复杂的ViewHelper链式调用
  • 使用
    <f:translate>
    替代硬编码字符串
  • 使用
    <f:link.page>
    /
    <f:link.typolink>
    替代手动
    <a href>
  • 使用
    <f:image>
    替代手动
    <img>
    标签
  • 重复标记使用Partials(遵循DRY原则)
  • Sections仅用于布局插槽,不可复用(复用请用Partials)
  • 非必要情况禁止使用
    {variable -> f:format.raw()}
    (存在XSS风险)
  • 变量采用小驼峰命名法
  • 移除空的
    <f:section>
  • 将嵌套的
    <f:if>
    简化为
    <f:switch>
    或三元表达式(更清晰时)

TCA

TCA

  • Use v14
    items
    format with
    label
    /
    value
    keys
  • Remove redundant
    'exclude' => true
    on fields already restricted
  • Use dedicated types:
    'type' => 'email'
    ,
    'type' => 'datetime'
    ,
    'type' => 'number'
    ,
    'type' => 'link'
    ,
    'type' => 'color'
    ,
    'type' => 'json'
  • Use
    'required' => true
    instead of
    'eval' => 'required'
  • Use
    'nullable' => true
    instead of
    'eval' => 'null'
  • Remove
    'default' => ''
    on string fields (already default)
  • Consolidate palette definitions (remove single-field palettes)
  • Remove boilerplate
    columns
    definitions auto-created from
    ctrl
    (v13.3+):
    hidden
    ,
    starttime
    ,
    endtime
    ,
    fe_group
    ,
    sys_language_uid
    ,
    l10n_parent
    ,
    l10n_diffsource
  • Use palettes for enablecolumns:
    visibility
    for
    hidden
    ,
    access
    for
    starttime, endtime
  • Remove convention fields from
    ext_tables.sql
    (auto-added to database)
  • Remove unused
    showitem
    fields from types
  • 使用v14的
    items
    格式,采用
    label
    /
    value
  • 移除已受限制字段上多余的
    'exclude' => true
    配置
  • 使用专用类型:
    'type' => 'email'
    'type' => 'datetime'
    'type' => 'number'
    'type' => 'link'
    'type' => 'color'
    'type' => 'json'
  • 使用
    'required' => true
    替代
    'eval' => 'required'
  • 使用
    'nullable' => true
    替代
    'eval' => 'null'
  • 移除字符串字段上多余的
    'default' => ''
    配置(已为默认值)
  • 合并调色板定义(移除单字段调色板)
  • 移除
    ctrl
    自动生成的冗余
    columns
    定义(v13.3+):
    hidden
    starttime
    endtime
    fe_group
    sys_language_uid
    l10n_parent
    l10n_diffsource
  • 为启用列使用调色板:
    visibility
    对应
    hidden
    access
    对应
    starttime, endtime
  • ext_tables.sql
    中移除约定字段(会自动添加到数据库)
  • 移除类型中未使用的
    showitem
    字段

Services.yaml

Services.yaml

  • Use autowiring (remove explicit argument definitions when type-hintable)
  • Use
    _defaults: autowire: true, autoconfigure: true, public: false
  • Remove manual service definitions for classes that autowiring handles
  • Replace
    factory
    definitions with
    #[Autoconfigure]
    where possible
  • Remove
    public: true
    unless needed for
    GeneralUtility::makeInstance()
  • 使用自动注入(类型可提示时移除显式参数定义)
  • 使用
    _defaults: autowire: true, autoconfigure: true, public: false
  • 移除自动注入可处理的类的手动服务定义
  • 尽可能用
    #[Autoconfigure]
    替代
    factory
    定义
  • 除非需要
    GeneralUtility::makeInstance()
    ,否则移除
    public: true

ext_localconf.php / ext_tables.php

ext_localconf.php / ext_tables.php

  • Minimize code — move to
    Configuration/
    files where possible
  • Plugin registration only (no business logic)
  • Use
    ExtensionUtility::configurePlugin()
    (not
    registerPlugin
    for frontend)
  • No
    addPageTSConfig
    — use
    Configuration/page.tsconfig
  • No
    addUserTSConfig
    — use
    Configuration/user.tsconfig
  • No
    addTypoScript
    — use
    Configuration/TypoScript/setup.typoscript
  • 最小化代码 — 尽可能迁移到
    Configuration/
    目录下的文件
  • 仅保留插件注册(无业务逻辑)
  • 使用
    ExtensionUtility::configurePlugin()
    (前端插件不使用
    registerPlugin
  • 禁止使用
    addPageTSConfig
    — 改用
    Configuration/page.tsconfig
  • 禁止使用
    addUserTSConfig
    — 改用
    Configuration/user.tsconfig
  • 禁止使用
    addTypoScript
    — 改用
    Configuration/TypoScript/setup.typoscript

Pass 3: Efficiency

第三轮:执行效率

  • QueryBuilder: select only needed columns, not
    *
  • QueryBuilder: add
    setMaxResults()
    when expecting single row
  • Use
    count()
    queries instead of fetching all rows to count
  • Cache expensive operations with TYPO3 Caching Framework
  • Avoid N+1 queries in Extbase repositories (use
    JOIN
    or batch loading)
  • Use
    TYPO3\CMS\Core\Resource\ProcessedFileRepository
    not re-processing on every request
  • Remove
    findAll()
    calls without pagination
  • Lazy-load file references with
    @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
  • Replace
    foreach
    + manual
    in_array()
    filtering with QueryBuilder
    WHERE IN
  • Remove redundant
    cache:flush
    calls in CLI commands
  • QueryBuilder:仅选择所需列,而非
    *
  • QueryBuilder:预期单行结果时添加
    setMaxResults()
  • 使用
    count()
    查询替代获取所有行后再计数
  • 使用TYPO3缓存框架缓存耗时操作
  • 避免Extbase仓库中的N+1查询(使用
    JOIN
    或批量加载)
  • 使用
    TYPO3\CMS\Core\Resource\ProcessedFileRepository
    而非每次请求都重新处理
  • 移除无分页的
    findAll()
    调用
  • 使用
    @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
    懒加载文件引用
  • 用QueryBuilder的
    WHERE IN
    替代
    foreach
    + 手动
    in_array()
    过滤
  • 移除CLI命令中冗余的
    cache:flush
    调用

Output Format

输出格式

After analysis, report findings grouped by file:
text
undefined
分析完成后,按文件分组报告发现的问题:
text
undefined

Classes/Controller/MyController.php

Classes/Controller/MyController.php

:42 — replace GeneralUtility::makeInstance(MyService::class) → constructor injection :18 — add return type
: ResponseInterface
:55 — deprecated: $GLOBALS['TSFE']->id → $request routing attribute :67 — guard clause: invert condition, return early, reduce nesting
:42 — replace GeneralUtility::makeInstance(MyService::class) → constructor injection :18 — add return type
: ResponseInterface
:55 — deprecated: $GLOBALS['TSFE']->id → $request routing attribute :67 — guard clause: invert condition, return early, reduce nesting

Resources/Private/Templates/List.html

Resources/Private/Templates/List.html

:12 — hardcoded string "No items found" → f:translate :34 — manual <a href> → f:link.page
:12 — hardcoded string "No items found" → f:translate :34 — manual <a href> → f:link.page

Configuration/TCA/Overrides/tt_content.php

Configuration/TCA/Overrides/tt_content.php

:8 — v12 items format ['Label', 'value'] → ['label' => 'Label', 'value' => 'value']
Applied 7 fixes. No behavior changes. Run tests to verify.
undefined
:8 — v12 items format ['Label', 'value'] → ['label' => 'Label', 'value' => 'value']
Applied 7 fixes. No behavior changes. Run tests to verify.
undefined

Version Fallbacks

版本兼容回退方案

When simplifying for v12/v13 compatibility:
  • Keep
    Configuration/RequestMiddlewares.php
    alongside
    #[AsMiddleware]
  • Keep
    Services.yaml
    event listener config alongside
    #[AsEventListener]
  • Keep numeric TCA
    items
    arrays alongside
    label
    /
    value
    format
  • Use
    #[Autoconfigure]
    only on v14+ (not available in v12)
为v12/v13兼容进行简化时:
  • 保留
    Configuration/RequestMiddlewares.php
    #[AsMiddleware]
    并存
  • 保留
    Services.yaml
    事件监听器配置与
    #[AsEventListener]
    并存
  • 保留数字键的TCA
    items
    数组与
    label
    /
    value
    格式并存
  • 仅在v14+版本使用
    #[Autoconfigure]
    (v12不支持)

v14-Only Simplification Targets

仅适用于v14的简化目标

The following simplification opportunities are v14-specific.
以下简化优化仅适用于v14版本

v14 Simplification Patterns [v14 only]

v14简化模式 [仅v14]

PatternSimplification
$GLOBALS['TSFE']
access
Replace with
$request->getAttribute('frontend.page.information')
Extbase annotations (
@validate
)
Replace with
#[Validate]
PHP attribute
MailMessage->send()
Replace with
Mailer::send()
FlexFormService
usage
Replace with
FlexFormTools
Bootstrap Modal JSReplace with native
<dialog>
pattern
TCA
ctrl.searchFields
Replace with per-column
'searchable' => true
Custom localization parsersRemove, use Symfony Translation Component
GeneralUtility::createVersionNumberedFilename()
Remove, use System Resource API

现有模式简化方案
访问
$GLOBALS['TSFE']
替换为
$request->getAttribute('frontend.page.information')
Extbase注解(
@validate
替换为PHP属性
#[Validate]
MailMessage->send()
替换为
Mailer::send()
使用
FlexFormService
替换为
FlexFormTools
Bootstrap Modal JS替换为原生
<dialog>
模式
TCA
ctrl.searchFields
替换为按列配置
'searchable' => true
自定义本地化解析器移除,使用Symfony Translation Component
GeneralUtility::createVersionNumberedFilename()
移除,使用System Resource API

Credits & Attribution

致谢与归属

Adapted from Boris Cherny's (Anthropic) code-simplifier agent and Claude Code's bundled
/simplify
skill for TYPO3 contexts.
Copyright (c) Anthropic — Code simplification patterns (MIT License)
Thanks to Netresearch DTT GmbH for their contributions to the TYPO3 community.
改编自Boris Cherny(Anthropic)的code-simplifier Agent,以及Claude Code为TYPO3场景提供的内置
/simplify
技能。
版权所有 (c) Anthropic — 代码简化模式(MIT许可证)
感谢Netresearch DTT GmbH为TYPO3社区做出的贡献。