{"id":80,"date":"2026-10-23T09:00:00","date_gmt":"2026-10-23T07:00:00","guid":{"rendered":"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/"},"modified":"2026-10-16T14:00:12","modified_gmt":"2026-10-16T12:00:12","slug":"rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable","status":"publish","type":"post","link":"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/","title":{"rendered":"Rector and Fractor for TYPO3 v14: a workflow that stays reviewable"},"content":{"rendered":"<p>The first time I ran TYPO3 Rector over a whole extension with every set enabled, I was proud for about ten minutes. Old APIs gone, tests green. Then I opened the merge request and understood my mistake: thousands of changed lines, the real migrations hidden between reordered imports and new type declarations. Nobody can review that properly. An approval of such a diff is not a review, it is a prayer.<\/p>\n<p>Since then I run the tools in a different way. Same tools, same rules, but the result is a series of small commits that a human can actually read. This post shows the setup for an extension going to TYPO3 v14.<\/p>\n<h2>The two tools<\/h2>\n<ul>\n<li><strong>TYPO3 Rector<\/strong> (<code>ssch\/typo3-rector<\/code>) changes PHP code: removed classes, renamed methods, new signatures. It builds on <code>rector\/rector<\/code>.<\/li>\n<li><strong>Fractor<\/strong> (<code>a9f\/typo3-fractor<\/code>) does the same for everything that is not PHP: TypoScript, FlexForms, Fluid, YAML, XLIFF and <code>.htaccess<\/code> files.<\/li>\n<\/ul>\n<p>Both are dev dependencies:<\/p>\n<pre><code class=\"language-bash\">composer require --dev ssch\/typo3-rector a9f\/typo3-fractor<\/code><\/pre>\n<p>One precondition that people skip: <code>composer.json<\/code> must already allow the target core and <code>composer update<\/code> must have worked. Rector reads the installed code to understand types. If v13 is still installed while you apply v14 rules, it guesses.<\/p>\n<h2>Rule one: one target version<\/h2>\n<p>Both tools offer cumulative level sets like <code>Typo3LevelSetList::UP_TO_TYPO3_14<\/code>, which include all rules from older versions too, and single-version sets like <code>Typo3SetList::TYPO3_14<\/code>. For an extension that already runs on v13 and should support v13 and v14 together, the level must be the <em>lowest<\/em> supported major, so 13. Rules from v14 may produce code that does not exist in v13. Only when you drop v13 do you raise it to 14. The examples below are for an extension that goes v14-only.<\/p>\n<h2>Rule two: one set per run, one commit per set<\/h2>\n<p>Instead of one config with every set, I let an environment variable choose the step. The config stays in git, and each step is reproducible:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\ndeclare(strict_types=1);\n\nuse RectorConfigRectorConfig;\nuse RectorSetValueObjectLevelSetList;\nuse RectorValueObjectPhpVersion;\nuse SschTYPO3RectorConfigurationTypo3Option;\nuse SschTYPO3RectorSetTypo3LevelSetList;\nuse SschTYPO3RectorSetTypo3SetList;\n\n$sets = match (getenv('RECTOR_STEP') ?: 'typo3') {\n    'php' =&gt; [LevelSetList::UP_TO_PHP_82],\n    'typo3' =&gt; [Typo3LevelSetList::UP_TO_TYPO3_14],\n    'quality' =&gt; [Typo3SetList::CODE_QUALITY, Typo3SetList::GENERAL],\n};\n\nreturn RectorConfig::configure()\n    -&gt;withPaths([\n        __DIR__ . '\/Classes',\n        __DIR__ . '\/Configuration',\n        __DIR__ . '\/Tests',\n        __DIR__ . '\/ext_localconf.php',\n        __DIR__ . '\/ext_tables.php',\n    ])\n    -&gt;withPhpVersion(PhpVersion::PHP_82)\n    -&gt;withSets($sets)\n    -&gt;withPHPStanConfigs([Typo3Option::PHPSTAN_FOR_RECTOR_PATH])\n    -&gt;withSkip([\n        __DIR__ . '\/.Build',\n        __DIR__ . '\/vendor',\n    ]);<\/code><\/pre>\n<p>The <code>PHPSTAN_FOR_RECTOR_PATH<\/code> line teaches Rector&#8217;s PHPStan about TYPO3, for example what <code>GeneralUtility::makeInstance()<\/code> returns. Without it some rules do not fire because the type is unknown.<\/p>\n<p>Fractor gets its own small config:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\ndeclare(strict_types=1);\n\nuse a9fFractorConfigurationFractorConfiguration;\nuse a9fTypo3FractorSetTypo3LevelSetList;\n\nreturn FractorConfiguration::configure()\n    -&gt;withPaths([\n        __DIR__ . '\/Configuration',\n        __DIR__ . '\/Resources\/Private',\n    ])\n    -&gt;withSets([\n        Typo3LevelSetList::UP_TO_TYPO3_14,\n    ]);<\/code><\/pre>\n<p>Then the runs, each one first as a dry run:<\/p>\n<pre><code class=\"language-bash\">RECTOR_STEP=typo3 vendor\/bin\/rector process --dry-run\nRECTOR_STEP=typo3 vendor\/bin\/rector process\ngit add -A &amp;&amp; git commit -m \"[TASK] Apply TYPO3 Rector level set up to v14\"\n\nvendor\/bin\/fractor process --dry-run\nvendor\/bin\/fractor process\ngit add -A &amp;&amp; git commit -m \"[TASK] Apply Fractor migrations for TYPO3 v14\"\n\nRECTOR_STEP=php vendor\/bin\/rector process\ngit add -A &amp;&amp; git commit -m \"[TASK] Apply PHP 8.2 level set\"\n\nvendor\/bin\/php-cs-fixer fix\ngit add -A &amp;&amp; git commit -m \"[TASK] Apply coding standards\"<\/code><\/pre>\n<p>The order is deliberate. The TYPO3 migrations come first and alone, because they are the commit a reviewer must read carefully. PHP modernisation and code style come later, because they touch many lines but carry little risk. If you mix style into the TYPO3 commit, the important changes drown again.<\/p>\n<h2>How I read the dry-run diff<\/h2>\n<p>The dry run is not a formality. I look for three things:<\/p>\n<ol>\n<li><strong>Changed public API.<\/strong> If Rector renames or retypes a public method in <code>Classes\/<\/code>, another extension that calls it may break. That goes into the changelog of the extension.<\/li>\n<li><strong>Rules that guessed.<\/strong> A type taken from an old <code>@var<\/code> docblock, or a parameter that became nullable. The docblock was wrong before, so the new type is wrong now.<\/li>\n<li><strong>Changes in tests.<\/strong> They are fine, but check that the assertion still tests the same thing.<\/li>\n<\/ol>\n<p>When one rule produces broken code, I do not fix its output by hand on every run. I skip that single rule in <code>withSkip()<\/code> with a comment, and write the affected place on my list of manual work. Hand edits on top of generated code get lost the next time somebody runs the tool.<\/p>\n<h2>What stays manual<\/h2>\n<p>After both tools are done, there is always a rest. For v14 projects these are the usual suspects in my work:<\/p>\n<ul>\n<li><strong>Runtime behaviour in Fluid.<\/strong> Fluid 5 validates ViewHelper arguments more strictly. Fractor can rename things in templates, but whether a variable holds an array at runtime is not visible in the file.<\/li>\n<li><strong>Database and data.<\/strong> A changelog entry like <code>Breaking-17406<\/code> (the field <code>pages.url<\/code> was removed in v14, the page type &#8220;Link&#8221; uses <code>pages.link<\/code>) needs an upgrade wizard or a migration of data. No code tool touches your rows.<\/li>\n<li><strong>Backend module names.<\/strong> v14 renamed main modules (<code>web<\/code> became <code>content<\/code>, with an alias). Check your <code>Configuration\/Backend\/Modules.php<\/code> by eye.<\/li>\n<li><strong>Behaviour changes without a new API.<\/strong> When a method keeps its name but returns something else, no rule can know your code relied on the old result. Only tests catch that.<\/li>\n<\/ul>\n<p>To measure the rest, I run the extension scanner in the Upgrade module of the install tool, or simply search the code for the class names listed in the Breaking entries of the target version. Every hit is a task, written down before I start fixing.<\/p>\n<h2>Why this is worth it<\/h2>\n<p>Small commits are not only kind to reviewers. When something breaks three weeks later, <code>git bisect<\/code> lands on &#8220;Apply Fractor migrations&#8221; instead of &#8220;Upgrade everything&#8221;, and you know in which world to search. And when the agent or a junior colleague runs the same workflow, the result looks the same, because the config decides, not the mood of the day.<\/p>\n<p>Cheers, and may your diffs stay small!<\/p>\n<h2>Further reading<\/h2>\n<ul>\n<li><a href=\"https:\/\/github.com\/sabbelasichon\/typo3-rector\">TYPO3 Rector on GitHub<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/andreaswolf\/fractor\">Fractor on GitHub<\/a><\/li>\n<li><a href=\"https:\/\/getrector.com\/documentation\">Rector documentation<\/a><\/li>\n<li><a href=\"https:\/\/docs.typo3.org\/c\/typo3\/cms-core\/main\/en-us\/Index.html\">TYPO3 core changelog<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>One big Rector run over an extension gives a diff nobody can review. My workflow: one target version, one set per run, one commit per set, and a clear list of manual work.<\/p>\n","protected":false},"author":1,"featured_media":81,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17],"tags":[37,38,30,24,25],"class_list":["post-80","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-typo3","tag-automation","tag-code-review","tag-extension-development","tag-typo3-v14","tag-upgrades"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Rector and Fractor for TYPO3 v14: a reviewable workflow<\/title>\n<meta name=\"description\" content=\"Run TYPO3 Rector and Fractor for v14 set by set, commit each set separately and keep the diff reviewable. Configs, commands and what stays manual.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Rector and Fractor for TYPO3 v14: a reviewable workflow\" \/>\n<meta property=\"og:description\" content=\"Run TYPO3 Rector and Fractor for v14 set by set, commit each set separately and keep the diff reviewable. Configs, commands and what stays manual.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/\" \/>\n<meta property=\"og:site_name\" content=\"Hoja Mustaffa Abdul Latheef \u2013 Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-23T07:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Hoja Mustaffa Abdul Latheef\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@hojaonline\" \/>\n<meta name=\"twitter:site\" content=\"@hojaonline\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Hoja Mustaffa Abdul Latheef\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\\\/\"},\"author\":{\"name\":\"Hoja Mustaffa Abdul Latheef\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/e6fbd54c2061674d8ea3e7861d858c7b\"},\"headline\":\"Rector and Fractor for TYPO3 v14: a workflow that stays reviewable\",\"datePublished\":\"2026-10-23T07:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\\\/\"},\"wordCount\":808,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/e6fbd54c2061674d8ea3e7861d858c7b\"},\"image\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hoja.in\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable.jpg\",\"keywords\":[\"Automation\",\"Code review\",\"Extension development\",\"TYPO3 v14\",\"Upgrades\"],\"articleSection\":[\"TYPO3\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/hoja.in\\\/blog\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\\\/\",\"url\":\"https:\\\/\\\/hoja.in\\\/blog\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\\\/\",\"name\":\"Rector and Fractor for TYPO3 v14: a reviewable workflow\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hoja.in\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable.jpg\",\"datePublished\":\"2026-10-23T07:00:00+00:00\",\"description\":\"Run TYPO3 Rector and Fractor for v14 set by set, commit each set separately and keep the diff reviewable. Configs, commands and what stays manual.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/hoja.in\\\/blog\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\\\/#primaryimage\",\"url\":\"https:\\\/\\\/hoja.in\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable.jpg\",\"contentUrl\":\"https:\\\/\\\/hoja.in\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable.jpg\",\"width\":1200,\"height\":630,\"caption\":\"Rector without the monster diff\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/hoja.in\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Rector and Fractor for TYPO3 v14: a workflow that stays reviewable\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/hoja.in\\\/blog\\\/\",\"name\":\"Hoja Mustaffa Abdul Latheef \u2013 Blog\",\"description\":\"Notes from daily work with TYPO3, PHP and AI-assisted engineering\",\"publisher\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/e6fbd54c2061674d8ea3e7861d858c7b\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/hoja.in\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/e6fbd54c2061674d8ea3e7861d858c7b\",\"name\":\"Hoja Mustaffa Abdul Latheef\",\"logo\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/image\\\/\"},\"description\":\"Senior TYPO3 Developer at jweiland.net, TYPO3 CMS Certified Developer. I write about TYPO3 upgrades, extension development, PHP and AI-assisted engineering with Claude Code.\",\"sameAs\":[\"https:\\\/\\\/hoja.in\\\/\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Rector and Fractor for TYPO3 v14: a reviewable workflow","description":"Run TYPO3 Rector and Fractor for v14 set by set, commit each set separately and keep the diff reviewable. Configs, commands and what stays manual.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/","og_locale":"en_US","og_type":"article","og_title":"Rector and Fractor for TYPO3 v14: a reviewable workflow","og_description":"Run TYPO3 Rector and Fractor for v14 set by set, commit each set separately and keep the diff reviewable. Configs, commands and what stays manual.","og_url":"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/","og_site_name":"Hoja Mustaffa Abdul Latheef \u2013 Blog","article_published_time":"2026-10-23T07:00:00+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable.jpg","type":"image\/jpeg"}],"author":"Hoja Mustaffa Abdul Latheef","twitter_card":"summary_large_image","twitter_creator":"@hojaonline","twitter_site":"@hojaonline","twitter_misc":{"Written by":"Hoja Mustaffa Abdul Latheef","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/#article","isPartOf":{"@id":"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/"},"author":{"name":"Hoja Mustaffa Abdul Latheef","@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/e6fbd54c2061674d8ea3e7861d858c7b"},"headline":"Rector and Fractor for TYPO3 v14: a workflow that stays reviewable","datePublished":"2026-10-23T07:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/"},"wordCount":808,"commentCount":0,"publisher":{"@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/e6fbd54c2061674d8ea3e7861d858c7b"},"image":{"@id":"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/#primaryimage"},"thumbnailUrl":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable.jpg","keywords":["Automation","Code review","Extension development","TYPO3 v14","Upgrades"],"articleSection":["TYPO3"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/","url":"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/","name":"Rector and Fractor for TYPO3 v14: a reviewable workflow","isPartOf":{"@id":"https:\/\/hoja.in\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/#primaryimage"},"image":{"@id":"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/#primaryimage"},"thumbnailUrl":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable.jpg","datePublished":"2026-10-23T07:00:00+00:00","description":"Run TYPO3 Rector and Fractor for v14 set by set, commit each set separately and keep the diff reviewable. Configs, commands and what stays manual.","breadcrumb":{"@id":"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/#primaryimage","url":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable.jpg","contentUrl":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable.jpg","width":1200,"height":630,"caption":"Rector without the monster diff"},{"@type":"BreadcrumbList","@id":"https:\/\/hoja.in\/blog\/rector-and-fractor-for-typo3-v14-a-workflow-that-stays-reviewable\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/hoja.in\/blog\/"},{"@type":"ListItem","position":2,"name":"Rector and Fractor for TYPO3 v14: a workflow that stays reviewable"}]},{"@type":"WebSite","@id":"https:\/\/hoja.in\/blog\/#website","url":"https:\/\/hoja.in\/blog\/","name":"Hoja Mustaffa Abdul Latheef \u2013 Blog","description":"Notes from daily work with TYPO3, PHP and AI-assisted engineering","publisher":{"@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/e6fbd54c2061674d8ea3e7861d858c7b"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/hoja.in\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/e6fbd54c2061674d8ea3e7861d858c7b","name":"Hoja Mustaffa Abdul Latheef","logo":{"@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/image\/"},"description":"Senior TYPO3 Developer at jweiland.net, TYPO3 CMS Certified Developer. I write about TYPO3 upgrades, extension development, PHP and AI-assisted engineering with Claude Code.","sameAs":["https:\/\/hoja.in\/"]}]}},"_links":{"self":[{"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/posts\/80","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/comments?post=80"}],"version-history":[{"count":1,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/posts\/80\/revisions"}],"predecessor-version":[{"id":163,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/posts\/80\/revisions\/163"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/media\/81"}],"wp:attachment":[{"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/media?parent=80"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/categories?post=80"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/tags?post=80"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}