CDN Product Images: Technik
Architektur, Entscheidungslogik und Caching des Sylius-Plugins CDN Product Images.
CDN Product Images: Technik
Diese Dokumentation bezieht sich immer auf die aktuellste veroeffentlichte Version.
Live Demo: Teste dieses und weitere Plugins live — ohne Installation, ohne Risiko: demo.markus-michalski.net
Entscheidungslogik
graph TD
A["Bild-Pfad"] --> B{"Beginnt mit http(s)?"}
B -->|Nein| C["lokaler Upload, unveraendert"]
B -->|Ja| D{"Host passt zu CDN-Domain?"}
D -->|Nein| E["fremde URL, Passthrough"]
D -->|Ja| F["s3-Bucket/Key extrahieren"]
F --> G{"Signierte URL im Cache?"}
G -->|Ja| H["gecachte URL zurueckgeben"]
G -->|Nein| I["Signing-Service aufrufen"]
I --> J{"HTTP 200?"}
J -->|Ja| K["24h cachen, signierte URL"]
J -->|Nein| L["30s cachen, Original-URL"]
Die Erkennung "CDN-Bild oder lokaler Upload" läuft rein über das Pfad-Präfix (http(s)://) - Sylius' eigener UploadedImagePathGenerator erzeugt ausschließlich relative, Hash-basierte Pfade, die niemals so beginnen können. Es gibt dafür keine eigene Datenbank-Spalte und keine Migration.
Plugin-Struktur
src/
├── Cdn/ # Signing-Kern: Konfiguration, URL-Signer, Preset-Map
├── Command/ # mmd:cdn-product-images:setup
├── Controller/Admin/ # Einstellungsseite + Token-Entfernung
├── DependencyInjection/ # Bundle-Extension, Compiler Pass, (leere) Configuration
├── Entity/ # SigningCredentials (Singleton-Settings-Zeile)
├── Form/Extension/ # cdnUrl-Feld auf Product-/TaxonImageType
├── Form/Type/ # SigningCredentialsType (Admin-Formular)
├── Imagine/ # dekorierte imagine_filter Twig-Extension
├── Menu/ # Admin-Sidebar-Eintrag
├── Migrations/ # Doctrine-Migration für die Settings-Tabelle
├── Repository/ # SigningCredentialsRepository
├── Security/ # SigningTokenCipher (libsodium)
├── Serializer/ # dekorierter Shop-API-Bild-Normalizer
└── Uploader/ # CDN-fähiger Image-Uploader + Pfad-Erkennung
Dekorierte Services
| Dekorierter Service | Decorator-Klasse | Zweck |
|---|---|---|
liip_imagine.templating.filter_extension |
CdnAwareImagineFilterExtension |
imagine_filter auf Twig-Storefront/Admin CDN-fähig machen |
sylius.uploader.image |
CdnAwareImageUploader |
verhindert, dass ein CDN-Pfad als lokale Datei gelöscht wird |
sylius_api.normalizer.image |
CdnAwareApiImageNormalizer |
dieselbe Logik für den Shop-API-Kanal - nur registriert, wenn SyliusApiBundle vorhanden ist (eigener Compiler Pass, da Reihenfolge-unabhängig) |
Entity & Migration
| Entity | Tabelle | Zweck |
|---|---|---|
SigningCredentials |
mmd_cdn_signing_credentials |
Singleton-Zeile (id immer 1) mit CDN-Domain, Signing-API-URL, verschlüsseltem Token-Ciphertext, Schema-Override |
Kein Sylius-Resource (kein Grid, keine Liste, kein Create/Delete) - der Admin bearbeitet ausschließlich diese eine Zeile über die Einstellungsseite.
Caching
| Was | TTL | Grund |
|---|---|---|
| Erfolgreich signierte URL | 24 Stunden | Signaturen sind deterministisch - vermeidet einen Netzwerk-Roundtrip pro Bild-Render |
| Fehlgeschlagener Signing-Versuch | 30 Sekunden | begrenzt einen Retry-Sturm gegen das Rate-Limit der Signing-API während eines Ausfalls |
| Aufgelöste Zugangsdaten (Entity → aufbereitete Konfiguration) | 60 Sekunden | vermeidet eine DB-Abfrage pro Bild-Render; eine Admin-Änderung wirkt innerhalb von rund einer Minute |
Resize-Mapping
Jede Sylius-Imagine-Filtergröße wird 1:1 auf eine imgproxy-Resize-Option gemappt (inkl. format: webp und quality: 80, damit ein CDN-Bild dieselbe Bild-Qualität liefert wie ein lokal verarbeitetes). Ein unbekannter Filtername fällt immer auf Passthrough zurück - ein falsch geratenes Resizing wäre schlechter als keines.