DevDairy TYPO3 Extension 3m5.DevModules #2

Titelbild mit TYPO3-Logo und Unterschirft "DevMods by 3m5."

Im ersten Beitrag habe ich mir einen perfekten Plan geschmiedet: Ich habe mir eine Roadmap erstellt, mein Ziel abgesteckt und dieses nach besten Wissen und Gewissen eingegrenzt. Nun geht es ans Eingemachte. Erster Punkt auf der Agenda ist die Erstellung eines Git-Repos. Bei 3m5. nutzen wir Gitlab und habe die Möglichkeit persönliche Repositories zu erstellen. Also kurz um:

  1. Neues Projekt in der dafür vorgesehene Gruppe erstellen (Gruppe öffnen, neues Projekt, blank mit Readme (Sichtbarkeit vorerst privat, keine weiteren Einstellungen)
  2. In PHPStorm clone (Git -> Clone, https-Clone URI pasten und done)
  3. Testcommit mit update der README.md

Wie starte ich nun?

Repo steht und ist lokal ausgecheckt. Den PHPStorm-Workflow spare ich mir hier. Die Frage ist, wie starte ich nun? Da ich das Rad nicht neu erfinden möchte ist der erste logische Schritt herauszufinden welche Ressourcen bzw. Boilerplates bzw. BestPractices ich für meine frische Extension nutzen kann.

Die Extension Extensionbuilder für den Kickstart zu nutzen war zu Beginn meiner TYPO3-Entwickler-Karriere eine Zeit lang das Maß aller Dinge. Mittlerweile weiß ich, dass ich dabei sehr davon abhängig bin, wie gut diese Extension gewartet wird (aktuell nur für Version 9).

Ein geeignetes Boilerplate habe ich auf die Schnelle nicht gefunden (Spoiler: Kommt später noch). Auch mit Blick in das offizielle TYPO3-Github-Repository konnte ich kein Beispiel für eine minimal extension finden. Daher entschloss ich mich meine Entwickler-Kollegen zu fragen… leider ohne Erfolg. In der Annahme, dass mir die TYPO3-Dokumentation schon weiterhelfen wird, entscheide ich mich eine Extension handmade zu entwickeln. Die Vorteile liegen ja schließlich auf der Hand:

  • Ich kann meine Kenntnisse zur TYPO3-Extension-Konfiguration auffrischen,
  • orientiere mich an aktuellen Standards,
  • und entdecke ggf. Settings, die ich bisher vielleicht überlesen habe.

Also frisch ans Werk – mit der aktuellsten Extension-Dokumentation die ich finden konnte (TYPO3 Version 11 – zu dem Zeitpunkt master).

Composer.json

Klar ist, und dass sollte meiner Meinung nach Meinung nach jeder PHP-/TYPO3-Entwickler wissen, dass Composer als Dependency-Management in TYPO3 Standard ist. TYPO3 hat da eine recht ausführliche Dokumentation. Doch obwohl diese Dokumentation aus meiner Sicht sehr gut ist, blieben Fragen offen.

Vendorname klein?

Die Extension ext:news gibt die Antwort: Bitte lowercase.

Support URL angeben?

Ja wieso eigentlich nicht. Ziel soll es ja sein die Extension irgendwann zu veröffentlichen (da wir Gitlab nutzen prinzipiell kein Problem, ggf. ist zum aktuellen Stand sogar Github besser?)

Was bedeutet eigentlich diese replace-Angabe?

Bei replace war ich mir selbst nicht sicher. Da der Vendorname fehlt, reicht es aus den Extension-Key anzugeben? Was ist die korrekte Schreibweise? Ein Blick auf die Doku hat geholfen: Nicht zwingend notwendig, aber ich gebe es trotzdem erstmal an. Die Extension devmodules wird es schon nicht geben… Ich hab auch alles in lowercase angegeben, nur um sicher zu gehen.

Autoload?

Autoload für PSR-4 war wieder einfach: Ich weiß, dass die Konvention UpperCamelCase ist. Also DMF/DevModules (wir schreiben statt 3m5 immer DMF… it is what it is). Konsequenter wäre natürlich „Dmf/DevMods“. Ein Kontrollblick auf ext:news verrät, dass UpperCamelCase eigtl. recht konsequent umgesetzt wird.

Require dev? Was soll das sein?

Require dev für das Testing habe ich erstmal rausgenommen (test-driven-development, was ist das?). Leider ist dieser Absatz wenig dokumentiert. 🙁

Für was ist Extra?

Ich hab hier einfach den zweiten Part des Namens genommen (was ja später auch der Extension-Ordner sein soll). Aber warum wird das eigtl. nicht als Extensionordner sondern als Extension-Key bezeichnet? Ein kurzer Blick auf die Doku verrät, dass der Anlass dafür eigentlich Packagist verantwortlich ist – aka ersetze Bindestriche mit Unterstrichen. Hey, trifft in meinem Fall nicht zu, also easy.

Das Ergebnis lautet wie folgt:

{
  "name": "dmf/devmoduls",
  "type": "typo3-cms-extension",
  "description": "A TYPO3 Extension that provides different modules with features especially for developers.",
  "license": "GPL-2.0-or-later",
  "require": {
    "php": "^7.2",
    "typo3/cms-backend": "^9.5 || ^10.4 || ^11.0",
    "typo3/cms-core": "^9.5 || ^10.4 || ^11.0"
  },
  "authors": {
    "name": "Jan Suchandt",
    "role": "Developer",
    "email": "jan.suchandt@3m5.de",
    "homepage": "www.3m5.de"
  },
  "keywords": [
    "typo3",
    "modules",
    "developer"
  ],
  "support": {
    "issues": "https://gitlab.3m5.de/3m5-typo3/devMods"
  },
  "replace": {
    "typo3-ter/devmods": "self.version"
  },
  "autoload": {
    "psr-4": {
      "DMF\\DevModules\\": "Classes/"
    }
  },
  "extra": {
    "typo3/cms": {
      "devmodules": "devmodules"
    }
  }
}

Short break

Mittlerweile sind 1,5 Wochen ohne aktive Entwicklung vergangen. Dennoch habe ich mir bereits erstes Feedback von Entwickler-Kollegen gesammelt:

Den Namen DevMods finde ich etwas komisch. Klingt wie Modification.

Und der Einwand ist korrekt. Darüber habe ich im ersten Moment gar nicht nachgedacht. Deswegen einen Schritt zurück und den zuvor definierten Extensionkey in DevModules umbenennen. Das ist wesentlich eindeutiger. Zudem bin ich nun auch auf zwei Best-Practice Extensions gestoßen:

Also weiter geht es mit der ext_emconf.php, die Meta-Informationen für TYPO3 selbst bereit stellt.

<?php
// https://docs.typo3.org/m/typo3/reference-coreapi/master/en-us/ExtensionArchitecture/DeclarationFile/Index.html
$EM_CONF[$_EXTKEY] = [
  'title' => 'Developer Modules',
  'description' => 'A TYPO3 Extension that provides different modules with features especially for developers.',
  'category' => 'module',
  'author' => 'Jan Suchandt',
  'author_company' => '3m5. Media GmbH',
  'author_email' => 'jan.suchandt@3m5.de',
  // TODO update on release
  'state' => 'alpha',
  'clearCacheOnLoad' => true,
  'version' => '1.0.0',
  'constraints' => [
    'depends' => [
      'typo3' => '10.0.0-11.99.99',
    ],
    'conflicts' => [],
    // Define the extension load order
    'suggests' => [],
  ],
  'autoload' => [
    // Autoload classes in composer mode
    'psr-4' => [
      'DMF\\DevModules\\' => 'Classes'
    ]
  ],
];

Eigentlich sind alle Einträge selbsterklärend, doch ein zwei Dinge musste ich dann doch in der Dokumentation nachlesen:

  • category: Hier gibt es eine große Auswahl definierter Werte. Für meinen Anwendungsfall passt am besten module. Dabei ist mir aufgefallen, dass zahlreiche selbst entwickelte Extensions falsch deklariert sind. Unser Firmen-Sitepackage könnte bspw. als distribution definiert werden. Ohne weiter nachzuforschen, wird sich diese Angabe aber ohnehin ausschließlich auf die Angabe im TER (TYPO3-Extension-Repository) beziehen.
  • state: Okay, aktuell sehr eindeutig – alpha. Generell finde ich diese Angabe aber wieder schwierig, da diese Information in der composer.json abgebildet werden kann.
  • constraints: Habe ich noch suggest und conflicts erweitert. Insbesondere suggest nutze ich gern um die Reihenfolge der Extensions zu definieren.
  • autoload und clearCacheOnLoad: Definitiv nice2know. Bei autoload verzichte ich bewusst auf eine eigene ClassMap. IMO sollte jede Extension über den Composer-Mode laufen.

Next step ist die ext_localconf.php, die zwar nicht zwingend notwendig ist, aber für Kollegen zumindestens einen Einstiegspunkt ermöglichen.

<?php
// Prevent Script from being called directly
defined('TYPO3') or die();

// encapsulate all locally defined variables
(function () {

})();

Insbesondere der Teil define… wird oftmals vergessen. Auch die Kapselung der lokal definierten Variablen wird oft vergessen.

Weiter steht auf meiner TODO-Liste noch die .gitignore und .editorconfig. Beide Dateien sind nicht zwingend notwendig, gehören aber meiner Meinung nach zum Best-Practice jeder TYPO3-Extension. In der .gitignore füge ich vorerst nur folgendes ein:

/.idea/*

Diese Anweisung ist evtl. sehr speziell, da ich meine IDE-Settings von PHPStorm nicht in VCS haben möchte. Je nach IDE muss das natürlich an eure IDE angepasst werden. In der .editorconfig bediene ich mich beim offiziellen TYPO3-Repository:

# EditorConfig is awesome: http://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true

# TS/JS-Files
[*.{ts,js}]
indent_size = 2

# JSON-Files
[*.json]
indent_style = tab

# ReST-Files
[*.rst]
indent_size = 3
max_line_length = 80

# YAML-Files
[*.{yaml,yml}]
indent_size = 2

# package.json
[package.json]
indent_size = 2

# TypoScript
[*.{typoscript,tsconfig}]
indent_size = 2

# XLF-Files
[*.xlf]
indent_style = tab

# SQL-Files
[*.sql]
indent_style = tab
indent_size = 2

# .htaccess
[{_.htaccess,.htaccess}]
indent_style = tab

Fazit

Nach zwei Sessions und der Ernüchterung, dass für insgesamt fünf Dateien doch einiges an Recherche notwendig ist, schließe ich diesen Beitrag.

Theoretisch hätte ich auch eine gut gewartete Extension (z.B.news) kopieren können, alle für mich unnötige Stellen entfernen können und wäre wahrscheinlich um einiges schneller gewesen. Dennoch habe ich – allein aus dieser Methodik heraus – einige Erkenntnisse gewonnen und Probleme erkannt:

  • Es gehört doch eben mehr dazu eine Extension zu konfigurieren.
  • Die Dokumentation und die Boilerplates sind nicht so leicht zu finden, wie ich es erhofft habe.
  • Auch aktuell entwickelte Extensions besitzen Verbesserungspotenzial (wenn auch nur in der ext_emconf.php).
  • In der Extensionentwicklung gibt es zwischen composer.json und ext_emconf.php mehr Redundanz als angenommen.
  • Warum ist die ext_emconf.php eigentlich ein PHP-Array?

Schon jetzt habe ich meine eigene Roadmap im ersten Beitrag nicht eingehalten: Es fehlt noch die notwendige Ordnerstruktur (classes/). Da dieser Beitrag aber – zu mindestens für mich – erstmal genug Input bietet, schließe ich den Post. Über euer Feedback würde ich mich natürlich sehr freuen! Wie geht ihr an das Thema „extension from scratch“ an? Habt ihr ggf. bessere Ressourcen oder nutzt ihr gar den Extension-Builder?

In diesem Sinne: Vielen Dank fürs lesen und stay prepared for part #3.


Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert