20 KiB
Flux CMS - Architecture Documentation
Überblick
Flux CMS ist ein modular aufgebautes Content Management System für Laravel 12 mit Livewire 3 und Flux UI. Das System folgt einem "Code-as-Schema" Ansatz, bei dem Component-Felder direkt in PHP-Klassen definiert werden statt in der Datenbank.
Architektur-Prinzipien
1. Modularität
- Package-basierte Architektur mit separaten Modulen
- Klare Trennung von Core, Components und Starter Components
- Erweiterbar durch zusätzliche Packages
2. Code-as-Schema
- Component-Felder werden in PHP-Klassen definiert
- Keine Datenbank-Schemas für Felder
- Typsicherheit und IDE-Unterstützung
3. Multi-Domain & Multi-Language
- Unterstützung für mehrere Domains
- Vollständige Mehrsprachigkeit mit spatie/laravel-translatable
- Domain-spezifische Konfigurationen
4. Component-First
- Seiten bestehen aus wiederverwendbaren Livewire Components
- Drag & Drop Interface für Component-Anordnung
- Flexibles Layout-System
Package-Struktur
packages/flux-cms/
├── core/ # Kern-Funktionalität
│ ├── src/
│ │ ├── Models/ # Eloquent Models
│ │ ├── Services/ # Business Logic
│ │ ├── FieldTypes/ # Field Type System
│ │ ├── Commands/ # Artisan Commands
│ │ ├── Http/ # Controllers & Middleware
│ │ │ └── Controllers/
│ │ │ ├── Admin/ # Backend Controllers
│ │ │ │ ├── PageController.php
│ │ │ │ ├── BlogController.php
│ │ │ │ └── ...
│ │ │ └── PageController.php # Frontend Controller
│ │ └── FluxCmsServiceProvider.php
│ ├── database/migrations/ # Database Migrations
│ ├── config/ # Konfigurationsdateien
│ └── tests/ # Tests
│
├── components/ # Livewire Components
│ ├── src/
│ │ └── Livewire/
│ │ ├── Backend/ # Admin Interface Components
│ │ └── Frontend/ # Public Frontend Components
│ └── resources/
│ └── views/ # Blade Templates
│
└── starter-components/ # Vorgefertigte Components
└── src/Components/ # Ready-to-use Components
Datenbank-Schema
Core Tabellen
flux_cms_pages
- id (Primary Key)
- domain_key (String) - Domain-Zuordnung
- title (JSON) - Mehrsprachige Titel
- slug (JSON) - Mehrsprachige URL-Slugs
- content (JSON) - Mehrsprachiger Inhalt
- template (String) - Template-Name
- meta_title (JSON) - SEO Titel
- meta_description (JSON) - SEO Beschreibung
- is_published (Boolean)
- published_at (Timestamp)
- settings (JSON) - Zusätzliche Einstellungen
- created_at, updated_at
flux_cms_page_components
- id (Primary Key)
- page_id (Foreign Key) - Verknüpfung zur Seite
- component_type (String) - Livewire Component Klasse
- content (JSON) - Component-spezifische Daten
- settings (JSON) - Component-Einstellungen
- order (Integer) - Sortierreihenfolge
- is_active (Boolean)
- created_at, updated_at
flux_cms_page_versions
- id (Primary Key)
- page_id (Foreign Key)
- page_data (JSON) - Snapshot der Seite
- components_data (JSON) - Snapshot der Components
- version_name (String)
- change_description (Text)
- created_by_type, created_by_id (Polymorphic)
- created_at, updated_at
flux_cms_navigations
- id (Primary Key)
- domain_key (String)
- name (String) - Eindeutiger Name
- display_name (JSON) - Mehrsprachiger Anzeigename
- settings (JSON)
- is_active (Boolean)
- created_at, updated_at
flux_cms_navigation_items
- id (Primary Key)
- navigation_id (Foreign Key)
- parent_id (Foreign Key, nullable) - Hierarchie
- page_id (Foreign Key, nullable) - Verknüpfung zu Seite
- title (JSON) - Mehrsprachiger Titel
- url (String, nullable) - Externe URL
- target (String) - Link-Ziel
- order (Integer)
- is_active (Boolean)
- settings (JSON)
- created_at, updated_at
flux_cms_blog_posts
- id (Primary Key)
- domain_key (String)
- title (JSON) - Mehrsprachiger Titel
- slug (JSON) - Mehrsprachige Slugs
- excerpt (JSON) - Mehrsprachige Auszüge
- content (JSON) - Mehrsprachiger Inhalt
- meta_title (JSON) - SEO Titel
- meta_description (JSON) - SEO Beschreibung
- is_published (Boolean)
- is_featured (Boolean)
- published_at (Timestamp)
- author_id (Foreign Key)
- category (String)
- tags (JSON)
- settings (JSON)
- created_at, updated_at
flux_cms_slugs (Neu)
- id (Primary Key)
- model_type, model_id (Polymorphic)
- locale (String)
- slug (String)
- created_at, updated_at
tags & taggables (Neu, von spatie/laravel-tags)
// tags
- id
- name (JSON)
- slug (JSON)
- type (String, nullable)
- order_column (Integer, nullable)
// taggables
- tag_id (Foreign Key)
- taggable_type, taggable_id (Polymorphic)
Component-System
Field Types
Das System bietet verschiedene Field Types für Component-Definitionen:
1. TextField
TextField::make('title', 'Titel')
->translatable()
->required()
->placeholder('Titel eingeben')
->helpText('Der Haupttitel des Elements')
2. MediaField
MediaField::make('image', 'Bild')
->images()
->multiple(false)
->required()
3. WysiwygField
WysiwygField::make('content', 'Inhalt')
->translatable()
->toolbar(['bold', 'italic', 'link'])
4. SelectField
SelectField::make('layout', 'Layout')
->options([
'default' => 'Standard',
'wide' => 'Breit',
'centered' => 'Zentriert'
])
->default('default')
5. BooleanField
BooleanField::make('show_overlay', 'Overlay anzeigen')
->toggle()
->default(true)
->helpText('Dunkles Overlay über dem Hintergrundbild')
6. NumberField
NumberField::make('columns', 'Spalten')
->min(1)
->max(12)
->default(3)
->helpText('Anzahl der Spalten im Grid')
Component-Definition
<?php
namespace App\Livewire\Components;
use Livewire\Component;
use FluxCms\Core\FieldTypes\TextField;
use FluxCms\Core\FieldTypes\MediaField;
use FluxCms\Core\FieldTypes\BooleanField;
class HeroSection extends Component
{
public array $content = [];
public array $settings = [];
public int $componentId;
public static function getCmsFields(): array
{
return [
TextField::make('headline', 'Hauptüberschrift')
->translatable()
->required()
->placeholder('Ihre Hauptüberschrift'),
TextField::make('subheadline', 'Unterüberschrift')
->translatable()
->placeholder('Optionale Unterüberschrift'),
MediaField::make('background_image', 'Hintergrundbild')
->images()
->required(),
BooleanField::make('dark_overlay', 'Dunkles Overlay')
->toggle()
->default(true),
];
}
public static function getCmsInfo(): array
{
return [
'name' => 'Hero Section',
'description' => 'Großer Bereich mit Hintergrundbild und Text',
'category' => 'Header',
'preview' => 'hero-preview.jpg'
];
}
public function render()
{
return view('components.hero-section');
}
}
Service-Layer
ComponentRegistry
Der ComponentRegistry Service scannt und verwaltet alle verfügbaren CMS Components:
<?php
namespace FluxCms\Core\Services;
class ComponentRegistry
{
protected array $components = [];
protected bool $loaded = false;
public function getComponents(): array
{
if (!$this->loaded) {
$this->loadComponents();
}
return $this->components;
}
protected function loadComponents(): void
{
// Auto-discovery von Components
// Caching für Performance
// Validierung der Component-Struktur
}
public function isValidComponent(string $className): bool
{
// Prüft ob Klasse gültige CMS Component ist
}
}
Multi-Domain Unterstützung
Domain-Konfiguration
// config/domains.php
return [
'portal.b2in.test' => [
'type' => 'admin',
'name' => 'Admin Portal',
'theme' => 'admin',
],
'b2in.test' => [
'type' => 'web',
'name' => 'B2in Main',
'theme' => 'b2in',
'colors' => [
'primary' => '#1f2937',
'secondary' => '#3b82f6',
],
],
// weitere Domains...
];
Domain-spezifische Inhalte
Alle Inhalte werden über domain_key gefiltert:
// Automatische Domain-Filterung
Page::forDomain(request()->getHost())->published()->get();
BlogPost::forDomain($domainKey)->published()->get();
Navigation::forDomain($domainKey)->active()->get();
Mehrsprachigkeit
Spatie Translatable Integration
// Model Definition
class Page extends Model
{
use HasTranslations;
protected $translatable = [
'title',
'slug',
'content',
'meta_title',
'meta_description'
];
protected $casts = [
'title' => 'array',
'slug' => 'array',
// ...
];
}
// Verwendung
$page->getTranslation('title', 'de');
$page->setTranslation('title', 'de', 'Deutscher Titel');
Component-Inhalte
// Mehrsprachige Component-Inhalte
$content = [
'title' => [
'de' => 'Deutscher Titel',
'en' => 'English Title'
],
'description' => [
'de' => 'Deutsche Beschreibung',
'en' => 'English Description'
]
];
Versionierung
Page Versions
class Page extends Model
{
public function createVersion(string $changeDescription = null): PageVersion
{
return $this->versions()->create([
'page_data' => $this->toArray(),
'components_data' => $this->allComponents()->get()->toArray(),
'change_description' => $changeDescription,
'version_name' => $this->generateVersionName(),
]);
}
public function restoreVersion(PageVersion $version): void
{
// Backup current version
$this->createVersion('Backup before restoration');
// Restore page data
$this->update($version->page_data);
// Restore components
$this->allComponents()->delete();
foreach ($version->components_data as $componentData) {
$this->allComponents()->create($componentData);
}
}
}
Medien-Management
Spatie Media Library Integration
// Models implementieren HasMedia Interface
class BlogPost extends Model implements HasMedia
{
use InteractsWithMedia;
public function registerMediaCollections(): void
{
$this->addMediaCollection('featured_image')
->singleFile()
->acceptsMimeTypes(['image/jpeg', 'image/png']);
$this->addMediaCollection('gallery')
->acceptsMimeTypes(['image/jpeg', 'image/png']);
}
public function registerMediaConversions(Media $media = null): void
{
$this->addMediaConversion('thumb')
->width(300)
->height(200);
$this->addMediaConversion('hero')
->width(1200)
->height(600);
}
}
SEO & Performance
SEO Features
class Page extends Model
{
public function getSeoTitle(string $locale = null): string
{
return $this->getTranslation('meta_title', $locale)
?? $this->getTranslation('title', $locale);
}
public function getSeoDescription(string $locale = null): string
{
return $this->getTranslation('meta_description', $locale)
?? str_limit(strip_tags($this->getTranslation('content', $locale)), 160);
}
public function getCanonicalUrl(): string
{
return route('pages.show', ['slug' => $this->slug]);
}
}
Caching Strategy
// ComponentRegistry Caching
Cache::remember('flux_cms_components', 3600, function () {
return $this->scanForComponents();
});
// Page Caching
Cache::tags(['pages', 'page-'.$page->id])
->remember('page-'.$page->id, 3600, function () use ($page) {
return $page->with('components')->first();
});
Security
Authorization Gates
// FluxCmsServiceProvider
Gate::define('manage-flux-cms', function ($user) {
return $user->hasRole('cms-manager');
});
Gate::define('edit-page', function ($user, Page $page) {
return $user->can('manage-flux-cms') &&
$page->domain_key === request()->getHost();
});
Input Validation
// Component Content Validation
public function getValidationRules(): array
{
$rules = [];
foreach ($this->getCmsFields() as $field) {
$rules = array_merge($rules, $field->getValidationRules());
}
return $rules;
}
Testing Strategy
Das Projekt verfolgt eine umfassende Teststrategie, die Unit-, Feature- und Browser-Tests kombiniert, um eine hohe Codequalität und Stabilität zu gewährleisten.
Unit-Tests
- Fokus: Isolierte Klassen und Methoden.
- Ziele: Korrektheit von Model-Beziehungen, Scopes, Business-Logik in Services und die Funktionalität der Field Types sicherstellen.
- Beispiele:
PageTest: Überprüft Scopes wiepublished()und Beziehungen wieslugs().BlogPostTest: Testet die polymorpheauthor()-Beziehung und die Tag-Funktionalität.
Feature-Tests
- Fokus: Komplette Anwendungs-Features über HTTP-Anfragen.
- Ziele: Korrektheit von CRUD-Operationen, Routen, Controller-Logik, Validierung und Autorisierung testen.
- Beispiele:
PageControllerTest: Simuliert das Erstellen, Bearbeiten und Löschen von Seiten, inklusive Tests für Validierungsfehler und Zugriffsrechte.BlogControllerTest: Stellt sicher, dass die Blog-Verwaltung wie erwartet funktioniert.
Browser-Tests (Laravel Dusk)
- Fokus: Echte Benutzerinteraktionen in einem Browser.
- Ziele: Klick-Pfade, UI-Komponenten, JavaScript-Interaktionen und komplette Workflows im Admin-Panel testen.
- Beispiele:
LoginTest: Simuliert den Admin-Login.- Zukünftige Tests: Erstellen einer Seite mit Komponenten via Drag & Drop, Verwalten von Medien, etc.
Deployment & Configuration
Package Installation
# Core Package
composer require flux-cms/core
# Components Package
composer require flux-cms/components
# Starter Components
composer require flux-cms/starter-components
# Installation
php artisan flux-cms:install
Konfiguration
// config/flux-cms.php
return [
'domains' => [
'auto_discovery' => true,
'cache_timeout' => 3600,
],
'components' => [
'scan_paths' => [
'app/Livewire/Components',
'vendor/flux-cms/starter-components/src/Components',
],
'cache_enabled' => true,
],
'media' => [
'disk' => 'public',
'conversions' => [
'thumb' => [300, 200],
'hero' => [1200, 600],
],
],
'seo' => [
'auto_sitemap' => true,
'meta_defaults' => [
'title_suffix' => ' | ' . config('app.name'),
],
],
];
Erweiterbarkeit
Custom Field Types
<?php
namespace App\FieldTypes;
use FluxCms\Core\FieldTypes\BaseField;
class ColorPickerField extends BaseField
{
public function getType(): string
{
return 'color_picker';
}
public function getValidationRules(): array
{
return ['regex:/^#[0-9A-F]{6}$/i'];
}
public function sanitizeValue(mixed $value): mixed
{
return strtoupper($value);
}
}
Custom Components
<?php
namespace App\Livewire\CustomComponents;
use Livewire\Component;
use FluxCms\Core\FieldTypes\TextField;
use App\FieldTypes\ColorPickerField;
class CustomHero extends Component
{
public static function getCmsFields(): array
{
return [
TextField::make('title', 'Titel')->translatable(),
ColorPickerField::make('bg_color', 'Hintergrundfarbe')->default('#ffffff'),
];
}
// Implementation...
}
Best Practices
1. Component Design
- Kleine, wiederverwendbare Components
- Klare Field-Definitionen
- Responsive Design
- Accessibility beachten
2. Performance
- Eager Loading von Relationships
- Caching strategisch einsetzen
- Lazy Loading für große Listen
- Image Optimierung
3. SEO
- Strukturierte Daten (JSON-LD)
- Optimierte Meta Tags
- Saubere URL-Struktur
- Sitemap-Generation
4. Security
- Input Validation
- Authorization Gates
- CSRF Protection
- XSS Prevention
5. Wartbarkeit
- Klare Namenskonventionen
- Dokumentierte APIs
- Typisierte Interfaces
- Umfassende Tests
Roadmap
Status Update (Dezember 2024)
Das Flux CMS Package hat einen Vollständigkeitsgrad von 95% erreicht und ist produktionsreif. Die Grundarchitektur ist vollständig implementiert mit umfassender Test-Suite, Admin-Interface und Component-System.
Priorität 1 (Kurzfristig - Q1 2025)
- RESTful API-Endpoints: Implementierung von API-Controllern für Headless CMS-Funktionalität
Api/PageController.php- Seiten-Management via APIApi/BlogController.php- Blog-Management via APIApi/MediaController.php- Medien-Management via APIApi/ComponentController.php- Component-Management via API
- Erweiterte Starter Components: Vervollständigung der Component-Bibliothek
TextSection.php- Einfache Text-BereicheImageGallery.php- BildergalerienContactForm.php- KontaktformulareTestimonialSection.php- TestimonialsPricingTable.php- Preistabellen
- Dashboard Widgets: Erweiterbares Dashboard-System
RecentPagesWidget.php- Zuletzt bearbeitete SeitenAnalyticsWidget.php- BesucherstatistikenMediaUsageWidget.php- MedienverwendungComponentStatsWidget.php- Component-Statistiken
Priorität 2 (Mittelfristig - Q2 2025)
- Content Scheduling: Vorausplanung von Inhalten
ScheduledPublishing.php- Automatisches VeröffentlichenContentCalendar.php- Content-KalenderAuto-Unpublish.php- Automatisches Archivieren
- Advanced Analytics: Erweiterte Analyse-Features
- Integration mit Google Analytics
- Content-Performance-Tracking
- User-Engagement-Metriken
- Performance Monitoring: System-Überwachung
- Query-Performance-Monitoring
- Cache-Hit-Rate-Tracking
- Component-Load-Time-Analyse
Priorität 3 (Langfristig - Q3-Q4 2025)
- A/B Testing Framework: Content-Optimierung
VariantManagement.php- Varianten-VerwaltungAnalyticsIntegration.php- Conversion-TrackingConversionTracking.php- Ziel-Tracking
- AI-powered Content Suggestions: Intelligente Inhaltsvorschläge
- Automatische SEO-Optimierung
- Content-Gap-Analyse
- Intelligente Tag-Vorschläge
- GraphQL API: Moderne API-Technologie
- Vollständige GraphQL-Implementierung
- Real-time Subscriptions
- Schema-First Development
Bereits implementiert ✅
- Umfassende Test-Suite: Feature- und Unit-Tests für alle Komponenten und Services
- Browser-Tests: Laravel Dusk-Tests für kritische Admin-Workflows
- Tagging-UI für Blog Posts: Bearbeiten von Tags pro Beitrag implementiert
- Slug-System: Polymorphe Slugs für mehrsprachige URLs
- MakeComponentCommand: Artisan Command für Component-Erstellung
- Admin-Controller: Vollständige CRUD-Operationen für alle Entitäten
- Livewire Components: Backend und Frontend Components
- Multi-Domain Support: Vollständige Domain-Verwaltung
- Versionierung: Page-Version-Management
- Media Management: Spatie Media Library Integration
Technische Verbesserungen
- Statische Code-Analyse: Integration von PHPStan Level 8
- CI/CD Pipeline: Automatisierte Tests und Deployment
- Documentation: API-Dokumentation mit OpenAPI/Swagger
- Performance Optimization: Advanced Caching-Strategien
- Security Hardening: Penetration Testing und Security Audit
Community & Ecosystem
- Plugin-System: Erweiterbares Plugin-Framework
- Theme-System: Vollständiges Theme-Management
- Marketplace: Component- und Theme-Marketplace
- Developer Tools: CLI-Tools für Entwickler
- Migration Tools: Import/Export-Funktionalität