mivita/dev/subdomain-optimization-grok
2025-10-20 17:42:08 +02:00
..
src update 20.10.2025 2025-10-20 17:42:08 +02:00
tests update 20.10.2025 2025-10-20 17:42:08 +02:00
MIGRATION_GUIDE.md update 20.10.2025 2025-10-20 17:42:08 +02:00
README.md update 20.10.2025 2025-10-20 17:42:08 +02:00

Domain Management System - Optimierte Architektur

Übersicht

Dieses optimierte Domain Management System löst die Session-Probleme des aktuellen Systems und bietet eine saubere, wartbare Architektur für Multi-Domain-Anwendungen.

Hauptprobleme der aktuellen Implementierung

  1. Session-Konflikte: DomainResolver wird zu früh ausgeführt, bevor die Session-Middleware verfügbar ist
  2. Zwei Sessions: Dadurch werden zwei separate Sessions erstellt
  3. Komplexe Logik: Domain-Auflösung und Session-Management sind eng gekoppelt
  4. Performance: Ineffizientes Caching und wiederholte DB-Abfragen

Neue Architektur

Kernkomponenten

├── DomainResolver (Middleware) - Reine Domain-Auflösung
├── DomainContext (DTO) - Unveränderlicher Domain-Kontext
├── DomainService - Zentraler Service für Domain-Logik
├── SessionHandler - Event-basiertes Session-Management
├── RouteService - Domain-aware Route-Loading
└── CacheManager - Optimiertes Caching

Middleware-Reihenfolge (Behoben)

'web' => [
    \App\Http\Middleware\EncryptCookies::class,
    \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
    \App\Http\Middleware\DomainResolver::class,        // ✅ Nach Cookies, vor Session
    \Illuminate\Session\Middleware\StartSession::class,
    \App\Http\Middleware\DomainSessionHandler::class,  // ✅ Nach Session-Start
    // ... weitere Middleware
]

Hauptverbesserungen

1. Session-Problem gelöst

  • DomainResolver: Läuft nach Cookie-Encryption, aber vor Session-Start
  • DomainSessionHandler: Verarbeitet Session-Updates nach Session-Initialisierung
  • Event-basierte Kommunikation: Domain-Änderungen werden als Events behandelt

2. Saubere Trennung der Verantwortlichkeiten

  • DomainResolver: Nur Domain-Auflösung und Kontext-Erstellung
  • DomainSessionHandler: Nur Session-Management
  • DomainService: Reine Geschäftslogik

3. Performance-Optimierungen

  • Intelligentes Caching: Mehrere Cache-Schichten
  • Lazy Loading: UserShop-Daten werden nur bei Bedarf geladen
  • Batch-Operations: Mehrere Domain-Validierungen in einem Durchgang

4. Domain-Types

enum DomainType: string {
    case MAIN = 'main';           // mivita.care
    case SHOP = 'shop';           // mivita.shop
    case CRM = 'crm';             // my.mivita.care
    case PORTAL = 'portal';       // in.mivita.care
    case CHECKOUT = 'checkout';   // checkout.mivita.care
    case USER_SHOP = 'user-shop'; // {slug}.mivita.care
    case UNKNOWN = 'unknown';
}

Implementierung

DomainResolver (Neue Middleware)

class DomainResolver
{
    public function handle(Request $request, Closure $next)
    {
        // 1. Domain parsen und Context erstellen
        $context = $this->resolveDomain($request->getHost());

        // 2. Context in Request speichern (nicht Session!)
        $request->merge(['domain_context' => $context]);

        // 3. Session-Domain setzen für Cookies
        $this->setSessionDomain($context);

        // 4. Domain-Changed Event auslösen (falls nötig)
        if ($this->domainChanged($context)) {
            event(new DomainChangedEvent($context));
        }

        return $next($request);
    }
}

DomainSessionHandler (Neue Middleware)

class DomainSessionHandler
{
    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);

        // Session nur updaten, wenn Domain-Context verfügbar
        if ($context = $request->get('domain_context')) {
            $this->updateSessionForDomain($context);
        }

        return $response;
    }

    private function updateSessionForDomain(DomainContext $context): void
    {
        // UserShop in Session setzen/behalten
        if ($context->isUserShop()) {
            Session::put('user_shop', $context->userShop);
            Session::put('user_shop_domain', $context->host);
        }

        // Session-Domain aktualisieren
        Config::set('session.domain', $this->getSessionDomain($context));
    }
}

DomainService (Optimierte Version)

class DomainService
{
    public function resolveDomain(string $host): DomainContext
    {
        // 1. Host normalisieren
        $normalizedHost = $this->normalizeHost($host);

        // 2. Domain-Info parsen
        $domainInfo = $this->parseDomain($normalizedHost);

        // 3. Domain-Type bestimmen
        $type = $this->determineDomainType($domainInfo);

        // 4. UserShop laden (nur bei Bedarf)
        $userShop = $this->loadUserShopIfNeeded($type, $domainInfo);

        return new DomainContext($type, $normalizedHost, $domainInfo['subdomain'], $userShop);
    }

    private function loadUserShopIfNeeded(DomainType $type, array $domainInfo): ?UserShop
    {
        if (!$type->isUserShop()) {
            return null;
        }

        return $this->getUserShop($domainInfo['subdomain']);
    }
}

Migration Guide

Schritt 1: Neue Dateien hinzufügen

# Neue Middleware
cp dev/subdomain-optimization-grok/src/Middleware/DomainResolver.php app/Http/Middleware/
cp dev/subdomain-optimization-grok/src/Middleware/DomainSessionHandler.php app/Http/Middleware/

# Neue Services
cp dev/subdomain-optimization-grok/src/Services/DomainService.php app/Services/
cp dev/subdomain-optimization-grok/src/Services/DomainCacheManager.php app/Services/

# Neue Domain-Klassen
cp dev/subdomain-optimization-grok/src/Domain/DomainContext.php app/Domain/
cp dev/subdomain-optimization-grok/src/Domain/DomainType.php app/Domain/

Schritt 2: Kernel.php aktualisieren

'web' => [
    // ... existing middleware ...
    \App\Http\Middleware\DomainResolver::class,        // Nach Cookies
    \Illuminate\Session\Middleware\StartSession::class,
    \App\Http\Middleware\DomainSessionHandler::class,  // Nach Session
    // ... rest of middleware ...
],

Schritt 3: DomainServiceProvider aktualisieren

// Alte DomainResolver-Middleware entfernen
// Neue Services registrieren

Vorteile der neuen Architektur

  1. Session-Konflikte behoben: Klare Trennung zwischen Domain-Auflösung und Session-Management
  2. Bessere Performance: Optimiertes Caching und Lazy Loading
  3. Wartbarkeit: Klare Trennung der Verantwortlichkeiten
  4. Testbarkeit: Jede Komponente kann isoliert getestet werden
  5. Skalierbarkeit: Einfache Erweiterung um neue Domain-Types
  6. Event-Driven: Lose Kopplung durch Events

Tests

# Unit Tests
php artisan test tests/Unit/Domain/

# Feature Tests
php artisan test tests/Feature/DomainRouting/

# Integration Tests
php artisan test tests/Feature/SessionDomainSwitching/

Monitoring

Das neue System integriert sich nahtlos mit Laravel's Logging und Monitoring:

// Domain-Resolution Metrics
Log::channel('domain')->info('Domain resolved', [
    'host' => $host,
    'type' => $context->type,
    'resolution_time' => $time,
    'cache_hit' => $cacheHit
]);

Fazit

Diese optimierte Architektur löst alle identifizierten Probleme und bietet eine solide Grundlage für zukünftige Erweiterungen des Domain-Systems.