mcpField
T
typo3-simplify

typo3-simplify

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

关于 typo3-simplify

用于精简近期修改的 TYPO3 v14 代码并保持功能不变的代码审查技能。它引导开发者并行检查 TYPO3 API 复用、代码质量和效率,再应用并验证修复。

主要功能

  1. 01三阶段代码审查
  2. 02TYPO3 v14 API 与弃用指引
  3. 03PHP、Fluid、TCA 和服务检查
  4. 04效率与查询审查
  5. 05保持行为的修复与验证

适用场景

  1. 01审查近期 TYPO3 扩展改动
  2. 02用 TYPO3 核心 API 替换自定义代码
  3. 03发现 v14 弃用模式
  4. 04减少低效数据库访问

安装

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

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

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

详细介绍

TYPO3 代码简化器

根据 Boris Cherny(Anthropic)面向 TYPO3 场景的代码简化 Agent 改编。 **目标:**仅适用于 TYPO3 v14.x。

简化并改进最近更改的 TYPO3 代码。保留所有功能。优先考虑清晰易懂,而非巧妙复杂;优先使用 TYPO3 API,而非自定义实现;优先采用 v14 模式,而非已弃用的做法。

流程

  1. 确定最近修改的文件(使用 git diff --name-only HEAD~1 或暂存的更改)
  2. 并行执行三轮审查:复用、质量、效率
  3. 汇总审查结果、去重,并按影响排序
  4. 应用修复,验证行为未发生变化

第 1 轮:复用 TYPO3 API

查找重复实现 TYPO3 现有功能的自定义代码。

用核心 API 替换自定义代码
自定义模式TYPO3 API 替代方案
手动数据库查询($connection->executeQuery(...))使用命名参数的 QueryBuilder
$GLOBALS['TYPO3_REQUEST']通过中间件/控制器注入 ServerRequestInterface
new FlashMessage(...) + 手动入队通过 DI 使用 FlashMessageService
手动构造 JSON 响应使用 PSR-7 中的 JsonResponse
GeneralUtility::makeInstance()通过 Services.yaml 进行构造函数注入
$GLOBALS['TSFE']->id$request->getAttribute('frontend.page.information')?->getId()(v14 的规范方式;routing 页面 ID 也可用)
$GLOBALS['BE_USER']注入 Context 或 BackendUserAuthentication
ObjectManager::get()构造函数 DI
手动解析文件路径使用 PathUtility、Environment::getPublicPath()
使用全局变量进行自定义缓存通过 DI 使用带缓存配置的 CacheManager
对单个字段使用 BackendUtility::getRecord()使用 QueryBuilder,仅选择所需列
手动遍历页面树使用 RootlineUtility 或 PageRepository
GeneralUtility::_GP() / _POST() / _GET()$request->getQueryParams() / getParsedBody()
写入 $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']使用 PSR-14 事件或 ExtensionConfiguration
手动生成链接使用 UriBuilder(后端)或 ContentObjectRenderer::typoLink()
替换已弃用模式(v14)
已弃用v14 替代方案
ext_localconf.php 钩子数组在 PSR-14 事件上使用 #[AsEventListener]
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'] 钩子PSR-14 事件
ext_tables.php 模块注册Configuration/Backend/Modules.php
XCLASSPSR-14 事件或 DI 装饰
用于 required、null 的 TCA eval专用 TCA 键:required、nullable
用于 trim 的 TCA eval在 v14 中仍然有效——没有专用的 TCA 替代方案;需要时保留 eval 中的 trim
renderType => 'inputDateTime''type' => 'datetime'
'type' => 'input', 'eval' => 'int''type' => 'number'
使用数字数组键的 items使用 label/value 键的 items
历史移除项(你可能仍会看到的 v14 之前代码)
已移除 / 旧式做法时间现代方案
switchableControllerActions在 v10.3 弃用(#89463),在 v12.0 移除单独注册插件
Signal/Slot Dispatcher在 v12 移除PSR-14 事件
AbstractPlugin(pi_base)v12.0 标记为 @internal(#98281),v12.4 弃用(#100639),v13.0 移除Extbase 或中间件
代码质量(非弃用项)
主题指引
$querySettings->setRespectStoragePage(false)有效的 Extbase API——为保持清晰,优先在仓库工厂或控制器中设置查询设置,而不是分散在各个仓库中

第 2 轮:代码质量

PHP 类
  • 每个文件定义一个类,使用 PSR-4 自动加载
  • 每个 PHP 文件都使用 declare(strict_types=1)
  • 对不为继承而设计的类使用 final
  • 对不可变属性使用 readonly
  • 使用构造函数属性提升注入依赖
  • 所有方法都显式声明返回类型
  • 不要使用未用到的 use 导入
  • 不要屏蔽错误(@)
  • 优先使用守卫子句,避免深层嵌套(尽早返回)
  • 有具体类型可用时,不要使用 mixed 类型
  • 将 array 类型提示替换为带类型的数组或 DTO
// 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 模板
  • 不要使用内联 PHP 或复杂的 ViewHelper 链
  • 使用 <f:translate>,不要硬编码字符串
  • 使用 <f:link.page> / <f:link.typolink>,不要手动编写 <a href>
  • 使用 <f:image>,不要手动编写 <img> 标签
  • 对重复标记使用 Partial(DRY)
  • Section 用于布局插槽,不用于复用(请使用 Partial)
  • 除非绝对必要,否则不要使用 {variable -> f:format.raw()}(有 XSS 风险)
  • 变量使用 camelCase
  • 删除空的 <f:section> 块
  • 在更清晰时,将嵌套的 <f:if> 简化为 <f:switch> 或三元表达式
TCA
  • 使用 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'
  • 仍支持 eval => trim — 除非在其他层替代了修剪操作,否则不要删除
  • 删除字符串字段上的 'default' => ''(这本来就是默认值)
  • 合并 palette 定义(删除仅包含一个字段的 palette)
  • 删除 TYPO3 v14 中由 ctrl 自动创建的样板 columns 定义:hidden、starttime、endtime、fe_group、sys_language_uid、l10n_parent、l10n_diffsource
  • 对 enablecolumns 使用 palette:Core 对 hidden 使用 palette 键 hidden,对 starttime、endtime、fe_group 使用 access(请在表的 types showitem 中确认键名)
  • 当 ctrl 启用了 标准 ctrl 列 时,从 ext_tables.sql 中删除它们(hidden、starttime、endtime、fe_group、sys_language_uid、l10n_parent、l10n_source、sorting、deleted、crdate、tstamp)——仅当这些列由该表自动管理时
  • 从各类型中删除未使用的 showitem 字段
Services.yaml
  • 使用自动装配(对于可通过类型提示解析的依赖,删除显式参数定义)
  • 使用 _defaults: autowire: true, autoconfigure: true, public: false
  • 删除自动装配可处理的类的手动服务定义
  • 自动装配可处理构造时,删除 factory: 块;对于自动装配无法解析的非简单构造,保留 factory:。#[Autoconfigure] 标签/配置服务,但不能替代 factory: 构造
  • 除非 GeneralUtility::makeInstance() 需要,否则删除 public: true
ext_localconf.php / ext_tables.php
  • 尽量精简代码 — 尽可能移至 Configuration/ 文件
  • 仅注册插件(不包含业务逻辑)
  • 前端插件:在 ext_localconf.php 中使用 ExtensionUtility::configurePlugin(),并且在 Configuration/TCA/Overrides/tt_content.php 中使用 ExtensionUtility::registerPlugin()(或 TCA items)— 两者都是完整注册所必需的
  • 不要使用 addPageTSConfig — 请使用 Configuration/page.tsconfig
  • 不要使用 addUserTSConfig — 请使用 Configuration/user.tsconfig
  • 不要使用 addTypoScript — 请使用 Configuration/TypoScript/setup.typoscript

第 3 轮:效率

  • QueryBuilder:仅选择所需列,而不是 *
  • QueryBuilder:预期结果为单行时,添加 setMaxResults()
  • 使用 count() 查询代替获取所有行后再计数
  • 使用 TYPO3 Caching Framework 缓存开销较大的操作
  • 避免 Extbase 仓库中的 N+1 查询(使用 JOIN 或批量加载)
  • 使用 TYPO3\CMS\Core\Resource\ProcessedFileRepository,不要在每次请求时重新处理文件
  • 移除没有分页的 findAll() 调用
  • 使用 #[\TYPO3\CMS\Extbase\Attribute\ORM\Lazy] 延迟加载文件引用(替换旧版 @Lazy 注解)
  • 用 QueryBuilder WHERE IN 替换 foreach + 手动 in_array() 筛选
  • 移除 CLI 命令中多余的 cache:flush 调用

输出格式

分析后,按文件分组报告发现:

## 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

## Resources/Private/Templates/List.html

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

## Configuration/TCA/Overrides/tt_content.php

:8 — legacy items format `['Label', 'value']` → `['label' => 'Label', 'value' => 'value']`

Applied 7 fixes. No behavior changes. Run tests to verify.

版本回退方案

当同一代码库必须同时运行于 TYPO3 v13 和 v14(双版本扩展)时,可以暂时保留过渡模式:

  • 在 Configuration/RequestMiddlewares.php 中注册 PSR-15 中间件(Core 支持的模式)
  • 保留 Services.yaml 事件监听器配置,同时使用 #[AsEventListener]
  • 保留数字型 TCA items 数组,同时使用 label/value 格式
  • 优先使用 Services.yaml _defaults(autowire / autoconfigure)以及 Core 注册属性(#[AsCommand]、#[AsEventListener],……),而不是临时拼凑的 factory: 配置块

仅适用于 v14 的简化目标

以下简化机会仅适用于 v14。

v14 简化模式 [仅限 v14]
模式简化方式
$GLOBALS['TSFE'] 访问在 v14 中会触发致命错误(Breaking #107831)——替换为 $request->getAttribute('frontend.page.information')
Extbase 注解(@validate)替换为 #[\TYPO3\CMS\Extbase\Attribute\Validate]
MailMessage->send()注入 TYPO3\CMS\Core\Mail\MailerInterface 并调用 $this->mailer->send($email)
使用 FlexFormService优先使用 FlexFormTools;FlexFormService 在 v14 中仍作为 BC 别名保留,但新代码中不应使用
Bootstrap Modal JS**前端:**在适当情况下使用原生 <dialog>。后端:使用 @typo3/backend/modal——它在 v14 中封装了原生 <dialog>(Breaking #107443);不要使用原始 Bootstrap modal JS
TCA ctrl.searchFields(在 v14 中已移除)TYPO3 v14 会自动推导后端搜索字段;在支持的列上通过 'searchable' => true/false 调整是否纳入搜索(支持的字段类型:input、text、email、link、slug、color、datetime(不带自定义 dbType)、flex、json、uuid)
自定义本地化解析器已由 Symfony Translation Component 集成取代(Feature #107436);v14 中仍维护向后兼容性——新代码优先使用新的 Symfony Translation API
GeneralUtility::createVersionNumberedFilename()替换为 SystemResourceFactory / SystemResourcePublisherInterface(System Resource API,Feature #107537)

致谢与署名

此 skill 基于 Anthropic 的优秀成果。

原始仓库:https://github.com/anthropics/claude-plugins-official/tree/main/plugins/code-simplifier

特别感谢 Anthropic 慷慨的开源贡献,这些贡献帮助塑造了这个 skill 集合。 由 webconsulting.at 为此 skill 集合改编

评论

支持 Markdown