Blog

Upgrade eines PrestaShop-Moduls auf PrestaShop 9: Was ist schiefgelaufen und wie haben wir das Problem behoben?

Das PrestaShopAddons-Team 9 Minuten Lesezeit

Block Sliding Cart ist eines der ältesten Module in unserem Katalog. Es wurde 2013 erstmals auf PrestaShop Addons gelistet und funktionierte jahrelang einwandfrei. Dann kam PrestaShop 8 auf den Markt, wir konnten nicht mithalten, und 2023 wurde der Eintrag deaktiviert.

Im Jahr 2026 haben wir es wieder eingeführt: eine einzige Codebasis für PrestaShop 1.7, 8 und 9, das Classic-Theme und Hummingbird. Hier ist eine Liste der Probleme, die dabei tatsächlich aufgetreten sind, und wie jedes einzelne behoben wurde. Wenn Sie ein Upgrade auf PrestaShop 9 planen, trifft das meiste davon auch auf Ihre eigenen Module zu.

Kurzfassung: Auf der PHP-Seite waren weniger Änderungen erforderlich als erwartet. Der größte Teil der Zeit floss in das neue Standard-Theme und in das Bestehen der Addons-Validierung, bei der bereits eine einzige Warnung in einer PrestaShop-Version zum Scheitern der gesamten Überprüfung führen kann.

1. PHP: Was wurde in PrestaShop 9 entfernt oder verschoben?

Tools::displayPrice() ist weg

Das Modul formatierte die Preise an sieben Stellen mit Tools::displayPrice(). Die Methode war schon seit langem veraltet und wurde in PrestaShop 9 schließlich entfernt, sodass jeder dieser Aufrufe nun zu einem schwerwiegenden Fehler führte.

Als Ersatz dient die aktuelle Ländereinstellung, die das Währungsformat des Shops bereits kennt. Wir haben beide Pfade in einem einzigen Helper zusammengefasst, sodass der Rest des Moduls sich nie darum kümmern muss, auf welcher PrestaShop-Version es läuft:

public function formatPrice($price)
{
    if (method_exists('Tools', 'displayPrice')) {
        // PrestaShop 1.7 / 8: keep the old behaviour
        return Tools::displayPrice((float) $price);
    }
    $locale = $this->context->getCurrentLocale();
    $isoCode = isset($this->context->currency) ? $this->context->currency->iso_code : '';

    return $locale->formatPrice((float) $price, $isoCode);
}

Vorlagen nutzen denselben Helper über einen kleinen Smarty-Modifikator, der vom Modul registriert wird, daher {$price|scdisplayprice} funktioniert bei jeder Version.

Der Namespace der Presenter-Klassen wurde geändert

Das Modul stellt den Warenkorb mit PrestaShop-eigenen CartPresenter, sodass Preise, Rabatte und Produktnamen genau so aussehen wie im restlichen Shop. Zwischen 1.7 und 8 wurde dieser Kurs verlegt von Adapter\Cart zu Adapter\Presenter\Cart. Anstelle von class_alias Tricks: Das Modul löst den Klassennamen einmalig auf:

private function getCartPresenterClass()
{
    return class_exists('PrestaShop\\PrestaShop\\Adapter\\Presenter\\Cart\\CartPresenter')
        ? 'PrestaShop\\PrestaShop\\Adapter\\Presenter\\Cart\\CartPresenter'
        : 'PrestaShop\\PrestaShop\\Adapter\\Cart\\CartPresenter';
}

Das gleiche Muster gilt auch für die Produktpräsentationen, die für Cross-Selling genutzt werden. Noch ein Detail: auf PrestaShop 8 und 9 present() gibt ein „lazy“-Array-Objekt zurück, kein einfaches Array; daher lauten Typangaben wie array müssen zulassen ArrayAccess ebenfalls.

Statische Analyse für PrestaShop 9

Der Addons-Validator führt PHPStan auf dem PrestaShop 9-Quellcode aus. Ein Aufruf, der zur Laufzeit vollkommen sicher ist, da er hinter einem method_exists() Der Fehler wird nach wie vor als “Aufruf einer undefinierten Methode” gemeldet. Wir haben den Validator lokal nachgebildet (PHPStan mit einem Bootstrap, das die PrestaShop-Quellcodes 8 und 9 lädt), sodass jede Korrektur innerhalb weniger Minuten überprüft werden konnte, anstatt auf eine weitere Überprüfung warten zu müssen.

2. Hummingbird: vier Fehler, die nur im neuen Design auftraten

Hummingbird ist das Standard-Theme von PrestaShop 9 (Quelle auf GitHub). Keines der unten aufgeführten Elemente wurde bei der statischen Analyse oder auf PrestaShop 8 mit dem Classic-Design gefunden. Alle vier wurden durch das Durchklicken eines echten PrestaShop 9-Shops entdeckt.

Durch die CSS-Kaskadenebenen wurde die Warenkorb-Liste in ein Raster umgewandelt

Hummingbird gestaltet die .products Klasse als zweispaltiges Raster innerhalb von @layer ps-components. Unsere Warenkorb-Liste verwendete aus Kompatibilitätsgründen denselben Klassennamen, sodass die Produkte im Seitenbereich plötzlich in zwei schmalen Spalten angezeigt wurden. Eine Erhöhung der Spezifität hilft in diesem Fall nicht wie üblich gegen überlagerte Regeln; was hier hilft, ist, dass nicht überlagerte CSS-Regeln Vorrang vor überlagerten CSS-Regeln haben. Eine kurze, nicht überlagerte Regel im Stylesheet des Moduls hat das Problem behoben:

#sclist .products,
#sclist .product_list_widget {
    display: block;
    grid-template-columns: none;
}

Das Warenkorb-Modal des Themes erwartet ein eigenes Markup

Das Modul öffnete sein Popup-Fenster “Zum Warenkorb hinzugefügt” über prestashop.blockcart.showModal. Hummingbird ersetzt diese Funktion durch eine eigene Version, die nach einem Element mit data-ps-ref="blockcart-modal" und löst einen Fehler aus, wenn anderes HTML übergeben wird. Die Lösung bestand darin, stets den moduleigenen Modal-Renderer anstelle desjenigen des Themes zu verwenden.

Ein veralteter Elementverweis in der “Zum Warenkorb hinzufügen”-Animation

Die Animation speicherte das Warenkorb-Symbol beim Klicken auf die Schaltfläche und las dessen Position 250 ms später aus. Bei Hummingbird wird der Warenkorb in der Kopfzeile zwischendurch neu gerendert, sodass das gespeicherte Element nicht mehr auf der Seite vorhanden war und offset() zurückgegeben undefined. Das Modul sucht nun das Symbol erneut, sobald es benötigt wird, und überspringt die Animation, wenn das Theme kein abrufbares Warenkorb-Symbol enthält. Das Fenster selbst wird in jedem Fall geöffnet.

Eine feste Schaltfläche, die auf Mobilgeräten über den Bildschirmrand hinausragt

Auf Smartphones lautet die Schaltfläche „Zur Kasse“ position: fixed am unteren Rand des Seitenbereichs. Ein festes Element wird relativ zum nächsthöheren Element mit einem transform — und das Fenster verfügt nur über eine, solange es geöffnet ist. Wenn das Fenster geschlossen war, wurde die Schaltfläche an das Ansichtsfenster angeheftet und schwebte am unteren Rand jeder Seite. Die Regel auf den geöffneten Zustand beschränken (.sc-widget-panel-open) hat das Problem gelöst.

3. Add-on-Prüfung: Was bei der Überprüfung tatsächlich geprüft wird

Um ein Modul wieder in die Liste aufzunehmen, musste man den PrestaShop-Validator und anschließend eine Konformitätsprüfung, bei der das Modul auf mehreren PrestaShop-Versionen mit aktiviertem Debug-Modus installiert wurde. Diese Ergebnisse nahmen am meisten Zeit in Anspruch.

Jede Smarty-Variable muss mit einem Escape-Zeichen versehen werden

Ältere Vorlagen basierten auf automatischer Escaping-Funktion. Bei der Überprüfung wird nun jede nicht-escapete Ausgabe als Blocker behandelt. Wir haben alle sieben Front-Office-Vorlagen durchgesehen: |escape:'html':'UTF-8' für Text, URLs und Attribute, |intval für Artikelnummern und Mengen, |escape:'javascript':'UTF-8' innerhalb von Inline-Skripten.

nofilter wird als Sicherheitsproblem gemeldet, selbst wenn dies gerechtfertigt ist

Das Modul ermöglicht es dem Shop-Betreiber, seinen eigenen Icon-HTML-Code (ein Font-Awesome-Tag oder eine SVG-Datei) einzufügen. Diese Ausgabe wird verwendet nofilter, zusammen mit einem Kommentar, in dem erklärt wurde, warum. Der Prüfer hat den Beitrag trotzdem markiert. Die akzeptierte Lösung war ein benutzerdefinierter Smarty-Modifikator, der den HTML-Code bereinigt – entfernt <script> und <style> Blöcke, Inline-Ereignisbehandler und javascript: URLs – damit die Vorlage nicht mehr nofilter überhaupt nicht.

Kein HTML innerhalb von PHP

Ein kleines Support-Feld auf der Konfigurationsseite wurde in PHP als HTML-Zeichenkette erstellt. Es wurde in eine eigene Admin-Vorlage verschoben. Eine Falle: Unter PrestaShop 8.1 blockiert die Smarty-Sicherheitsrichtlinie für den Admin-Bereich einen Raw-Befehl $this->context->smarty->fetch() einer Datei im Modulordner. Verwenden Sie stattdessen die Modulressource:

$output .= $this->fetch('module:yourmodule/views/templates/admin/support.tpl');

Eine Warnung im Debug-Modus kann dazu führen, dass die Überprüfung nicht bestanden wird

Dafür waren drei Versuche nötig. Im Compliance-Bericht hieß es, dass die Konfigurationsseite unter PrestaShop 8.1 und 9.0 “nicht aufgerufen werden konnte”, ohne dass eine Fehlermeldung angezeigt wurde. Die Ursache stellte sich als ein einziger Hinweis heraus: Undefined array key "is_default" in der HelperForm-Vorlage. Language::getLanguages() Wenn dieser Schlüssel nicht zurückgegeben wird, liest die Formularvorlage ihn für jede Sprache ein, und der strenge Debug-Modus der Überprüfung wandelt diese Meldung in eine fehlerhafte Seite um. In einem normalen Testshop mit Debug-Modus wird dies lediglich als Warnung angezeigt, weshalb es leicht zu übersehen war.

$languages = Language::getLanguages(false);
$idDefaultLang = (int) Configuration::get('PS_LANG_DEFAULT');
foreach ($languages as $k => $lang) {
    $languages[$k]['is_default'] = ((int) $lang['id_lang'] === $idDefaultLang) ? 1 : 0;
}

Die Lehre daraus: Öffnen Sie vor dem Absenden die Konfigurationsseite auf PrestaShop 8 und 9 im Debug-Modus und behandeln Sie jeden Hinweis als Fehler.

Codierungsstandards, mit einem Konflikt

Der Validator wendet die Regeln von PHP-CS-Fixer an. Zwei Kleinigkeiten haben uns jeweils eine erneute Einreichung gekostet: In einer Datei ohne Namespace muss man schreiben catch (Throwable $e), nicht \Throwable; und die Lizenz-Docblock direkt danach beibehalten <?php, ohne Leerzeile. Eine generische PHP-CS-Fixer-Konfiguration versucht, diese Leerzeile einzufügen; führen Sie daher die Regeln des Validators aus und nicht eine generische Voreinstellung.

Eine Checkliste für Ihre eigenen Module vor dem Upgrade auf PrestaShop 9

  • Probieren Sie unser kostenloses PrestaShop 9 Kompatibilitätsprüfung im Modul. Dort sind die entfernten Klassen, Methoden und hooks aufgeführt, auf die in den folgenden Punkten eingegangen wird, zusammen mit der Datei und der Zeilennummer.
  • Den Code nach … durchsuchen Tools::displayPrice sowie weitere Methoden, die in Version 9.0 entfernt wurden (die PrestaShop 9 – Entwicklerdokumentation (listet die Änderungen auf).
  • Achten Sie auf Klassen, auf die unter ihren alten Namespaces verwiesen wird, insbesondere auf Presenter und Adapter.
  • Installieren Sie das Modul auf einem PrestaShop 9-Gerät mit aktiviertem Debug-Modus und öffnen Sie dessen Konfigurationsseite. Lesen Sie alle Hinweise durch.
  • Testen Sie das front office auf Hummingbird, nicht nur Classic: Popups, den Warenkorb in der Kopfzeile, Produktlisten und das Layout für Mobilgeräte.
  • Prüfen Sie die Vorlagen auf nicht maskierte Variablen und nofilter.
  • Überprüfen Sie den angegebenen Kompatibilitätsbereich des Moduls. Er sollte mit den Versionen übereinstimmen, die Sie tatsächlich getestet haben.

Sie bereiten einen ganzen Shop vor, nicht nur ein Modul? Folgen Sie unserer Checkliste in 12 Schritten für das Update von PrestaShop 1.7 auf 9.

Wo sich das Modul derzeit befindet

Block Sliding Cart läuft auf PrestaShop 1.7, 8 und 9, hat die Add-ons-Validierung bestanden und ist wieder gelistet, wobei der Verlauf und die 36 Bewertungen (4,7★) erhalten geblieben sind. Sie können Schau dir hier an, was es macht, und die Gründe für einen AJAX-Warenkorb werden in AJAX-Warenkorb vs. Seitenneuladen und mobile Warenkorb-UX für PrestaShop.

Wenn ein Modul in Ihrem Shop nach einem Upgrade nicht mehr funktioniert oder Sie vor dem Upgrade wissen möchten, was nicht mehr funktionieren wird, dann ist das genau unsere Aufgabe. Sag uns, was los ist und wir melden uns dann mit Fragen oder einem Angebot bei Ihnen.

Häufig gestellte Fragen

Ist Tools::displayPrice() in PrestaShop 9 entfernt?

Ja. Verwenden Sie stattdessen die aktuelle Ländereinstellung: $this->context->getCurrentLocale()->formatPrice($price, $currencyIsoCode). Falls Ihr Modul auch PrestaShop 1.7 unterstützen muss, fassen Sie beide Pfade in einer Hilfsmethode zusammen.

Funktionieren die PrestaShop 1.7-Module auf dem PrestaShop 9?

Manche kommen ohne Änderungen aus. Module, die entfernte Kernmethoden, alte Klassennamensräume oder themenspezifisches JavaScript verwenden, müssen aktualisiert werden. Wenn man das Modul auf einer PrestaShop-9-Installation mit aktiviertem Debug-Modus installiert, werden die meisten Probleme innerhalb weniger Minuten sichtbar.

Warum sieht mein Modul bei Hummingbird fehlerhaft aus, bei Classic jedoch nicht?

Hummingbird verwendet für den Warenkorb ein anderes Markup, CSS-Kaskadenebenen und eigenes JavaScript. Am stärksten betroffen sind Module, die Klassennamen aus „Classic“ wiederverwenden oder die Warenkorb-Funktionen des Themes aufrufen.

Warum schlägt die Konformitätsprüfung für Add-ons auf der Konfigurationsseite fehl?

Im Rahmen des Tests wird das Modul auf mehreren PrestaShop-Versionen im strengen Debug-Modus installiert, wobei Hinweise wie “undefined array key” dazu führen, dass die Seite nicht mehr funktioniert. Öffnen Sie die Konfigurationsseite selbst in PrestaShop 8 und 9 bei aktiviertem Debug-Modus und beheben Sie jeden Hinweis, bevor Sie die Seite absenden.