Dokumentation durchblättern
Module entwickeln
Architektur-Überblick
Wie das Schneespur-Modulsystem aufgebaut ist: Tech-Stack, das Zwei-Marken-Modell, die Verzeichnisstruktur und das Registry-Prinzip, auf dem jede Erweiterung beruht.
Bevor Sie ein Modul schreiben, hilft ein Bild davon, woran es sich anlehnt. Schneespur ist eine Laravel-Anwendung, und Module sind keine Fremdkörper darin, sondern reguläre Laravel-ServiceProvider, die ihre Fähigkeiten an klar definierten Stellen anmelden. Diese Seite zeigt diese Stellen.
Tech-Stack
| Schicht | Technologie |
|---|---|
| Framework | Laravel 11+ (PHP 8.2+) |
| Datenbank | MySQL / MariaDB (Produktion). SQLite :memory: nur für die Test-Suite |
| Frontend | Blade-Templates, Tailwind CSS, Alpine.js |
DomPDF (austauschbar über PdfRendererRegistry) | |
| GPS | OwnTracks-Anbindung (MQTT/HTTP) |
| Wetter | OpenMeteo, BrightSky, Met Norway (austauschbar) |
| Auth | Laravel-Standard + eigener Customer-Guard für das Portal |
| Updates | Signierte Pakete vom Update-Server, geprüft mit libsodium |
Die meisten dieser Bausteine sind über eine Registry austauschbar — genau das ist der Hebel, an dem Module ansetzen. Welche das im Einzelnen sind, steht weiter unten und ausführlich unter Registries.
Zwei-Marken-Modell
Schneespur und Wintertrace sind dieselbe Codebasis. Die Marke wird zur Installationszeit über die Locale bestimmt:
- deutsche Locale → Schneespur
- jede andere Locale → Wintertrace
Die Marke liegt in der Einstellung app_brand und wird über zwei globale Helfer verfügbar
gemacht:
brand_slug(); // 'schneespur' oder 'wintertrace'
brand(); // 'Schneespur' oder 'Wintertrace'
Übersetzungsdateien laufen über einen BrandedTranslator, der den Markennamen automatisch
einsetzt. Ein Modul muss sich um die Marke nur dann kümmern, wenn es selbst sichtbaren Text
mit dem Produktnamen erzeugt — sonst nimmt der Translator die Arbeit ab.
Verzeichnisstruktur der Anwendung
So ist die Laravel-Anwendung aufgebaut. Für die Modul-Entwicklung sind vor allem
app/Services/Extension/ (die Registries) und modules/ (das Installationsverzeichnis)
relevant:
schneespur/ ← Laravel-Anwendungswurzel
├── app/
│ ├── Console/Commands/ ← Artisan-Commands (ModulesList, ModulesSync, …)
│ ├── Enums/ ← UserRole, JobType, WeatherMoment
│ ├── Events/ ← Domain-Events (JobCompleted, CustomerCreated, …)
│ ├── Exceptions/
│ ├── Http/
│ │ ├── Controllers/
│ │ │ ├── Admin/ ← Admin-Controller
│ │ │ ├── Auth/ ← Authentifizierung
│ │ │ ├── Driver/ ← Fahrer-Ansichten
│ │ │ ├── Portal/ ← Kundenportal
│ │ │ └── Api/ ← OwnTracks-API
│ │ ├── Middleware/ ← Auth-Guards, Rollen-Durchsetzung
│ │ └── Requests/ ← Form-Validierung
│ ├── Jobs/ ← Queue-Jobs (FetchWeather, SendCustomerReportEmail)
│ ├── Listeners/ ← Event-Listener
│ ├── Mail/ ← Mailable-Klassen
│ ├── Models/ ← Eloquent-Modelle
│ ├── Policies/ ← Autorisierungs-Policies
│ ├── Providers/ ← AppServiceProvider (Setup der Core-Registries)
│ └── Services/ ← Geschäftslogik
│ └── Extension/ ← ALLE Erweiterungs-Registries (Kern des Modulsystems)
├── config/
│ └── schneespur_modules.php ← Konfiguration des Modulsystems
├── modules/ ← Installationsverzeichnis der Module
│ └── example/ ← mitgeliefertes Referenzmodul
├── resources/
│ ├── views/layouts/ ← admin.blade.php, driver.blade.php, portal.blade.php
│ └── lang/ ← Core-Übersetzungen (de, en)
├── public/
│ └── modules/ ← Symlinks auf die dist/-Verzeichnisse der Module
└── storage/
└── app/ ← u. a. der Modul-Katalog-Status
Neben Services/Extension/ liegen weitere Service-Ordner, die jeweils ein Interface plus
zugehörige Registry bündeln (etwa Weather/, Storage/, Notification/, Pdf/,
Scheduler/, Backup/, Diagnostic/). Diese Interfaces sind die Verträge, gegen die ein
Modul implementiert.
Erweiterungs-Architektur
Das Modulsystem beruht auf einem Registry-Muster. Der Core definiert abstrakte Registries und Interfaces; Module liefern konkrete Implementierungen und melden sie während des Boots an.
┌──────────────────────────────────────────────────┐
│ AppServiceProvider │
│ (registriert alle Registries als Singletons, │
│ registriert die Core-Implementierungen) │
└──────────────┬───────────────────────────────────┘
│ boot()
▼
┌──────────────────────────────────────────────────┐
│ ModuleManager │
│ discover() → modules/*/module.json │
│ boot() → Autoloader → ServiceProvider │
└──────────────┬───────────────────────────────────┘
│ für jedes aktivierte Modul
▼
┌──────────────────────────────────────────────────┐
│ Modul-ServiceProvider │
│ register() → Services in den Container binden │
│ boot() → in die Erweiterungs-Registries │
│ eintragen; Routen, Views, Events │
└──────────────────────────────────────────────────┘
Das Kernprinzip
Module verändern nie Core-Dateien. Sie registrieren ihre Fähigkeiten während der
boot()-Methode ihres ServiceProviders in den Registries; der Core liest zur Laufzeit aus
diesen Registries.
Warum das so gebaut ist: Solange ein Modul nur registriert und nichts am Core patcht, bleiben Updates konfliktfrei. Eine neue Schneespur-Version kann den Core austauschen, ohne die Module zu zerstören — und ein Modul lässt sich entfernen, ohne Spuren im Core zu hinterlassen. Das ist der Unterschied zwischen einem Erweiterungssystem und einer Sammlung von Patches.
Die Core-Registries im Überblick
| Registry | Zweck | zu implementierendes Interface |
|---|---|---|
NavigationRegistry | Menüpunkte der Admin-Seitenleiste | — (Config-Array) |
DashboardWidgetRegistry | Dashboard-Karten/-Widgets | — (Config-Array + Blade-View) |
FilterRegistry | Hook-/Filter-Pipeline (WordPress-Stil) | — (Callable) |
SlotRegistry | Template-Einschubpunkte | — (Blade-View) |
PermissionRegistry | Berechtigungen | — (Config-Array) |
RoleTemplateRegistry | vorgefertigte Rollen-Konfigurationen | — (Config-Array) |
DispatchStrategyRegistry | Algorithmen zur Einsatz-Zuteilung | DispatchStrategyInterface |
NotificationChannelRegistry | Benachrichtigungs-Kanäle | NotificationChannelInterface |
TwoFactorMethodRegistry | 2FA-Verfahren | TwoFactorMethodInterface |
BackupTargetRegistry | Backup-Ziele | BackupTargetInterface |
StorageBackendRegistry | Datei-Speicher-Backends | StorageBackendInterface |
WeatherProviderRegistry | Wetter-Datenquellen | WeatherProviderInterface |
PdfRendererRegistry | PDF-Engines | PdfRendererInterface |
ReportFormatRegistry | Export-Formate | ReportFormatInterface |
ScheduledTaskRegistry | Cron-Aufgaben | ScheduledTaskInterface |
DiagnosticReporterRegistry | Fehler-/Crash-Reporting | DiagnosticReporterInterface |
ModuleAssetRegistry | Laden von CSS/JS | — (manifest.json) |
ModuleApiRegistrar | REST-API-Routengruppen | — (Routen-Closure) |
Die vollständige API jeder Registry — mit Methoden und Beispielen — finden Sie unter Registries. Wenn Sie zum ersten Mal ein Modul bauen, ist der schnellste Weg der Schnelleinstieg.