whoami

Lucas Jenß

cat /etc/motd

The Coding Journal ツ — Notes taken on an epic coding journey. Technical solutions, debugging notes, and practical guides from the trenches of software development.

Close-up of white dominoes with black dots standing on green felt surface, shallow depth of field, focused mood

ls -la ~/languages/

total 8
drwxr-xr-x
▶ PHP
▶ Ruby
▶ Scala
▶ C#
▶ JavaScript
▶ Objective-C
▶ Shell Scripting

ls -la ~/toolchain/

total 7
drwxr-xr-x
▶ Typo3
▶ Akka
▶ Capistrano
▶ Git
▶ MAMP
▶ Adobe Illustrator
▶ NSTrackingArea (Cocoa)

uname -a

platforms
drwxr-xr-x
▶ Mac OS X
▶ Unix

Repairing custom backend modules after a TYPO3 v11 upgrade

An upgrade from TYPO3 v10 to v11 can finish without obvious frontend damage and still leave editors unable to open a custom module. The route returns a server error, the JavaScript console reports missing configuration, or a menu link points to an obsolete module identifier. These are common symptoms of code that depended on APIs removed during the v11 migration.

Backend extensions often mix Extbase controllers, repositories, session access, FlashMessage queues and hand-built URLs. A small framework change can therefore surface far from the original component. The safest repair is to identify the exact failing call, replace only the unsupported behaviour and prove the module under v11 before changing broader project settings.

This journal entry records that debugging sequence: reproduce the problem on a clean staging copy, read the server and browser errors, follow the call into core, then refactor the extension around supported APIs. It applies equally to a bespoke records tool and a module that only appears broken after deployment to an Australian hosting environment.

What changes in the v11 jump

TYPO3 v11 is not simply a feature release. It has firm PHP compatibility constraints, removes deprecated core APIs and moves configuration and dependency handling towards PSR-style, Symfony-backed services. An extension can pass a syntax check yet fail because it extends an unavailable base class or requests a configuration value through a global that no longer exists.

Common migration warnings include deprecated environment helpers, global language state and manually assembled backend module URLs. GeneralUtility::getIndpEnv() is one concrete example: code that reads TYPO3_SITE_URL through it should use Environment::getPublicUrl() in v11. Similar review is needed for FlashMessage construction and language handling.

Third-party packages matter just as much as local code. A compatible typo3/cms-* set can still be held back by an old extension requiring a TYPO3 v10 API. Independent TYPO3 examples on Mike Meredith’s site are useful cross-checks, but the installed package versions and actual exception remain the source of truth.

Reproduce the failure before editing

Start with the Composer lock file, not the production database. Copy the repository, use the same PHP CLI version as deployment, run composer install, and record the result of composer check-platform-reqs. Then ask Composer why a required package cannot coexist with the selected v11 release, using a command such as composer why-not typo3/cms-core "11.5.*".

Next, clear TYPO3 and framework caches in staging and reproduce the exact route while watching the PHP log, the TYPO3 log and browser developer tools. A server-side exception identifies a PHP problem; a blank panel with a failed AJAX request often points to route arguments, JavaScript configuration or an outdated asset bundle. Repeat the navigation with a non-editor account to separate rendering failures from permission checks.

Do not repair this by deleting caches on production or changing every dependency at once. A local extension repository can contain unrelated experiments, and its ignored files may hide the versions actually running elsewhere. Platform differences can also matter: my Mac OS X notes cover the kind of local PHP, shell and path assumptions worth checking before blaming core.

Replace APIs that no longer exist

Once the failure is isolated, work through the stack trace and replace removed calls with their v11 equivalents rather than suppressing the warning. Move environment and path lookups to Environment, inject LanguageService where translated labels are required, and use the FlashMessage queue with the supported FlashMessage object. Keep framework objects out of static properties, because request-specific state does not belong in a shared service.

URL generation needs particular care. A module that previously appended tx_myext_module parameters to a manually formed link should register a backend route and generate the destination through its route-aware URI builder. Give the route a stable identifier and keep its parameters typed. If a redirect depends on the current module name, read it from the request context instead of assuming that the legacy global still exists.

PHP notices can expose the next layer of incompatibility. Constructor arguments, nullable return values and array shapes may now be enforced where older code relied on loose values. Fix those issues at the boundary rather than adding broad casts. Introduce declare(strict_types=1) only after the extension passes its tests, because enabling it during an upgrade can turn harmless assumptions into visible fatal errors.

Modernise Extbase modules and routes

Extbase modules benefit from clear separation of responsibilities. Controllers should validate the request and choose a response; repositories should own persistence; domain services should coordinate permissions, records and side effects. This prevents a failed route from becoming a tangled repair where every action shares session variables and temporary state. It also makes the migration easier to review with another developer.

That principle is not unique to PHP. The same separation appears in Ruby service object refactoring, where moving side effects out of an oversized method makes the remaining behaviour easier to understand. The language differs, but the migration lesson does not: a thin controller is easier to test, and a failure in a repository or service has a clearer boundary than a stack trace buried in rendering code.

Confirm that the extension registers its backend route in Configuration/Backend/Routes.php, along with its Extbase plugin mapping and permissions. Then test list, filter, create, edit and delete actions with representative records. Check JavaScript integration as well: v11 still has clients that rely on the global TYPO3 namespace, but stale bundles or renamed settings can make an otherwise valid module appear empty.

Account for Australian deployment conditions

Australian projects add operational realities to this work. Development teams in Sydney, Melbourne and Brisbane often share staging environments, while release windows must account for Australian Eastern Standard Time and daylight-saving changes. A job that runs at 02:00 in Sydney can land at a different local hour in Brisbane, so cron jobs and queue workers need an explicit Australia/Sydney, Australia/Melbourne or Australia/Brisbane timezone.

For organisations covered by the Privacy Act 1988, the Australian Privacy Principles matter when a backend module handles customer names, contact details or support histories. Restrict records by role, avoid logging unnecessary personal information, and make deletion or export behaviour explicit. A locally hosted TYPO3 installation still processes personal information, and geographical placement does not remove those obligations.

The Australian market also mixes established TYPO3 estates with SaaS tools, so custom modules may expose records originating in a CRM rather than TYPO3 itself. Keep identifiers and timestamps in a consistent internal format, then apply Australian date presentation such as dd/mm/yyyy at the interface. These details are small compared with a fatal error, but they are exactly where otherwise successful upgrades fail acceptance testing.

Build a repeatable release path

After the code works, make the repair repeatable rather than leaving the next upgrade to chance. The following checks belong in the release checklist:

  • Pin an approved TYPO3 v11 patch release and a PHP version supported by that exact release.
  • Align every typo3/cms-* package and third-party extension through Composer rather than editing constraints individually.
  • Search the extension for deprecated globals, removed APIs, old module identifiers and untyped request data.
  • Cover list, create, edit, permission-denied and not-found paths with functional or integration tests.
  • Deploy with a database backup, cache flush and tested rollback path, then watch the logs immediately after release.
  • Record the failing route, complete stack trace, package versions and changed files in the project history.

A concise before-and-after view helps reviewers spot work that has updated syntax while leaving old behaviour in place:

Area TYPO3 v10-era pattern TYPO3 v11-oriented repair
Core configuration Global environment helpers Environment and explicit services
Backend navigation Manually composed module URLs Registered routes and route-aware builders
Extbase actions Controller handles data and rendering Thin controller with repositories and services
Messages and language Global or loosely typed access FlashMessageQueue and LanguageService
Validation Manual action-level checks Typed boundaries and automated tests

Use this sequence on the next staging upgrade: open one failing module, preserve the complete stack trace, replace unsupported calls, and verify the same list, edit and permission paths after deployment. With the package versions and reproducible route recorded, a future TYPO3 upgrade becomes a controlled software change rather than an emergency repair on the live site.


cat ~/interests.json

KeyValue
editorTerminal-first workflow
osMac OS X / Unix
vcsGit, distributed version control
deployCapistrano, cron automation
graphicsSVG, Adobe Illustrator troubleshooting
networkingIP validation, SSH, VPN

git log --oneline --reverse

2013-10-30

Solving SVG import issues in Adobe Illustrator CS6 and CC

When importing an SVG into Illustrator, the operation fails with an unknown error [CANT]. A workaround for this Adobe-side bug.

2013

Solving NDK build issues on OS X

Troubleshooting native development kit compilation problems on Mac OS X.

2013

Programmatically adding PHP generated TypoScript to the backend configuration

Integrating dynamically generated TypoScript into Typo3 backend setups using PHP.

2013

ArgumentError: Could not parse PKey: no start line

Debugging an SSH key parsing error encountered during deployment.

2011-08-04

Validating IP-Addresses in PHP

Using PHP filter functions with flags like FILTER_FLAG_IPV4 and FILTER_FLAG_IPV6, and understanding how filter_var handles reserved IP addresses.

2011-07-09

Cocoa: Using NSTrackingArea

A short tutorial on using Cocoa's NSTrackingArea to capture mouseEntered and mouseExited events.


cat ~/contact.txt

github: github.com/x3ro
stackoverflow: x3ro
coderwall: coderwall.com/x3ro
twitter: @x3rames