Templating
Inhalt dieser Seite:
Guppy verfolgt einen komponentenbasierten Ansatz, um eine saubere Trennung von Logik und Darstellung zu gewährleisten. Unser Ziel ist es, ein System zu schaffen, das sowohl wartungsfreundlich als auch zukunftssicher ist. Um dies zu erreichen, setzen wir auf dynamische und modulare Mechanismen, wie sie auch in der Gestaltung von Templates zum Einsatz kommen. Dies ermöglicht uns, individuelle Anpassungen vorzunehmen, ohne die Kernfunktionen von Shopware 6 zu beeinträchtigen. Durch diese Methodik bleibt Guppy vollständig updatefähig und reduziert langfristig Wartungsaufwand.
Warum dieser Ansatz?
Shopware 6 ist ein mächtiges Framework, dessen Updatefähigkeit und Flexibilität durch unser Vorgehen bestmöglich erhalten bleiben. Die dynamische Handhabung von Konfigurationen ermöglicht:
- Maximale Anpassbarkeit: Unterschiedliche Anforderungen können durch gezielte Konfigurationen erfüllt werden, ohne den Kerncode zu modifizieren.
- Modularität: Komponenten wie Footer, Header oder Widgets werden als eigenständige Module behandelt, was ihre Wiederverwendbarkeit erhöht.
- Upgrade-Kompatibilität: Da wir uns an die Richtlinien von Shopware 6 halten und spezifische Anpassungen in separaten Dateien vornehmen, bleiben künftige Updates des Systems reibungslos anwendbar.
- Barrierefreiheit: Durch modulare Templates lassen sich barrierefreie Anpassungen gezielt und flexibel integrieren, ohne globalen Code anzupassen.
Theme-Integration
Guppy nutzt die Theme-Konfiguration (theme.json
) als zentrale Steuerungsinstanz für dynamische Anpassungen von Komponenten. Die Konfiguration ermöglicht es, spezifische Designentscheidungen direkt über die Theme-Einstellungen vorzunehmen, ohne tief in den Code eingreifen zu müssen.
Vorteile
Die Verwendung von theme.json
erlaubt es, wichtige Einstellungen wie den Footer-Typ flexibel zu definieren. Dies bringt folgende Vorteile:
- Klarheit und Struktur: Alle Anpassungen werden an einer zentralen Stelle verwaltet.
- Wartungsfreundlichkeit: Änderungen können einfach durch Anpassungen der
theme.json
vorgenommen werden, ohne den Template-Code zu berühren. - Erweiterbarkeit: Neue Konfigurationsmöglichkeiten können einfach hinzugefügt werden, was das System zukunftssicher macht.
- Upgrade-Kompatibilität: Anpassungen erfolgen auf Basis von Shopware-Konventionen, was Konflikte bei zukünftigen Updates minimiert.
Funktionsweise (am Beispiel des Footers)
Der Code für den Footer berücksichtigt die Einstellungen in der theme.json
, indem er die Funktion theme_config()
verwendet. Diese liest die in der theme.json
definierten Werte aus.
Beispielcode:
{% if theme_config('guppy-footer') != "default" %}
{% set configFooter = theme_config('guppy-footer') %}
{% endif %}
INFO
Erklärung Die Funktion theme_config('guppy-footer')
überprüft, ob in der theme.json
eine spezifische Footer-Konfiguration (guppy-footer
) definiert wurde.
Ergänzung im Footer-Template:
{# src/Resources/views/storefront/base.html.twig #}
{% block base_footer %}
<footer class="footer-main{% if configFooter %} footer-main-{{ configFooter }} pt-md-3 pt-4{% endif %}">
{% block base_footer_inner %}
{% if configFooter %}
{% sw_include '@Storefront/storefront/layout/footer/footer-' ~ configFooter ~ '.html.twig' %}
{% else %}
{{ parent() }}
{% endif %}
{% endblock %}
</footer>
{% endblock %}
Beispielhafte Konfiguration in theme.json
:
// src/Resources/theme.json
{
...
"config": {
...
"fields": {
...
"guppy-footer": {
"label": {
"en-GB": "Footer variant",
"de-DE": "Footer Variante"
},
"type": "text",
"value": "guppy-default",
"custom": {
"componentName": "sw-single-select",
"options": [
{
"value": "default",
"label": {
"en-GB": "Shopware Default",
"de-DE": "Shopware Standard"
}
},
{
"value": "guppy-default",
"label": {
"en-GB": "Guppy Default",
"de-DE": "Guppy Standard"
}
}
]
},
"editable": true,
"tab": "footer",
"block": "layoutFooter",
"order": 100
}
}
}
}
Erweiterung der Template-Logik
Die in der theme.json
ausgewählte Footer-Konfiguration guppy-default
erfordert ein spezifisches Template mit dem Namen footer-guppy-default.html.twig
. Dieses Template wird automatisch geladen, wenn der Wert guppy-default
in der Theme-Konfiguration gesetzt wird. Das neue Template wird von der Standardvorlage footer.html.twig
abgeleitet, um Änderungen spezifisch und modular zu halten.
Beispielcode für das Template:
{# src/Resources/views/storefront/layout/footer/footer-guppy-default.html.twig #}
{% sw_extends '@Storefront/storefront/layout/footer/footer.html.twig' %}
// Hier Inhalt
INFO
Durch die Integration von Theme-Variablen wie theme_config('guppy-footer')
bleibt Guppy hochgradig anpassbar und gleichzeitig kompatibel mit zukünftigen Shopware-Updates. Die Theme-Konfiguration erlaubt es Entwicklern und Admins, Änderungen schnell und effizient vorzunehmen, ohne tief in die Codebasis eingreifen zu müssen.
Template-Varianten-System
Das Guppy Theme implementiert ein umfassendes Varianten-System für verschiedene Komponenten:
Header-Varianten
Der Header kann in verschiedenen Varianten dargestellt werden:
{% if theme_config('guppy-header') != "default" %}
{% set configHeader = theme_config('guppy-header') %}
{% endif %}
{% block base_header %}
<header class="header-main{% if configHeader %} header-variant-{{ configHeader }}{% endif %}">
{% block base_header_inner %}
{% if configHeader %}
{% sw_include '@Storefront/storefront/layout/header/header-' ~ configHeader ~ '.html.twig' %}
{% else %}
{{ parent() }}
{% endif %}
{% endblock %}
</header>
{% endblock %}
Verfügbare Header-Varianten:
default
: Shopware Standard-Headercompact
: Guppy Standard - Kompakte Header-Varianteextended
: Erweiterte Header-Variante mit Top-Barsimple
: Minimalistische Header-Variante
Theme-Konfiguration:
"guppy-header": {
"type": "text",
"value": "extended",
"custom": {
"componentName": "sw-single-select",
"options": [
{"value": "default", "label": {"de-DE": "Shopware Standard"}},
{"value": "compact", "label": {"de-DE": "Guppy Standard"}},
{"value": "extended", "label": {"de-DE": "Erweitert"}},
{"value": "simple", "label": {"de-DE": "Simpel"}}
]
}
}
Navigation-Varianten
Die Navigation unterstützt verschiedene Flyout-Varianten:
{% if theme_config('guppy-navigation') != "content" %}
{% set navigationStyle = theme_config('guppy-navigation') %}
{% endif %}
{% block base_navigation %}
<nav class="nav-main{% if navigationStyle %} nav-{{ navigationStyle }}{% endif %}">
{% sw_include '@Storefront/storefront/layout/navbar/' ~ (navigationStyle ?: 'content') ~ '.html.twig' %}
</nav>
{% endblock %}
Verfügbare Navigation-Varianten:
content
: Shopware Standard-Navigationcontent-compact
: Kompakte Navigation mit optimierter Darstellung
Produktkarten-System
Das Produktkarten-System bietet verschiedene Darstellungsvarianten:
{% if theme_config('guppy-productcard-config') %}
{% set boxDesign = theme_config('guppy-productcard-config') %}
{% endif %}
<article class="card product-box box-{{ layout }}{% if boxDesign %} box-{{ boxDesign }}{% endif %}">
<!-- Produktkarten-Inhalt -->
</article>
Verfügbare Produktkarten-Varianten:
default
: Shopware Standard-Produktkarteguppy-default
: Guppy Standard - Barrierefreie Produktkarte
Erweiterte Produktkarten-Konfiguration:
"guppy-productcard-protective-frame": true,
"guppy-productcard-image-object-fit": "contain"
Login & Register-Varianten
Login- und Registrierungsseiten können kompakt dargestellt werden:
{% if theme_config('guppy-login-register') == "compact" %}
{% set loginStyle = "compact" %}
{% endif %}
{% block page_account_login %}
<div class="account-login{% if loginStyle %} account-login-{{ loginStyle }}{% endif %}">
<!-- Login-Inhalt -->
</div>
{% endblock %}
Checkout-Varianten
Der Checkout-Prozess unterstützt verschiedene Darstellungsformen:
{% if theme_config('guppy-checkout') == "compact" %}
{% set checkoutStyle = "compact" %}
{% endif %}
{% block page_checkout %}
<div class="checkout-main{% if checkoutStyle %} checkout-{{ checkoutStyle }}{% endif %}">
<!-- Checkout-Inhalt -->
</div>
{% endblock %}
Template-Struktur
Die vollständige Template-Hierarchie des Guppy Themes:
src/Resources/views/storefront/
├── base.html.twig # Basis-Template mit Skip-Links
├── layout/
│ ├── header.html.twig # Header-Haupttemplate
│ ├── header/
│ │ ├── header-compact.html.twig # Kompakte Header-Variante
│ │ ├── header-extended.html.twig # Erweiterte Header-Variante
│ │ ├── header-simple.html.twig # Einfache Header-Variante
│ │ ├── logo.html.twig # Logo-Komponente
│ │ ├── search.html.twig # Suchkomponente
│ │ └── top-bar-extended.html.twig # Erweiterte Top-Bar
│ ├── footer.html.twig # Footer-Haupttemplate
│ ├── footer/
│ │ └── footer-guppy-default.html.twig # Guppy-Footer-Variante
│ ├── navbar/
│ │ ├── navbar.html.twig # Navbar-Haupttemplate
│ │ ├── content.html.twig # Standard-Navigation
│ │ └── content-compact.html.twig # Kompakte Navigation
│ ├── breadcrumb.html.twig # Breadcrumb-Navigation
│ └── sidebar/
│ └── category-navigation-onelevel.html.twig
├── component/
│ ├── product/
│ │ ├── card/
│ │ │ ├── box-standard.html.twig # Standard-Produktkarte
│ │ │ ├── box-landscape.html.twig # Landscape-Produktkarte
│ │ │ ├── badges.html.twig # Produkt-Badges
│ │ │ ├── box-image.html.twig # Produktbild-Komponente
│ │ │ ├── action.html.twig # Produkt-Aktionen
│ │ │ └── price-unit.html.twig # Preis-Komponente
│ │ ├── listing.html.twig # Produktlisting
│ │ ├── description.html.twig # Produktbeschreibung
│ │ ├── properties.html.twig # Produkteigenschaften
│ │ └── properties-offcanvas.html.twig # Eigenschaften-Offcanvas
│ ├── buy-widget/
│ │ ├── buy-widget.html.twig # Buy-Widget-Hauptkomponente
│ │ ├── buy-widget-form.html.twig # Buy-Widget-Formular
│ │ └── buy-widget-price.html.twig # Buy-Widget-Preis
│ ├── account/
│ │ ├── login.html.twig # Login-Komponente
│ │ └── register.html.twig # Registrierung-Komponente
│ ├── checkout/
│ │ ├── offcanvas-cart.html.twig # Offcanvas-Warenkorb
│ │ └── offcanvas-cart-summary.html.twig # Warenkorb-Zusammenfassung
│ ├── line-item/
│ │ ├── element/
│ │ │ ├── quantity.html.twig # Mengenauswahl
│ │ │ ├── remove.html.twig # Entfernen-Button
│ │ │ └── total-price.html.twig # Gesamtpreis
│ │ └── type/
│ │ └── product.html.twig # Produkt-Line-Item
│ ├── address/
│ │ └── address-form.html.twig # Adress-Formular
│ ├── listing/
│ │ └── filter-panel.html.twig # Filter-Panel
│ └── delivery-information.html.twig # Lieferinformationen
├── element/
│ ├── cms-element-buy-box.html.twig # Buy-Box-Element
│ ├── cms-element-image-gallery.html.twig # Bildergalerie-Element
│ ├── cms-element-product-listing.html.twig # Produktlisting-Element
│ ├── cms-element-sidebar-filter.html.twig # Sidebar-Filter-Element
│ ├── cms-element-splide-slider.html.twig # Splide-Slider-Element
│ ├── cms-element-category-navigation-onelevel.html.twig # Kategorienavigation
│ └── cms-element-product-description-reviews.html.twig # Produktbeschreibung
├── page/
│ ├── account/
│ │ ├── _page.html.twig # Account-Basis-Template
│ │ ├── sidebar.html.twig # Account-Sidebar
│ │ ├── profile/
│ │ │ └── index.html.twig # Profil-Seite
│ │ ├── register/
│ │ │ └── index.html.twig # Registrierung-Seite
│ │ └── order-history/
│ │ └── index.html.twig # Bestellhistorie
│ ├── checkout/
│ │ ├── _page.html.twig # Checkout-Basis-Template
│ │ ├── cart/
│ │ │ └── index.html.twig # Warenkorb-Seite
│ │ ├── confirm/
│ │ │ └── index.html.twig # Bestätigungsseite
│ │ ├── finish/
│ │ │ ├── index.html.twig # Abschlussseite
│ │ │ └── finish-details.html.twig # Abschluss-Details
│ │ ├── address/
│ │ │ ├── index.html.twig # Adress-Seite
│ │ │ └── register.html.twig # Adress-Registrierung
│ │ ├── summary.html.twig # Checkout-Zusammenfassung
│ │ ├── progress.html.twig # Checkout-Fortschritt
│ │ └── aside-actions-footer.html.twig # Checkout-Sidebar-Footer
│ ├── content/
│ │ ├── index.html.twig # Content-Seite
│ │ ├── detail.html.twig # Content-Detail
│ │ └── product-detail.html.twig # Produktdetail-Seite
│ └── product-detail/
│ ├── index.html.twig # Produktdetail-Hauptseite
│ ├── buy-widget.html.twig # Buy-Widget
│ ├── buy-widget-form.html.twig # Buy-Widget-Formular
│ └── headline-buybox.html.twig # Headline-Buybox
├── section/
│ └── cms-section-sidebar.html.twig # CMS-Sidebar-Sektion
├── block/
│ ├── cms-block-category-navigation-onelevel.html.twig # Kategorienavigation-Block
│ └── cms-block-gallery-buybox.html.twig # Galerie-Buybox-Block
└── utilities/
├── alert.html.twig # Alert-Komponente
├── icon.html.twig # Icon-Komponente
├── offcanvas.html.twig # Offcanvas-Komponente
└── thumbnail.html.twig # Thumbnail-Komponente
Custom Twig-Extensions
Das Guppy Theme erweitert Twig um zusätzliche Funktionen:
CategoryOneLevelExtension
Die categoryOneLevel()
Funktion ermöglicht die Darstellung einstufiger Kategorie-Navigationen:
{% set navigationData = categoryOneLevel(navigationTree, currentCategoryId) %}
{% for category in navigationData %}
<a href="{{ category.url }}" class="nav-link">
{{ category.name }}
</a>
{% endfor %}
Implementierung:
// src/Twig/CategoryOneLevelExtension.php
class CategoryOneLevelExtension extends AbstractExtension
{
public function getFunctions(): array
{
return [
new TwigFunction('categoryOneLevel', [$this, 'categoryOneLevel'])
];
}
public function categoryOneLevel($navigationTree, $currentCategoryId)
{
// Implementierung der einstufigen Kategorienavigation
}
}
Barrierefreiheits-Features
Skip-Links
Das Theme bietet konfigurierbare Skip-Links für bessere Accessibility:
{# base.html.twig #}
{% block base_body_inner %}
{% if theme_config('guppy-header-skip-to-main-content') %}
<a href="#content-main" class="skip-link">
{{ 'skipLink.toMainContent'|trans|sw_sanitize }}
</a>
{% endif %}
{% if theme_config('guppy-header-skip-to-main-nav') %}
<a href="#main-navigation" class="skip-link">
{{ 'skipLink.toMainNavigation'|trans|sw_sanitize }}
</a>
{% endif %}
{% if theme_config('guppy-header-skip-to-search') %}
<a href="#search" class="skip-link">
{{ 'skipLink.toSearch'|trans|sw_sanitize }}
</a>
{% endif %}
{{ parent() }}
{% endblock %}
Verfügbare Skip-Links:
guppy-header-skip-to-main-content
: Sprung zum Hauptinhaltguppy-header-skip-to-main-nav
: Sprung zur Hauptnavigationguppy-header-skip-to-search
: Sprung zur Suche
USP-Banner-Integration
Das USP-Banner-System wird über Templates integriert:
{# layout/_includes/usp-banner.html.twig #}
{% if theme_config('guppy-usp-active') %}
<div class="usp-banner" data-usp-banner-plugin="true">
{% if theme_config('guppy-usp-layout') == 'benefits' %}
{% for i in 1..4 %}
{% set benefit = theme_config('guppy-usp-layout-benefit' ~ i) %}
{% if benefit %}
<div class="usp-item">
{{ benefit }}
</div>
{% endif %}
{% endfor %}
{% else %}
<div class="usp-item">
<a href="{{ theme_config('guppy-usp-layout-link') }}"
{% if theme_config('guppy-usp-layout-newTab') %}target="_blank"{% endif %}>
{{ theme_config('guppy-usp-layout-text') }}
</a>
</div>
{% endif %}
</div>
{% endif %}
Praktische Implementierung
Neuen Header-Typ erstellen
- Template erstellen:
{# src/Resources/views/storefront/layout/header/header-custom.html.twig #}
{% sw_extends '@Storefront/storefront/layout/header/header.html.twig' %}
{% block layout_header_inner %}
<div class="header-custom">
{# Custom Header-Inhalt #}
</div>
{% endblock %}
- Theme-Konfiguration erweitern:
"guppy-header": {
"custom": {
"options": [
{"value": "custom", "label": {"de-DE": "Custom Header"}}
]
}
}
- SCSS-Styling hinzufügen:
.header-variant-custom {
.header-custom {
// Custom Header-Styles
}
}
Neue Produktkarten-Variante
- Template erstellen:
{# src/Resources/views/storefront/component/product/card/box-custom.html.twig #}
{% sw_extends '@Storefront/storefront/component/product/card/box-standard.html.twig' %}
{% block component_product_box %}
<div class="product-box box-custom">
{# Custom Produktkarte-Inhalt #}
</div>
{% endblock %}
- Theme-Konfiguration erweitern:
"guppy-productcard-config": {
"custom": {
"options": [
{"value": "custom", "label": {"de-DE": "Custom Produktkarte"}}
]
}
}
Alert-Varianten konfigurieren
{# utilities/alert.html.twig #}
{% set alertClass = 'alert-' ~ type %}
{% if theme_config('guppy-alert-alert-outline-active') %}
{% set alertClass = alertClass ~ ' alert-outline' %}
{% endif %}
<div class="alert {{ alertClass }}" role="alert">
{{ message }}
</div>
Theme-Konfiguration:
"guppy-alert-color-success": "#D3F2E7",
"guppy-alert-color-success-text": "dark",
"guppy-alert-alert-outline-active": true
Best Practices
Template-Vererbung
{# Immer von der entsprechenden Shopware-Vorlage erben #}
{% sw_extends '@Storefront/storefront/layout/header/header.html.twig' %}
{# Spezifische Blöcke überschreiben #}
{% block layout_header_logo %}
<div class="header-logo-custom">
{{ parent() }}
</div>
{% endblock %}
Theme-Konfiguration verwenden
{# Immer Theme-Konfiguration für Varianten verwenden #}
{% if theme_config('guppy-component-variant') %}
{% set variant = theme_config('guppy-component-variant') %}
{% endif %}
{# Fallback für Standard-Verhalten #}
{% if variant %}
{# Custom Logik #}
{% else %}
{{ parent() }}
{% endif %}
Barrierefreiheit berücksichtigen
{# Immer semantische HTML-Elemente verwenden #}
<nav role="navigation" aria-label="{{ 'navigation.main'|trans }}">
{# Navigation-Inhalt #}
</nav>
{# Skip-Links für wichtige Bereiche #}
<a href="#main-content" class="skip-link">
{{ 'skipLink.toMainContent'|trans }}
</a>