Ich werde die README.md für das REDAXO Addon "Definitions" anpassen, um die neuen domain- und sprachabhängigen Funktionen zu dokumentieren.
┓ ┓• • ┓ ┏• • •
┣┓┏┓┏┏┓┏┏┓┏┓┏┫┓╋┓┏┓┏┓ ┏┫┏┓╋┓┏┓┓╋┓┏┓┏┓┏
┗┛┗┻┛┗ ┗┗┛┛┗┗┻┗┗┗┗┛┛┗ ┗┻┗ ┛┗┛┗┗┗┗┗┛┛┗┛
Ein REDAXO-Addon zur zentralen Verwaltung von Konfigurationen und Definitionen über YAML-Dateien.
- Zentrale Verwaltung von Konfigurationen über YAML-Dateien
- Automatische Template-, Domain- und Sprachkontext-Erkennung
- Flexibles Caching-System für optimale Performance
- Erweiterbare Struktur durch Extension Points
- Unterstützung für Template-, Navigations- und Modulkonfigurationen
- Freie Konfigurationen für eigene Anwendungsfälle
- Automatisches Laden von Konfigurationen beim Systemstart
- Vererbung von Basis-Konfigurationen durch
extend
-Funktionalität - Flexible Registrierung von Definition-Verzeichnissen
- Überschreiben von Definitionen durch strukturelle Übereinstimmung und Ladereihenfolge
- Priorisierte Ladereihenfolge (EARLY, NORMAL, LATE)
- Domain-spezifische Konfigurationen
- Sprachspezifische Konfigurationen
- Im REDAXO-Installer das Addon "definitions" auswählen und installieren
- Mindestvoraussetzungen:
- REDAXO >= 5.15.0
- PHP >= 8.1
Das Addon bietet drei Hauptanwendungsfälle:
- System-Definitionen: Vordefinierte Strukturen für Templates, Navigation und Module
- Context-Definitionen: Domain- und sprachspezifische Konfigurationen
- Freie Konfigurationen: Beliebige eigene YAML-basierte Konfigurationen
redaxo-root/
├── redaxo/
│ ├── data/
│ │ └── definitions/
│ │ ├── navigation/
│ │ │ ├── main.yml # Standard (domain- und sprachübergreifend)
│ │ │ ├── de/ # Sprachspezifisch (domainübergreifend)
│ │ │ │ └── main.yml
│ │ │ └── example.com/ # Domainspezifisch
│ │ │ ├── main.yml # Nur Domain
│ │ │ └── de/ # Domain + Sprache
│ │ │ └── main.yml
│ │ ├── template/
│ │ │ ├── home.yml # Standard-Template
│ │ │ ├── article.yml # Standard-Template
│ │ │ ├── de/ # Sprachspezifische Templates
│ │ │ │ └── home.yml
│ │ │ └── example.com/ # Domainspezifische Templates
│ │ │ ├── home.yml
│ │ │ └── de/
│ │ │ └── home.yml
│ │ └── module/
│ │ ├── text_image/ # Standard-Module
│ │ │ └── default.yml
│ │ ├── gallery/
│ │ │ └── default.yml
│ │ ├── de/ # Sprachspezifische Module
│ │ │ └── text_image/
│ │ │ └── default.yml
│ │ └── example.com/ # Domainspezifische Module
│ │ └── text_image/
│ │ ├── default.yml
│ │ └── de/
│ │ └── default.yml
redaxo-root/
├── redaxo/
│ └── addons/
│ └── project/ # Für projekt-spezifische Anpassungen (optional)
│ └── definitions/
│ ├── navigation/
│ ├── template/
│ └── module/
redaxo-root/
├── themes/
│ └── private/
│ └── definitions/
│ ├── navigation/
│ │ ├── main.yml # Standard (domain- und sprachübergreifend)
│ │ ├── de/ # Sprachspezifisch (domainübergreifend)
│ │ │ └── main.yml
│ │ └── example.com/ # Domainspezifisch
│ │ ├── main.yml # Nur Domain
│ │ └── de/ # Domain + Sprache
│ │ └── main.yml
│ ├── template/
│ └── module/
Das Definitions Addon erkennt automatisch den Template-Key des aktuell verwendeten Artikels, die aktuelle Domain und die aktuelle Sprache. Dies ermöglicht eine dynamische Zusammenstellung der Definitionen ohne manuelle Verkettung.
// Im Template oder Modul
$templateConfig = BSC\config::get('template');
// Lädt automatisch die Template-Definition basierend auf dem aktiven Template
$moduleConfig = BSC\config::get('module');
// Lädt automatisch die Modul-Definition passend zum Template-Kontext
Definitionen können domainspezifisch abgelegt werden:
definitions/
└── template/
├── home.yml # Standard für alle Domains
└── example.com/ # Spezifisch für example.com
└── home.yml # Überschreibt Standards für diese Domain
Definitionen können sprachspezifisch abgelegt werden:
definitions/
└── template/
├── home.yml # Standard für alle Sprachen
└── de/ # Spezifisch für deutsche Inhalte
└── home.yml # Überschreibt Standards für diese Sprache
Die verschiedenen Kontexte können beliebig kombiniert werden:
definitions/
└── template/
├── home.yml # Standard
├── de/ # Sprachspezifisch
│ └── home.yml
├── example.com/ # Domainspezifisch
│ ├── home.yml
│ └── de/ # Domain + Sprache
│ └── home.yml
└── de/home/ # Sprache + Template
└── default.yml
Die Definitionen werden in folgender Prioritätsreihenfolge geladen und überschrieben:
- Allgemeine Basisdefinitionen (z.B.
/template/home.yml
) - Template-spezifische Definitionen (z.B.
/template/default/home.yml
) - Sprachspezifische Definitionen (z.B.
/template/de/home.yml
) - Sprach- und Template-spezifische Definitionen (z.B.
/template/de/default/home.yml
) - Domainspezifische Definitionen (z.B.
/template/example.com/home.yml
) - Domain- und Template-spezifische Definitionen (z.B.
/template/example.com/default/home.yml
) - Domain- und Sprachspezifische Definitionen (z.B.
/template/example.com/de/home.yml
) - Domain-, Sprach- und Template-spezifische Definitionen (z.B.
/template/example.com/de/default/home.yml
)
Spätere Definitionen überschreiben frühere bei gleichem Schlüssel. Dies ermöglicht eine flexible Anpassung von Konfigurationen für verschiedene Kontexte.
Die Registrierung erfolgt nach einer klaren Prioritätenreihenfolge:
- Core/AddOn Definitionen (EARLY):
rex_extension::register('BSC_CONFIG_LOAD', function(rex_extension_point $ep) {
$schemes = $ep->getSubject();
if ($addon = rex_addon::get('mein_addon')) {
$schemes[] = $addon->getPath('definitions/*.yml');
}
return $schemes;
}, rex_extension::EARLY);
- Theme Definitionen (NORMAL):
rex_extension::register('BSC_CONFIG_LOAD', function(rex_extension_point $ep) {
$schemes = $ep->getSubject();
if (rex_addon::exists('theme')) {
$schemes[] = theme_path::base('private/definitions/navigation/*.yml');
$schemes[] = theme_path::base('private/definitions/template/*.yml');
$schemes[] = theme_path::base('private/definitions/module/*/*.yml');
}
return $schemes;
});
- Project-Addon Definitionen (LATE):
rex_extension::register('BSC_CONFIG_LOAD', function(rex_extension_point $ep) {
$schemes = $ep->getSubject();
$projectPath = rex_addon::get('project')->getPath();
$schemes[] = $projectPath . 'definitions/navigation/*.yml';
$schemes[] = $projectPath . 'definitions/template/*.yml';
$schemes[] = $projectPath . 'definitions/module/*/*.yml';
return $schemes;
}, rex_extension::LATE);
Die extend
-Funktionalität ermöglicht die Vererbung von Basis-Konfigurationen:
# /themes/private/definitions/template/base.yml
template:
base:
sections:
- header
- content
- footer
defaults:
show_breadcrumb: true
cache_ttl: 3600
# /themes/private/definitions/template/home.yml
extend: base.yml # erbt die Basis-Konfiguration
template:
home:
sections:
- header
- slider # eigene Sektion
- content
- footer
defaults:
show_breadcrumb: false # überschreibt einzelnen Wert
Das Überschreiben erfolgt durch strukturelle Übereinstimmung und Ladereihenfolge:
# /redaxo/data/definitions/template/default.yml
template:
default:
name: "Standard Template"
sections:
- header
- content
- footer
# /themes/private/definitions/template/default.yml
template:
default:
name: "Theme Template" # überschreibt den Namen
sections:
- header
- slider # überschreibt die sections
- content
- footer
# /redaxo/addons/project/definitions/template/default.yml
template:
default:
name: "Projekt Template" # überschreibt den Namen erneut
Domain-Mappings können über die Konfigurationsseite des Addons oder programmatisch eingerichtet werden:
// Domain-Mapping registrieren
\BSC\Domain\DomainContextProvider::registerDomainMapping('example.com', 'example_com');
Bei Verwendung des YRewrite-Addons werden Domains automatisch erkannt:
// Wird automatisch in der boot.php bei vorhandenem YRewrite Addon ausgeführt
if (rex_addon::exists('yrewrite') && rex_addon::get('yrewrite')->isAvailable()) {
rex_extension::register('BSC_DOMAIN_DETECTION', function(rex_extension_point $ep) {
$domain = \rex_yrewrite::getCurrentDomain();
if ($domain) {
return $domain->getName();
}
return $ep->getSubject();
}, rex_extension::EARLY);
}
// Aktuelle Domain ermitteln
$currentDomain = \BSC\Domain\DomainContextProvider::getCurrentDomain();
// Domain-Key für Verzeichnisstruktur ermitteln
$domainKey = \BSC\Domain\DomainContextProvider::getDomainKey();
Das Addon integriert sich nahtlos mit REDAXO's Sprachsystem:
// Aktuelle Sprache ermitteln
$currentLanguage = \BSC\Language\LanguageContextProvider::getCurrentLanguage();
// Alle verfügbaren Sprachen abrufen
$languages = \BSC\Language\LanguageContextProvider::getAvailableLanguages();
Die Config-Klasse ist das zentrale Element für den Zugriff auf Definitionen und Konfigurationen.
use BSC\config;
// Template-Definition abrufen
$templateConfig = config::get('template');
// Navigations-Definition abrufen
$navigationConfig = config::get('navigation.main');
// Modul-Definition abrufen
$moduleConfig = config::get('module');
Die Config-Klasse berücksichtigt automatisch den aktuellen Domain-, Sprach- und Template-Kontext:
// Lädt automatisch die passende Konfiguration für aktuelle Domain, Sprache und Template
$config = config::get('template');
Die Config-Klasse eignet sich auch für eigene Konfigurationen:
use BSC\config;
// Konfigurationsdateien laden
config::loadConfig([
'resources/*.yml', // Verzeichnis
'config/listener.yml', // Einzelne Datei
'services/*.yml' // Weiteres Verzeichnis
]);
// Zugriff auf Konfigurationen
$apiKey = config::get('resources.api.key');
$serviceConfig = config::get('services.mail');
# services/listener.yml
services:
listener:
PAGE_HEADER:
- SecurityHeaderService::addSecurityHeaders
PACKAGES_INCLUDED:
- CacheService::clearCache
// Listener registrieren
$listeners = config::get('services.listener');
foreach($listeners as $event => $callbacks) {
foreach($callbacks as $callback) {
rex_extension::register($event, $callback);
}
}
# resources/api.yml
api:
endpoints:
users: "https://api.example.com/users"
posts: "https://api.example.com/posts"
settings:
timeout: 30
retries: 3
Die Config-Klasse unterstützt auch das dynamische Setzen von Werten:
// Einzelwert setzen
config::set('cache.enabled', true);
// Komplette Sektion setzen
config::set('mail', [
'host' => 'smtp.example.com',
'port' => 587
]);
// Wert an String anhängen
config::addStringTo('assets.css', 'custom.css');
Zur Überprüfung der geladenen Definitionen:
rex_extension::register('BSC_CONFIG_LOADED', function(rex_extension_point $ep) {
if (rex::isDebugMode()) {
dump('Geladene Definition Pfade:', BSC\config::getAll());
if ($templateConfig = BSC\config::get('template')) {
dump('Template Konfigurationen:', $templateConfig);
}
// Domain- und Sprachkontext ausgeben
dump('Kontext-Informationen:', [
'domain' => \BSC\Domain\DomainContextProvider::getDomainKey(),
'language' => \BSC\Language\LanguageContextProvider::getCurrentLanguage(),
'template' => BSC\base::getTemplateKey()
]);
}
});
Das Addon bietet folgende Extension Points:
BSC_CONFIG_LOAD
: Beim Laden der Konfigurationen, kann zur Modifikation der Suchpfade genutzt werdenBSC_CONFIG_LOADED
: Nach dem Laden aller Konfigurationen, ideal für Debugging oder NachbearbeitungBSC_DEFINITIONS_LOAD
: Beim Laden der Definitionen, ermöglicht Modifikation der Definition-SuchpfadeBSC_DOMAIN_DETECTION
: Ermöglicht Einflussnahme auf die Domain-ErkennungBSC_LANGUAGE_DETECTION
: Ermöglicht Einflussnahme auf die Sprach-Erkennung
BSC_DEFINITION_SET
: Vor dem Setzen einer DefinitionBSC_DEFINITION_SET_AFTER
: Nach dem Setzen einer DefinitionBSC_DEFINITION_OVERWRITE
: Vor dem Überschreiben einer DefinitionBSC_DEFINITION_OVERWRITE_MERGED
: Nach dem Zusammenführen, aber vor dem Setzen einer überschriebenen DefinitionBSC_DEFINITION_VALUE_SET
: Vor dem Setzen eines WertsBSC_DEFINITION_VALUE_SET_AFTER
: Nach dem Setzen eines WertsBSC_DEFINITION_STRING_ADD
: Vor dem Hinzufügen eines StringsBSC_DEFINITION_STRING_ADD_AFTER
: Nach dem Hinzufügen eines Strings
DEFINITION_CACHE_KEY
: Zur Modifikation des Cache-KeysDEFINITION_BEFORE_CACHE_LOAD
: Vor dem Laden des CachesDEFINITION_AFTER_CACHE_LOAD
: Nach dem Laden des CachesDEFINITION_BEFORE_CACHE_SAVE
: Vor dem Speichern des CachesDEFINITION_AFTER_CACHE_SAVE
: Nach dem Speichern des Caches
-
Strukturierung:
- Nutzen Sie die empfohlene Verzeichnisstruktur
- Gruppieren Sie Konfigurationen nach logischen Einheiten
- Verwenden Sie sprechende Dateinamen
- Legen Sie domainspezifische Konfigurationen nur bei Bedarf an
-
Kontextualisierung:
- Nutzen Sie Domain-Verzeichnisse nur für domain-spezifische Anpassungen
- Legen Sie sprachspezifische Konfigurationen in separaten Sprach-Verzeichnissen ab
- Kombinieren Sie Domain-, Sprach- und Template-Kontexte bei Bedarf
-
Ladereihenfolge:
- Beachten Sie die EARLY/NORMAL/LATE Prioritäten
- Nutzen Sie das Project-Addon für finale Überschreibungen
- Laden Sie projekt-spezifische Konfigurationen früh im Boot-Prozess
-
Konfigurationsmanagement:
- Nutzen Sie
extend
für die Vererbung innerhalb einer Ebene - Verwenden Sie strukturelle Überschreibungen für ebenenübergreifende Anpassungen
- Halten Sie sensible Daten in separaten Konfigurationsdateien
- Nutzen Sie
-
Performance:
- Aktivieren Sie das Caching in Produktivumgebungen
- Vermeiden Sie das mehrfache Laden gleicher Konfigurationen
- Cachen Sie häufig verwendete Konfigurationswerte
-
Entwicklung:
- Aktivieren Sie den Debug-Modus während der Entwicklung
- Dokumentieren Sie Ihre Konfigurationsstrukturen
- Nutzen Sie Versionskontrolle für Konfigurationsdateien
- Autor: Joachim Doerr
- Support: https://github.com/basecondition/definitions