VOL. X

- Voting results
- Eslint rules update
- Frontend reconstruction
- Benchmarks
- T3Lang - TYPO3 Translation Manager
- Dungeon Pick - The Math of Why You Can't Focus at Work
Voting Results
PHP Version
Since the active support for PHP v8.3 is coming to an end we discussed on when we want to upgrade to v8.4. We came to the conclusion that we will upgrade Projects to v8.4 and stay at v8.3 for extensions since older projects rely on those.
concat vs sprintf
Since string concatenation is faster than sprintf we decided to prefer the usage of concat but stick with sprintf if
the use case would keep things clearer (readability).
Eslint rules
With the introduction of @fullhaus/eslint-config@v0.3.0
we want to add coverage for imports.
Imports
Therefore, thsoe rules will get added:
- Enforce usage of the
node:protocol when importing Node.js builtin modules (import/enforce-node-protocol-usage) - Enforce imports to come first (import/first)
- Enforce a new line after last import statement (import/newline-after-import)
- Disallow empty named blocks (import/no-empty-named-blocks)
- Forbids the use of mutable exports with var or let (import/no-mutable-exports)
- Enforces import order (import/order)
- ['builtin', 'external', 'parent', 'sibling', 'index', 'type']
- Enforce consistent usage of type imports (@typescript-eslint/consistent-type-imports)
- Enforce top-level import type qualifier when only inline type qualifiers are used (@typescript-eslint/no-import-type-side-effects)
Updated rules
In addition to the import rules we also want to add a rule which enforces empty lines before return statements.
Frontend Reconstruction
In order to improve current Frontend structure we presented following ideas:
Drop of duplicated names
Currently most of the files inside a component include the name of the component in the filename. This is kinda redundant since the files live in a directory called after the component name.
- /components/contributor-spotlight/contributor-spotlight.component.ts
+ /components/contributor-spotlight/component.ts
Dropping the name from the filenames reduces this redundancy and allows shorter but still meaningful import statements.
import ContributorSpotlightComponent from './components/contributor-spotlight/contributor-spotlight.component';
import ContributorSpotlightComponent from './components/contributor-spotlight/component';
Farther grouping by component
Most types and interfaces are currently located in the models directory, requiring extra navigation from the source
file. Placing them in a dedicated file within the component directory would improve proximity and reduce the time needed
to find relevant type definitions.
└── components/
└── component-foo/
├── component.ts
├── controller.ts
└── models.ts // types, interfaces
Generic definitions however will stay at root level since their usage is unlikely component scoped but global.
Drop of "I" inside interface definitions
Interface names currently include an “I” prefix to indicate that they are interfaces. While this may seem useful at first, it is largely superfluous, as interfaces cannot be used as runtime values anyway. For interfaces that represent API responses, a descriptive, written-out suffix such as EmployeeInterface should be used instead to clearly convey their purpose.
- export interface IEmployee
+ export interface Employee
+ export interface EmployeeInterface // if designed for API-response scheme only
None of those are an approved design decision which needs to be followed. For now, it is only a suggested approach to reconstruct the current frontend. Since this might require further evaluation and fine-tuning we decided that the upcoming STIHL Project might be a good starting point to test things out and try implementing them their.
Benchmarks
Benchmarks tested on:
PHP 8.5.0 (cli) (built: Nov 18 2025 08:02:20) (NTS)
Copyright (c) The PHP Group
Built by Homebrew
Zend Engine v4.5.0, Copyright (c) Zend Technologies
with Zend OPcache v8.5.0, Copyright (c), by Zend Technologies
switch vs. match
const ITERATIONS = 10_000_000;
function testSwitch(int $value): int
{
switch ($value) {
case 1:
return 10;
case 2:
return 20;
case 3:
return 30;
case 4:
return 40;
default:
return 0;
}
}
function testMatch(int $value): int
{
return match ($value) {
1 => 10,
2 => 20,
3 => 30,
4 => 40,
default => 0,
};
}
Resulting in:
Switch (warm-up): 380.95 ms (sum=200000000)
Match (warm-up): 372.87 ms (sum=200000000)
----
Switch: 378.41 ms (sum=200000000)
Match: 371.61 ms (sum=200000000)
foreach vs. for
// Configuration
$size = 1_000_000;
$iterations = 10;
// Prepare test data
$array = range(1, $size);
// -------------------------
// foreach benchmark
// -------------------------
$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$sum = 0;
foreach ($array as $value) {
$sum += $value;
}
}
$foreachTime = microtime(true) - $start;
// -------------------------
// for benchmark
// -------------------------
$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$sum = 0;
$count = count($array);
for ($j = 0; $j < $count; $j++) {
$sum += $array[$j];
}
}
Results:
php -dxdebug.mode=off benchmark2.php
Array size: 1000000
Iterations: 10
foreach time: 0.036243915557861 seconds
for time: 0.042963027954102 seconds
Difference (foreach - for): -0.0067191123962402 seconds
Dungeon Pick
The Math of Why You Can't Focus at Work. Read here
TL;DR:
- reduce notifications and interruptions
- set deep work start rituals
- create smaller chunks to reduce needed theta / deep work time
Additional take away: Consider your colleagues deep work slots!

