Poradniki Poradnik

Motywy potomne PrestaShop: Classic i Hummingbird

Tworzenie motywów potomnych PrestaShop — nadpisywanie szablonów, personalizacja SCSS, hooki JavaScript, szablony modułów i zmiany w PS 9.

Czym jest motyw potomny i dlaczego ma znaczenie

Motyw potomny (child theme) dziedziczy szablony i zasoby z motywu nadrzędnego, pozwalając nadpisać tylko to, co zmieniasz. Bez niego każda poprawka CSS czy edycja szablonu trafia do plików motywu nadrzędnego — i zostaje nadpisana przy kolejnej aktualizacji.

Motyw potomny to przezroczysta nakładka. PrestaShop najpierw szuka pliku w motywie potomnym. Jeśli go znajdzie — używa go. Jeśli nie — sięga do motywu nadrzędnego. Dodajesz tylko to, co zmieniasz.

Używaj motywu potomnego do punktówych modyfikacji — kolory, poprawki układu, nadpisywanie szablonów, własne CSS/JS. Buduj pełny własny motyw tylko wtedy, gdy potrzebujesz zasadniczo innej architektury.

Motyw nadrzędnyWersja PSFrameworkNajlepszy do
Classic1.7.x / 8.xBootstrap 4, jQueryMaksymalna kompatybilność, stabilna baza
Hummingbird9.1+Bootstrap 5.3, TypeScriptNowoczesne sklepy, gotowość na PS 9

W nowych projektach na PrestaShop 9.1+ wybierz Hummingbird — to domyślny motyw przyszłości i jedyny aktywnie rozwijany przez projekt PrestaShop.

Struktura motywu potomnego

Motyw potomny żyje obok motywu nadrzędnego w katalogu /themes/. Minimalny motyw potomny wymaga zaledwie dwóch plików:

themes/my-child-theme/
  config/
    theme.yml             <-- wymagany: konfiguracja motywu
  preview.png             <-- wymagany: podgląd motywu 200x200

W miarę rozrastania się dostosowań katalog odzwierciedla strukturę motywu nadrzędnego, ale zawiera tylko zmodyfikowane pliki:

themes/my-child-theme/
  config/theme.yml
  assets/
    css/custom.css
    js/custom.js
  templates/
    catalog/product.tpl
    _partials/header.tpl
  modules/
    ps_featuredproducts/views/templates/hook/
      ps_featuredproducts.tpl
  translations/en-US/Shop/Theme.xlf
  preview.png
Dodawaj tylko pliki, które zmieniasz. Każdy dodany plik to plik, który musisz utrzymywać. Pusty motyw potomny dziedziczący wszystko jest lepszy niż zatłoczony niezmienionymi kopiami.

Konfiguracja theme.yml

Plik config/theme.yml to serce motywu potomnego. Kluczowa linia to parent: classic (lub parent: hummingbird) — ustanawia ona łańcuch dziedziczenia:

parent: classic
name: my-child-theme
display_name: My Child Theme
version: 1.0.0
author:
  name: "Your Name"
  email: "you@example.com"
  url: "https://yoursite.com"

meta:
  compatibility:
    from: 1.7.0.0
    to: ~

assets:
  use_parent_assets: true

theme_settings:
  default_layout: layout-full-width
  layouts:
    category: layout-left-column

Tworzenie motywu potomnego dla Classic

Classic to oryginalny domyślny motyw PrestaShop od wersji 1.7. Proces składa się z czterech kroków:

# 1. Utwórz katalog
mkdir -p themes/my-classic-child/config

# 2. Utwórz config/theme.yml z parent: classic (patrz wyżej)

# 3. Dodaj preview.png (200x200)

# 4. Aktywuj przez Back Office > Design > Theme & Logo
#    Lub CLI: php bin/console prestashop:theme:enable my-classic-child

Z ustawieniem use_parent_assets: true i bez nadpisań otrzymujesz idealną kopię Classic. Szablony, CSS, JS, typy obrazów, układy i nadpisania szablonów modułów — wszystko jest dziedziczone.

Tworzenie motywu potomnego dla Hummingbird

Hummingbird używa Bootstrap 5.3 (CSS custom properties), CSS Layers (@layer), TypeScript kompilowanego z Webpack 5 oraz nazewnictwa BEM (.product__name, .product__description-short). Konfiguracja jest identyczna jak dla Classic — utwórz theme.yml z parent: hummingbird i kompatybilnością from: 9.0.0. Różnica polega na dostosowywaniu zasobów.

System warstw CSS w Hummingbird

Hummingbird definiuje następującą kolejność warstw w swoim SCSS:

@layer vendors, bs-base, bs-components, bs-custom-components,
       ps-base, ps-components, ps-pages, ps-modules, utilities;

Style w późniejszych warstwach nadpisują wcześniejsze niezależnie od specyficzności selektora. Umieszczaj własne reguły w odpowiedniej warstwie:

@layer ps-components {
  .product__name {
    font-family: 'Your Custom Font', sans-serif;
  }
}

@layer ps-pages {
  .page--category .product-miniature {
    border: 1px solid #eee;
    border-radius: 8px;
  }
}

Kompilacja SCSS

Aby używać własnego SCSS, dodaj krok kompilacji. Utwórz package.json z sass jako zależnością deweloperską i skryptami build:css (sass src/scss/custom.scss assets/css/custom.css --style=compressed) oraz watch:css. Następnie npm install && npm run build:css, aby skompilować.

Dart Sass może dodać znacznik UTF-8 BOM na początku skompilowanego CSS, powodując że przeglądarki po cichu ignorują reguły. Usuń go: sed -i '1s/^\xEF\xBB\xBF//' assets/css/custom.css

Nadpisywanie szablonów

Nadpisywanie szablonów to domena motywów potomnych. PrestaShop używa Smarty, który wspiera przejrzysty model dziedziczenia.

Kolejność rozpoznawania szablonów

  1. Motyw potomnythemes/my-child/templates/
  2. Motyw nadrzędnythemes/hummingbird/templates/

Metoda 1: Pełna kopia (prosta, trudniejsza w utrzymaniu)

Skopiuj szablon nadrzędny i edytuj go. Twoja wersja całkowicie zastępuje wersję nadrzędną:

cp themes/hummingbird/templates/catalog/product.tpl \
   themes/my-child/templates/catalog/product.tpl

Wada: Jesteś właścicielem całego pliku. Aktualizacje szablonu nadrzędnego do Ciebie nie dotrą.

Metoda 2: Smarty {extends} (preferowana)

Rozszerz szablon nadrzędny i nadpisz tylko konkretne bloki:

{extends file='parent:catalog/listing/category.tpl'}

{block name='product_list_header'}
  <div class="custom-category-header">
    <h1>{$category.name}</h1>
    <p>{$listing.pagination.total_items} products</p>
  </div>
{/block}

Prefiks parent: jest kluczowy — bez niego Smarty znajdzie własny plik motywu potomnego i stworzy nieskończoną pętlę.

Modyfikatory bloków

Zamiast zastępować cały blok, dodaj treść na końcu lub na początku:

{extends file='parent:catalog/product.tpl'}

{block name='product_description' append}
  <div class="shipping-notice">Free shipping on orders over $50</div>
{/block}

{block name='product_prices' prepend}
  <span class="price-badge">Best Price</span>
{/block}

Struktura bloków w Hummingbird

Kluczowe punkty nadpisywania na stronie produktu Hummingbird (catalog/product.tpl):

{block name='product_cover_thumbnails'}   — zdjęcia produktu
{block name='product_header'}              — nazwa produktu (h1)
{block name='product_manufacturer'}        — link do marki
{block name='product_prices'}              — wyświetlanie ceny
{block name='product_description_short'}   — krótki opis
{block name='product_variants'}            — selektory kombinacji
{block name='product_add_to_cart'}         — przycisk dodaj do koszyka
{block name='product_tabs'}               — akordeon opis/szczegóły
{block name='product_accessories'}         — produkty powiązane

Aby znaleźć dostępne bloki na dowolnej stronie, przeczytaj plik szablonu motywu nadrzędnego — każdy {block name='...'} to punkt nadpisania.

Dostosowywanie CSS

Rejestracja CSS w theme.yml

assets:
  use_parent_assets: true
  css:
    all:
      - id: my-child-custom-style
        path: assets/css/custom.css
        media: all
        priority: 200

Wyższe wartości priority ładują się później, pozwalając nadpisać style nadrzędne. W Hummingbird preferuj deklaracje @layer zamiast walczyć ze specyficznością. W Classic dopasuj głębokość selektora do motywu nadrzędnego. Unikaj !important.

Zmiana schematu kolorów

W Hummingbird (Bootstrap 5) nadpisz CSS custom properties:

:root {
  --bs-primary: #2563eb;
  --bs-primary-rgb: 37, 99, 235;
  --bs-body-font-family: 'Inter', system-ui, sans-serif;
}

Dostosowywanie JavaScript

Rejestracja JS w theme.yml

assets:
  use_parent_assets: true
  js:
    all:
      - id: my-child-custom-js
        path: assets/js/custom.js
        priority: 200

Zastąp all nazwą strony, aby ograniczyć zasięg skryptów: product, category, cart, checkout, cms, index (strona główna) lub dowolna nazwa kontrolera.

Zdarzenia JavaScript w PrestaShop

Twoje skrypty mogą nasłuchiwać zdarzeń PrestaShop poprzez globalny obiekt prestashop:

prestashop.on('updatedProduct', function(event) { /* combination changed */ });
prestashop.on('updateCart', function(event) { /* cart updated */ });

Dostępność jQuery

W motywie Classic jQuery jest ładowany globalnie. W Hummingbird jQuery 3.x jest nadal ładowany dla kompatybilności z modułami, ale sam motyw używa TypeScript. W nowym kodzie motywu potomnego preferuj czysty JS.

Nie usuwaj jQuery z motywu potomnego — zepsujesz moduły zewnętrzne, które na nim polegają. Ale we własnym kodzie czysty JS zapewnia lepszą wydajność i kompatybilność na przyszłość.

Nadpisywanie szablonów modułów

Możesz nadpisać sposób renderowania dowolnego modułu, umieszczając szablony w katalogu modules/ motywu.

Kolejność rozpoznawania

  1. Motyw potomny: themes/my-child/modules/module_name/views/templates/...
  2. Motyw nadrzędny: themes/parent/modules/module_name/views/templates/...
  3. Sam moduł: modules/module_name/views/templates/...

Jak nadpisać

Znajdź szablon modułu (np. modules/ps_featuredproducts/views/templates/hook/ps_featuredproducts.tpl), skopiuj go do odpowiedniej ścieżki w themes/my-child/modules/ i edytuj kopię. Moduł może się aktualizować bez wpływu na Twoją wersję.

Nadpisania w motywie mają absolutny priorytet. Jeśli moduł zaktualizuje swój szablon w celu naprawy luki bezpieczeństwa, a Twój motyw ma starszą kopię, stara wersja nadal będzie używana. Okresowo porównuj swoje nadpisania z aktualnymi wersjami modułów.

Tłumaczenia w motywach potomnych

Kolejność rozpoznawania tłumaczeń:

  1. Tłumaczenia z bazy danych (Back Office > International > Translations)
  2. Katalog translations/ motywu potomnego
  3. Katalog translations/ motywu nadrzędnego
  4. Tłumaczenia modułów
  5. Tłumaczenia jądra

Najprostsze podejście to Back Office (International > Translations). Aby tłumaczenia były kontrolowane wersją, utwórz pliki XLIFF w themes/my-child/translations/en-US/Shop/Theme/Global.xlf:

<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
  <file original="shop-theme-global" source-language="en-US"
        target-language="en-US" datatype="plaintext">
    <body>
      <trans-unit id="add_to_cart" approved="yes">
        <source>Add to cart</source>
        <target>Add to bag</target>
      </trans-unit>
    </body>
  </file>
</xliff>

W sklepach wielojęzycznych utwórz pliki dla każdego locale (translations/fr-FR/, translations/de-DE/). Wyczyść cache po zmianach: php bin/console cache:clear

Typowe dostosowania

Własny układ nagłówka

{extends file='parent:_partials/header.tpl'}

{block name='header_nav'}
  <nav class="custom-header-nav container">
    <div class="row align-items-center">
      <div class="col-md-3">{hook h='displayNav1'}</div>
      <div class="col-md-6 text-center">
        <a href="{$urls.base_url}"><img src="{$shop.logo}" alt="{$shop.name}"></a>
      </div>
      <div class="col-md-3 text-end">{hook h='displayNav2'}</div>
    </div>
  </nav>
{/block}

Własne czcionki

Umieść pliki WOFF2 w assets/fonts/ i odwołaj się do nich w CSS:

@font-face {
  font-family: 'CustomFont';
  src: url('../fonts/CustomFont-Regular.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}
body { font-family: 'CustomFont', system-ui, sans-serif; }
Zawsze używaj font-display: swap, aby zapobiec niewidocznemu tekstowi podczas ładowania. Wstępnie ładuj krytyczne czcionki: <link rel="preload" as="font" type="font/woff2" crossorigin>.

Zmiana układu strony produktu

{extends file='parent:catalog/product.tpl'}

{block name='product_description_short'}
  <div class="product__description-short">{$product.description_short nofilter}</div>
  {if $product.description}
    <div class="product__description-full mt-3">{$product.description nofilter}</div>
  {/if}
{/block}

{block name='product_description'}{/block} {* usunięty z kart *}

Zmiany w motywach PS 9

  • Hummingbird jest domyślny. Classic pozostaje dostępny, ale aktywny rozwój jest skierowany na Hummingbird.
  • Smarty pozostaje w front office. Twig służy tylko do panelu administracyjnego. Twoje nadpisania {extends} i {block} działają jak dotychczas.
  • Bootstrap 5.3 zastępuje Bootstrap 4. Zapoznaj się z przewodnikiem migracji, jeśli przechodzisz z Classic.
  • CSS Layers (@layer) zmieniają sposób działania specyficzności w Hummingbird.
  • WebP domyślnie dla obrazów. Nowy klucz framework w theme.yml: bootstrap-v5.3.3.
  • Niektóre stare zmienne globalne JS usunięte. Testuj dokładnie przy migracji z PS 8.

Twig może w przyszłości trafić do front office w kolejnej głównej wersji. Pisanie czystych szablonów z minimalnymi nadpisaniami ułatwi każdą przyszłą migrację.

Debugowanie problemów z motywem

Najpierw wyczyść wszystkie cache: php bin/console cache:clear. Na czas prac deweloperskich ustaw cache szablonów na “Force compilation” i wyłącz CCC w Advanced Parameters > Performance.

Podczas prac deweloperskich zawsze wymuszaj kompilację szablonów i wyłączaj CCC. Bez tego debugujesz pliki z cache.

Włącz debugowanie Smarty, dodając ?SMARTY_DEBUG do dowolnego adresu URL front office. Pokaże to załadowane szablony, ścieżki plików i zmienne. Włącz to w config/defines.inc.php, ustawiając _PS_SMARTY_FORCE_COMPILE_ i _PS_SMARTY_CONSOLE_ na 1.

Typowe błędy

ObjawPrawdopodobna przyczynaRozwiązanie
Biała stronaBłąd składni SmartySprawdź var/logs/
Szablon nie znalezionyZła ścieżka lub brak prefiksu parent:Upewnij się, że ścieżka odzwierciedla motyw nadrzędny
Nieskończona pętla / timeout{extends} bez prefiksu parent:Użyj {extends file='parent:...'}
Brak treści blokuNiezgodność nazwy blokuSprawdź dokładne nazwy w szablonie nadrzędnym
CSS nie działaProblem z cache lub specyficznościąWyczyść cache, sprawdź priorytet w DevTools
Podwójnie zakodowany HTMLAutomatyczne escapowanie już zakodowanej treściUżyj {$var nofilter}

Jeśli cache się utrzymuje, usuń również var/cache/prod/smarty/compile/ i var/cache/prod/smarty/cache/.

Aktualizacje z motywami potomnymi

To właśnie tutaj motywy potomne się spłacają. Gdy motyw nadrzędny się aktualizuje:

  • Pliki tylko w motywie nadrzędnym — aktualizowane normalnie, motyw potomny dziedziczy je automatycznie.
  • Pliki nadpisane w motywie potomnym — wersja potomna nadal jest używana, aktualizacja nadrzędna jest niewidoczna.
  • Pliki własne motywu potomnego — całkowicie niezagrożone.

Przed aktualizacją: zrób kopię zapasową, wypisz swoje nadpisania (find themes/my-child/templates -name "*.tpl"), zaktualizuj w środowisku testowym (poradnik lokalnego developmentu), porównaj zmienione szablony nadrzędne ze swoimi nadpisaniami za pomocą diff i przetestuj każdą dostosowaną stronę.

Precyzyjne nadpisania {extends} są lepsze niż pełne kopie plików. Przy nadpisywaniu bloków nowe bloki nadrzędne są automatycznie włączane. Pełne kopie plików całkowicie je pomijają.

Lista kontrolna przed uruchomieniem motywu potomnego

Konfiguracja: theme.yml ma poprawne parent: i name: (małe litery, bez spacji). use_parent_assets: true jest ustawione. preview.png istnieje. Zakres kompatybilności odpowiada Twojej wersji PS.

Szablony: Wszystkie nadpisania używają {extends file='parent:...'} tam, gdzie to możliwe. Nazwy bloków dokładnie odpowiadają motywowi nadrzędnemu. Brak błędów Smarty w var/logs/. Nadpisania szablonów modułów przetestowane z aktualnymi wersjami modułów. nofilter użyty dla zmiennych HTML.

Zasoby: Własny CSS ładuje się po nadrzędnym (wysoki priority). Brak nadmiernego użycia !important. Czcionki używają font-display: swap i WOFF2. Brak błędów JS w konsoli. CCC włączone bez żadnych problemów.

Testowanie: Desktop (Chrome, Firefox, Safari, Edge), mobile (iOS Safari, Android Chrome), breakpointy responsywne. Zweryfikuj: stronę główną, kategorie, produkt, koszyk, checkout, konto klienta, CMS, wyszukiwarkę, 404.

Utrzymanie: Motyw potomny w Git. Nadpisane szablony udokumentowane. Proces kompilacji udokumentowany (zobacz nasz poradnik narzędzi deweloperskich). Zespół wie, że nie należy edytować plików nadrzędnych.

Ładowanie...
Do góry