Tipps und Tricks

Bei diesen Tipps & Tricks wird davon ausgegangen, dass ein eigenes Child-Template angelegt wurde. Dies stellt unter anderem sicher, dass das entsprechende (Parent-)Template weiterhin updatefähig bleibt.

Note

Die JTL-Templates des Shops basieren auf leicht unterschiedlichen Technologien zur Seitendarstellung: Das NOVA-Template nutzt hierfür Sass (SCSS).

Sass/SCSS sind Erweiterungen der herkömmlichen CSS-Syntax und schaffen hauptsächlich die Möglichkeit, CSS ähnlich komfortabel zu schreiben wie Programm-Code. Diese Technologien setzen einen Pre-Prozessor voraus, um die jeweilige Style-Sprache in CSS zu übersetzen. Je nach Template und Shop-Version gibt es hierfür unterschiedliche Werkzeuge (siehe Abschnitt "Theme editieren").

SCSS

Mithilfe von SCSS können Sie verschiedene Werte für Farben, Schriften, Abstände und Rahmen als Variablen definieren, die dann in allen oder auch nur einigen Templates benutzt werden können. Um nun schnell und einfach das Aussehen von JTL-Shop zu verändern, bietet es sich an, diese SCSS-Variablen des Templates in einem Child-Template zu überschreiben.

Einen guten Anfang für ein neues NOVA-Child-Theme bietet das von JTL zur Verfügung gestellte NOVAChild-Template, welches alle nötigen Dateien mitbringt und bereits ein eigenes Theme anlegt ("my-nova"). Dieses Theme ändert jedoch noch nicht das Aussehen des Shops.

Javascript in Templatedateien

Jede Templatedatei (*.tpl) wird von der Template-Engine Smarty gelesen und interpretiert. Hierbei nutzt Smarty für die Auszeichnungen von Variablen- und Code-Ersetzungen geschweifte Klammern ({, }). Geschweifte Klammern sind aber ebenso in Javascript ein Sprachelement um beispielsweise Code-Blöcke zu umschließen.

Damit sich diese beiden unterschiedlichen Auszeichnungsarten nicht überschneiden, ist es möglich, Javascript-Code von der Bearbeitung durch Smarty auszuschließen. Hierfür existieren zwei unterschiedliche Ansätze.

Für kleinere Javascript-Codefragmente ist es möglich, alle öffnenden und schließenden geschweiften Klammern durch zwei Smarty-Funktionen zu ersetzen - {ldelim} für { und {rdelim} für } - und sie anschließend von Smarty wieder als echte Klammern ausgeben zu lassen.

Beispiel:

Dies ist eine smarty.tpl Datei,<br>
die ein Javascript enthält.<br>

<script>
    function helloWorld() {ldelim}
        alert('Hello World');
    {rdelim}

</script>

(Siehe auch: Smarty Docs ldelim,rdelim)

Für umfangreicheren Code empfehlen wir allerdings die übersichtlichere Variante mit den zwei Smarty-Tags {literal} und {/literal}. Mit diesen beiden Tags läßt sich ein größerer Javascript-Block ganz einfach umschließen und von der Verarbeitung durch Smarty ausschließen.

Beispiel:

Dies ist eine smarty.tpl Datei,<br>
die ein Javascript enthält.<br>

{literal}
<script>
    function helloWorld() {
        alert('Hello World');
    }

</script>
{/literal}

(Siehe auch: Smarty Docs literal)

Möchten Sie in Ihrem Javascript weiterhin Variablen durch Smarty ersetzen lassen, kann der literal-Block auch vor der Smarty-Variable beendet und nach ihr wieder begonnen werden.

Beispiel:

Dies ist eine smarty.tpl Datei,<br>
die ein Javascript enthält.<br>

{literal}
<script>
    function helloWorld() {
        alert({/literal}'{$HelloWorldText}'{literal});
    }

</script>
{/literal}

In diesem Fall hätten Sie zwei getrennte literal-Blöcke, die Smarty nicht interpretiert. Die Variable in der Mitte wird dann wie gewohnt von Smarty ersetzt.

Um Javascript automatisiert nachladen zu lassen und so den Pagespeed der Seite zu verbessern, bietet der Shop ausserdem die Möglichkeit den Smarty-Block inline-script zu verwenden.

Beispiel:

Dies ist eine smarty.tpl Datei,<br>
die ein Javascript enthält. Es wird automatisch beim Seitenaufruf nachgeladen (defer).<br>

{inline-script}
<script>
    function helloWorld() {
        alert('Hello World');
    }

</script>
{/inline-script}

Theme-Variablen

Diese Variablen sind, soweit möglich, in einigen wenigen Dateien zusammengefasst.

Im NOVA-Template liegen sie im Ordner <Shop-Root>templates/NOVA/themes/<Theme>/sass/_variables.scss.

Hint

Alle themerelevanten Variablen finden Sie in der _variables.scss. Sehen Sie sich diese Datei(en) an und probieren Sie es aus, einige Werte zu ändern. Zum Teil werden auch aus dem zugrundeliegenden Bootstrap Regeln übernommen.

Merkmale abfragen

Merkmale dienen, auf der Artikeldetailseite, der Auflistung bestimmter Artikeleigenschaften wie z. B. der Farbe des Produktes. Merkmale werden in JTL-Wawi, pro Sprache, definiert.

Template-Code

im NOVA-Template: templates/NOVA/productdetails/attributes.tpl :

{block name='productdetails-attributes-shop-attributes'}
    {foreach $Artikel->Attribute as $Attribut}
        <tr class="attr-custom">
            <td class="h6">{$Attribut->cName}: </td>
            <td class="attr-value">{$Attribut->cWert}</td>
        </tr>
    {/foreach}
{/block}

Der Zugriff ist auch über ein assoziatives Array möglich:

{assign var="attrname" value="Name des Funktionsattributes hier eintragen"}
{$Artikel->AttributeAssoc.$attrname}

Funktionsattribute

In JTL-Wawi können Sie in den Artikeldetails im Reiter "Attribute/Merkmale" sogenannte Funktionsattribute im Artikel hinterlegen. Anders als Artikelattribute (siehe vorheriger Abschnitt "Merkmale") werden Funktionsattribute nicht mehrsprachig definiert, da sie Funktionalitäten und Aktionen im Shop auslösen bzw. das Template steuern können. (Siehe auch: Beispielartikel mit Funktionsattributen im JTL-Demoshop)

Funktionsattribute am Artikel stehen templateseitig in den Artikeldetails als Variable zur Verfügung und können artikelbezogen im Frontend abgefragt werden.

Funktionsattribute können im Template per {$Artikel->FunktionsAttribute['funktionsattributname']} ausgelesen werden. ("funktionsattributname" reflektiert hier den Namen des Funktionsattributes, wie es in JTL-Wawi definiert wurde)

Natürlich können Sie auch eigene Funktionsattribute in JTL-Wawi anlegen und diese im Shop-Template nutzen.

Attention

Schreiben Sie Funktionsattributnamen auch dann in Kleinbuchstaben, wenn deren Namen in JTL-Wawi Großbuchstaben enthalten.

Beispiel:

Sie möchten ein Funktionsattribut highlightclass neu erstellen und abfragen sowie abhängig davon den Hintergrund der Kurzbeschreibung auf der Artikeldetailseite in Gelb erscheinen lassen, quasi "highlighted".

Wir gehen hier wieder von einem eigenen Child-Template aus (siehe Eigenes Template). Definieren Sie die CSS-Klasse in einer eigenen custom.css Datei. Geladen wird diese CSS-Klasse via template.xml, Tag <Minify><CSS Name="clear.css">...</CSS> für das jeweilige Theme. In NOVA ist es das Theme "clear".

/* custom.css */
.highlightclass {
    background-color: yellow;
}

Das neue Funktionsattribut soll den Name highlightclass tragen und muss natürlich noch in JTL-Wawi angelegt werden. Rufen Sie dazu in JTL-Wawi die Artikelstammdaten des Zielartikels auf und wechseln Sie in den Reiter "Attribute/Merkmale". Diese zweigeteilte Maske beinhaltet im oberen Bereich "Artikelattribute" die Attribute, die wir anreichern wollen. Klicken Sie rechts auf :guilabel:Attribute verwalten und wählen Sie in der folgenden Maske unter "Attribut anlegen" den Unterpunkt "neues Funktionsattribut" aus. Vergeben Sie einen Namen und legen Sie den Onlineshop fest, an den dieses Attribut gesendet werden soll.

Ändern Sie nun in der Template-Datei templates/NOVA/productdetails/details.tpl den folgenden Code-Block so ab, dass Sie den Wert des Funktionsattributes einfügen können, wenn er gesetzt ist:

/* productdetails/details.tpl */
{block name='productdetails-details-info-description'}
    {include file='snippets/opc_mount_point.tpl' id='opc_before_short_desc'}
    <div class="{if !empty($Artikel->FunktionsAttribute['highlightclass']}{$Artikel->FunktionsAttribute['highlightclass']} {/if}shortdesc mb-2 d-none d-md-block" itemprop="description">
        {$Artikel->cKurzBeschreibung}
    </div>
{/block}

Sonderfall: "Sonderzeichen im Funktionsattributnamen"

Bei Sonderzeichen im Namen des Funktionsattributes können Sie wie folgt darauf zugegreifen:

{assign var="fktattrname" value="größe"}
{$Artikel->FunktionsAttribute[$fktattrname]}

Kategorieattribute abfragen

Ähnlich den Funktionsattributen eines Artikels lassen sich in der JTL-Wawi, in den Kategoriedetails, auch Kategorieattribute definieren. Diese werden beim Synchronisieren zum Onlineshop übertragen und können dort Steuerungsaufgaben übernehmen können.

Es werden Kategorie-Funktionsattribute und Kategorieattribute unterschieden. Kategorie-Funktionsattribute (categoryFunctionAttributes) sind key/value-Paare die zur Aufnahme der Funktionsattribute dienen, während Kategorieattribute in Form von "array of objects" lokalisierte Kategorieattribute aufnehmen. Funktionsattribute dienen der Steuerung von Aktionen im Onlineshop selbst nur im Template, während Kategorieattribute lokalisierte Werte - passend zur eingestellten Shop-Sprache - enthalten können.

Diese Kategorieattribute können im Template wie folgt abgefragt werden:

PHP-Code für Funktionsattribut

(Einbindung in Plugins oder in die php/functions.php des Templates):

$Kategorien = new KategorieListe();
$Kategorien->getAllCategoriesOnLevel( 0 );
foreach ($Kategorien->elemente as $Kategorie) {
  $funktionsWert = $Kategorie->getCategoryFunctionAttribute('meinkategoriefunktionsattribut');
}

PHP-Code für lokalisiertes Attribut

(Einbindung als Plugin oder in die php/functions.php des Templates):

$Kategorien = new KategorieListe();
$Kategorien->getAllCategoriesOnLevel( 0 );
foreach ($Kategorien->elemente as $Kategorie) {
  $attributWert = $Kategorie->getCategoryAttributeValue('meinkategorieattribut');
}

Template-Code

zur Steuerung mittels Kategorie-Funktionsattributen in der Kategorieansicht (am besten mit der Smarty Debug-Konsole nach dem eigenen Kategorieattribut suchen):

{if $oNavigationsinfo->getCategory()->getCategoryFunctionAttribute('meinkategoriefunktionsattribut') === 'machedies'}
    <span>MacheDies</span>
{else}
    <span>MacheDas</span>
{/if}

Template-Code

zur Ausgabe eines lokalisierten Kategorieattributs in Kategorieansicht (am besten mit der Smarty Debug-Konsole nach dem eigenen Kategorieattribut suchen):

<span>{$oNavigationsinfo->getCategory()->getCategoryAttributeValue('meinkategorieattribut')}</span>

Eigene Sprachvariablen verwenden

Um eigene Sprachvariablen zu erstellen, öffnen Sie im Backend von JTL-Shop die "Sprachverwaltung" (Einstellungen -> Sprachverwaltung) und klicken Sie auf die Schaltfläche :guilabel:Variable hinzufügen. Per Smarty-Funktion {lang} und den Parametern key und section können Sie diese Variablen im Template verwenden.

Beispiel:

Fügen Sie über die Sprachverwaltung folgende Sprachvariable hinzu:

  • Sprachsektion: custom
  • Variable: "safetyBoxTitle"
  • Wert Deutsch: "SSL-Verschlüsselung"
  • Wert Englisch: "SSL-Encryption"

Template-Code:

{lang key="safetyBoxTitle" section="custom"}

PHP-Code (z. B. in Plugins, wobei hier im Beispiel der Plugin-Kontext gegeben ist; zu erkennen am $this->):

$langVar = $this->getLocalization()->getTranslation('safetyBoxTitle');

Sprachvariable als Smarty-Variable speichern und abfragen:

Template-Code:

{* Sprachvariable einfügen *}
{lang key="safetyBoxTitle" section="custom"}

{* Variable mit assign zuweisen *}
{lang assign="testVariableSafetyBoxTitle" key="safetyBoxTitle" section="custom"}

{* die zuvor zugewiesene Variable kann nun normal aufgerufen oder abgefragt werden *}
{if $testVariableSafetyBoxTitle eq "SSL-Verschlüsselung"}<span class="de">{$testVariableSafetyBoxTitle}</span>
{else}<span>{$testVariableSafetyBoxTitle}</span>{/if}

Erstellen eigener Smarty-Funktionen

Um eigene Smarty-Funktionen zu registrieren, gibt es template-abhängig diesen Weg.

NOVA-Template

Wenn Sie ein Child-Template des NOVA-Templates verwenden, erstellen Sie, sofern nicht bereits vorhanden, im Wurzelverzeichnis Ihres Child-Templates eine PHP-Klasse namens Bootstrap.php mit folgendem Inhalt:

<?php declare(strict_types=1);

namespace Template\[NOVA-child-name];

/**
 * Class Bootstrap
 * @package Template\[NOVA-child-name]
 */
class Bootstrap extends \Template\NOVA\Bootstrap
{
    // eigene Methoden
}

Hint

Die PHP-Datei, wie auch die PHP-Klasse, wird beim Start automatisch geladen und ermöglicht das Registrieren von Smarty-Plugins. Danach können Sie Ihre eigenen Smarty-Funktionen implementieren und in Smarty registrieren.

Funktionen im NOVA-Child registrieren

Im nachfolgenden Beispiel wird eine Methode zur Berechnung der Kreiszahl PI in die Bootstrap-Klasse eingebunden und in Smarty registriert:

<?php declare(strict_types=1);

namespace Template\[NOVA-child-name];

use Smarty;

/**
 * Class Bootstrap
 * @package Template\[NOVA-child-name]
 */
class Bootstrap extends \Template\NOVA\Bootstrap
{
    public function boot(): void
    {
        parent::boot();
        try {
            $this->getSmarty()->registerPlugin(Smarty::PLUGIN_FUNCTION, 'getPI', [$this, 'getPI']);
        } catch (\SmartyException $e) {
            throw new \RuntimeException('Problems during smarty instantiation: ' . $e->getMessage());
        }
    }

    public function getPI($args)
    {
        $precision = $args['precision'];
        $iterator  = 1;
        $factor    = -1;
        $nenner    = 3;

        for ($i = 0; $i < $precision; $i++) {
            $iterator = $iterator + $factor / $nenner;
            $factor   *= -1;
            $nenner   += 2;
        }

        return $iterator * 4;
    }
}

Funktionen nutzen

Die Funktion getPI() kann dann im Template z. B. mit {getPI precision=12} verwendet werden.

Überschreiben bestehender Funktionen

Das Überschreiben von Funktionalitäten ist ebenfalls möglich.

Funktionen im NOVA-Child überschreiben

In Ihrem NOVA-Child überschreiben sie Funktionen, indem Sie die entsprechende Basisklasse des NOVA-Templates templates/NOVA/Plugins.php mit einer eigenen Klasse in Ihrem NOVA-Child templates/[NOVA-child-name]/Plugins.php erweitern.

Im nachfolgenden Beispiel wird die Funktion getTranslation() des NOVA-Templates dahingehend erweitert, dass bei nicht vorhandener Übersetzung der Text "-no translation-" ausgegeben wird.

<?php declare(strict_types=1);

namespace Template\[NOVA-child-name];

use JTL\Shop;

/**
 * Class Bootstrap
 * @package Template\[NOVA-child-name]
 */
class Plugins extends \Template\NOVA\Plugins
{
    public function getTranslation($mixed, $to = null): ?string
    {
        $to = $to ?: Shop::getLanguageCode();

        if ($this->hasTranslation($mixed, $to)) {
            return \is_string($mixed) ? $mixed : $mixed[$to];
        }

        return '-no translation-';
    }
}

Um ihre Variante der Funktion getTranslation() nutzen zu können, müssen sie erst die alte Variante aus dem System entfernen ("unregister") und die neue definieren. Dies geschieht in templates/NOVA/Bootstrap.php wie folgt:

<?php declare(strict_types=1);

namespace Template\NOVAChild;

use Smarty;

/**
 * Class Bootstrap
 * @package Template\NOVAChild
 */
class Bootstrap extends \Template\NOVA\Bootstrap
{
    /**
     * @inheritdoc
     */
    public function boot(): void
    {
        parent::boot();
        // whatever you do, always call parent::boot() or delete this method!
    }

    protected function registerPlugins(): void
    {
        parent::registerPlugins();
        $plugins        = new Plugins($this->getDB(), $this->getCache());
        $smarty = parent::getSmarty();

        $smarty->unregisterPlugin(Smarty::PLUGIN_FUNCTION,'getTranslation');
        $smarty->registerPlugin(Smarty::PLUGIN_FUNCTION, 'getTranslation', [$plugins, 'getTranslation']);

        // whatever you do, always call parent::registerPlugins() or delete this method!
    }
}

Unabhängige Artikellisten erzeugen

Ab JTL-Shop Version 3.10, bis einschließlich 5.0, ist es möglich, eigene Artikel-Arrays über eine Smarty-Funktion {get_product_list} zu erzeugen. Dies kann beispielsweise dazu genutzt werden, um auf bestimmte Artikel(-gruppen) abseits von Cross-Selling gesondert aufmerksam zu machen.

Der Funktion können die folgenden Parameter übergeben werden:

Parametername Typ Pflichtattribut Beschreibung
nLimit Numeric Ja Maximale Anzahl Artikel, welche geholt werden sollen
cAssign String Ja Name der Smarty-Variable, in welcher das Array mit Artikeln gespeichert wird
kKategorie Numeric -- Primärschlüssel einer Kategorie, siehe Datenbank tkategorie.kKategorie
kHersteller Numeric -- Primärschlüssel eines Herstellers, siehe Datenbank thersteller.kHersteller
kArtikel Numeric -- Primärschlüssel eines Artikels, siehe Datenbank tartikel.kArtikel
kSuchanfrage String -- Primärschlüssel einer Suchanfrage, siehe Datenbank tsuchcache.kSuchCache
kMerkmalWert String -- Primärschlüssel eines Merkmalwerts, siehe Datenbank tmerkmalwert.kMerkmalwert
kSuchspecial Numeric -- Filterung nach Suchspecials, siehe Tabelle unten "Suchspecialschlüssel"
kKategorieFilter Numeric -- Zusätzlicher Filter nach einer Kategorie in Kombination mit einem Hauptfilter z. B. kHersteller.
kHerstellerFilter Numeric -- Zusätzlicher Filter nach einem Hersteller in Kombination mit einem Hauptfilter z. B. kKategorie. Primärschlüssel siehe Datenbank thersteller.kHersteller
nBewertungSterneFilter Numeric -- Zusätzlicher Filter nach Mindest-Durschnittsbewertung in Kombination mit einem Hauptfilter, z. B. kKategorie.
cPreisspannenFilter String -- Zusätzlicher Filter nach Preisspanne in Kombination mit einem Hauptfilter, z. B. kKategorie. Schreibweise für "von 20 € bis 40,99 €": "20_40.99"
nSortierung Numeric -- Gibt an, nach welchem Artikelattribut sortiert werden soll. Details siehe Tabelle unten "Sortierungsschlüssel"
cMerkmalFilter String -- Primärschlüssel der Merkmalwerte durch Semikolon getrennt, z. B. "100;101". Primärschlüsselangabe siehe Datenbank tmerkmalwert.kMerkmalwert
cSuchFilter String -- Primärschlüssel der Suchfilter durch Semikolon getrennt, z. B. "200;201". Primärschlüsselangabe siehe Datenbank tsuchcache.kSuchCache
cSuche String -- Suchbegriff, z. B. "zwiebel ananas baguette"

Beispiel

Binden Sie den folgenden Code im Template ein:

<h2>Unsere Verkaufschlager aus dem Bereich Gemüse</h2>
{get_product_list kKategorie=9 nLimit=3 nSortierung=11 cAssign="myProducts"}
{if $myProducts}
  <ul>
  {foreach name=custom from=$myProducts item=oCustomArtikel}
    <li><a href="{$oCustomArtikel->cURLFull}">{$oCustomArtikel->cName}</a></li>
  {/foreach}
  </ul>
{/if}

Sortierungsschlüssel

Name Wert Konstante
Standard 100 SEARCH_SORT_STANDARD
Artikelname von A bis Z 1 SEARCH_SORT_NAME_ASC
Artikelname von Z bis A 2 SEARCH_SORT_NAME_DESC
Preis aufsteigend 3 SEARCH_SORT_PRICE_ASC
Preis absteigend 4 SEARCH_SORT_PRICE_DESC
EAN 5 SEARCH_SORT_EAN
neuste zuerst 6 SEARCH_SORT_NEWEST_FIRST
Artikelnummer 7 SEARCH_SORT_PRODUCTNO
Verfügbarkeit 8 SEARCH_SORT_AVAILABILITY
Gewicht 9 SEARCH_SORT_WEIGHT
Erscheinungsdatum 10 SEARCH_SORT_DATEOFISSUE
Bestseller 11 SEARCH_SORT_BESTSELLER
Bewertungen 12 SEARCH_SORT_RATING

Suchspecialschlüssel

Name Wert Konstante
Bestseller 1 SEARCHSPECIALS_BESTSELLER
Sonderangebote 2 SEARCHSPECIALS_SPECIALOFFERS
Neu im Sortiment 3 SEARCHSPECIALS_NEWPRODUCTS
Top-Angebote 4 SEARCHSPECIALS_TOPOFFERS
In Kürze verfügbar 5 SEARCHSPECIALS_UPCOMINGPRODUCTS
Top bewertet 6 SEARCHSPECIALS_TOPREVIEWS
Ausverkauft 7 SEARCHSPECIALS_OUTOFSTOCK
Auf Lager 8 SEARCHSPECIALS_ONSTOCK
Vorbestellung möglich 9 SEARCHSPECIALS_PREORDER

Eigene Mount-Points einfügen

Mit dem OnPage Composer können Inhalte in vordefinierte Bereiche des Templates platziert werden. Diese Bereiche werden im Smarty Codes des Template durch sogenannte Mount Points ausgezeichnet. Falls Sie eigene Mount Points definieren wollen, nutzen Sie die folgende Smarty-Anweisung:

{opcMountPoint id='mount_point_id'}

Mit dem Parameter id geben Sie dem Mount Point einen Identifikator, der für die Seite eindeutigen sein muss.

Optional können Sie der Smarty-Funktion noch den Parameter title mitgeben. Dieser definiert einen im OnPage Composer-Editor sichtbaren Anzeigenamen.

Beispiel:

{opcMountPoint id='opc_in_header' title='Im Header'}