Rozwiązania typowych problemów technicznych: białe ekrany, błędy 500, konflikty modułów, problemy z cache i wydajnością.
Żadne pytanie nie pasuje do wyszukiwania.
Krok 1: Włącz tryb debugowania — edytuj /config/defines.inc.php i ustaw define('_PS_MODE_DEV_', true);. Odśwież stronę, aby zobaczyć właściwy błąd PHP. Krok 2: Jeśli nie możesz uzyskać dostępu do panelu administracyjnego, użyj FTP, aby zmienić nazwę folderu problematycznego modułu (np. zmień /modules/nazwamodulu/ na /modules/nazwamodulu_disabled/). Wyłączy to moduł bez potrzeby dostępu do panelu. Krok 3: Prześlij nam komunikat błędu, a naprawimy problem.
Learn more: our troubleshooting guide.
Edytuj plik /config/defines.inc.php w katalogu głównym PrestaShop. Znajdź linię define('_PS_MODE_DEV_', false); i zmień false na true. Zapisz plik i odśwież stronę. Zobaczysz teraz szczegółowe błędy PHP zamiast pustych stron lub ogólnych komunikatów o błędach. Pamiętaj, aby wyłączyć tryb debugowania po rozwiązaniu problemu — pozostawienie go włączonego na produkcji ujawnia wrażliwe informacje i spowalnia sklep.
Learn more: our troubleshooting guide.
Użyj narzędzi deweloperskich przeglądarki (F12 → karta Network), aby zidentyfikować, co jest wolne. Częste przyczyny: (1) Moduł ładujący ciężkie zewnętrzne skrypty (czcionki, analityka, widgety czatu). (2) Moduł wykonujący wolne zapytania do bazy — sprawdź pasek profilera Symfony w trybie debugowania. (3) Zbyt wiele modułów zarejestrowanych na tym samym hooku (np. displayHeader). (4) Wyłączony OPcache na serwerze. (5) Wyczerpane zasoby hostingu. Wyłączaj moduły jeden po drugim, aby znaleźć winowajcę.
Najczęstsze przyczyny: (1) Różne wersje PHP na środowisku testowym i produkcyjnym — sprawdź oba. (2) OPcache cachujący stary kod na produkcji — wyczyść OPcache po wdrożeniu (to bardzo częsta pułapka). (3) Różne uprawnienia do plików — moduły potrzebują prawa zapisu do własnych katalogów. (4) Różne wersje PrestaShop lub konfiguracje. (5) Inny moduł zainstalowany na produkcji, który powoduje konflikt. Porównaj wyjście phpinfo() z obu środowisk, aby znaleźć rozbieżności.
Learn more: our troubleshooting guide.
Błąd 500 oznacza, że coś się zawaliło po stronie serwera. Sprawdź w kolejności: (1) Log błędów PHP na serwerze — to najważniejsze źródło, zawiera właściwy błąd. Zapytaj hosting, gdzie się znajduje. (2) Log PrestaShop w /var/logs/. (3) Log błędów Apache/Nginx. (4) Włącz tryb debugowania, aby zobaczyć błąd w przeglądarce. Jeśli widzisz „500", ale nigdzie nie ma szczegółów błędu, prawdopodobnie chodzi o problem z .htaccess lub regułę mod_security blokującą żądanie.
Learn more: our troubleshooting guide.
Sprawdź następujące rzeczy: (1) Czy na stronie występują błędy JavaScript? Otwórz narzędzia deweloperskie przeglądarki → Konsola. Błędy JS mogą blokować wysyłanie formularza. (2) Czy token jest prawidłowy? PrestaShop używa tokenów bezpieczeństwa — spróbuj wyczyścić cache przeglądarki lub użyć innej przeglądarki. (3) Czy tabela konfiguracji modułu została prawidłowo utworzona? Niektóre moduły przechowują konfigurację w niestandardowych tabelach, które mogły nie zostać utworzone podczas instalacji. Skontaktuj się z nami, podając konkretny moduł, a zbadamy sprawę.
Learn more: contact our support team.
Całkowite wyłączenie cache znacząco spowolni sklep. Zamiast tego wyczyść cache prawidłowo: Zaawansowane parametry → Wydajność → Wyczyść cache. Jeśli problemy utrzymują się po wyczyszczeniu: ręcznie usuń zawartość /var/cache/prod/ i /var/cache/dev/. Dla cache Smarty: sprawdź, czy „Wymuś kompilację" jest ustawione na „Tak" (na produkcji powinno być „Nie"). Jeśli konkretny moduł zachowuje się nieprawidłowo z cache, zgłoś to deweloperowi modułu — to błąd, który powinien zostać naprawiony.
Jeśli strona jest całkowicie niedostępna: użyj FTP, aby zastąpić plik .htaccess. PrestaShop może go wygenerować ponownie: przejdź do Parametry sklepu → Ruch i SEO i kliknij „Generuj plik .htaccess". Jeśli nie możesz uzyskać dostępu do panelu: zmień nazwę uszkodzonego .htaccess na .htaccess_backup, utwórz minimalny plik .htaccess, uzyskaj dostęp do panelu administracyjnego i wygeneruj prawidłowy plik. Minimalny plik wymaga jedynie RewriteEngine On i RewriteBase / (dostosuj ścieżkę bazową w razie potrzeby).
Learn more: our troubleshooting guide.
To prawie zawsze problem z cachowaniem. Wyczyść w tej kolejności: (1) Cache PrestaShop: Zaawansowane parametry → Wydajność → Wyczyść cache. (2) Jeśli używasz CCC (Combine, Compress, Cache): wyłącz go, wyczyść cache, wprowadź zmiany, włącz CCC ponownie. (3) Cache przeglądarki: Ctrl+Shift+R dla twardego odświeżenia lub wyczyść cache przeglądarki całkowicie. (4) Jeśli Twój hosting używa Varnish, Cloudflare lub innego CDN: wyczyść także ten cache. (5) Jeśli używasz OPcache z validate_timestamps=0: zrestartuj PHP-FPM.
Learn more: PrestaShop performance and caching.
Sprawdź: (1) Czy faktycznie przetłumaczyłeś ciągi tekstowe? Przejdź do Międzynarodowe → Tłumaczenia → Tłumacz moduły, wybierz moduł i swój język i przetłumacz ciągi. (2) Cache Smarty może serwować starą wersję — wyczyść cache. (3) Niektóre moduły używają własnego systemu tłumaczeń zamiast systemu PrestaShop — sprawdź dokumentację modułu. (4) Jeśli moduł używa {l s='...' mod='nazwamodulu'} w szablonach, tłumaczenie musi znajdować się we własnym pliku tłumaczeń modułu, nie w globalnych tłumaczeniach PrestaShop.
Learn more: our troubleshooting guide.
Przejdź do Wygląd → Pozycje w panelu administracyjnym. Znajdź moduł na liście hooków i: (1) Zmień jego pozycję w ramach bieżącego hooka za pomocą przeciągnij i upuść. (2) Odepnij go z bieżącego hooka i przenieś do innego. Pamiętaj, że nie wszystkie hooki są dostępne we wszystkich szablonach — jeśli przeniesiesz moduł do hooka, którego Twój szablon nie wyświetla, nic się nie pojawi. Sprawdź dokumentację szablonu pod kątem obsługiwanych hooków.
Learn more: PrestaShop hooks guide.
Najczęstsza przyczyna: konieczność regeneracji miniaturek. Przejdź do Wygląd → Ustawienia obrazów i kliknij „Regeneruj miniatury". Sprawdź również: (1) Uprawnienia do plików w katalogu /img/ (powinien być zapisywalny). (2) Reguły rewrite w .htaccess dla obrazów mogą wymagać aktualizacji — wygeneruj ponownie .htaccess z ustawień SEO i URL. (3) Jeśli używasz CDN, zaktualizuj konfigurację CDN, aby wskazywała na nowy serwer.
Learn more: our troubleshooting guide.
Zazwyczaj jest to spowodowane przez: (1) Długotrwały proces importu lub aktualizacji. (2) Brakujące indeksy w bazie danych (częste po aktualizacjach PrestaShop). (3) Moduł wykonujący nieefektywne zapytania. Aby zdiagnozować: uruchom SHOW PROCESSLIST; w phpMyAdmin, aby zobaczyć aktywne zapytania. Zabij zablokowane zapytania. Dla zapobiegania: upewnij się, że MySQL/MariaDB jest prawidłowo skonfigurowana (innodb_buffer_pool_size powinno wynosić ~70% dostępnej pamięci RAM na dedykowanym serwerze). Skontaktuj się z hostingiem, jeśli nie masz dostępu do administracji MySQL.
See also: Cleanup Revolution — advanced database maintenance for PrestaShop
Przejdź do Zaawansowane parametry → E-mail i sprawdź ustawienia poczty. Jeśli używasz SMTP: zweryfikuj serwer, port, nazwę użytkownika i hasło. Kliknij „Wyślij testowy e-mail", aby sprawdzić. Częste problemy: (1) Hosting blokuje wychodzące połączenia SMTP (częste na hostingu współdzielonym). (2) Rekordy SPF/DKIM nie są skonfigurowane, co powoduje lądowanie e-maili w spamie. (3) Funkcja PHP mail() jest wyłączona na serwerze. Dla niezawodnej dostawy e-maili użyj zewnętrznej usługi SMTP, takiej jak Mailgun, SendGrid lub nawet Gmail SMTP.
Learn more: Support Revolution — complete helpdesk for PrestaShop
Częste przyczyny: (1) Zbyt wiele modułów z hookami back-office — każdy z nich dodaje obciążenie do każdej strony administracyjnej. (2) Tryb debugowania pozostawiony włączony — dodaje ogromny narzut. (3) Wolne zapytania MySQL — sprawdź profiler Symfony. (4) Duży katalog produktów z wieloma kombinacjami spowalniający listy. (5) Brak pamięci RAM na serwerze. Szybkie rozwiązania: wyłącz tryb debugowania, włącz OPcache i sprawdź, które moduły ładują się na każdej stronie administracyjnej przez Wygląd → Pozycje → displayBackOfficeHeader.
Learn more: PrestaShop performance guide.
Zazwyczaj oznacza to, że autoloader modułu nie działa. Przyczyny: (1) Katalog vendor/ wewnątrz modułu jest brakujący lub niekompletny — ponownie prześlij moduł z oryginalnego pliku ZIP. (2) Twoja wersja PHP jest zbyt stara dla przestrzeni nazw używanych w module. (3) OPcache serwuje cachowaną wersję starego kodu — wyczyść OPcache. (4) Uprawnienia plików uniemożliwiają PHP odczytanie plików klas. Spróbuj: usuń folder modułu, rozpakuj ponownie z ZIP i zainstaluj od nowa.
Learn more: our troubleshooting guide.
Spróbuj kolejno: (1) Wyczyść ciasteczka przeglądarki dla swojej domeny. (2) Spróbuj w innej przeglądarce lub w trybie prywatnym. (3) Usuń zawartość /var/cache/. (4) Sprawdź, czy PS_SHOP_DOMAIN odpowiada domenie, z której faktycznie korzystasz. (5) Jeśli używasz SSL, upewnij się, że PS_SSL_ENABLED jest poprawne. (6) Sprawdź .htaccess pod kątem nieprawidłowych reguł przekierowań. W ostateczności: wyłącz wszystkie overridy, ustawiając odpowiednie definicje _PS_CACHE_ENABLED_ i _PS_MODULES_DIR_, aby zdiagnozować problem.
Learn more: PrestaShop security guide.
Zdarza się to, gdy aktualizacja wprowadza zmiany, na które szablon nie jest przygotowany. Kroki: (1) Tymczasowo przełącz się na domyślny szablon (Classic lub Hummingbird), aby potwierdzić, że to problem szablonu. (2) Sprawdź, czy deweloper szablonu wydał aktualizację kompatybilną z nową wersją PrestaShop. (3) Jeśli używasz szablonu potomnego, sprawdź, które pliki szablonów wymagają aktualizacji. (4) Jeśli szablon nie jest już rozwijany, konieczna może być migracja na inny szablon — bolesny, ale czasem niezbędny proces. Nigdy nie aktualizuj PrestaShop bez wcześniejszego sprawdzenia kompatybilności szablonu.
Learn more: PrestaShop child themes guide.
Systematyczne podejście: (1) Wyłącz wszystkie moduły firm trzecich (nie wbudowane moduły PrestaShop). (2) Sprawdź, czy problem zniknął. (3) Włączaj moduły jeden po drugim, testując po każdym. (4) Gdy problem powróci, znalazłeś winowajcę. To żmudne, ale skuteczne. W przypadku problemów z wydajnością profiler Symfony (dostępny w trybie debugowania) pokazuje, które hooki i moduły wykonują się najdłużej.
Learn more: our troubleshooting guide.
Sprawdź: (1) Ścieżka pliku override jest prawidłowa. Dla nadpisań w szablonie: /themes/twoj-szablon/modules/nazwamodulu/views/templates/... musi dokładnie odzwierciedlać strukturę katalogów modułu. (2) Wyczyść cache Smarty — PrestaShop cachuje ścieżki plików szablonów. (3) Sprawdź, czy Twój szablon jest faktycznie aktywny (nie inny szablon). (4) Niektóre moduły nie obsługują nadpisań szablonów, jeśli używają bezpośrednich wywołań fetch() zamiast display() — sprawdź dokumentację modułu.
Learn more: PrestaShop hooks and overrides.
Duże importy napotykają limity czasu wykonania PHP. Rozwiązania: (1) Zwiększ max_execution_time w php.ini do 300 lub więcej. (2) Zwiększ memory_limit do 512M lub więcej. (3) Podziel CSV na mniejsze partie (1000–2000 produktów każda). (4) Uruchamiaj import w godzinach niskiego ruchu. (5) Dla bardzo dużych importów (50 000+ produktów) rozważ użycie skryptu importu CLI zamiast importu z panelu — nie podlega on limitom timeout serwera WWW.
Learn more: PrestaShop performance guide.
Katalogi /var/cache/ i /var/smarty/compile/ muszą być zapisywalne przez użytkownika serwera WWW. Po migracji właściciel plików często się zmienia. Napraw: chmod -R 775 var/cache var/smarty i chown -R www-data:www-data var/cache var/smarty (zamień www-data na użytkownika Twojego serwera WWW). Usuń również zawartość tych katalogów, aby wymusić czystą regenerację.
Learn more: our troubleshooting guide.
Zazwyczaj jest to spowodowane przez: (1) Wiele modułów e-mail aktywnych jednocześnie (np. wbudowany e-mail PrestaShop + niestandardowy moduł e-mail). (2) Moduł płatności, który uruchamia potwierdzenie zamówienia dwukrotnie z powodu webhooków + przekierowania potwierdzających płatność jednocześnie. (3) Klient klikający przycisk „Zapłać" dwa razy szybko. Sprawdź listę modułów pod kątem zduplikowanej funkcjonalności e-mailowej i sprawdź konfigurację webhooków w module płatności. Jeśli problem jest sporadyczny, prawdopodobnie chodzi o podwójne kliknięcie lub podwójny webhook.
Learn more: PrestaShop email deliverability guide.
Tłumaczenia modułów są specyficzne dla danego języka. Jeśli widzisz tekst angielski w panelu administracyjnym modułu, gdy Twój język administratora jest ustawiony na francuski, oznacza to, że tłumaczenie francuskie dla tego modułu nie jest zainstalowane lub jest niekompletne. Przejdź do Międzynarodowe → Tłumaczenia → Tłumacz moduły, wybierz moduł i swój język i przetłumacz brakujące ciągi. Niektóre moduły zawierają również pliki tłumaczeń, które należy zaimportować — sprawdź dokumentację modułu.
Learn more: our troubleshooting guide.
Problem: potrzebujesz modułu, ale nie jego zasobów na każdej stronie
Istnieje wiele sytuacji, w których chcesz zachować moduł PrestaShop zainstalowany i aktywny, ale zapobiec ładowaniu jego plików CSS lub JavaScript na konkretnych stronach, a nawet na wszystkich stronach. Być może masz moduł, którego funkcjonalność jest Ci potrzebna, ale którego stylizacja koliduje z Twoim szablonem. Być może moduł ładuje ciężką bibliotekę JavaScript, którą już dołączyłeś przez swój szablon. Być może chcesz zastąpić domyślne style modułu własnym niestandardowym CSS bez ingerencji oryginalnych stylów. Lub być może zidentyfikowałeś w audycie wydajności, że moduł ładuje zasoby na stronach, gdzie nie ma żadnego widocznego wyniku, i chcesz wyeliminować to marnotrawstwo.
Odinstalowanie modułu nie wchodzi w grę, ponieważ potrzebujesz jego podstawowej funkcjonalności: jego hooków, tabel bazy danych, konfiguracji, funkcji panelu administracyjnego. Musisz jedynie chirurgicznie usunąć konkretne pliki CSS lub JavaScript z wyjścia front office. PrestaShop zapewnia kilka mechanizmów do osiągnięcia tego celu, a ten artykuł omawia je wszystkie szczegółowo, od najprostszych po najbardziej zaawansowane.
Metoda 1: Używanie Theme.yml do usuwania zasobów modułu
Najprostszym i najłatwiejszym w utrzymaniu sposobem usunięcia CSS lub JavaScript modułu w PrestaShop 1.7 i nowszych jest plik konfiguracyjny szablonu, theme.yml. Ten plik, znajdujący się w katalogu głównym Twojego szablonu, kontroluje, które zasoby szablon ładuje i które zasoby modułów usuwa.
Otwórz swój plik theme.yml i poszukaj sekcji assets. Jeśli nie istnieje, możesz ją utworzyć. W sekcji assets możesz określić pliki CSS i JavaScript do usunięcia po ich identyfikatorze zasobu (asset ID). Każdy zasób zarejestrowany przez registerStylesheet lub registerJavascript ma identyfikator, który zazwyczaj składa się z nazwy modułu i opisowego sufiksu.
Aby znaleźć identyfikatory zasobów używane przez moduł, sprawdź kod źródłowy strony i poszukaj znaczników link arkuszy stylów oraz elementów skryptów. PrestaShop dodaje atrybut id do tych elementów w trybie debugowania, lub możesz znaleźć identyfikatory w kodzie źródłowym modułu, gdzie wywołuje registerStylesheet lub registerJavascript.
W pliku theme.yml dodaj sekcję pod assets, następnie css, następnie all. Dodaj wpis z identyfikatorem zasobu i ustaw go na false. Na przykład, jeśli moduł rejestruje arkusz stylów z identyfikatorem modulename-style, dodałbyś modulename-style z wartością false pod sekcją css all. Zrób to samo dla plików JavaScript pod sekcją js all.
Po modyfikacji theme.yml musisz wyczyścić pamięć podręczną PrestaShop z poziomu Zaawansowane parametry, Wydajność. Zmiany w theme.yml wchodzą w życie po przebudowaniu pamięci podręcznej. To podejście utrzymuje się mimo aktualizacji modułów, ponieważ usunięcie jest zdefiniowane w Twoim szablonie, nie w samym module. Jednak usuwa zasoby ze wszystkich stron. Jeśli potrzebujesz zasobów na niektórych stronach, ale nie na innych, będziesz potrzebować bardziej ukierunkowanego podejścia.
Metoda 2: Media::unregisterStylesheet i Media::unregisterJavascript
PrestaShop 1.7 wprowadził metody klasy Media — unregisterStylesheet i unregisterJavascript — które pozwalają programistycznie usuwać konkretne zasoby zarejestrowane przez inne moduły. Te metody są potężne, ponieważ możesz wywoływać je warunkowo, usuwając zasoby tylko na konkretnych stronach, zachowując je na innych.
Aby skorzystać z tego podejścia, potrzebujesz niestandardowego modułu lub modyfikacji istniejącego modułu. W metodzie hookActionFrontControllerSetMedia swojego modułu wywołaj Media::unregisterStylesheet z identyfikatorem zasobu pliku CSS, który chcesz usunąć. Podobnie wywołaj Media::unregisterJavascript z identyfikatorem zasobu pliku JavaScript. Możesz opakować te wywołania w logikę warunkową, aby usuwać zasoby tylko na konkretnych typach stron.
Na przykład, jeśli chcesz usunąć zasoby modułu slidera z każdej strony oprócz strony głównej, sprawdziłbyś, czy bieżący kontroler to IndexController. Jeśli to nie strona główna, wywołujesz metody unregister. Jeśli to strona główna, nie robisz nic i pozwalasz zasobom ładować się normalnie.
Kluczową kwestią w tym podejściu jest kolejność wykonywania hooków. Twoja metoda hookActionFrontControllerSetMedia musi wykonać się po module, którego zasoby chcesz usunąć. PrestaShop wykonuje callbacki hooków w kolejności rejestracji modułów na hooku, co możesz kontrolować przez stronę Wygląd, Pozycje w panelu administracyjnym. Przesuń swój niestandardowy moduł poniżej docelowego modułu na hooku actionFrontControllerSetMedia, aby zapewnić, że Twoje wywołania unregister następują po zarejestrowaniu zasobów przez docelowy moduł.
Jeśli problematyczny moduł używa starszych metod addCSS i addJS zamiast registerStylesheet i registerJavascript, metody unregister mogą nie zadziałać, ponieważ starsze metody nie korzystają z tego samego systemu zarządzania zasobami. W takim przypadku potrzebujesz innego podejścia.
Metoda 3: Niestandardowy moduł do blokowania konkretnych zasobów
Gdy potrzebujesz precyzyjnej kontroli nad tym, które zasoby ładują się na których stronach, stworzenie dedykowanego modułu zarządzania zasobami jest najbardziej elastycznym rozwiązaniem. Ten moduł działa jako centralne miejsce, w którym definiujesz reguły blokowania lub zezwalania na konkretne zasoby modułów.
Utwórz nowy moduł z metodą hookActionFrontControllerSetMedia. Wewnątrz tej metody zdefiniuj tablicę reguł zasobów. Każda reguła określa nazwę modułu, identyfikatory zasobów do zablokowania oraz warunki, w których je blokować. Warunki mogą być oparte na nazwie kontrolera, typie strony lub dowolnych innych kryteriach dostępnych w kontekście PrestaShop.
Twój moduł iteruje przez reguły przy każdym ładowaniu strony, sprawdza warunki i wywołuje Media::unregisterStylesheet lub Media::unregisterJavascript dla każdego zasobu, który powinien być zablokowany na bieżącej stronie. To scentralizowane podejście jest znacznie łatwiejsze w utrzymaniu niż rozpraszanie logiki usuwania zasobów po wielu modułach lub plikach szablonów.
Możesz ulepszyć ten moduł o stronę konfiguracji w panelu administracyjnym, która pozwala zarządzać regułami przez interfejs administratora PrestaShop zamiast edytować kod. Prosty formularz z polami na nazwę modułu, identyfikator zasobu i multiselect dla typów stron, na których zasób powinien być zablokowany, daje Ci przyjazny dla użytkownika sposób zarządzania ładowaniem zasobów bez dotykania kodu po początkowej konfiguracji.
To podejście działa zarówno z nowym systemem registerStylesheet, jak i ze starszym systemem addCSS, choć możesz potrzebować różnych technik dla każdego z nich. Dla zasobów zarejestrowanych nowym systemem użyj metod Media::unregister. Dla zasobów dodanych starszym systemem możesz bezpośrednio manipulować tablicami css_files i js_files kontrolera w metodzie hookActionFrontControllerSetMedia.
Metoda 4: Podejście z odpinaniem hooków
Bardziej agresywnym, ale czasami koniecznym podejściem jest całkowite odpięcie modułu od hooków, na których rejestruje swoje zasoby. Przejdź do Wygląd, następnie Pozycje w panelu administracyjnym. Znajdź moduł na hooku displayHeader lub actionFrontControllerSetMedia. Kliknij przycisk usunięcia lub odpięcia, aby usunąć moduł z tego hooka całkowicie.
To zapobiega ładowaniu jakichkolwiek zasobów przez moduł na jakiejkolwiek stronie. Inne hooki modułu, takie jak displayProductAdditionalInfo czy displayFooter, nadal działają normalnie. Jednak wyjście front office modułu może się zepsuć, jeśli zależy od swojego CSS do stylizacji lub JavaScript do interaktywnego zachowania.
To podejście jest najbardziej przydatne, gdy planujesz całkowicie zastąpić stylizację modułu własnym niestandardowym CSS. Odpinasz moduł od displayHeader, aby zapobiec ładowaniu jego CSS, a następnie piszesz własne style w niestandardowym pliku CSS szablonu, celując w elementy HTML modułu. To daje Ci pełną kontrolę nad wyglądem modułu bez żadnego konfliktu między oryginalnymi stylami a Twoimi modyfikacjami.
W przypadku JavaScript odpinanie jest bardziej ryzykowne. Jeśli moduł polega na swoim JavaScript do podstawowej funkcjonalności, takiej jak wywołania AJAX, walidacja formularzy lub dynamiczne ładowanie treści, usunięcie JavaScript zepsuje te funkcje. Odpinaj JavaScript tylko wtedy, gdy masz pewność, że wyjście front office modułu od niego nie zależy, lub jeśli zapewniasz zastępczą implementację przez swój szablon.
Ważne zastrzeżenie: jeśli zaktualizujesz moduł, proces aktualizacji może ponownie zarejestrować moduł na hookach, z których go usunąłeś. Po każdej aktualizacji modułu sprawdź Wygląd, Pozycje, aby potwierdzić, że Twoje odpięcie nadal obowiązuje. Niektóre moduły jawnie rejestrują swoje hooki podczas procesu aktualizacji, co nadpisuje Twoje ręczne odpięcie.
Metoda 5: Nadpisywanie zasobów modułu przez szablon
System szablonów PrestaShop pozwala nadpisywać pliki szablonów modułów, umieszczając je w katalogu modules Twojego szablonu. Choć jest to głównie używane do nadpisywania szablonów, możesz to również wykorzystać do pośredniej kontroli ładowania zasobów.
Jeśli moduł ładuje swoje zasoby przez pliki szablonów za pomocą funkcji Smarty, takich jak znaczniki skryptów lub arkuszy stylów bezpośrednio w plikach TPL, zamiast przez hooki PHP, możesz nadpisać te szablony w swoim szablonie i usunąć odniesienia do zasobów. Skopiuj plik szablonu modułu do katalogu modules swojego szablonu, zachowując tę samą strukturę katalogów, i edytuj kopię, aby usunąć niechciane odniesienia do CSS lub JavaScript.
To podejście jest specyficzne dla szablonu, co oznacza, że wpływa tylko na bieżący szablon. Jeśli zmienisz szablon, nadpisania nie zostaną przeniesione. Wymaga również utrzymania: gdy moduł aktualizuje swoje szablony, musisz zaktualizować swoje nadpisania, aby dopasować wszelkie zmiany strukturalne, zachowując jednocześnie swoje modyfikacje usuwania zasobów.
Dla modułów ładujących zasoby przez hooki PHP, a nie szablony, nadpisania szablonów nie pomagają w blokowaniu zasobów. W takim przypadku użyj jednej z innych metod opisanych w tym artykule.
PrestaShop 1.7 vs 8.x: różnice w podejściu
PrestaShop 8.x udoskonalił system zarządzania zasobami wprowadzony w wersji 1.7, ale fundamentalne podejścia pozostają takie same. Główne różnice dotyczą wewnętrznej implementacji i kilku dodatkowych funkcji.
W PrestaShop 1.7 system zarządzania zasobami wykorzystuje registerStylesheet i registerJavascript z systemem priorytetów. Metody Media::unregisterStylesheet i Media::unregisterJavascript działają niezawodnie dla zasobów zarejestrowanych przez ten system. Jednak moduły, które nadal używają starszych metod addCSS i addJS (które są przestarzałe, ale wciąż funkcjonalne), nie przechodzą przez nowy system zarządzania zasobami, co utrudnia ich czyste usunięcie.
PrestaShop 8.x poprawił wsteczną kompatybilność, dzięki czemu nawet zasoby dodane starszymi metodami są przetwarzane przez nowy potok zasobów. Oznacza to, że metody Media::unregister działają bardziej spójnie we wszystkich modułach, niezależnie od użytej metody rejestracji. Jeśli korzystasz z PrestaShop 8.x, podejście z unregister jest najbardziej niezawodną metodą dla wszystkich modułów.
PrestaShop 8.x wprowadził również lepsze unieważnianie pamięci podręcznej zasobów (cache-busting), co oznacza, że gdy usuwasz lub modyfikujesz zasoby, zmiany wchodzą w życie natychmiast po wyczyszczeniu pamięci podręcznej, bez klientów widzących przestarzałe wersje z cache. W PrestaShop 1.7 czasami trzeba było wyczyścić zarówno pamięć podręczną PrestaShop, jak i pamięć podręczną przeglądarki, lub poczekać na ponowne wygenerowanie połączonych plików przez system Combine, Compress, Cache (CCC).
Obie wersje obsługują podejście z theme.yml do usuwania zasobów, a składnia jest identyczna. Jeśli piszesz niestandardowy moduł do zarządzania zasobami, ten sam kod działa zarówno na 1.7, jak i 8.x z minimalnymi różnicami.
Pomiar zysków wydajności po wyłączeniu zasobów
Po wyłączeniu zasobów modułu powinieneś zmierzyć poprawę wydajności, aby potwierdzić, że Twoje zmiany przyniosły oczekiwany efekt. Użyj kombinacji narzędzi do kompleksowego pomiaru.
Zacznij od zakładki Sieć (Network) w Chrome DevTools. Porównaj łączną liczbę żądań i łączny przesłany rozmiar przed i po zmianach. Filtruj po CSS i JS, aby zobaczyć konkretną redukcję w liczbie i rozmiarach plików arkuszy stylów i JavaScript. Znacząca optymalizacja powinna wykazać wyraźną redukcję zarówno liczby żądań, jak i łącznego rozmiaru.
Uruchom audyt wydajności Lighthouse przed i po zmianach. Skup się na metrykach najbardziej dotkniętych przez ładowanie CSS i JavaScript: First Contentful Paint jest wpływany przez CSS blokujący renderowanie, Largest Contentful Paint jest wpływany przez ogólne ładowanie zasobów, a Total Blocking Time jest wpływany przez parsowanie i wykonywanie JavaScript. Zapisz te metryki z co najmniej trzech uruchomień i porównaj średnie.
Użyj zakładki Coverage w Chrome DevTools do mierzenia wykorzystania CSS i JavaScript. Otwórz zakładkę Coverage z menu trzech kropek pod Więcej narzędzi, następnie przeładuj stronę. Zakładka Coverage pokazuje, ile z każdego pliku CSS i JavaScript jest faktycznie używane na bieżącej stronie. Pliki z wysokim procentem nieużywanego kodu (pokazane na czerwono) są kandydatami do usunięcia lub warunkowego ładowania. Po wyłączeniu zasobów modułu pozostałe pliki powinny wykazywać wyższe procenty wykorzystania, co wskazuje, że pomyślnie usunąłeś marnotrawstwo.
Rozważ również metryki z rzeczywistego ruchu z Twojej platformy analitycznej. Jeśli korzystasz z Google Analytics lub podobnego narzędzia, porównaj czasy ładowania stron za tydzień przed i po optymalizacji. Dane z rzeczywistego ruchu od prawdziwych odwiedzających na różnych urządzeniach i w różnych warunkach sieciowych dają Ci najbardziej dokładny obraz poprawy wydajności.
Ryzyka i kwestie kompatybilności
Wyłączanie zasobów modułu niesie ze sobą ryzyka, które musisz zrozumieć i zarządzać. Najczęstszym ryzykiem jest psucie się wyglądu wizualnego. Gdy usuniesz CSS modułu, jego elementy HTML tracą stylizację i mogą wyświetlać się nieprawidłowo. Może to obejmować drobne problemy kosmetyczne, takie jak złe kolory lub odstępy, po poważne problemy z układem, takie jak nakładające się elementy lub niewidoczna treść.
Usuwanie JavaScript niesie wyższe ryzyko. Nowoczesne moduły często polegają na swoim JavaScript do podstawowej funkcjonalności. Usunięcie JavaScript może spowodować, że funkcje przestaną działać całkowicie: przyciski niereagrujące na kliknięcia, formularze niewykonujące wysyłki, popupy nieotwierające się, treść AJAX nieładująca się. Zawsze testuj każdą funkcję modułu po usunięciu jego JavaScript.
Istnieje również ryzyko kompatybilności z aktualizacjami modułu. Gdy moduł jest aktualizowany, deweloper może dodać nowe pliki CSS lub JavaScript z innymi identyfikatorami zasobów. Twoje reguły usuwania, czy to w theme.yml, czy w niestandardowym module, mogą nie przechwycić nowych zasobów, ponieważ celują w stare identyfikatory. Po każdej aktualizacji modułu zweryfikuj, że Twoje blokowanie zasobów nadal działa poprawnie i w razie potrzeby zaktualizuj reguły.
Niektóre moduły wykonują detekcję funkcji w swoim JavaScript i zachowują się inaczej, gdy ich CSS nie jest załadowany. Moduł może sprawdzać istnienie konkretnych klas CSS lub obliczonych stylów przed inicjalizacją swojej funkcjonalności JavaScript. Usunięcie CSS w tym przypadku nie tylko zmienia wygląd, ale również psuje zachowanie JavaScript zależne od tych stanów zdefiniowanych przez CSS.
Na koniec zwróć uwagę na zależności między modułami. Moduł A może ładować bibliotekę JavaScript, taką jak plugin lightbox, którą Moduł B również używa, ale nie ładuje samodzielnie, ponieważ zakłada, że Moduł A ją zapewnia. Usunięcie plików JavaScript Modułu A zepsułoby oba moduły w tym scenariuszu. Sprawdź współdzielone zależności przed usunięciem jakichkolwiek zasobów.
Praktyczny przebieg bezpiecznego usuwania zasobów
Postępuj zgodnie z tym przebiegiem, aby bezpiecznie wyłączyć zasoby modułu bez psucia sklepu. Po pierwsze, udokumentuj swój aktualny stan. Zrób zrzuty ekranu każdego typu strony, na którym moduł wyświetla treść. Zapisz wyniki Lighthouse i statystyki z zakładki Sieć. To daje Ci punkt odniesienia do porównania i referencję tego, jak moduł powinien wyglądać i funkcjonować.
Po drugie, zidentyfikuj konkretne zasoby, które chcesz usunąć. Użyj DevTools do znalezienia dokładnych nazw plików i identyfikatorów zasobów. Określ, które strony potrzebują zasobów, a które nie.
Po trzecie, wdróż usunięcie używając najbardziej odpowiedniej metody z tego artykułu. Dla prostego globalnego usunięcia użyj theme.yml. Dla warunkowego usunięcia opartego na typie strony utwórz niestandardowy moduł z wywołaniami Media::unregister. Dla pełnej wymiany zasobów odpnij moduł i dostarcz własne style.
Po czwarte, testuj dokładnie. Sprawdź każdy typ strony, na którym moduł powinien wyświetlać treść. Zweryfikuj, że wygląd wizualny modułu jest prawidłowy i wszystkie interaktywne funkcje działają. Sprawdź strony, na których usunąłeś zasoby, aby potwierdzić, że nie są już ładowane. Testuj na wielu przeglądarkach i urządzeniach.
Po piąte, zmierz poprawę wydajności. Uruchom audyty Lighthouse i porównaj z bazowym pomiarem. Sprawdź zakładkę Sieć pod kątem zmniejszonej liczby żądań i rozmiarów. Jeśli poprawa jest znacząca, Twoja optymalizacja była udana. Jeśli poprawa jest minimalna, usunięte zasoby mogły nie być głównym wąskim gardłem wydajności i powinieneś zbadać inne możliwości optymalizacji.
Po szóste, udokumentuj swoje zmiany. Zapisz, które zasoby usunąłeś, jakiej metody użyłeś i które strony są dotknięte. Ta dokumentacja jest niezbędna do rozwiązywania przyszłych problemów, szczególnie po aktualizacjach modułów, oraz do przekazywania wiedzy, jeśli ktoś inny będzie utrzymywał sklep.
Stosując to systematyczne podejście, możesz bezpiecznie zmniejszyć wagę stron swojego sklepu i poprawić czasy ładowania bez poświęcania funkcjonalności modułów, na których Twój sklep polega. Kluczem jest zawsze testowanie i pomiar: nigdy nie zakładaj, że usunięcie zasobu jest bezpieczne, i zawsze weryfikuj wyniki konkretnymi danymi.
Zrozumienie PHP memory_limit
Dyrektywa memory_limit w PHP kontroluje, ile pamięci RAM może zużyć pojedynczy proces PHP, zanim silnik zakończy go błędem krytycznym. Gdy widzisz komunikat \"Allowed memory size of X bytes exhausted\" w PrestaShop, oznacza to, że konkretne żądanie PHP próbowało zużyć więcej pamięci, niż pozwala skonfigurowany limit.
Każde załadowanie strony w PrestaShop uruchamia kod PHP, który ładuje framework, łączy się z bazą danych, przetwarza dane, renderuje szablony i wysyła HTML do przeglądarki. Każdy z tych kroków zużywa pamięć. memory_limit działa jako siatka bezpieczeństwa: zapobiega sytuacji, w której jeden wymykający się spod kontroli proces pochłonie całą dostępną pamięć RAM serwera, co spowodowałoby awarię innych procesów i potencjalnie wyłączenie całego serwera.
Domyślna wartość memory_limit w PHP to zazwyczaj 128M (128 megabajtów). PrestaShop oficjalnie zaleca co najmniej 256M, a wiele sklepów wymaga 512M lub więcej w zależności od rozmiaru katalogu, zainstalowanych modułów i ruchu. Zrozumienie, co napędza zużycie pamięci, pomaga określić właściwą wartość dla Twojego sklepu, zamiast ślepo zwiększać limit.
Jak sprawdzić aktualny limit pamięci
Istnieje kilka sposobów na weryfikację, jaki limit pamięci aktualnie używa Twoja instalacja PrestaShop.
Z poziomu panelu administracyjnego PrestaShop
Przejdź do Zaawansowane > Informacje. Ta strona wyświetla konfigurację PHP Twojego serwera, w tym aktualną wartość memory_limit. PrestaShop pokaże również ostrzeżenia, jeśli wartość jest poniżej zalecanego minimum.
Używając phpinfo()
Utwórz tymczasowy plik o nazwie info.php w głównym katalogu PrestaShop z następującą zawartością:
<?php phpinfo(); ?>Przejdź do niego przez przeglądarkę pod adresem twojadomena.com/info.php. Wyszukaj na stronie „memory_limit", aby zobaczyć zarówno Local Value (co jest faktycznie aktywne), jak i Master Value (co jest ustawione w php.ini). Wartość lokalna może różnić się od wartości głównej, jeśli .htaccess, .user.ini lub sama aplikacja ją nadpisuje.
Ważne: Usuń ten plik natychmiast po sprawdzeniu. Strona phpinfo() ujawnia szczegółową konfigurację serwera, którą atakujący mogą wykorzystać.
Przez wiersz poleceń
Jeśli masz dostęp SSH, uruchom:
php -i | grep memory_limitPamiętaj, że konfiguracja PHP w trybie CLI może różnić się od konfiguracji serwera WWW. Aby sprawdzić wartość widoczną po stronie serwera WWW, użyj metody phpinfo() lub panelu administracyjnego PrestaShop.
Typowe przyczyny błędów limitu pamięci
Duże importy produktów
Importowanie produktów przez CSV jest jedną z najbardziej wymagających pamięciowo operacji w PrestaShop. Każdy wiersz w pliku importu jest ładowany do pamięci, przetwarzany, walidowany i wstawiany do bazy danych. Plik CSV z 10 000 produktów, każdy z wieloma kombinacjami, zdjęciami i opisami, może łatwo wymagać 512 MB lub więcej pamięci.
Narzędzie importu PrestaShop przetwarza produkty partiami, ale rozmiar partii i ilość danych na produkt determinują całkowite zużycie pamięci. Duże pola tekstowe (opisy z HTML), wiele kolumn i pliki zakodowane w UTF-8 ze znakami specjalnymi zwiększają zużycie pamięci na wiersz.
Aby zmniejszyć zużycie pamięci podczas importów:
- Podziel duże pliki CSV na mniejsze porcje (1000-2000 wierszy każda)
- Importuj produkty bez zdjęć najpierw, a następnie importuj zdjęcia osobno
- Wyłącz nieistotne moduły podczas importu (statystyki, indeksowanie wyszukiwania)
- Użyj importu z wiersza poleceń, jeśli jest dostępny, co pozwala uniknąć limitów czasu serwera WWW
Produkty z wieloma kombinacjami
Produkty z wieloma atrybutami (rozmiar, kolor, materiał) generują kombinacje wykładniczo. Produkt z 5 rozmiarami, 10 kolorami i 3 materiałami tworzy 150 kombinacji. Każda kombinacja to osobny rekord w bazie danych z własną ceną, referencją, stanem magazynowym i powiązaniami ze zdjęciami. Gdy PrestaShop ładuje stronę produktu do edycji w back office, ładuje wszystkie kombinacje do pamięci naraz.
Produkty z ponad 500 kombinacjami to znany problem. Przy ponad 1000 kombinacji prawie na pewno przekroczysz limity pamięci przy domyślnej konfiguracji. Rozwiązania obejmują:
- Zwiększenie
memory_limitdo 512M lub 1G dla back office - Restrukturyzację produktów w celu zmniejszenia liczby kombinacji (oddzielne produkty zamiast mega-kombinacji)
- Używanie modułów, które obsługują kombinacje wydajniej poprzez paginację
Rozdęte lub źle napisane moduły
Moduły zewnętrzne (third-party) są częstym źródłem problemów z pamięcią. Typowe problemy to:
- Ładowanie całych tabel bazy danych do tablic PHP: Moduł, który uruchamia
SELECT * FROM ps_ordersbez klauzuli LIMIT, ładuje każde kiedykolwiek złożone zamówienie do pamięci. Dla sklepu ze 100 000 zamówień może to pochłonąć setki megabajtów. - Wycieki pamięci w pętlach: Moduły, które przetwarzają elementy w pętli, ale akumulują obiekty bez ich zwalniania. Garbage collector PHP radzi sobie z prostymi przypadkami, ale cykliczne referencje i przechowywane referencje mogą uniemożliwić oczyszczanie.
- Nadmierne logowanie: Logowanie debugowe, które zapisuje duże tablice lub obiekty do plików logów, używając
var_export()lubprint_r()na złożonych obiektach PrestaShop, może pochłaniać ogromne ilości pamięci. - Niezoptymalizowane przetwarzanie obrazów: Moduły, które zmieniają rozmiar lub dodają znaki wodne na obrazach za pomocą GD lub ImageMagick, ładują cały nieskompresowany obraz do pamięci. Obraz 5000x5000 pikseli przy 24-bitowej głębi koloru wymaga około 75 MB RAM-u tylko na dane pikseli.
Aby zidentyfikować, który moduł powoduje problemy z pamięcią, uważnie przeczytaj komunikat o błędzie. Zazwyczaj zawiera ścieżkę do pliku wskazującą na odpowiedzialny moduł. Możesz również włączyć tryb debugowania PrestaShop, aby uzyskać bardziej szczegółowe ślady stosu (stack traces).
Duże katalogi i złożone zapytania
Sklepy z dziesiątkami tysięcy produktów, wieloma kategoriami i złożonymi strukturami atrybutów wywierają większą presję na pamięć podczas normalnej pracy. Strony kategorii z nawigacją warstwową (wyszukiwanie fasetowe) są szczególnie wymagające, ponieważ silnik filtrów musi obliczać dostępne wartości atrybutów wśród tysięcy produktów.
Strony z listą produktów, zamówień i klientów w back office ładują dane do pamięci w celu wyświetlenia. Przy bardzo dużych zbiorach danych nawet podstawowy widok listy może przekroczyć limity pamięci, szczególnie gdy moduły dodają dodatkowe kolumny lub obliczenia do tych list.
Kompilacja szablonów Smarty
PrestaShop używa silnika szablonów Smarty, który kompiluje szablony do plików PHP dla szybszego renderowania. Sam proces kompilacji zużywa pamięć, a złożone szablony z wieloma dołączeniami (includes), pętlami i blokami warunkowymi wymagają więcej pamięci do kompilacji. Po pierwszej kompilacji używane są wersje z cache, więc jest to głównie problem przy czyszczeniu cache lub podczas programowania.
Jak zwiększyć limit pamięci
Metoda 1: php.ini
Najbardziej niezawodną metodą jest bezpośrednia edycja pliku konfiguracyjnego PHP. Lokalizacja zależy od konfiguracji:
- Debian/Ubuntu:
/etc/php/8.x/fpm/php.ini(PHP-FPM) lub/etc/php/8.x/apache2/php.ini(mod_php) - CentOS/RHEL:
/etc/php.inilub/etc/php.d/ - cPanel: MultiPHP INI Editor w WHM lub cPanelu
Znajdź linię memory_limit i zmień ją:
memory_limit = 512MPo zapisaniu zrestartuj PHP-FPM lub Apache:
# PHP-FPM\nsudo systemctl restart php8.2-fpm\n\n# Apache z mod_php\nsudo systemctl restart apache2Metoda 2: .htaccess (tylko Apache z mod_php)
Dodaj tę linię do pliku .htaccess w głównym katalogu PrestaShop:
php_value memory_limit 512MTa metoda działa tylko z Apache używającym mod_php. Jeśli korzystasz z PHP-FPM (co jest częstsze w nowoczesnych konfiguracjach), ta dyrektywa jest cicho ignorowana lub może spowodować błąd 500. Aby sprawdzić, którego handlera PHP używasz, zobacz linię Server API w wynikach phpinfo().
Metoda 3: .user.ini (PHP-FPM)
Utwórz lub edytuj plik o nazwie .user.ini w głównym katalogu PrestaShop:
memory_limit = 512MPHP-FPM odczytuje pliki .user.ini z katalogu dokumentów (document root). Pamiętaj, że zmiany wchodzą w życie po upływie okresu user_ini.cache_ttl (domyślnie 300 sekund / 5 minut), więc może być konieczne poczekanie lub restart PHP-FPM, aby zmiana zadziałała natychmiast.
Metoda 4: W kodzie PrestaShop
PrestaShop ustawia własny limit pamięci w pliku config/defines.inc.php. Szukaj linii w stylu:
@ini_set('memory_limit', '256M');Możesz zwiększyć tę wartość bezpośrednio w kodzie. Jednak to podejście ma ograniczenie: funkcja ini_set() może jedynie zwiększyć limit pamięci do wartości ustawionej w php.ini. Jeśli php.ini ustawia memory_limit = 128M, a Twój kod próbuje ustawić 512M, rzeczywisty limit pozostanie 128M (chyba że wartość główna pozwala na nadpisywanie, co zależy od klasyfikacji PHP_INI_ALL vs PHP_INI_SYSTEM).
Metoda 5: Konfiguracja per pula (PHP-FPM)
Jeśli zarządzasz własnym serwerem, możesz ustawić limity pamięci per pula PHP-FPM. Edytuj plik konfiguracyjny puli (np. /etc/php/8.2/fpm/pool.d/www.conf) i dodaj:
php_admin_value[memory_limit] = 512MUżycie php_admin_value sprawia, że to ustawienie jest niezmienne — nie może być nadpisane przez .user.ini ani ini_set(). Jest to przydatne do wymuszania limitów w środowiskach wielodostępowych (multi-tenant).
Pamięć per proces vs pamięć współdzielona
Ważne jest, aby zrozumieć, że memory_limit dotyczy każdego indywidualnego procesu PHP, a nie PHP jako całości. Jeśli ustawisz memory_limit = 512M, a Twój serwer uruchomi 20 współbieżnych procesów PHP, teoretyczne maksymalne zużycie pamięci przez PHP to 10 GB (20 x 512 MB).
Dlatego ślepe zwiększanie limitu pamięci może powodować problemy. Na serwerze z 4 GB RAM, ustawienie memory_limit = 1G przy 10 workerach PHP-FPM oznacza, że sam PHP mógłby próbować użyć 10 GB, powodując intensywne korzystanie ze swap lub uruchomienie Linux OOM killera, który siłowo kończy procesy, aby zwolnić pamięć.
Prawidłowe podejście to zrównoważenie limitu pamięci z liczbą workerów PHP:
- Dostępna RAM dla PHP = Całkowita RAM - narzut systemu operacyjnego - pamięć MySQL - pamięć serwera WWW - inne usługi
- Maks. workerów PHP = Dostępna RAM dla PHP / memory_limit
Na przykład na VPS z 4 GB: 4 GB łącznie - 0,5 GB OS - 1 GB MySQL - 0,25 GB Nginx = 2,25 GB dla PHP. Przy memory_limit = 256M możesz bezpiecznie uruchomić 8-9 workerów PHP-FPM. Przy memory_limit = 512M możesz uruchomić tylko 4 workery, co oznacza, że mniej współbieżnych żądań może być obsłużonych.
Skonfiguruj pulę PHP-FPM odpowiednio:
pm = dynamic\npm.max_children = 8\npm.start_servers = 3\npm.min_spare_servers = 2\npm.max_spare_servers = 5Diagnostyka wycieków pamięci i nadmiernego zużycia
Jeśli zwiększenie limitu pamięci jedynie opóźnia błąd zamiast go naprawiać, prawdopodobnie masz wyciek pamięci lub nieefektywny proces. Oto jak zdiagnozować przyczynę źródłową.
Włącz tryb debugowania PrestaShop
Edytuj config/defines.inc.php i ustaw:
define('_PS_MODE_DEV_', true);To włącza szczegółowe raportowanie błędów, w tym dokładny plik i numer linii, w której limit pamięci został przekroczony. Ślad stosu (stack trace) pokazuje łańcuch wywołań funkcji, które doprowadziły do błędu, pomagając zidentyfikować odpowiedzialny moduł lub funkcję rdzenia.
Monitoruj zużycie pamięci w kodzie
Możesz dodać monitorowanie pamięci do konkretnych sekcji kodu, aby precyzyjnie zlokalizować, gdzie występują skoki pamięci:
error_log('Pamięć przed operacją: ' . memory_get_usage(true) / 1024 / 1024 . ' MB');\n// ... operacja ...\nerror_log('Pamięć po operacji: ' . memory_get_usage(true) / 1024 / 1024 . ' MB');\nerror_log('Szczytowe zużycie pamięci: ' . memory_get_peak_usage(true) / 1024 / 1024 . ' MB');Funkcja memory_get_usage(true) zwraca faktyczną ilość pamięci przydzielonej PHP przez system operacyjny, natomiast memory_get_peak_usage(true) zwraca maksymalną ilość przydzieloną w dowolnym momencie podczas żądania.
Użyj profilowania Xdebug
Profiler Xdebug generuje szczegółowe raporty wywołań funkcji, czasu wykonania i zużycia pamięci. Włącz go tymczasowo w konfiguracji PHP:
xdebug.mode = profile\nxdebug.output_dir = /tmp/xdebugOtwórz wygenerowane pliki cachegrind w narzędziu takim jak KCacheGrind lub Webgrind, aby zwizualizować, które funkcje zużywają najwięcej pamięci. Jest to najbardziej dokładne podejście diagnostyczne, ale powinno być używane tylko na serwerach deweloperskich ze względu na znaczny narzut wydajnościowy.
Sprawdź wolne zapytania i MySQL
Czasami to, co wygląda na problem z pamięcią PHP, jest w rzeczywistości problemem MySQL. Wolne zapytanie, które zwraca miliony wierszy, spowoduje przydzielenie pamięci przez PHP na cały zbiór wyników. Sprawdź log wolnych zapytań MySQL:
sudo tail -100 /var/log/mysql/slow-query.logJeśli widzisz zapytania z dużymi zbiorami wyników, dodaj odpowiednie klauzule LIMIT lub zaimplementuj paginację w odpowiedzialnym module.
Pamięć OPcache
OPcache to rozszerzenie PHP, które cachuje skompilowany bajtkod PHP we współdzielonej pamięci, eliminując potrzebę parsowania i kompilowania plików PHP przy każdym żądaniu. OPcache ma własną alokację pamięci, oddzielną od memory_limit.
Domyślna pamięć OPcache (opcache.memory_consumption) wynosi 128 MB. PrestaShop z kilkoma zainstalowanymi modułami może łatwo przekroczyć tę wartość. Gdy OPcache wyczerpie pamięć, zaczyna usuwać zapisane wpisy i rekompilować pliki przy każdym żądaniu, powodując znaczącą degradację wydajności.
Sprawdź status OPcache z wiersza poleceń:
php -r \"print_r(opcache_get_status());\"Lub sprawdź sekcję opcache w wynikach phpinfo(). Kluczowe wartości do monitorowania:
- opcache.memory_consumption: Całkowita pamięć przydzielona dla OPcache (zwiększ do 256M dla PrestaShop)
- opcache.max_accelerated_files: Maksymalna liczba plików, które OPcache może cachować (zwiększ do 20000 dla PrestaShop)
- Użyta pamięć vs Wolna pamięć: Jeśli wolna pamięć jest bliska zeru, zwiększ
memory_consumption - Współczynnik trafień cache (cache hit rate): Powinien być powyżej 99%. Poniżej 95% wskazuje na presję pamięciową lub częste unieważnianie cache
Zalecana konfiguracja OPcache dla PrestaShop:
opcache.enable = 1\nopcache.memory_consumption = 256\nopcache.max_accelerated_files = 20000\nopcache.validate_timestamps = 1\nopcache.revalidate_freq = 0\nopcache.interned_strings_buffer = 16Pamiętaj, że pamięć OPcache jest współdzielona między wszystkimi procesami PHP, w przeciwieństwie do memory_limit, który jest per-procesowy. Zwiększenie pamięci OPcache nie mnoży się przez liczbę workerów.
Konfiguracja pamięci MySQL
MySQL ma własną konfigurację pamięci, która pośrednio wpływa na wydajność PrestaShop i może przyczyniać się do ogólnej presji pamięciowej serwera. Kluczowe ustawienia pamięci MySQL obejmują:
- innodb_buffer_pool_size: Główny bufor pamięci dla tabel InnoDB. Ustaw na 50-70% dostępnej RAM na dedykowanym serwerze bazy danych lub 25-50% na serwerze współdzielonym, na którym działają zarówno PHP, jak i MySQL. To najważniejsze ustawienie wydajności MySQL.
- sort_buffer_size i join_buffer_size: Bufory per połączenie do sortowania i łączenia. Zachowaj domyślne wartości, chyba że masz konkretne wolne zapytania, które korzystają z większych buforów. Ustawienie ich zbyt wysoko marnuje pamięć, ponieważ są alokowane per połączenie.
- query_cache_size: Przestarzały w MySQL 8.0 i całkowicie usunięty. Jeśli nadal używasz MySQL 5.7, mały cache zapytań (64M) może pomóc, ale duże cache zapytań powodują rywalizację o zasoby i obniżają wydajność.
Jeśli MySQL zużywa zbyt dużo pamięci, pozostawia mniej dla PHP, potencjalnie zmuszając do zmniejszenia liczby workerów PHP-FPM lub limitu pamięci. Użyj mysqladmin status lub SHOW GLOBAL STATUS do monitorowania zużycia pamięci przez MySQL.
Kiedy zaktualizować hosting
Czasami zwiększenie limitu pamięci i optymalizacja kodu nie wystarczą. Oto oznaki, że potrzebujesz mocniejszego serwera:
- Stale działasz na maksymalnym limicie pamięci: Jeśli Twoje procesy regularnie używają 90%+ przydzielonej pamięci, nawet po optymalizacji, potrzebujesz więcej RAM.
- Serwer intensywnie korzysta ze swap: Sprawdź poleceniem
free -hlubvmstat 1. Jeśli użycie swap jest konsekwentnie wysokie, nie masz wystarczająco dużo fizycznego RAM-u. - Zmniejszenie workerów PHP szkodzi wydajności: Jeśli musiałeś zmniejszyć liczbę workerów PHP-FPM do 3-4, aby zmieścić się w limicie pamięci, Twoja strona nie może efektywnie obsługiwać współbieżnych odwiedzających.
- Twój katalog stale rośnie: Sklep, który działał dobrze z 1000 produktów, może mieć problemy z 10 000. Zapotrzebowanie na pamięć rośnie wraz z rozmiarem katalogu, szczególnie przy indeksowaniu wyszukiwania, listowaniu kategorii i operacjach w back office.
- Potrzebujesz memory_limit powyżej 1G: Jeśli pojedynczy proces PHP potrzebuje więcej niż 1 GB pamięci do normalnych operacji (nie importów), coś jest fundamentalnie nie tak z Twoim kodem lub wydajnością hostingu. Zbadaj przyczynę źródłową przed dalszym zwiększaniem limitu.
Przy aktualizacji priorytetyzuj więcej RAM-u nad większą liczbę rdzeni CPU dla PrestaShop. Serwer z 8 GB RAM i 2 rdzeniami będzie lepiej obsługiwał PrestaShop niż serwer z 4 GB RAM i 4 rdzeniami. Rozważ również przeniesienie MySQL na oddzielny serwer lub użycie zarządzanej usługi bazodanowej, co zwalnia całą pamięć RAM serwera aplikacji wyłącznie dla PHP.
Szybka referencyjna tabela: Zalecane ustawienia według rozmiaru sklepu
Poniższe zalecenia stanowią punkt wyjścia. Monitoruj faktyczne zużycie i dostosowuj odpowiednio.
- Mały sklep (poniżej 1000 produktów, kilka modułów):
memory_limit = 256M, 2 GB RAM, 4-6 workerów PHP - Średni sklep (1000-10 000 produktów, 20+ modułów):
memory_limit = 512M, 4 GB RAM, 6-8 workerów PHP - Duży sklep (10 000+ produktów, wiele kombinacji):
memory_limit = 512M-1G, 8 GB+ RAM, 8-16 workerów PHP, oddzielny serwer bazy danych - Podczas importów: Tymczasowo zwiększ do
1Glub2G, następnie przywróć normalną wartość
Pamiętaj, że limit pamięci to pułap bezpieczeństwa, a nie cel. Dobrze zoptymalizowany sklep PrestaShop powinien rzadko zużywać więcej niż 128-256 MB na żądanie przy normalnym ładowaniu stron. Jeśli normalne operacje konsekwentnie wymagają 512 MB lub więcej, zbadaj i napraw przyczynę źródłową, zamiast ciągle zwiększać limit.
Zrozumienie max_input_vars w PrestaShop
Jeśli kiedykolwiek próbowałeś zapisać produkt z dziesiątkami lub setkami kombinacji w PrestaShop i napotkałeś ciche niepowodzenie, częściowy zapis lub tajemniczy błąd, winowajcą jest niemal na pewno dyrektywa PHP max_input_vars. To ustawienie kontroluje, ile poszczególnych pól formularza PHP zaakceptuje w pojedynczym żądaniu POST. Gdy PrestaShop przesyła formularz produktu, który przekracza ten limit, każde pole powyżej progu jest po cichu odrzucane, co prowadzi do niekompletnych zapisów, brakujących kombinacji lub danych, które po prostu znikają bez widocznego komunikatu o błędzie.
Domyślnie większość instalacji PHP ma ustawiony max_input_vars na 1000. Dla prostego bloga czy strony informacyjnej to więcej niż wystarczająco. Jednak w przypadku PrestaShop strony edycji produktów mogą generować tysiące pól formularza, szczególnie gdy w grę wchodzą kombinacje, pola wielojęzyczne i niestandardowe cechy. Zrozumienie tej dyrektywy, umiejętność obliczenia wartości, jakiej faktycznie potrzebuje Twój sklep, i prawidłowe zastosowanie poprawki zaoszczędzą Ci godzin debugowania.
Dlaczego PrestaShop potrzebuje wysokich wartości max_input_vars
Formularz edycji produktu w PrestaShop jest jednym z najbardziej złożonych formularzy w jakiejkolwiek platformie e-commerce. Każda kombinacja produktu generuje wiele pól formularza: jedno dla wpływu na cenę, jedno dla wpływu na wagę, jedno dla ilości, jedno dla referencji, jedno dla EAN-13, jedno dla UPC, jedno dla MPN, jedno dla minimalnej ilości, jedno dla progu niskiego stanu, jedno dla daty dostępności i kilka kolejnych w zależności od konfiguracji. Pojedyncza kombinacja może łatwo wygenerować od 15 do 25 pól formularza.
Teraz pomnóż to przez liczbę kombinacji. Koszulka dostępna w 5 rozmiarach i 10 kolorach ma 50 kombinacji. Przy 20 polach na kombinację daje to już 1000 pól tylko dla zakładki kombinacji. Dodaj podstawowe pola produktu, pola SEO dla każdego języka, wartości cech, ceny specjalne i inne zakładki, a łatwo osiągniesz 1500 do 2000 pól dla umiarkowanie złożonego produktu.
W przypadku sklepów sprzedających produkty z rozbudowanymi zestawami atrybutów, takich jak elektronika z różnymi pojemnościami pamięci, kolorami, opcjami RAM i wariantami regionalnymi, pojedynczy produkt może mieć 200 lub więcej kombinacji, generując ponad 4000 pól formularza. Domyślny limit 1000 jest zdecydowanie niewystarczający.
Objawy zbyt niskiej wartości max_input_vars
Najbardziej frustrującym aspektem osiągnięcia limitu max_input_vars jest to, że PHP nie wyrzuca żadnego błędu. Po cichu obcina dane wejściowe. Oznacza to, że zobaczysz szereg mylących objawów bez wyraźnej wskazówki, co poszło nie tak.
Najczęstszym objawem jest znikanie kombinacji po zapisie. Tworzysz 80 kombinacji, klikasz zapisz, a po przeładowaniu strony widocznych jest tylko 40. Formularz przesłał wszystkie 80, ale PHP przetworzył tylko pierwszą część danych POST przed osiągnięciem limitu, więc pozostałe kombinacje nigdy nie dotarły do serwera.
Innym częstym objawem jest częściowy zapis danych produktu. Zakładka z podstawowymi informacjami zapisuje się poprawnie, ale dane cenowe, SEO lub kombinacji są tracone. Dzieje się tak, ponieważ pola formularza są przesyłane w określonej kolejności, a wszystkie pola pojawiające się po punkcie obcięcia zostają odrzucone.
Możesz również doświadczyć sytuacji, gdy strona produktu po prostu przeładowuje się bez zapisywania, lub PrestaShop wyświetla ogólny błąd, taki jak „Wystąpił błąd podczas aktualizacji produktu." W PrestaShop 1.7 i 8.x strona produktu oparta na Symfony może wyświetlać błędy walidacji dla wymaganych pól, które w rzeczywistości były wypełnione, ale zostały obcięte przez PHP.
Mniej oczywisty objaw dotyczy sklepów wielojęzycznych. Jeśli Twój sklep obsługuje 5 języków, każde pole tekstowe jest mnożone przez 5. Produkt, który zapisuje się poprawnie w sklepie jednojęzycznym, nie zapisuje się w wielojęzycznym, ponieważ dodatkowe pola językowe przesuwają łączną liczbę powyżej limitu.
Jak sprawdzić aktualną wartość max_input_vars
Przed dokonaniem zmian zweryfikuj swoje aktualne ustawienie. Utwórz plik PHP w głównym katalogu PrestaShop (pamiętaj, aby usunąć go potem ze względów bezpieczeństwa):
<?php phpinfo(); ?>
Otwórz ten plik przez przeglądarkę i wyszukaj max_input_vars. Zobaczysz zarówno Local Value (co jest aktualnie aktywne), jak i Master Value (wartość domyślna z php.ini). Zwróć uwagę na Local Value, ponieważ może się różnić od Master Value, jeśli konfiguracja .htaccess lub per-katalogowa ją nadpisuje.
Alternatywnie, możesz sprawdzić z poziomu panelu administracyjnego PrestaShop. Przejdź do Zaawansowane, następnie Informacje. Sekcja konfiguracji PHP wyświetla kluczowe ustawienia PHP, w tym max_input_vars. PrestaShop 1.7.7 i nowsze wersje wyświetlają również ostrzeżenie na tej stronie, jeśli wartość jest uznawana za zbyt niską.
Obliczanie potrzebnej wartości max_input_vars
Zamiast ślepo ustawiać wysoką liczbę, możesz oszacować wartość wymaganą przez Twój sklep. Użyj tego wzoru jako punktu wyjścia:
Wymagana wartość = (liczba kombinacji x pola na kombinację) + podstawowe pola produktu + (pola tekstowe x liczba języków) + margines bezpieczeństwa
Jako praktyczny przykład rozważ sklep z 3 językami i produktem mającym 100 kombinacji. Obliczenie wyglądałoby tak: 100 kombinacji pomnożone przez 20 pól każda daje 2000. Podstawowe pola produktu ze wszystkich zakładek dają około 200. Pola tekstowe (nazwa, opis, meta tytuł, meta opis, link rewrite i inne) pomnożone przez 3 języki dodają kolejne 150. Dodanie 20% marginesu bezpieczeństwa daje łącznie około 2820.
Dla większości sklepów PrestaShop ustawienie max_input_vars na 10000 zapewnia wystarczający zapas. Sklepy z produktami mającymi ponad 300 kombinacji lub działające w więcej niż 5 językach powinny rozważyć wartość 20000 lub nawet 50000. Narzut pamięciowy wyższej wartości jest znikomy na nowoczesnych serwerach.
Jak zwiększyć max_input_vars
Metoda 1: php.ini (Zalecana)
Jeśli masz dostęp do konfiguracji PHP na serwerze, edycja php.ini jest najczystszym podejściem. Znajdź plik php.ini (wynik phpinfo() powie dokładnie, który plik jest załadowany) i znajdź lub dodaj następującą linię:
max_input_vars = 10000
Po zapisaniu pliku zrestartuj serwer WWW lub usługę PHP-FPM, aby zmiana zaczęła działać. Na Apache z mod_php zrestartuj Apache. Na Nginx z PHP-FPM zrestartuj usługę php-fpm. Dokładne polecenie zależy od systemu operacyjnego i wersji PHP.
Metoda 2: .htaccess (Apache z mod_php lub mod_fcgid)
Jeśli nie masz dostępu do php.ini, na przykład na hostingu współdzielonym, możesz spróbować dodać dyrektywę do pliku .htaccess w głównym katalogu PrestaShop:
php_value max_input_vars 10000
Ta metoda działa tylko wtedy, gdy PHP działa jako moduł Apache (mod_php). Jeśli Twój hosting używa PHP-FPM lub CGI, ta dyrektywa spowoduje błąd 500 Internal Server Error. W takim przypadku natychmiast usuń tę linię i spróbuj następnej metody.
Metoda 3: .user.ini (PHP-FPM / CGI)
Dla serwerów z PHP-FPM utwórz lub edytuj plik .user.ini w głównym katalogu PrestaShop:
max_input_vars = 10000
Pamiętaj, że zmiany w .user.ini nie działają natychmiast. PHP cachuje ten plik przez okres zdefiniowany przez user_ini.cache_ttl, który domyślnie wynosi 300 sekund (5 minut). Odczekaj co najmniej 5 minut po zapisaniu pliku przed testowaniem.
Metoda 4: Panel hostingowy
Wielu dostawców hostingu udostępnia ustawienia PHP przez swój panel sterowania. W cPanelu przejdź do „Select PHP Version" lub „MultiPHP INI Editor" i poszukaj max_input_vars. W Plesku przejdź do PHP Settings dla swojej domeny. DirectAdmin i inne panele mają podobne opcje. Jest to często najłatwiejsza metoda na hostingu współdzielonym.
Komplikacja z łatką Suhosin
Suhosin to łatka bezpieczeństwa PHP, która była powszechna na starszych serwerach, szczególnie tych działających na PHP 5.x. Nakłada ona własny zestaw limitów wejściowych, które nadpisują standardowe ustawienie max_input_vars. Nawet jeśli zwiększysz max_input_vars do 10000, Suhosin może nadal wymuszać niższy limit poprzez własne dyrektywy.
Ustawienia specyficzne dla Suhosin, które musisz dostosować, to:
suhosin.post.max_vars = 10000suhosin.request.max_vars = 10000
Muszą być ustawione oprócz standardowego max_input_vars. Jeśli wynik phpinfo() pokazuje sekcję Suhosin, jesteś dotknięty tym problemem i musisz dostosować wszystkie trzy wartości. Ustawienia Suhosin mogą być zazwyczaj zmieniane tylko w php.ini, nie w .htaccess ani .user.ini.
Na nowoczesnych instalacjach PHP 7.x i 8.x Suhosin jest rzadko obecny. Jeśli używasz aktualnej wersji PHP, niemal na pewno nie musisz się tym martwić. Jednak jeśli korzystasz ze starszego konta na hostingu współdzielonym, które nie było aktualizowane, warto to sprawdzić.
Alternatywne podejścia dla produktów z ponad 500 kombinacjami
Choć zwiększenie max_input_vars rozwiązuje bezpośredni problem, sklepy z ekstremalnie dużą liczbą kombinacji na produkt powinny rozważyć alternatywne podejścia, które zmniejszają liczbę pól formularza lub całkowicie omijają to ograniczenie.
Import kombinacji przez CSV
Wbudowana funkcjonalność importu PrestaShop przetwarza kombinacje przez przesyłanie plików, a nie przesyłanie formularzy, całkowicie omijając limit max_input_vars. Przygotuj plik CSV z danymi kombinacji i zaimportuj go przez back office w sekcji Zaawansowane, Import. Jest to często najbardziej praktyczne podejście dla produktów z setkami kombinacji.
Użyj API Webservice PrestaShop
API webservice PrestaShop pozwala tworzyć i aktualizować kombinacje programistycznie. Żądania API nie podlegają limitowi max_input_vars, ponieważ używają strukturalnych ładunków XML lub JSON zamiast danych POST zakodowanych formularzem. To podejście wymaga wiedzy technicznej, ale skaluje się do dowolnej liczby kombinacji.
Podziel duże produkty
W niektórych przypadkach z biznesowego punktu widzenia sensowniej jest podzielić produkt z ponad 500 kombinacjami na kilka produktów. Produkt z 5 rozmiarami i 100 kolorami mógłby zostać podzielony na 5 produktów, po jednym na rozmiar, każdy ze 100 opcjami kolorystycznymi. To nie tylko pozwala uniknąć ograniczenia technicznego, ale często poprawia również doświadczenie klienta.
Zarządzaj kombinacjami partiami
Jeśli musisz korzystać z formularza w back office, twórz kombinacje w mniejszych partiach. Generuj 50 kombinacji na raz, zapisz, następnie generuj kolejne 50. Jest to żmudne, ale pozwala uniknąć osiągnięcia limitu bez konieczności zmian konfiguracji serwera.
Weryfikacja poprawki
Po zwiększeniu max_input_vars zweryfikuj, czy zmiana zadziałała. Sprawdź ponownie phpinfo() i potwierdź, że Local Value odpowiada temu, co ustawiłeś. Następnie przetestuj, edytując swój najbardziej złożony produkt, wprowadzając drobną zmianę i zapisując. Wszystkie kombinacje i dane powinny zostać zachowane.
Jeśli problem utrzymuje się po zwiększeniu wartości, sprawdź te dodatkowe możliwości. Twój dostawca hostingu może nadpisywać Twoje ustawienia konfiguracją globalną. Instancja PHP obsługująca Twoją stronę może być inna niż ta pokazywana w CLI phpinfo(). Może istnieć limit serwera WWW, taki jak LimitRequestBody Apache lub client_max_body_size Nginx, który również obcina żądanie. Niektóre firewalle aplikacji webowych (WAF) lub wtyczki bezpieczeństwa (jak ModSecurity) nakładają własne limity na rozmiar danych POST i liczbę parametrów.
Powiązane ustawienia PHP do sprawdzenia
Przy okazji dostosowywania max_input_vars przejrzyj te powiązane ustawienia, które również mogą powodować problemy z dużymi formularzami produktów:
post_max_size: Ustawia maksymalny rozmiar danych POST w bajtach. Jeśli dane formularza przekraczają ten limit (zazwyczaj gdy produkty mają wiele dużych pól tekstowych w wielu językach), cały POST jest odrzucany. Ustaw na co najmniej 32M dla PrestaShop.
memory_limit: Przetwarzanie tysięcy pól formularza wymaga pamięci. Jeśli PHP wyczerpie pamięć podczas parsowania danych wejściowych, żądanie nie powiedzie się. Zalecana wartość dla PrestaShop to 256M lub 512M.
max_execution_time: Zapisywanie produktu z wieloma kombinacjami wiąże się z licznymi zapytaniami do bazy danych. Jeśli operacja zapisu trwa dłużej niż dozwolony czas wykonania, zostanie przerwana w trakcie procesu, prowadząc do częściowych zapisów. Ustaw na co najmniej 300 sekund dla sklepów ze złożonymi produktami.
max_input_nesting_level: PrestaShop używa zagnieżdżonych tablic w danych formularzy (na przykład pola wielojęzyczne używają tablic jak name[1], name[2]). Domyślny poziom zagnieżdżenia 64 jest zazwyczaj wystarczający, ale jeśli napotkasz problemy z głęboko zagnieżdżonymi strukturami formularzy, zwiększ go do 128 lub 256.
Uwagi specyficzne dla wersji PrestaShop
W PrestaShop 1.6 strona produktu jest całkowicie oparta na starszym kodzie PHP z tradycyjnym przesyłaniem formularzy. Problem z max_input_vars dotyczy wszystkich operacji na stronie produktu. Nie ma obejścia poza zwiększeniem limitu lub użyciem importów.
PrestaShop 1.7 wprowadził częściowo opartą na Symfony stronę produktu. Choć architektura się zmieniła, bazowe przesyłanie formularzy nadal korzysta z danych POST i podlega tym samym limitom PHP. Komponent formularzy Symfony może wyświetlać bardziej informacyjne komunikaty o błędach, gdy brakuje pól, ale przyczyna źródłowa jest taka sama.
PrestaShop 8.x zawiera całkowicie przeprojektowaną stronę produktu z nową strukturą formularzy Symfony. Zarządzanie kombinacjami zostało znacząco przebudowane — kombinacje są teraz zarządzane przez dedykowany interfejs, który ładuje i zapisuje dane przez AJAX w mniejszych partiach. Ta zmiana architektury naturalnie zmniejsza wpływ max_input_vars na dane kombinacji, choć główny formularz produktu może nadal być dotknięty w sklepach wielojęzycznych z wieloma cechami.
PrestaShop 9.x kontynuuje trend w kierunku obsługi danych opartej na AJAX, dalej zmniejszając zależność od masowego przesyłania formularzy. Jednak max_input_vars pozostaje istotny dla operacji zbiorczych i starszych modułów, które nadal korzystają z tradycyjnego przesyłania formularzy.
Zapobieganie przyszłym problemom
Ustaw max_input_vars na hojną wartość podczas początkowej instalacji PrestaShop, zamiast czekać na pojawienie się problemów. Wartość 20000 jest bezpieczna praktycznie dla wszystkich scenariuszy i nie ma znaczącego wpływu na wydajność. Udokumentuj to ustawienie w swoich notatkach konfiguracyjnych serwera, aby przyszłe migracje serwera je zachowały.
Jeśli jesteś dostawcą hostingu lub administratorem systemów zarządzającym wieloma instalacjami PrestaShop, rozważ ustawienie max_input_vars = 20000 jako domyślnej wartości w swoich szablonach konfiguracji PHP. Ta pojedyncza zmiana eliminuje jedno z najczęstszych zgłoszeń wsparcia związanych z zarządzaniem produktami w PrestaShop.
Monitoruj logi błędów po wprowadzeniu zmian. Choć samo obcięcie max_input_vars nie generuje błędów PHP, niektóre wersje PrestaShop logują ostrzeżenia, gdy wykrywają, że otrzymane dane nie odpowiadają oczekiwanym danym. Te wpisy w logach mogą pomóc zidentyfikować, czy limit jest nadal osiągany pomimo zwiększenia wartości.
Dlaczego białe strony pojawiają się po aktualizacjach PrestaShop
Pusta biała strona, często nazywana Białym Ekranem Śmierci (WSOD — White Screen of Death), jest jednym z najczęstszych i najbardziej niepokojących problemów, z jakimi spotykają się właściciele sklepów PrestaShop po aktualizacji oprogramowania rdzenia. Inicjujesz aktualizację z wersji 1.7.8.7 do 1.7.8.8, lub z 8.1.0 do 8.1.5, proces wydaje się zakończony, a następnie cały Twój sklep — zarówno front office, jak i back office — wyświetla jedynie biały ekran. Żadnego komunikatu o błędzie, żadnej częściowej treści, tylko pustka.
Zrozumienie, dlaczego tak się dzieje, wymaga zrozumienia, co robi aktualizacja rdzenia PrestaShop. Proces aktualizacji zastępuje setki plików PHP, modyfikuje tabele bazy danych, regeneruje indeksy klas, czyści cache i potencjalnie uruchamia zapytania migracyjne. Każda awaria w dowolnym punkcie tego łańcucha może pozostawić sklep w niespójnym stanie, w którym PHP napotyka błąd krytyczny, ale nie ma sposobu, aby go wyświetlić, ponieważ raportowanie błędów jest wyłączone w trybie produkcyjnym.
Najczęstsze przyczyny można podzielić na kilka kategorii: niekompatybilne moduły odwołujące się do usuniętych lub zmienionych klas rdzenia, niezgodność wersji PHP między starą a nową wersją PrestaShop, konflikty plików nadpisań (overrides), w których niestandardowe nadpisania kolidują ze zmienionymi plikami rdzenia, niewystarczające zasoby serwera powodujące przerwanie aktualizacji w trakcie procesu oraz niepowodzenia migracji bazy danych, które pozostawiają tabele w niespójnym stanie.
Krok 1: Włącz tryb debugowania
Pierwszą czynnością w przypadku białej strony jest uwidocznienie błędów. PrestaShop tłumi wyświetlanie błędów w trybie produkcyjnym, aby nie ujawniać wrażliwych informacji odwiedzającym. Musisz tymczasowo włączyć tryb debugowania, aby zobaczyć, co faktycznie idzie nie tak.
Najszybszą metodą jest edycja pliku /config/defines.inc.php. Znajdź linię definiującą _PS_MODE_DEV_ i zmień ją:
define('_PS_MODE_DEV_', true);
Jeśli nie możesz uzyskać dostępu do plików przez FTP lub SSH, ponieważ Twój panel hostingowy jest również niedostępny, niektórzy dostawcy hostingu oferują menedżer plików przez panel sterowania (cPanel, Plesk, DirectAdmin), który działa niezależnie od Twojej instalacji PrestaShop.
W PrestaShop 8.x możesz również włączyć tryb debugowania przez plik .env w katalogu głównym. Zmień APP_ENV=prod na APP_ENV=dev i ustaw APP_DEBUG=1. Aktywuje to pasek debugowania Symfony i szczegółowe strony błędów.
Po włączeniu trybu debugowania przeładuj stronę. Zamiast pustego ekranu powinieneś teraz zobaczyć szczegółowy komunikat o błędzie ze ścieżką do pliku, numerem linii i śladem stosu (stack trace). Ten komunikat o błędzie jest kluczem do diagnozy i naprawy problemu.
Krok 2: Sprawdź logi błędów
Jeśli włączenie trybu debugowania nadal pokazuje pustą stronę (co może się zdarzyć, gdy błąd występuje zanim PHP w ogóle załaduje framework PrestaShop), sprawdź logi błędów serwera bezpośrednio.
Na serwerach Apache log błędów znajduje się zazwyczaj w /var/log/apache2/error.log lub /var/log/httpd/error_log. Na Nginx z PHP-FPM sprawdź /var/log/nginx/error.log i /var/log/php-fpm/error.log (lub /var/log/php8.1-fpm.log w zależności od wersji PHP). Na hostingu współdzielonym logi błędów są zazwyczaj dostępne przez panel sterowania hostingu lub w katalogu logs na Twoim koncie hostingowym.
PrestaShop prowadzi również własne pliki logów w katalogu /var/logs/ (PrestaShop 1.7) lub /var/log/ (PrestaShop 8.x). Szukaj plików nazwanych bieżącą datą. Te logi oparte na Symfony mogą zawierać szczegółowe informacje o tym, co poszło nie tak podczas procesu aktualizacji.
Dodatkowo sprawdź katalog /log/ w głównym katalogu PrestaShop pod kątem plików logów błędów. Niektóre wersje PrestaShop zapisują tutaj krytyczne błędy, gdy nie mogą ich wyświetlić na ekranie.
Częsta przyczyna 1: Niekompatybilne moduły
Moduły są najczęstszą przyczyną białych stron po aktualizacjach. Moduł, który działał idealnie na PrestaShop 1.7.8.7, może zablokować cały sklep na wersji 1.7.8.8, jeśli korzysta z wewnętrznych klas lub metod rdzenia, które zmieniły się w aktualizacji.
Komunikat o błędzie zazwyczaj wygląda następująco: Fatal error: Class 'SomeClassName' not found lub Fatal error: Call to undefined method ClassName::methodName() lub Fatal error: Declaration of ModuleClass::hookMethod() must be compatible with CoreClass::hookMethod().
Aby to naprawić, musisz zidentyfikować i wyłączyć problematyczny moduł. Jeśli masz dostęp do back office (czasami tylko front office się zawiesza), przejdź do Modułów i wyłączaj ostatnio zainstalowane lub zaktualizowane moduły jeden po drugim, aż problem się rozwiąże.
Jeśli back office jest również niedostępne, wyłącz moduły przez bazę danych. Połącz się z bazą danych za pomocą phpMyAdmin lub klienta MySQL i wykonaj:
UPDATE ps_module SET active = 0 WHERE name = 'nazwa_problematycznego_modulu';
Jeśli nie wiesz, który moduł powoduje problem, możesz wyłączyć wszystkie moduły zewnętrzne (third-party) naraz, ustawiając ich kolumnę active na 0. Najpierw zidentyfikuj, które moduły są zewnętrzne, sprawdzając katalog /modules/ pod kątem modułów niebędących częścią PrestaShop. Następnie selektywnie je wyłączaj.
Bardziej agresywne podejście polega na zmianie nazwy katalogu modułu. Na przykład zmień nazwę /modules/somemodule/ na /modules/somemodule_disabled/. PrestaShop nie może załadować modułu, którego katalog nie odpowiada zarejestrowanej nazwie, co skutecznie go dezaktywuje bez modyfikacji bazy danych.
Częsta przyczyna 2: Niekompatybilność wersji PHP
Każda wersja PrestaShop wymaga określonego zakresu wersji PHP. PrestaShop 1.7.6 i wcześniejsze wymagają PHP 7.1 do 7.3. PrestaShop 1.7.7 do 1.7.8 obsługują PHP 7.2 do 8.0. PrestaShop 8.0 wymaga PHP 7.2 do 8.1. PrestaShop 8.1 wymaga PHP 8.0 do 8.2. PrestaShop 9.0 wymaga PHP 8.1 lub wyższego.
Jeśli Twoje środowisko hostingowe zmieniło wersję PHP podczas aktualizacji PrestaShop lub obok niej, możesz napotkać błędy składni lub wywołania przestarzałych funkcji. Typowe błędy kompatybilności PHP to: Deprecated: Function create_function() is deprecated (PHP 7.2+ z kodem pisanym dla PHP 5.x), Fatal error: Uncaught Error: Call to undefined function mysql_connect() (PHP 7.0+ usunęło rozszerzenie mysql) oraz Fatal error: Array and string offset access syntax with curly braces is no longer supported (PHP 8.0+).
Sprawdź aktualną wersję PHP, przeglądając wynik phpinfo() lub uruchamiając php -v w wierszu poleceń. Jeśli wersja jest poza obsługiwanym zakresem dla Twojej wersji PrestaShop, przełącz się na kompatybilną wersję PHP przez panel sterowania hostingu.
Częsta przyczyna 3: Konflikty nadpisań (overrides)
System nadpisań PrestaShop pozwala modułom i programistom modyfikować zachowanie rdzenia poprzez umieszczanie zmodyfikowanych plików klas w katalogu /override/. Podczas aktualizacji klasy rdzenia się zmieniają, ale pliki nadpisań pozostają. Jeśli nadpisanie odwołuje się do sygnatury metody, która się zmieniła, właściwości, która została usunięta, lub klasy, która została przemianowana, nadpisanie powoduje błąd krytyczny.
Plik indeksu klas /var/cache/prod/class_index.php (lub /cache/class_index.php w starszych wersjach) mapuje nazwy klas do ich lokalizacji plików, w tym nadpisań. Przestarzały lub uszkodzony indeks klas może ładować nieprawidłowy plik dla klasy, powodując natychmiastowe awarie.
Aby sprawdzić, czy nadpisania są problemem, tymczasowo wyłącz system nadpisań. Edytuj /config/defines.inc.php i dodaj lub zmodyfikuj:
define('_PS_HOST_MODE_', false);
Następnie usuń plik indeksu klas, aby wymusić na PrestaShop jego regenerację bez nadpisań. Jeśli sklep załaduje się po tej zmianie, problem tkwi w jednym z Twoich plików nadpisań.
Aby zidentyfikować konkretne problematyczne nadpisanie, przejrzyj katalogi /override/classes/ i /override/controllers/. Usuwaj pliki nadpisań po jednym, kasując indeks klas po każdym usunięciu, aż znajdziesz ten powodujący awarię. Po zidentyfikowaniu albo zaktualizuj nadpisanie, aby było kompatybilne z nową wersją rdzenia, albo usuń je całkowicie, jeśli nie jest już potrzebne.
Częsta przyczyna 4: Cache i skompilowane pliki
PrestaShop generuje skompilowane szablony Smarty, cache kontenerów Symfony, mapy klas i różne inne pliki cache, które stają się nieaktualne po aktualizacji. Jeśli proces aktualizacji nie wyczyścił prawidłowo tych cache, sklep próbuje używać plików cache odwołujących się do starej struktury kodu.
Wyczyść wszystkie cache ręcznie, usuwając zawartość następujących katalogów (usuń zawartość, nie same katalogi):
/var/cache/prod/ i /var/cache/dev/ dla cache Symfony. Usuń wszystko wewnątrz tych katalogów. PrestaShop zregeneruje je przy następnym ładowaniu strony.
/cache/smarty/compile/ i /cache/smarty/cache/ dla cache szablonów Smarty. Przestarzałe skompilowane szablony są bardzo częstą przyczyną białych stron po aktualizacjach.
/var/cache/prod/class_index.php (lub /cache/class_index.php) dla mapy klas. Ten plik musi być zregenerowany po każdej aktualizacji.
W konfiguracjach PHP-FPM zresetuj również OPcache. OPcache przechowuje skompilowany bajtkod PHP w pamięci i może serwować stary kod nawet po zastąpieniu plików. Zrestartuj usługę PHP-FPM, lub jeśli nie możesz tego zrobić, utwórz mały plik PHP wywołujący opcache_reset() i otwórz go przez przeglądarkę.
Częsta przyczyna 5: Niepowodzenia migracji bazy danych
Aktualizacje PrestaShop często zawierają zmiany schematu bazy danych: nowe kolumny, zmodyfikowane indeksy, nowe tabele lub migracje danych. Jeśli proces aktualizacji został przerwany (timeout, limit pamięci, zerwanie połączenia), baza danych może znajdować się w częściowo zmigrowanym stanie.
Sprawdź bazę danych PrestaShop w tabeli ps_configuration i poszukaj wartości PS_VERSION_DB. Jeśli ta wartość nie odpowiada wersji plików na dysku, aktualizacja nie zakończyła się prawidłowo. PrestaShop może próbować ponownie uruchomić migracje przy następnym ładowaniu, lub może po prostu się zawiesić.
Niepowodzenia migracji bazy danych są najtrudniejsze do odzyskania bez kopii zapasowej. Jeśli masz kopię zapasową bazy danych sprzed aktualizacji, jej przywrócenie i ponowne uruchomienie aktualizacji jest często najbezpieczniejszą ścieżką. Jeśli nie masz kopii zapasowej, możesz być zmuszony do ręcznego zastosowania brakujących plików migracji SQL znajdujących się w katalogu /install/upgrade/sql/.
Procedura odzyskiwania krok po kroku
Postępuj zgodnie z tą sekwencją podczas odzyskiwania po białej stronie po aktualizacji rdzenia. Kolejność ma znaczenie, ponieważ każdy krok albo naprawia problem, albo eliminuje możliwą przyczynę.
Krok 1: Włącz tryb debugowania w /config/defines.inc.php, ustawiając _PS_MODE_DEV_ na true. Przeładuj stronę i przeczytaj komunikat o błędzie.
Krok 2: Usuń zawartość /var/cache/prod/, /var/cache/dev/, /cache/smarty/compile/ i /cache/smarty/cache/. Usuń class_index.php. Przeładuj stronę.
Krok 3: Jeśli błąd wskazuje na konkretny moduł, wyłącz ten moduł, zmieniając nazwę jego katalogu lub ustawiając active = 0 w tabeli ps_module bazy danych. Przeładuj stronę.
Krok 4: Jeśli błąd wskazuje na plik nadpisania, przenieś zawartość katalogu /override/ do tymczasowej lokalizacji kopii zapasowej. Ponownie usuń class_index.php. Przeładuj stronę.
Krok 5: Sprawdź, czy Twoja wersja PHP jest kompatybilna z wersją PrestaShop, do której zaktualizowałeś. Sprawdź phpinfo() lub php -v. Przełącz wersję PHP, jeśli to konieczne.
Krok 6: Sprawdź uprawnienia plików. Proces aktualizacji mógł utworzyć pliki z nieprawidłowym właścicielstwem. Wszystkie pliki PrestaShop powinny być czytelne dla użytkownika serwera WWW, a katalogi /var/, /cache/, /img/, /upload/, /download/, /translations/, /themes/ i /modules/ powinny być zapisywalne.
Krok 7: Jeśli żaden z powyższych kroków nie rozwiązuje problemu i masz kopię zapasową bazy danych, przywróć bazę danych i pliki z kopii zapasowej, a następnie ponów próbę aktualizacji po rozwiązaniu wszelkich problemów zidentyfikowanych podczas diagnostyki.
Bezpieczna procedura aktualizacji na przyszłość
Zapobieganie jest znacznie lepsze niż odzyskiwanie. Stosuj tę procedurę przy każdej aktualizacji rdzenia PrestaShop, aby zminimalizować ryzyko białych stron i utraty danych.
Przed aktualizacją: Utwórz kompletną kopię zapasową zarówno bazy danych, jak i wszystkich plików. Nie tylko bazy danych, nie tylko plików, ale obydwu. Przechowuj te kopie zapasowe w lokalizacji poza kontem hostingowym, jeśli to możliwe. Przetestuj, czy faktycznie możesz przywrócić dane z tych kopii zapasowych, zanim przejdziesz dalej.
Wyłącz wszystkie moduły zewnętrzne (third-party). To jest najskuteczniejszy pojedynczy krok, jaki możesz podjąć, aby zapobiec białym stronom. Moduły rdzenia (te dostarczane z PrestaShop) są zaprojektowane tak, aby były kompatybilne z aktualizacją, ale moduły zewnętrzne nie mają tej gwarancji. Wyłącz je przed aktualizacją i włączaj ponownie jeden po drugim potem, testując sklep po każdym ponownym włączeniu.
Wyłącz system nadpisań. Jeśli masz niestandardowe nadpisania, wyłącz je przed aktualizacją. Ponownie oceń każde nadpisanie po aktualizacji, aby określić, czy jest nadal kompatybilne i nadal potrzebne.
Przeczytaj informacje o wydaniu (release notes). Każde wydanie PrestaShop zawiera notatki o wymaganiach kompatybilności, znanych problemach i zmianach powodujących niekompatybilność. Przeczytaj je przed aktualizacją, a nie po tym, gdy coś się zepsuje.
Przełącz sklep w tryb konserwacji. Zapobiega to składaniu zamówień przez klientów podczas aktualizacji i napotykaniu błędów. Przejdź do Parametry sklepu, Ogólne, Konserwacja w back office i włącz tryb konserwacji.
Podczas aktualizacji: Monitoruj proces aktualizacji. Nie zamykaj zakładki przeglądarki ani nie przechodź na inną stronę. Jeśli aktualizacja trwa dłużej niż oczekiwano, sprawdź logi błędów serwera pod kątem błędów timeout lub pamięci. Jeśli proces wydaje się zawieszony, odczekaj co najmniej 10 minut przed podjęciem jakichkolwiek działań, ponieważ duże sklepy mogą mieć znaczące migracje bazy danych do przetworzenia.
Po aktualizacji: Wyczyść wszystkie cache. Sprawdź, czy back office ładuje się prawidłowo. Sprawdź front office. Włączaj ponownie moduły jeden po drugim, sprawdzając sklep po każdym z nich. Włącz ponownie nadpisania jeden po drugim, jeśli dotyczy. Wyłącz tryb konserwacji. Monitoruj logi błędów przez następne 24 godziny.
Strategie wycofywania zmian (rollback)
Gdy odzyskanie nie jest możliwe lub zajmuje zbyt dużo czasu, wycofanie do poprzedniej wersji może być najlepszą opcją. Jednak PrestaShop nie posiada wbudowanego mechanizmu wycofywania, więc musisz zaplanować tę ewentualność przed rozpoczęciem aktualizacji.
Pełne wycofanie z kopii zapasowej: Przywróć zarówno bazę danych, jak i pliki z kopii zapasowej sprzed aktualizacji. Jest to najczystsze podejście, ale wymaga, abyś wykonał kompletną kopię zapasową przed aktualizacją. Po przywróceniu sprawdź, czy sklep działa prawidłowo i czy żadne zamówienia ani dane klientów utworzone podczas nieudanego okresu aktualizacji nie zostały utracone (jeśli sklep był w trybie konserwacji, nic nie powinno się zmienić).
Częściowe wycofanie plików: Jeśli uszkodzone są tylko pliki, a baza danych jest w porządku, możesz zastąpić pliki PrestaShop poprzednią wersją, zachowując aktualną bazę danych. Pobierz dokładną poprzednią wersję PrestaShop z oficjalnego archiwum wydań, rozpakuj ją i nadpisz pliki na serwerze. Zachowaj swoje niestandardowe moduły, motywy i pliki konfiguracyjne. To podejście jest ryzykowne, ponieważ baza danych mogła zostać częściowo zmigrowana, tworząc niespójność między plikami a schematem bazy danych.
Naprawa do przodu (forward fix): Czasami najszybszą ścieżką nie jest wycofanie, ale naprawienie konkretnego błędu. Jeśli błąd jest spowodowany pojedynczym niekompatybilnym modułem lub nadpisaniem, naprawienie lub usunięcie tego jednego komponentu może zająć minuty w porównaniu do godzin potrzebnych na pełne wycofanie. To podejście jest najlepsze, gdy wyraźnie zidentyfikowałeś przyczynę z komunikatu o błędzie.
Znaczenie kopii zapasowych bazy danych
Każda sekcja tego przewodnika wspomina o kopiach zapasowych i nie bez powodu. Baza danych PrestaShop zawiera każdy produkt, każde zamówienie, każde konto klienta, każde ustawienie konfiguracji i każdą treść w Twoim sklepie. Jej utrata oznacza utratę danych biznesowych.
Automatyczne codzienne kopie zapasowe nie są opcjonalne dla produkcyjnego sklepu PrestaShop. Skonfiguruj system kopii zapasowych swojego dostawcy hostingu, użyj modułu do tworzenia kopii zapasowych bazy danych lub ustaw zadanie cron uruchamiające mysqldump w regularnych odstępach czasu. Przechowuj kopie zapasowe w wielu lokalizacjach. Okresowo testuj procedurę przywracania, aby upewnić się, że kopie zapasowe są faktycznie użyteczne.
Przed każdą aktualizacją utwórz ręczną kopię zapasową oprócz automatycznych kopii zapasowych. Nazwij ją wyraźnie z datą i wersją PrestaShop, abyś mógł natychmiast ją zidentyfikować w razie potrzeby przywrócenia.
Kiedy szukać profesjonalnej pomocy
Jeśli wykonałeś wszystkie kroki z tego przewodnika i nadal widzisz białą stronę, lub jeśli komunikaty o błędach wskazują na głębokie problemy rdzenia wymagające napraw na poziomie kodu, może nadszedł czas, aby zaangażować programistę PrestaShop. Przekaż mu zebrane komunikaty o błędach, wersje PrestaShop (przed i po aktualizacji), wersję PHP oraz wszelkie działania, które już podjąłeś. Te informacje znacząco skrócą czas potrzebny na diagnozę i rozwiązanie problemu.
Próby ręcznej edycji plików rdzenia PrestaShop bez zrozumienia architektury frameworka mogą stworzyć dodatkowe problemy. Jeśli komunikat o błędzie odnosi się do kontenerów Symfony, wstrzykiwania zależności (dependency injection) lub konfiguracji kernela, są to obszary, w których nieprawidłowe zmiany mogą kaskadowo prowadzić do wielu awarii.
Jak działają aktualizacje koszyka w PrestaShop
Zanim przejdziemy do rozwiązywania problemów, warto zrozumieć, jak PrestaShop obsługuje operacje koszyka. Gdy klient klika przycisk "Dodaj do koszyka", front-endowy JavaScript wysyła żądanie AJAX do serwera. Serwer przetwarza żądanie, aktualizuje koszyk w bazie danych i sesji, a następnie zwraca odpowiedź JSON zawierającą zaktualizowane podsumowanie koszyka. JavaScript odbiera tę odpowiedź i aktualizuje blok koszyka, stronę produktu oraz wszystkie inne elementy zależne od koszyka na stronie — bez pełnego przeładowania.
To podejście oparte na AJAX, w pełni wprowadzone w PrestaShop 1.7, zastąpiło starszą metodę z przeładowaniem strony stosowaną w PrestaShop 1.6. Choć zapewnia znacznie płynniejsze doświadczenie zakupowe, wprowadza również więcej potencjalnych punktów awarii. Aktualizacja koszyka może się nie powieść na poziomie JavaScript, żądania AJAX, przetwarzania po stronie serwera lub renderowania odpowiedzi. Każdy punkt awarii powoduje inne objawy i wymaga innego podejścia diagnostycznego.
W PrestaShop 1.7 i 8.x głównym plikiem JavaScript odpowiedzialnym za operacje koszyka jest core.js, który wykorzystuje jQuery do wysyłania żądań AJAX do kontrolera koszyka. Kontroler koszyka przetwarza żądanie i wysyła zdarzenia, do których moduły mogą się podłączyć. Odpowiedź wyzwala ogólnostronicowe zdarzenie (updateCart), na które nasłuchują wszystkie komponenty powiązane z koszykiem w celu odświeżenia wyświetlanych danych.
Objaw: kliknięcie "Dodaj do koszyka" nie daje żadnego efektu
Gdy kliknięcie przycisku "Dodaj do koszyka" nie powoduje absolutnie żadnej reakcji — brak animacji, brak spinnera, brak błędu — problem prawie zawsze leży w błędzie JavaScript, który uniemożliwia wykonanie handlera kliknięcia. Zdarzenie kliknięcia przycisku nigdy nie jest przechwytywane, więc żadne żądanie AJAX nie zostaje wysłane do serwera.
Otwórz narzędzia deweloperskie przeglądarki (F12 lub Ctrl+Shift+I w Chrome, Firefox i Edge) i przejdź do zakładki Konsola. Przeładuj stronę produktu i poszukaj czerwonych komunikatów o błędach. Typowe błędy to $ is not defined lub jQuery is not defined (jQuery nie załadował się), Uncaught TypeError: Cannot read property of undefined (JavaScript modułu odwołuje się do czegoś, co nie istnieje) lub Uncaught SyntaxError (plik JavaScript ma błąd składni, często z powodu nieprawidłowej minifikacji modułu).
Pojedynczy błąd JavaScript na stronie może zatrzymać wykonanie całego kolejnego JavaScript, w tym podstawowej funkcjonalności koszyka. Jeśli moduł załadowany przed głównym JavaScriptem PrestaShop wyrzuci błąd, cały system koszyka przestaje działać, mimo że moduł ten nie ma nic wspólnego z koszykiem.
Aby zidentyfikować problematyczny moduł, sprawdź nazwę pliku w komunikacie o błędzie. Zwykle będzie to ścieżka w stylu /modules/somemodule/views/js/somefile.js. Tymczasowo wyłącz ten moduł, aby potwierdzić, że jest przyczyną, a następnie skontaktuj się z deweloperem modułu w celu uzyskania poprawki.
Objaw: koszyk się kręci, ale nigdy nie kończy operacji
Jeśli kliknięcie "Dodaj do koszyka" uruchamia animację ładowania, ale kręci się w nieskończoność, żądanie AJAX zostało wysłane, ale nie otrzymało odpowiedzi lub otrzymało odpowiedź z błędem. Przejdź do zakładki Sieć w narzędziach deweloperskich, kliknij "Dodaj do koszyka" i poszukaj żądania AJAX. Zazwyczaj będzie to żądanie POST na URL zawierający controller=cart lub cart w ścieżce.
Kliknij na żądanie, aby je sprawdzić. Sprawdź kolumnę Status: status 200 z pustą lub nieprawidłowo sformatowaną treścią odpowiedzi oznacza błąd PHP po stronie serwera, który został przechwycony przed wygenerowaniem outputu. Status 500 oznacza nieobsłużony błąd serwera. Status 403 może oznaczać, że moduł bezpieczeństwa lub WAF blokuje żądanie. Status 408 lub timeout oznacza, że serwer zbyt długo przetwarzał żądanie.
Jeśli status to 200, ale treść odpowiedzi zawiera HTML zamiast JSON (poszukaj znaczników HTML w odpowiedzi), oznacza to, że PHP napotkał ostrzeżenie lub notice, które zostały wyświetlone przed odpowiedzią JSON, powodując błąd parsowania JSON. Jest to niezwykle częste i jest spowodowane przez moduły lub nadpisania, które generują tekst (nawet pustą linię przed otwierającym znacznikiem PHP) podczas hooków przetwarzania koszyka.
Objaw: koszyk się aktualizuje, ale pokazuje złe dane
Czasami koszyk wydaje się działać: animacja gra, ikona koszyka się aktualizuje, ale wyświetlane ilości, ceny lub produkty są nieprawidłowe. Jest to typowy problem z cache, gdzie klient widzi nieaktualne dane zamiast świeżo obliczonego koszyka.
PrestaShop posiada wiele warstw cache, z których każda może serwować nieaktualne informacje o koszyku. Zrozumienie i systematyczne sprawdzanie każdej warstwy jest kluczowe dla diagnozowania tego typu problemu.
Problemy z cache przeglądarki
Sama przeglądarka może buforować odpowiedzi AJAX lub statyczne pliki JavaScript. Chociaż żądania POST AJAX nie powinny być buforowane przez przeglądarki, niektóre agresywne konfiguracje buforowania lub service workery mogą zakłócać działanie.
Przetestuj otwierając okno incognito lub przeglądanie prywatne. Jeśli koszyk działa poprawnie w trybie incognito, problem jest związany z cache przeglądarki. Poinstruuj klienta, aby wyczyścił cache przeglądarki, lub bardziej precyzyjnie, spróbuj twardego odświeżenia za pomocą Ctrl+Shift+R (Windows/Linux) lub Cmd+Shift+R (Mac).
Jeśli motyw PrestaShop używa service workera do funkcjonalności progresywnej aplikacji webowej (PWA), service worker może przechwytywać i buforować żądania AJAX. Sprawdź zakładkę Aplikacja w narzędziach deweloperskich, następnie Service Workers, aby zobaczyć, czy jakiś jest zarejestrowany. Tymczasowo go wyrejestruj, aby sprawdzić, czy powoduje problem.
Statyczne pliki JavaScript również mogą być buforowane. Jeśli niedawno zaktualizowałeś moduł modyfikujący zachowanie koszyka, przeglądarka klienta może nadal używać starego pliku JavaScript. PrestaShop dodaje ciąg wersji do URL-i JavaScript (np. cart.js?v=1.0.0), ale działa to tylko wtedy, gdy moduł prawidłowo zwiększa numer wersji przy aktualizacji.
Konflikty cache Smarty
PrestaShop używa silnika szablonów Smarty do renderowania HTML po stronie serwera. Smarty posiada własny system kompilacji i buforowania, który może serwować nieaktualne dane z szablonów.
Jeśli szablony związane z koszykiem zostały zmodyfikowane (przez aktualizację motywu, instalację modułu lub ręczną edycję), ale cache Smarty nie został wyczyszczony, stary szablon nadal jest serwowany. Skompilowane szablony są przechowywane w /var/cache/prod/smarty/compile/, a buforowany output w /var/cache/prod/smarty/cache/. Usunięcie zawartości obu katalogów wymusza ponowną kompilację wszystkich szablonów z aktualnych plików źródłowych.
Cache Smarty można również wyczyścić z panelu administracyjnego. Przejdź do Zaawansowane > Wydajność i kliknij przycisk "Wyczyść pamięć podręczną". W PrestaShop 8.x możesz również użyć przycisku "Wyczyść cache Symfony", który czyści zarówno cache kontenera Symfony, jak i cache Smarty.
Bardziej subtelny problem z Smarty dotyczy ustawień "Wymuś kompilację" i "Cache" w Zaawansowane > Wydajność > Smarty. Podczas debugowania ustaw Kompilację szablonów na "Wymuś kompilację", a Cache na "Nie". To zapewnia, że każde załadowanie strony używa najnowszych plików szablonów. Pamiętaj, aby po zakończeniu debugowania przywrócić ustawienia na "Rekompiluj szablony, jeśli pliki zostały zmienione" i "Tak", ponieważ wymuszona kompilacja znacząco wpływa na wydajność.
Ustawienia CCC i ich wpływ
Funkcja CCC (Combine, Compress, Cache) w PrestaShop, dostępna w Zaawansowane > Wydajność, łączy i minifikuje pliki CSS i JavaScript w celu poprawy czasu ładowania strony. Choć jest korzystna dla wydajności, CCC może powodować problemy z koszykiem na kilka sposobów.
Gdy CCC jest włączone, PrestaShop łączy wiele plików JavaScript w jeden buforowany plik. Jeśli JavaScript modułu zależy od kolejności ładowania (musi się wykonać po jQuery, ale przed kodem innego modułu), proces łączenia może nieprawidłowo zmienić kolejność plików, powodując awarię zależnego kodu.
CCC również agresywnie buforuje połączone pliki. Po zainstalowaniu, aktualizacji lub usunięciu modułu, stary połączony plik może nadal być serwowany. Rozwiązaniem jest ręczne wyczyszczenie cache CCC — przejdź do Zaawansowane > Wydajność i kliknij "Wyczyść pamięć podręczną" lub usuń buforowane pliki w /themes/your_theme/cache/.
Szczególnie frustrujący problem CCC pojawia się, gdy plik JavaScript jednego modułu zawiera błąd składni. Gdy CCC łączy go z innymi plikami, błąd składni psuje cały połączony pakiet JavaScript, wyłączając całą funkcjonalność JavaScript na stronie, łącznie z koszykiem. Bez CCC tylko JavaScript tego jednego modułu by nie działał, podczas gdy reszta nadal by funkcjonowała. Tymczasowe wyłączenie CCC może pomóc w izolacji tego typu problemu.
Aby sprawdzić, czy CCC powoduje problem z koszykiem, wyłącz wszystkie trzy opcje CCC (Inteligentny cache dla CSS, Inteligentny cache dla JavaScript i Optymalizacja Apache) w ustawieniach Wydajności. Wyczyść wszystkie cache. Jeśli koszyk zacznie działać, włączaj opcje po jednej, aby zidentyfikować, która powoduje konflikt.
Problemy z cache CDN
Jeśli Twój sklep PrestaShop używa CDN (Content Delivery Network), takiego jak Cloudflare, KeyCDN lub CloudFront, CDN może buforować odpowiedzi, które nie powinny być buforowane. CDN-y są zaprojektowane do buforowania statycznej treści, ale błędy konfiguracji mogą powodować buforowanie dynamicznych odpowiedzi AJAX lub stron zależnych od sesji.
Cloudflare w szczególności bywa znane z buforowania odpowiedzi POST, gdy pewne reguły stron lub reguły "cache everything" są skonfigurowane zbyt szeroko. Endpoint AJAX koszyka zwraca dane specyficzne dla klienta, które nigdy nie powinny być buforowane przez CDN.
Aby sprawdzić, czy CDN jest zaangażowany, tymczasowo go obejdź. W Cloudflare możesz wstrzymać CDN lub dodać regułę strony, która tymczasowo wyłącza cache dla całej domeny. Jeśli koszyk działa poprawnie bez CDN, przejrzyj swoje reguły buforowania, aby upewnić się, że endpointy AJAX i dynamiczne strony są wyłączone z buforowania.
W przypadku Cloudflare upewnij się, że reguła "Cache Everything" nie obejmuje całej domeny. Jeśli musisz jej użyć, dodaj regułę o wyższym priorytecie, która wyłącza cache dla URL-i zawierających controller=cart, ajax=true oraz ścieżkę checkout. Sprawdź również, czy "Browser Cache TTL" nie jest ustawiony zbyt wysoko dla dynamicznych zasobów.
Problemy z ciasteczkami i sesjami
PrestaShop używa ciasteczek do utrzymywania sesji zakupowej, w tym koszyka. Jeśli ciasteczka nie działają poprawnie, koszyk nie może być zachowany między żądaniami. Każda aktualizacja koszyka AJAX tworzy nową sesję zamiast aktualizować istniejącą, co skutkuje koszykiem, który wydaje się pusty po każdym załadowaniu strony.
Typowe problemy z ciasteczkami to: błędna konfiguracja domeny ciasteczka (ciasteczko jest ustawione dla www.example.com, ale żądanie AJAX trafia na example.com bez prefiksu www, lub odwrotnie), błędna ścieżka ciasteczka, atrybut SameSite ustawiony na Strict, co blokuje ciasteczka w pewnych scenariuszach cross-origin, lub ciasteczko jest zbyt duże i jest odrzucane przez przeglądarkę (przeglądarki zazwyczaj ograniczają rozmiar ciasteczka do 4KB).
Sprawdź ciasteczka w zakładce Aplikacja narzędzi deweloperskich. Poszukaj ciasteczka sesji PrestaShop (nazwanego PrestaShop-[hash] w nowszych wersjach). Zweryfikuj, czy ma poprawną domenę, ścieżkę i czy jest wysyłane z żądaniami AJAX (sprawdź nagłówek Cookie w zakładce Sieć dla żądania AJAX koszyka).
W konfiguracjach wielodomenowych lub multi-sklepowych problemy z ciasteczkami są szczególnie częste. Jeśli sklep jest dostępny zarówno przez http, jak i https, lub zarówno przez wersję z www, jak i bez www, ciasteczko może nie być współdzielone między tymi wariantami. Upewnij się, że Twój sklep używa jednego kanonicznego URL-a i że wszystkie inne warianty przekierowują do niego.
Problemy z certyfikatem SSL mogą również uniemożliwić działanie ciasteczek. Jeśli flaga Secure jest ustawiona na ciasteczku, ale strona jest ładowana przez HTTP (lub mixed content), przeglądarka nie wyśle ciasteczka. Upewnij się, że cały sklep jest konsekwentnie serwowany przez HTTPS.
Konflikty modułów: proces diagnozy
Konflikty modułów są najczęstszą przyczyną problemów z koszykiem w PrestaShop. Dwa lub więcej modułów może podłączać się do tych samych zdarzeń koszyka i wzajemnie sobie przeszkadzać, lub pojedynczy moduł może mieć błąd, który uszkadza odpowiedź koszyka.
Systematyczne podejście do diagnozowania konfliktów modułów polega na wyłączaniu modułów w grupach. Zacznij od wyłączenia wszystkich modułów firm trzecich (zachowaj aktywne natywne moduły PrestaShop). Jeśli koszyk działa, ponownie włączaj moduły w grupach po 5. Gdy problem pojawi się ponownie, zawęziłeś go do 5 modułów. Wyłącz te 5 i włączaj je po jednym, aby znaleźć dokładnego winowajcę.
Zwróć szczególną uwagę na moduły podłączone do tych hooków PrestaShop, ponieważ bezpośrednio wpływają na zachowanie koszyka: actionCartSave, actionCartUpdate, displayShoppingCart, displayShoppingCartFooter, actionBeforeCartUpdateQty, actionAfterCartUpdateQty, displayHeader (moduły dodające tu JavaScript mogą kolidować z JS koszyka) i actionFrontControllerSetMedia.
Aby zobaczyć, które moduły są zarejestrowane na hookach związanych z koszykiem, sprawdź bazę danych:
SELECT h.name, m.name FROM ps_hook_module hm JOIN ps_hook h ON h.id_hook = hm.id_hook JOIN ps_module m ON m.id_module = hm.id_module WHERE h.name LIKE '%cart%' ORDER BY h.name, hm.position;
To zapytanie listuje wszystkie moduły podłączone do hooków związanych z koszykiem wraz z ich kolejnością wykonania. Konflikty często powstają, gdy dwa moduły próbują jednocześnie modyfikować sumę koszyka lub stosować rabaty w niekompatybilny sposób.
Debugowanie za pomocą narzędzi deweloperskich przeglądarki: szczegółowy przewodnik
Narzędzia deweloperskie przeglądarki to Twoja najpotężniejsza broń do diagnozowania problemów z koszykiem. Oto krok po kroku jak ich skutecznie używać.
Krok 1: Otwórz DevTools i przejdź do zakładki Konsola. Wyczyść wszystkie istniejące wiadomości. Przeładuj stronę produktu. Zanotuj wszelkie błędy lub ostrzeżenia, które się pojawią. Są to wcześniej istniejące problemy, które mogą, ale nie muszą być związane z problemem koszyka, ale powinny być udokumentowane.
Krok 2: Przejdź do zakładki Sieć. Zaznacz pole "Zachowaj log", aby żądania nie były czyszczone przy nawigacji. Filtruj po "XHR" lub "Fetch", aby widzieć tylko żądania AJAX. Kliknij przycisk "Dodaj do koszyka".
Krok 3: Zbadaj żądanie AJAX. Kliknij na żądanie koszyka, które się pojawi. W podzakładce Nagłówki zweryfikuj, że URL żądania jest poprawny i kod statusu to 200. W podzakładce Dane żądania lub Dane formularza sprawdź, czy wysyłany jest prawidłowy ID produktu, ilość i kombinacja atrybutów.
Krok 4: Sprawdź odpowiedź. Przejdź do podzakładki Odpowiedź lub Podgląd. Odpowiedź powinna być prawidłowym JSON-em. Jeśli widzisz wmieszany HTML, ostrzeżenie lub błąd PHP jest wyświetlany. Jeśli odpowiedź jest pusta, przetwarzanie po stronie serwera zakończyło się awarią przed wygenerowaniem outputu. Jeśli JSON jest prawidłowy, ale zawiera komunikaty o błędach, przeczytaj je w poszukiwaniu wskazówek.
Krok 5: Sprawdź konsolę po odpowiedzi AJAX. Błędy JavaScript, które występują podczas przetwarzania odpowiedzi AJAX, pojawią się w konsoli po zakończeniu żądania sieciowego. Te błędy wskazują, że odpowiedź została odebrana, ale nie mogła być prawidłowo przetworzona przez JavaScript front-endu.
Zagadnienia specyficzne dla PrestaShop 8.x
PrestaShop 8.x używa znacząco zaktualizowanej architektury front-endu w porównaniu z wersją 1.7. JavaScript koszyka został zrefaktoryzowany, a niektóry wcześniej zależny od jQuery kod teraz używa czystego JavaScriptu lub zaktualizowanych metod jQuery. Moduły napisane dla PrestaShop 1.7, które bezpośrednio manipulują DOM koszyka, mogą nie działać na 8.x, ponieważ struktura HTML i nazwy klas CSS uległy zmianie.
Integracja Symfony w PrestaShop 8.x oznacza również, że czyszczenie cache jest bardziej złożone. Cache kontenera Symfony, znajdujący się w /var/cache/prod/ i /var/cache/dev/, może zawierać skompilowane definicje serwisów i mapowania tras, które wpływają na to, jak kontrolery koszyka przetwarzają żądania. Samo wyczyszczenie cache Smarty nie wystarczy — musisz również wyczyścić cache Symfony.
PrestaShop 8.x wprowadził również bardziej restrykcyjne nagłówki Content Security Policy (CSP) w niektórych konfiguracjach. Jeśli Twój serwer lub moduł bezpieczeństwa dodaje nagłówki CSP ograniczające inline JavaScript lub żądania AJAX do określonych domen, wywołania AJAX koszyka mogą być blokowane. Sprawdź konsolę pod kątem komunikatów o naruszeniu CSP, które pojawiają się jako czerwone błędy wspominające "Content Security Policy".
Problemy po stronie serwera: sesje PHP i konfiguracja
Konfiguracja sesji PHP może powodować problemy z koszykiem, które są trudne do zdiagnozowania, ponieważ pojawiają się sporadycznie. Jeśli katalog przechowywania sesji jest pełny, ma nieprawidłowe uprawnienia lub znajduje się na systemie plików nie obsługującym blokowania plików, sesje mogą być tracone lub uszkadzane między żądaniami.
Sprawdź konfigurację sesji PHP: session.save_path musi wskazywać na katalog z uprawnieniami do zapisu i wystarczającą ilością miejsca na dysku. session.gc_maxlifetime kontroluje, jak długo sesje są przechowywane; jeśli ustawiony zbyt nisko, klienci tracą swoje koszyki podczas długich sesji przeglądania. session.cookie_lifetime powinien odpowiadać lub przekraczać wartość gc_maxlifetime.
Na współdzielonym hostingu z wieloma stronami katalog sesji może zawierać miliony plików ze wszystkich hostowanych stron, co spowalnia dostęp do plików sesji. Jeśli Twój dostawca hostingu to obsługuje, skonfiguruj katalog sesji dla każdej strony osobno lub użyj sesji opartych na bazie danych.
Dla sklepów używających wielu serwerów webowych za load balancerem, sesje muszą być współdzielone między serwerami. Jeśli przechowywanie sesji jest plikowe i lokalne dla każdego serwera, kolejne żądanie klienta może trafić na inny serwer, który nie ma jego sesji, co skutkuje pustym koszykiem. Użyj współdzielonego magazynu sesji, takiego jak Redis, Memcached lub sesje bazodanowe w środowiskach z load balancingiem.
Krok po kroku: lista kontrolna diagnozy
Gdy klient zgłasza, że koszyk się nie aktualizuje, przepracuj tę listę kontrolną w kolejności:
1. Odtwórz problem. Spróbuj powtórzyć problem w oknie incognito, używając tego samego produktu i przeglądarki, które zgłosił klient. Jeśli nie możesz go odtworzyć, poproś klienta o wersję przeglądarki, typ urządzenia i dokładne kroki.
2. Sprawdź konsolę przeglądarki pod kątem błędów JavaScript. Każdy czerwony komunikat o błędzie jest potencjalnie przyczyną, nawet jeśli wydaje się niezwiązany z koszykiem.
3. Sprawdź żądanie sieciowe. Zweryfikuj, że żądanie AJAX jest wysyłane, zwraca status 200 i zawiera prawidłowy JSON.
4. Wyczyść wszystkie cache: cache kompilacji Smarty, cache Smarty, cache Symfony, cache CCC, OPcache i cache CDN, jeśli dotyczy.
5. Wyłącz CCC. Jeśli koszyk działa z wyłączonym CCC, przyczyną jest błąd kombinacji JavaScript.
6. Przetestuj z domyślnym motywem. Tymczasowo przełącz się na domyślny motyw classic PrestaShop. Jeśli koszyk działa na domyślnym motywie, problem leży w JavaScript lub szablonach Twojego własnego motywu.
7. Wyłącz moduły firm trzecich. Jeśli koszyk działa z wyłączonymi wszystkimi modułami firm trzecich, użyj metody wyszukiwania binarnego, aby zidentyfikować kolidujący moduł.
8. Sprawdź logi błędów PHP. Błędy po stronie serwera, które nie docierają do przeglądarki, są tu logowane.
9. Zweryfikuj konfigurację ciasteczek i sesji. Sprawdź ciasteczko sesji w DevTools i zweryfikuj ustawienia sesji PHP na serwerze.
10. Przetestuj na innym urządzeniu i w innej sieci. To eliminuje lokalne problemy przeglądarki, proxy sieciowe i problemy kompatybilności JavaScript specyficzne dla urządzenia jako potencjalne przyczyny.
Dlaczego logi błędów PrestaShop mają znaczenie
Każdy sklep PrestaShop generuje błędy. Niektóre to nieszkodliwe powiadomienia, które nigdy nie wpływają na klientów. Inne to krytyczne awarie, które zatrzymują cały proces zakupowy. Różnica między właścicielem sklepu, który czeka dniami na wsparcie techniczne, a takim, który naprawia problemy w kilka minut, często sprowadza się do jednej umiejętności: czytania logów błędów.
Logi błędów to diagnostyczny output Twojego serwera i aplikacji PrestaShop. Rejestrują każdy błąd PHP, każde nieudane zapytanie do bazy danych, każdy problem z uprawnieniami i każdy nieprzechwycony wyjątek. Gdy coś idzie nie tak, odpowiedź prawie zawsze znajduje się w pliku logów. Wyzwaniem jest wiedzieć, gdzie szukać, czego szukać i jak interpretować to, co znajdziesz.
Ten przewodnik obejmuje pełen krajobraz logowania błędów w PrestaShop. Dowiesz się, gdzie żyje każdy typ logów, jak włączyć szczegółowe raportowanie błędów, jak czytać stack trace'y i jak używać narzędzi linii poleceń do znalezienia igły w stogu siana. Niezależnie od tego, czy debugujesz biały ekran śmierci, czy tropiesz sporadyczną awarię procesu zakupowego — to jest wiedza, której potrzebujesz.
Gdzie znajdują się logi PrestaShop
PrestaShop generuje logi na wielu poziomach i każdy poziom ma własne pliki logów. Zrozumienie, który log sprawdzić w pierwszej kolejności, oszczędza ogromne ilości czasu.
Logi aplikacji PrestaShop (var/logs)
Począwszy od PrestaShop 1.7, aplikacja wykorzystuje framework Symfony do panelu administracyjnego i głównego routingu. Symfony zapisuje własne logi do katalogu var/logs/ w głównym katalogu PrestaShop. Znajdziesz tam pliki nazwane według bieżącego środowiska:
var/logs/dev.log zawiera logi, gdy PrestaShop działa w trybie deweloperskim. Ten plik jest niezwykle szczegółowy i rejestruje wszystko — od decyzji routingowych po zapytania do bazy danych. Może szybko urosnąć do setek megabajtów.
var/logs/prod.log zawiera logi z trybu produkcyjnego. Ten plik jest domyślnie znacznie mniej szczegółowy, rejestrując tylko ostrzeżenia i błędy. To jest plik, który powinieneś sprawdzić w pierwszej kolejności, gdy coś przestaje działać na działającym sklepie.
Te pliki logów mają format Monolog, który jest standardową biblioteką logowania w Symfony. Każda linia zawiera znacznik czasu, kanał logowania (np. request, security lub doctrine), poziom ważności i wiadomość. Typowy wpis wygląda tak:
[2024-03-15 14:22:33] request.CRITICAL: Uncaught PHP Exception Symfony\Component\HttpKernel\Exception\NotFoundHttpException: "No route found for GET /admin/nonexistent" at /var/www/html/vendor/symfony/http-kernel/EventListener/RouterListener.php line 136
Poziomy ważności, od najmniej do najbardziej poważnego, to: DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT i EMERGENCY. Podczas rozwiązywania problemów filtruj najpierw po ERROR i CRITICAL.
Log błędów PHP
Sam PHP prowadzi log błędów odrębny od logów aplikacji PrestaShop. Ten log przechwytuje błędy, które pojawiają się zanim framework logowania PrestaShop zostanie zainicjalizowany, lub błędy w kodzie, który nie korzysta z loggera Symfony. Lokalizacja tego pliku zależy od konfiguracji serwera.
Na większości serwerów Linux z Apache log błędów PHP znajduje się w /var/log/php_errors.log lub /var/log/php/error.log. Na współdzielonym hostingu z cPanel znajduje się często w /home/username/logs/error.log lub w katalogu public_html jako error_log.
Możesz znaleźć dokładną lokalizację, sprawdzając konfigurację PHP. Utwórz tymczasowy plik PHP z phpinfo(); i poszukaj dyrektywy error_log. Alternatywnie uruchom php -i | grep error_log z linii poleceń.
Logi błędów PHP przechwytują błędy fatalne, błędy parsowania, ostrzeżenia i powiadomienia. Typowy wpis błędu fatalnego wygląda tak:
[15-Mar-2024 14:22:33 UTC] PHP Fatal error: Uncaught Error: Class 'SomeModule\SomeClass' not found in /var/www/html/modules/somemodule/somemodule.php:45
Logi serwera webowego (Apache i Nginx)
Twój serwer webowy prowadzi własny zestaw logów niezależny od PHP i PrestaShop. Te logi są niezbędne do diagnozowania błędów 500, 404 i problemów z wydajnością.
Logi Apache zazwyczaj znajdują się w:
/var/log/apache2/error.log — log błędów na systemach Debian i Ubuntu./var/log/httpd/error_log — log błędów na systemach CentOS i RHEL./var/log/apache2/access.log — log dostępu, rejestrujący każde żądanie HTTP.
Logi Nginx zazwyczaj znajdują się w:
/var/log/nginx/error.log — log błędów./var/log/nginx/access.log — log dostępu.
Jeśli Twoja strona używa konfiguracji wirtualnych hostów, logi mogą być w lokalizacji specyficznej dla strony, zdefiniowanej przez dyrektywę ErrorLog (Apache) lub error_log (Nginx) w pliku wirtualnego hosta.
Logi błędów serwera webowego przechwytują takie problemy jak błędy braku uprawnień, gdy PHP próbuje pisać do katalogu, błędy składni konfiguracji po zmianie .htaccess oraz błędy timeout proxy, jeśli używasz PHP-FPM za Nginx. To są logi do sprawdzenia, gdy widzisz ogólny błąd 500 Internal Server Error bez szczegółów w logach PHP lub PrestaShop.
Starsze logi PrestaShop (panel administracyjny)
PrestaShop prowadzi również przeglądarkę logów w panelu administracyjnym w Zaawansowane > Logi. Ten interfejs pokazuje wpisy logów przechowywane w tabeli ps_log bazy danych. Te logi przechwytują zdarzenia, które PrestaShop jawnie rejestruje, takie jak nieudane próby logowania, błędy instalacji modułów i niepowodzenia wysyłki e-maili.
Choć przeglądarka logów w panelu administracyjnym jest wygodna, ma istotne ograniczenia. Nie przechwytuje błędów PHP, błędów serwera webowego ani większości błędów fatalnych, które uniemożliwiają załadowanie strony. Traktuj ją jako uzupełnienie logów plikowych, nie ich zamiennik.
Włączanie trybu debugowania w PrestaShop
Domyślnie PrestaShop działa w trybie produkcyjnym i ukrywa szczegółowe komunikaty o błędach przed odwiedzającymi. Jest to poprawne dla działającego sklepu, ale sprawia, że debugowanie jest prawie niemożliwe. Gdy coś się zepsuje, Twoim pierwszym krokiem powinno być włączenie trybu debugowania.
Metoda 1: Plik defines.inc.php
Otwórz plik config/defines.inc.php i znajdź linię ustawiającą _PS_MODE_DEV_. Zmień wartość z false na true:
define('_PS_MODE_DEV_', true);
Ta pojedyncza zmiana ma kilka efektów. Raportowanie błędów PHP jest ustawione na maksymalny poziom, pokazując wszystkie błędy, ostrzeżenia i powiadomienia. Buforowanie szablonów Smarty jest wyłączone, więc zmiany w szablonach pojawiają się natychmiast. Pasek profilowania Symfony pojawia się na dole stron panelu administracyjnego. I co najważniejsze, szczegóły błędów są wyświetlane na ekranie zamiast generycznej strony błędu.
Metoda 2: Tryb profilowania
Dla głębszej analizy możesz również włączyć profilowanie. W tym samym pliku ustaw:
define('_PS_DEBUG_PROFILING_', true);
To dodaje szczegółowe informacje o czasach wykonania i użyciu pamięci na dole każdej strony, pokazując, które hooki trwają najdłużej, które moduły zużywają najwięcej pamięci i ile zapytań do bazy danych generuje każda strona. Jest to nieocenione przy debugowaniu wydajności, ale nigdy nie powinno być włączone na produkcji.
Ostrzeżenie bezpieczeństwa
Tryb debugowania ujawnia wrażliwe informacje, w tym ścieżki plików, dane logowania do bazy danych w stack trace'ach i wewnętrzną strukturę aplikacji. Nigdy nie zostawiaj trybu debugowania włączonego na sklepie produkcyjnym dostępnym publicznie. Jeśli musisz debugować działający sklep, rozważ ograniczenie trybu debugowania do Twojego adresu IP, opakowując define w sprawdzenie IP, lub użyj środowiska stagingowego.
Czytanie stack trace'ów
Gdy PrestaShop napotyka błąd fatalny lub nieprzechwycony wyjątek w trybie debugowania, wyświetla stack trace. Stack trace to migawka łańcucha wywołań, który doprowadził do błędu, czytana od punktu awarii wstecz do oryginalnego punktu wejścia. Nauka czytania stack trace'ów to najcenniejsza umiejętność debugowania, jaką możesz rozwinąć.
Anatomia stack trace'a
Typowy stack trace PrestaShop wygląda tak:
PHP Fatal error: Uncaught TypeError: Argument 1 passed to Product::getProductProperties() must be of the type int, null given, called in /var/www/html/classes/Product.php on line 4523
Stack trace:
#0 /var/www/html/classes/Product.php(4523): Product::getProductProperties(NULL, Array)
#1 /var/www/html/modules/somemodule/somemodule.php(127): Product::getProductProperties(1, Array)
#2 /var/www/html/classes/Hook.php(523): SomeModule->hookDisplayHome(Array)
#3 /var/www/html/classes/Hook.php(460): Hook::coreCallHook(Object(SomeModule), 'hookDisplayHome', Array)
#4 /var/www/html/classes/Hook.php(408): Hook::exec('displayHome', Array)
Czytaj stack trace od góry do dołu. Pierwsza linia mówi Ci, co poszło nie tak: funkcja oczekiwała liczby całkowitej, ale otrzymała null. Linia #0 mówi Ci, gdzie wystąpił błąd. Linia #1 mówi Ci, co wywołało kod w #0. Linia #2 mówi Ci, co wywołało #1 i tak dalej.
W tym przykładzie łańcuch jest jasny: PrestaShop wykonał hook displayHome, który wywołał metodę hookDisplayHome w SomeModule, która wywołała Product::getProductProperties() z wartością null zamiast oczekiwanej liczby całkowitej. Błąd jest w module w linii 127, gdzie przekazuje nieprawidłową wartość.
Znajdowanie odpowiedniej ramki
Stack trace'y w PrestaShop mogą być długie, czasem 20 lub 30 ramek głębokie. Kluczem jest znalezienie ramki zawierającej Twój kod lub moduł powodujący problem. Szukaj ścieżek zawierających /modules/ lub /themes/, ponieważ to najbardziej prawdopodobne źródła błędów. Ramki odwołujące się do /classes/, /src/ lub /vendor/ to rdzeń PrestaShop lub biblioteki firm trzecich, które rzadziej są źródłem problemu, chyba że modyfikowałeś pliki rdzenia.
Typowe wzorce błędów PrestaShop
Po przeczytaniu tysięcy logów błędów PrestaShop pewne wzorce powtarzają się regularnie. Rozpoznanie tych wzorców pozwala diagnozować problemy w sekundach zamiast godzin.
Błędy "Class Not Found"
PHP Fatal error: Uncaught Error: Class 'ModuleName\ClassName' not found
Oznacza to, że autoloader nie może znaleźć określonej klasy. Typowe przyczyny to: brak pliku vendor/autoload.php (moduł wymaga uruchomienia composer install), niedopasowana deklaracja namespace, plik który nie został dołączony do archiwum ZIP modułu podczas instalacji, lub problem z wielkością liter na serwerach Linux, gdzie ClassName.php i classname.php to różne pliki.
Błędy braku uprawnień
Warning: file_put_contents(/var/www/html/var/cache/prod/some_file): failed to open stream: Permission denied
Występują, gdy użytkownik serwera webowego (zazwyczaj www-data na Debian/Ubuntu lub apache na CentOS) nie ma uprawnień do zapisu pliku lub katalogu. Napraw to, poprawiając właściciela: chown -R www-data:www-data var/cache/ i uprawnienia: chmod -R 775 var/cache/.
Błędy limitu pamięci
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 65536 bytes)
Liczba 134217728 bajtów to 128MB — domyślny limit pamięci PHP. PrestaShop zaleca minimum 256MB. Zwiększ go w pliku php.ini: memory_limit = 512M. Jeśli błąd utrzymuje się nawet przy wysokich limitach pamięci, kod prawdopodobnie ma wyciek pamięci, często spowodowany ładowaniem zbyt wielu produktów lub kategorii w jednym zapytaniu bez paginacji.
Błędy połączenia z bazą danych
Link to database cannot be established: SQLSTATE[HY000] [2002] Connection refused
Oznacza to, że PrestaShop nie może połączyć się z serwerem MySQL. Sprawdź, czy serwer bazy danych działa, czy dane logowania w app/config/parameters.php są poprawne i czy host bazy danych jest dostępny z serwera webowego.
Błędy szablonów Smarty
SmartyException: Unable to load template file 'module:somemodule/views/templates/hook/display.tpl'
Plik szablonu jest brakujący, błędnie nazwany lub w złym katalogu. Zweryfikuj, czy plik istnieje w oczekiwanej ścieżce i czy nazwa pliku dokładnie się zgadza, włącznie z wielkością liter.
Błędy tokena CSRF
Invalid token. Please try to log in again.
Pojawia się w panelu administracyjnym, gdy przesłanie formularza zawiera wygasły lub brakujący token bezpieczeństwa. Zwykle dzieje się tak, gdy sesja wygasa podczas długiej sesji edycji, gdy wiele zakładek jest otwartych na tej samej stronie admina lub gdy moduł nieprawidłowo generuje URL-e formularzy.
Używanie grep do wyszukiwania błędów
Gdy pliki logów są duże, ręczne ich przeglądanie jest niepraktyczne. Polecenie grep to Twój najlepszy przyjaciel do szybkiego znajdowania istotnych wpisów.
Podstawowe wyszukiwanie błędów
Aby znaleźć wszystkie błędy fatalne w logu PHP:
grep 'Fatal error' /var/log/php_errors.log
Aby znaleźć błędy z konkretnego modułu:
grep 'somemodule' /var/www/html/var/logs/prod.log
Aby znaleźć błędy tylko z dzisiaj (zakładając format daty w logu):
grep '2024-03-15' /var/www/html/var/logs/prod.log | grep 'ERROR\|CRITICAL'
Zaawansowane filtrowanie
Aby zobaczyć błędy z otaczającym kontekstem (3 linie przed i po każdym dopasowaniu):
grep -C 3 'Fatal error' /var/log/php_errors.log
Aby policzyć, ile razy pojawia się każdy unikalny błąd:
grep 'Fatal error' /var/log/php_errors.log | sort | uniq -c | sort -rn | head -20
Ten pipeline sortuje błędy, liczy duplikaty, sortuje malejąco po liczbie i pokazuje top 20. Jest to niezwykle przydatne do identyfikacji najczęściej występujących błędów wymagających uwagi w pierwszej kolejności.
Aby przeszukiwać jednocześnie wiele plików logów:
grep -r 'Fatal error' /var/log/ --include='*.log'
Flaga -r przeszukuje rekurencyjnie, a --include ogranicza wyszukiwanie do plików z rozszerzeniem .log.
Monitorowanie logów w czasie rzeczywistym za pomocą tail -f
Gdy aktywnie debugujesz problem, musisz widzieć błędy w momencie ich wystąpienia. Polecenie tail -f śledzi plik logów w czasie rzeczywistym, wyświetlając nowe wpisy w momencie ich zapisu.
Podstawowe monitorowanie w czasie rzeczywistym
Aby obserwować log produkcyjny PrestaShop w czasie rzeczywistym:
tail -f /var/www/html/var/logs/prod.log
Aby obserwować log błędów PHP:
tail -f /var/log/php_errors.log
Aby obserwować wiele plików logów jednocześnie:
tail -f /var/www/html/var/logs/prod.log /var/log/php_errors.log /var/log/apache2/error.log
Filtrowane monitorowanie w czasie rzeczywistym
Aby obserwować tylko wpisy poziomu error w czasie rzeczywistym, połącz tail z grep:
tail -f /var/www/html/var/logs/prod.log | grep --line-buffered 'ERROR\|CRITICAL'
Flaga --line-buffered jest tu ważna. Bez niej grep buforuje output i możesz nie widzieć dopasowań od razu.
Aby podświetlić konkretne słowa kluczowe, pokazując jednocześnie cały output:
tail -f /var/www/html/var/logs/prod.log | grep --color=always -E 'ERROR|CRITICAL|$'
To podświetla ERROR i CRITICAL kolorem, jednocześnie wyświetlając wszystkie linie.
Workflow debugowania
Najskuteczniejszy workflow debugowania łączy monitorowanie w czasie rzeczywistym z aktywnym testowaniem. Otwórz jedno okno terminala z uruchomionym tail -f na odpowiednich plikach logów. W przeglądarce odtwórz akcję powodującą błąd. Obserwuj terminal w poszukiwaniu nowych wpisów logów, które pojawiają się dokładnie w momencie wywołania problemu. To podejście eliminuje zgadywanie i pokazuje precyzyjnie, co dzieje się w momencie wystąpienia błędu.
Rotacja i zarządzanie logami
Pliki logów rosną nieprzerwanie i mogą zużyć całą dostępną przestrzeń dyskową, jeśli nie są zarządzane. Większość serwerów Linux używa logrotate do automatycznego zarządzania tym, ale własne logi PrestaShop w var/logs/ mogą nie być uwzględnione w domyślnej konfiguracji logrotate.
Zrozumienie logrotate
Narzędzie logrotate uruchamia się codziennie (zazwyczaj przez cron) i obsługuje rotację, kompresję i usuwanie plików logów. Pliki konfiguracyjne znajdują się w /etc/logrotate.d/. Rotacja logów Apache i Nginx jest zazwyczaj skonfigurowana fabrycznie.
Dla katalogu var/logs PrestaShop może być konieczne utworzenie niestandardowej konfiguracji logrotate:
/var/www/html/var/logs/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data www-data
}
To rotuje logi codziennie, przechowuje 14 dni historii, kompresuje stare logi i tworzy nowe pliki logów z poprawnymi uprawnieniami.
Ręczne czyszczenie logów
Jeśli plik logów urósł do ogromnych rozmiarów i musisz go wyczyścić bez utraty uchwytu pliku (ważne, jeśli jakiś proces aktywnie do niego pisze):
truncate -s 0 /var/www/html/var/logs/prod.log
Nie usuwaj pliku i nie twórz go ponownie, ponieważ każdy proces, który ma otwarty plik, będzie nadal pisał do inode'a usuniętego pliku do momentu restartu. Podejście z truncate czyści zawartość, zachowując inode.
Zrozumienie kontekstów błędów specyficznych dla PrestaShop
Błędy PrestaShop często pojawiają się z kontekstem unikalnym dla tej platformy. Zrozumienie tego kontekstu pomaga szybciej lokalizować i naprawiać problemy.
Błędy związane z hookami
Gdy błąd występuje wewnątrz hooka, stack trace będzie zawierał odwołania do Hook::exec() i Hook::coreCallHook(). Nazwa hooka mówi Ci dokładnie, w którym momencie renderowania strony pojawia się błąd. Na przykład błędy displayHome pojawiają się na stronie głównej, błędy actionValidateOrder podczas składania zamówienia, a błędy displayBackOfficeHeader przy ładowaniu dowolnej strony panelu administracyjnego.
Jeśli błąd hooka powoduje crash strony, możesz tymczasowo wyłączyć problematyczny moduł z bazy danych:
UPDATE ps_module SET active = 0 WHERE name = 'somemodule';
To pozwoli Ci uzyskać dostęp do panelu administracyjnego w celu prawidłowej diagnozy i naprawy problemu.
Konflikty nadpisań (override)
System nadpisań PrestaShop pozwala modułom rozszerzać klasy rdzenia, ale konflikty powstają, gdy dwa moduły nadpisują tę samą klasę. Błąd zazwyczaj pojawia się jako konflikt sygnatury metody lub nieoczekiwana zmiana zachowania. Sprawdź katalog override/, aby zobaczyć, które nadpisania są aktywne, i sprawdź plik cache/class_index.php, który mapuje klasy na ich pliki nadpisań. Usunięcie tego pliku cache zmusza PrestaShop do ponownego wygenerowania mapy nadpisań.
Błędy związane z cache
Wiele błędów PrestaShop jest spowodowanych przestarzałymi plikami cache. Jeśli widzisz błędy, które nie odpowiadają aktualnemu kodowi (na przykład błąd odwołujący się do numeru linii, który nie istnieje w pliku), cache jest prawdopodobnie nieaktualny. Wyczyść go, usuwając zawartość var/cache/prod/ i var/cache/dev/. W PrestaShop 1.6 wyczyść zamiast tego cache/smarty/compile/ i cache/smarty/cache/.
Błędy instalacji i aktualizacji modułów
Instalacje modułów mogą cicho się nie powieść, pozostawiając moduł w stanie częściowej instalacji. Sprawdź var/logs/prod.log pod kątem wpisów z czasu instalacji. Typowe problemy to brakujące tabele bazy danych (SQL w metodzie install() modułu się nie powiodło), brakujące hooki (wywołanie registerHook() się nie powiodło) oraz błędy duplikatu wpisu w tabeli ps_authorization_role przy ponownej instalacji modułu, który nie został w pełni odinstalowany.
Budowanie listy kontrolnej debugowania
Gdy napotkasz błąd PrestaShop, postępuj według tej systematycznej listy kontrolnej, aby efektywnie znaleźć przyczynę:
Po pierwsze, zidentyfikuj typ błędu. Czy to biały ekran (błąd 500), konkretny komunikat o błędzie, zepsuty układ strony czy nieoczekiwane zachowanie? Każdy typ wskazuje na inne pliki logów.
Po drugie, sprawdź najpierw najbardziej specyficzny log. Dla błędów PHP sprawdź log błędów PHP. Dla błędów HTTP sprawdź log serwera webowego. Dla błędów aplikacji sprawdź var/logs/prod.log.
Po trzecie, włącz tryb debugowania, jeśli logi nie ujawniają wystarczającej ilości informacji. Zmień _PS_MODE_DEV_ na true i odtwórz błąd.
Po czwarte, użyj tail -f na odpowiednich logach i odtwórz błąd w przeglądarce. To daje Ci widok w czasie rzeczywistym na dokładnie to, co się dzieje.
Po piąte, przeczytaj stack trace od góry do dołu. Znajdź ramkę odwołującą się do kodu Twojego modułu lub motywu. To tam trzeba zastosować poprawkę.
Po szóste, wyszukaj komunikat o błędzie w GitHub issues i na forach PrestaShop. Istnieje duże prawdopodobieństwo, że ktoś już napotkał i rozwiązał ten sam problem.
Po siódme, po zastosowaniu poprawki wyczyść wszystkie cache i monitoruj logi, aby potwierdzić, że błąd zniknął. Poprawka, która nie daje czystego logu, nie jest kompletną poprawką.
Podsumowanie
Czytanie logów błędów PrestaShop nie jest tajemną sztuką zarezerwowaną dla seniorskich programistów. To praktyczna umiejętność oparta na wiedzy, gdzie logi się znajdują, jak je filtrować i jak interpretować ich zawartość. Logi w var/logs/, log błędów PHP i log serwera webowego — każdy służy innemu celowi, a razem dają pełny obraz każdego problemu. Włączenie trybu debugowania daje szczegółowe komunikaty o błędach. Stack trace'y pokazują dokładny łańcuch wywołań funkcji, który doprowadził do awarii. Narzędzia takie jak grep i tail -f umożliwiają efektywne wyszukiwanie i monitorowanie błędów nawet w dużych, obciążonych plikach logów. Opanuj te techniki, a będziesz rozwiązywać problemy szybciej, z mniejszą frustracją i ze znacznie mniejszą zależnością od zewnętrznego wsparcia.
Zrozumienie kodów błędów HTTP w PrestaShop
Kody błędów HTTP to standardowe odpowiedzi z serwera WWW wskazujące, że coś poszło nie tak, gdy przeglądarka lub bot wyszukiwarki próbował uzyskać dostęp do strony. Dla właścicieli sklepów PrestaShop te błędy mogą oznaczać utratę sprzedaży, sfrustrowanych klientów i uszkodzone pozycje SEO.
Błąd 403 - Zabroniony
Błąd 403 oznacza, że serwer zrozumiał Twoje żądanie, ale odmawia jego autoryzacji. To zazwyczaj problem z uprawnieniami lub kontrolą dostępu.
1. Nieprawidłowe uprawnienia plików i katalogów
Katalogi powinny mieć 755, a pliki 644.
find /var/www/html/prestashop -type d -exec chmod 755 {} \;
find /var/www/html/prestashop -type f -exec chmod 644 {} \;
chown -R www-data:www-data /var/www/html/prestashop2. Reguły .htaccess blokujące dostęp
Zbyt restrykcyjny plik .htaccess może blokować prawidłowe żądania.
3. ModSecurity lub WAF blokujący żądania
Zapory aplikacji webowych mogą generować fałszywe alarmy.
Naprawianie błędów 403
- Sprawdź i napraw uprawnienia plików
- Przejrzyj .htaccess pod kątem zbyt restrykcyjnych reguł
- Sprawdź logi bezpieczeństwa hostingu
- Sprawdź, czy Twoje IP nie jest na liście blokowanych
Błąd 404 - Nie znaleziono
Błąd 404 oznacza, że serwer nie może znaleźć żądanej strony.
1. Wyłączone lub źle skonfigurowane przyjazne URL
Przejdź do Parametry sklepu > Ruch i SEO, upewnij się, że przyjazne URL są włączone i kliknij Zapisz. Sprawdź, czy mod_rewrite jest włączony na serwerze.
2. Usunięte produkty lub kategorie bez przekierowań
Zawsze ustawiaj przekierowania 301 przy usuwaniu treści.
3. Brakujący lub uszkodzony .htaccess
Zregeneruj .htaccess z Parametrów sklepu > Ruch i SEO.
Naprawianie błędów 404
- Sprawdź, czy .htaccess istnieje i jest poprawnie skonfigurowany
- Sprawdź, czy mod_rewrite jest włączony
- Zregeneruj .htaccess
- Ustaw przekierowania 301
- Sprawdź Google Search Console pod kątem błędów crawlowania
Błąd 500 - Wewnętrzny błąd serwera
Błąd 500 oznacza, że coś poszło nie tak po stronie serwera.
1. Przekroczony limit pamięci PHP
memory_limit = 512M2. Błędy składni PHP lub błędy krytyczne
define('_PS_MODE_DEV_', true);3. Niezgodność wersji PHP
| PrestaShop | PHP Minimum | PHP Zalecany |
|---|---|---|
| 1.7.x | 7.1 | 7.4 |
| 8.x | 7.2 | 8.1 |
| 9.x | 8.1 | 8.2+ |
4. Problemy z połączeniem z bazą danych
Sprawdź dane logowania w app/config/parameters.php.
5. Konflikty modułów
mv modules/problematic_module modules/problematic_module_disabledNaprawianie błędów 500
- Włącz tryb debug
- Sprawdź log błędów PHP
- Zwiększ limit pamięci PHP
- Sprawdź kompatybilność wersji PHP
- Wyłącz ostatnio zainstalowane moduły
Błąd 503 - Usługa niedostępna
Błąd 503 oznacza, że serwer tymczasowo nie może obsłużyć żądania.
1. Tryb konserwacji nadal aktywny
UPDATE ps_configuration SET value = '0' WHERE name = 'PS_SHOP_ENABLE';2. Przeciążenie serwera
- Ulepsz plan hostingowy
- Włącz cachowanie PrestaShop
- Użyj CDN jak Cloudflare
- Włącz OPcache dla PHP
3. Wyczerpanie workerów PHP-FPM
pm = dynamic
pm.max_children = 50
pm.start_servers = 10Naprawianie błędów 503
- Sprawdź i wyłącz tryb konserwacji
- Monitoruj zasoby serwera
- Sprawdź logi PHP-FPM
- Przejrzyj harmonogram zadań cron
- Rozważ ulepszenie hostingu
Ogólne wskazówki debugowania
- Apache -
/var/log/apache2/error.log - Nginx -
/var/log/nginx/error.log - PHP-FPM -
/var/log/php-fpm/error.log - PrestaShop -
/var/logs/
Po każdej poprawce wyczyść wszystkie cache.
Jak PrestaShop wykorzystuje ciasteczka
Każdy sklep PrestaShop polega na ciasteczkach, aby funkcjonować. Utrzymują one sesje klientów, zapamiętują zawartość koszyka, przechowują preferencje językowe i walutowe, śledzą status zalogowania i umożliwiają panelowi administracyjnemu uwierzytelnianie administratorów. Bez ciasteczek sklep PrestaShop nie może utrzymać stanu pomiędzy załadowaniami stron, co oznacza brak koszyka, brak logowania klienta i brak dostępu do panelu administracyjnego.
PrestaShop używa dwóch głównych ciasteczek. Ciasteczko front office, zazwyczaj nazwane według Twojego sklepu (np. PrestaShop-abc123), obsługuje wszystko, czego potrzebuje strona skierowana do klienta. Ciasteczko back office, o podobnym wzorcu nazewnictwa, ale innym zakresie, obsługuje uwierzytelnianie administratorów. Oba ciasteczka przechowują zserializowane dane bezpośrednio w wartości ciasteczka, co jest decyzją projektową mającą istotne konsekwencje dla wydajności, bezpieczeństwa i zgodności z RODO.
Struktura i zawartość ciasteczek PrestaShop
W przeciwieństwie do wielu aplikacji internetowych, które przechowują w ciasteczku jedynie identyfikator sesji, a wszystkie dane sesji trzymają na serwerze, PrestaShop przechowuje znaczną ilość danych bezpośrednio w samym ciasteczku. Ciasteczko front office zawiera pola obejmujące identyfikator klienta, imię i adres e-mail klienta, informację o tym, czy klient jest zalogowany, identyfikator koszyka, wybrany język, wybraną walutę, ostatnio odwiedzaną kategorię, ostatnio odwiedzany produkt, etap realizacji zamówienia oraz różne inne informacje o stanie.
Dane te są serializowane przy użyciu własnej klasy ciasteczek PrestaShop (Cookie.php w katalogu classes). Wartość ciasteczka jest zaszyfrowana kluczem wywodzącym się ze stałej _COOKIE_KEY_ w pliku config/settings.inc.php (PrestaShop 1.6/1.7) lub app/config/parameters.php (PrestaShop 8.x). To szyfrowanie zapobiega manipulacji i chroni wrażliwe dane, takie jak identyfikator klienta i adres e-mail, przed odczytaniem w przeglądarce.
Dlaczego PrestaShop przechowuje dane w ciasteczku
Historycznym powodem tej decyzji projektowej jest wydajność. Przechowując dane sesji w ciasteczku, PrestaShop unika wyszukiwania sesji po stronie serwera przy każdym zapytaniu. Nie ma potrzeby odczytu z pliku sesji, odpytywania bazy danych ani łączenia się z serwerem sesji. Dane przychodzą wraz z zapytaniem, już dostępne.
Jednak to podejście ma wady, które stają się bardziej istotne w miarę rozwoju sklepu. Rozmiar ciasteczka rośnie wraz z ilością przechowywanych danych, a każde zapytanie HTTP (w tym zapytania o obrazy, CSS i pliki JavaScript) wysyła pełne ciasteczko do serwera. Ciasteczko o rozmiarze 4 KB wysyłane z 30 zapytaniami o zasoby na każde załadowanie strony oznacza 120 KB niepotrzebnego pasma przesyłania na jedno załadowanie strony. Ten narzut jest mierzalny na połączeniach mobilnych i przy dużej skali.
Rozmiar ciasteczka i wpływ na wydajność
Ciasteczka przeglądarki mają praktyczny limit rozmiaru wynoszący około 4096 bajtów na jedno ciasteczko. Ciasteczko front office PrestaShop może zbliżyć się do tego limitu lub go przekroczyć, zwłaszcza gdy moduły dodają własne dane do ciasteczka za pośrednictwem hooka hookActionBeforeSubmitAccount lub bezpośrednio modyfikując obiekt ciasteczka.
Pomiar wpływu rozmiaru ciasteczka
Aby zobaczyć, jak ciasteczka wpływają na wydajność Twojego sklepu, otwórz narzędzia deweloperskie przeglądarki i przejdź do zakładki Sieć. Spójrz na nagłówki zapytania dla dowolnego zapytania do Twojej domeny. Nagłówek Cookie pokazuje wszystkie wysyłane ciasteczka. Zwróć uwagę na jego rozmiar. Teraz spójrz na nagłówki zapytania dla zasobu statycznego (obrazu lub pliku CSS) w tej samej domenie. Te same ciasteczka są wysyłane z tym zapytaniem, dodając narzut bez żadnego powodu.
Redukcja narzutu ciasteczek dla zasobów statycznych
Najskuteczniejszym sposobem eliminacji narzutu ciasteczek dla plików statycznych jest serwowanie ich z innej domeny (domeny bez ciasteczek). W PrestaShop możesz skonfigurować serwery mediów w back office w sekcji Zaawansowane parametry > Wydajność. Gdy ustawisz serwer mediów jak static.twojadomena.com, PrestaShop serwuje obrazy, CSS i JavaScript z tej domeny. Ponieważ ciasteczka są specyficzne dla domeny, żadne ciasteczka nie są wysyłane z zapytaniami do domeny mediów.
Alternatywnie, CDN taki jak Cloudflare, Fastly lub CloudFront może serwować Twoje zasoby statyczne. Serwery brzegowe CDN zazwyczaj usuwają ciasteczka z cachowanych odpowiedzi, więc nawet jeśli ciasteczka są wysyłane w zapytaniu, odpowiedź pochodzi z cache bez narzutu podróży w obie strony do serwera źródłowego.
Rozdęcie ciasteczek przez moduły
Moduły firm trzecich czasami dodają dane do ciasteczka PrestaShop bez uwzględnienia konsekwencji rozmiaru. Każdy moduł, który przechowuje wartość w ciasteczku, zwiększa jego rozmiar i narzut przy każdym zapytaniu. Jeśli Twoje ciasteczko jest niezwykle duże, sprawdź, jakie dane dodały moduły, badając odszyfrowaną zawartość ciasteczka lub przeglądając kod modułów w poszukiwaniu wywołań $this->context->cookie->mymodule_value = ....
Dobrze zaprojektowane moduły używają przechowywania po stronie serwera (bazy danych lub cache) i przechowują w ciasteczku co najwyżej mały identyfikator. Źle zaprojektowane moduły zrzucają pełne struktury danych do ciasteczka, nadmiernie zwiększając jego rozmiar. Jeśli zidentyfikujesz problematyczny moduł, skontaktuj się z deweloperem lub zastąp przechowywanie w ciasteczku przechowywaniem opartym na bazie danych z wykorzystaniem identyfikatora sesji.
Obsługa sesji: pliki, baza danych i Redis
Chociaż PrestaShop przechowuje niektóre dane bezpośrednio w ciasteczkach, PHP utrzymuje również własny system sesji. Back office PrestaShop w większym stopniu polega na sesjach PHP niż front office. Obsługa sesji określa, gdzie dane sesji są przechowywane po stronie serwera.
Sesje oparte na plikach (domyślne)
Domyślnie PHP przechowuje sesje jako pliki w katalogu session.save_path (zazwyczaj /tmp lub /var/lib/php/sessions). Każda sesja tworzy plik. Dla sklepu z tysiącami aktywnych sesji oznacza to tysiące małych plików. Sesje oparte na plikach działają dobrze dla małych i średnich sklepów, ale mogą powodować problemy przy dużej skali.
Typowe problemy z sesjami opartymi na plikach obejmują wolne czyszczenie sesji (garbage collection), gdy katalog sesji zawiera zbyt wiele plików, blokowanie plików, które może powodować serializację zapytań (dwa zapytania z tej samej sesji nie mogą być przetwarzane jednocześnie), oraz środowiska hostingu współdzielonego, w których katalog sesji się zapełnia lub ma restrykcyjne uprawnienia.
Sesje w bazie danych
PrestaShop obsługuje przechowywanie sesji w bazie danych. Jest to konfigurowane w ustawieniach PHP lub przez obsługę sesji PrestaShop. Sesje w bazie danych eliminują problemy systemu plików, ale dodają zapytanie do bazy danych przy każdym zapytaniu HTTP. Dla sklepów, które już mają duże obciążenie bazy danych, może to pogorszyć wydajność. Jednak sesje w bazie danych mają tę zaletę, że są współdzielone między wieloma serwerami WWW w konfiguracji z load balancerem.
Sesje w Redis lub Memcached
Dla sklepów PrestaShop o dużym ruchu, Redis jest optymalnym backendem do przechowywania sesji. Redis przechowuje dane sesji w pamięci, zapewniając czasy dostępu poniżej milisekundy. Obsługuje automatyczne wygasanie (timeout sesji), a dane sesji są współdzielone między wszystkimi instancjami serwerów WWW.
Aby skonfigurować PHP do używania Redis dla sesji, ustaw session.save_handler = redis i session.save_path = "tcp://127.0.0.1:6379" w pliku php.ini lub konfiguracji puli PHP-FPM. Jeśli instancja Redis wymaga uwierzytelniania, dodaj hasło do ścieżki zapisu: "tcp://127.0.0.1:6379?auth=twojehaslo".
PrestaShop już obsługuje Redis do cachowania obiektów (konfigurowane w back office w sekcji Zaawansowane parametry > Wydajność). Używanie tej samej instancji Redis zarówno dla sesji, jak i cachowania obiektów upraszcza infrastrukturę, zapewniając jednocześnie doskonałą wydajność dla obu zastosowań.
Atrybuty SameSite, Secure i HttpOnly
Nowoczesne przeglądarki wymuszają atrybuty bezpieczeństwa ciasteczek, które bezpośrednio wpływają na zachowanie ciasteczek PrestaShop. Nieprawidłowo skonfigurowane atrybuty ciasteczek powodują błędy logowania, utracone koszyki i problemy z przetwarzaniem płatności.
Atrybut SameSite
Atrybut SameSite kontroluje, czy ciasteczko jest wysyłane z zapytaniami między witrynami. Ma trzy możliwe wartości:
SameSite=Strict oznacza, że ciasteczko nigdy nie jest wysyłane z zapytaniami między witrynami. Jest to zbyt restrykcyjne dla PrestaShop, ponieważ klienci klikający link do Twojego sklepu z e-maila lub mediów społecznościowych nie mieliby wysyłanego ciasteczka sesji, co skutecznie wylogowałoby ich.
SameSite=Lax jest domyślną wartością w nowoczesnych przeglądarkach. Ciasteczko jest wysyłane z nawigacjami najwyższego poziomu (kliknięcie linku), ale nie z zapytaniami podrzędnymi między witrynami (obrazy, iframe, AJAX). Działa to dobrze dla ciasteczka front office PrestaShop w większości przypadków.
SameSite=None oznacza, że ciasteczko jest zawsze wysyłane, w tym z zapytaniami między witrynami. Musi to być połączone z atrybutem Secure. Jest to potrzebne, gdy Twój sklep jest osadzony w iframe na innej witrynie lub gdy bramki płatności firm trzecich muszą przekierować z powrotem do Twojego sklepu z nienaruszoną sesją.
Problemy z bramkami płatności
Wiele problemów z płatnościami w PrestaShop jest spowodowanych problemami z ciasteczkami SameSite. Typowy scenariusz wygląda następująco: klient realizuje zamówienie, jest przekierowywany na stronę bramki płatności, dokonuje płatności i jest przekierowywany z powrotem do Twojego sklepu. Jeśli ciasteczko sesji ma SameSite=Lax, może nie zostać wysłane przy przekierowaniu z bramki płatności, w zależności od sposobu implementacji przekierowania. Jeśli bramka używa przekierowania POST (typowe dla 3D Secure), polityka Lax blokuje ciasteczko, a PrestaShop traci sesję. Klient widzi pusty koszyk lub ogólną stronę błędu zamiast potwierdzenia zamówienia.
Rozwiązaniem jest ustawienie ciasteczka PrestaShop na SameSite=None; Secure. W PrestaShop 1.7.7+ i 8.x można to skonfigurować w ustawieniach ciasteczek. Dla starszych wersji może być konieczna modyfikacja klasy Cookie lub dodanie nagłówków przez konfigurację serwera WWW. Zawsze testuj przepływy płatności po zmianie ustawień SameSite.
Atrybut Secure
Atrybut Secure zapewnia, że ciasteczko jest wysyłane tylko przez połączenia HTTPS. Jeśli Twój sklep działa na HTTPS (co powinien), ten atrybut zapobiega przesyłaniu ciasteczka przez nieszyfrowane połączenie, chroniąc je przed przechwyceniem. PrestaShop ustawia ten atrybut, gdy sklep wykrywa połączenie HTTPS.
Typowy problem występuje przy mieszanych konfiguracjach HTTP/HTTPS. Jeśli back office działa na HTTPS, ale niektóre strony front office na HTTP, ciasteczka oznaczone jako Secure nie zostaną wysłane na stronach HTTP, przerywając sesję. Rozwiązaniem jest wymuszenie HTTPS wszędzie, co i tak powinieneś robić ze względów bezpieczeństwa i SEO.
Atrybut HttpOnly
Atrybut HttpOnly zapobiega dostępowi JavaScript do ciasteczka przez document.cookie. Jest to kluczowy środek bezpieczeństwa przeciwko atakom cross-site scripting (XSS). Jeśli atakujący wstrzyknie złośliwy JavaScript do Twojego sklepu (na przykład przez podatny moduł), atrybut HttpOnly zapobiega kradzieży ciasteczek sesji przez ten kod.
PrestaShop domyślnie ustawia flagę HttpOnly na swoich ciasteczkach. Nie wyłączaj tego, chyba że masz bardzo konkretny powód i rozumiesz konsekwencje bezpieczeństwa.
Debugowanie problemów z sesjami i ciasteczkami
Problemy z ciasteczkami i sesjami objawiają się tajemniczymi symptomami: losowe wylogowywanie klientów, koszyki, które same się opróżniają, sesje administracyjne wygasające natychmiast, procesy zamówienia kończące się cichym niepowodzeniem. Systematyczne debugowanie wymaga sprawdzenia kilku warstw.
Narzędzia deweloperskie przeglądarki
Otwórz zakładkę Application (Chrome) lub Storage (Firefox) i przejdź do Cookies. Znajdź domenę swojego sklepu i zbadaj wszystkie ciasteczka. Sprawdź kolumny Name, Value, Domain, Path, Expires, Size, HttpOnly, Secure i SameSite. Szukaj ciasteczek, które są nieoczekiwanie duże, mają nieprawidłowe ustawienia domeny (ciasteczko dla www.example.com nie zostanie wysłane do example.com) lub brakuje im atrybutów bezpieczeństwa.
Weryfikacja sesji po stronie serwera
Jeśli sesje są przechowywane w plikach, sprawdź katalog sesji pod kątem obecności i wieku plików sesji. Jeśli klient zgłasza wylogowanie, znajdź plik sesji (nazwa pliku to identyfikator sesji z ciasteczka PHPSESSID) i sprawdź, kiedy został ostatnio zmodyfikowany. Jeśli plik nie istnieje, sesja została albo wyczyszczona przez garbage collector, albo nigdy nie została prawidłowo utworzona.
Dla sesji Redis użyj redis-cli, aby sprawdzić, czy klucz sesji istnieje: EXISTS PHPREDIS_SESSION:session_id. Sprawdź TTL, aby zobaczyć, czy wkrótce wygaśnie: TTL PHPREDIS_SESSION:session_id.
Typowe przyczyny losowych wylogowań
Zmiana _COOKIE_KEY_. Jeśli ten klucz się zmieni (podczas nieprawidłowo skonfigurowanego wdrożenia, nadpisania pliku ustawień lub aktualizacji), wszystkie istniejące ciasteczka stają się nieczytelne, ponieważ zostały zaszyfrowane starym kluczem. Każdy klient jest efektywnie wylogowany. Rozwiązaniem jest przywrócenie oryginalnego klucza z kopii zapasowej.
Zbyt agresywne czyszczenie sesji. Parametr PHP session.gc_maxlifetime określa, jak długo (w sekundach) plik sesji jest uznawany za ważny. Jeśli jest ustawiony zbyt nisko (domyślnie 1440 sekund, czyli 24 minuty), sesje klientów przeglądających sklep wolno są usuwane. Dla sklepu ustaw to na co najmniej 3600 (1 godzinę) lub więcej.
Load balancer bez koligacji sesji. Jeśli Twój sklep działa na wielu serwerach WWW za load balancerem, a sesje są przechowywane w plikach, każdy serwer ma własny katalog sesji. Klient, którego zapytania na przemian trafiają do różnych serwerów, traci sesję przy każdym przełączeniu. Rozwiązaniem jest albo koligacja sesji (sticky sessions) na load balancerze, albo współdzielone przechowywanie sesji za pomocą Redis lub bazy danych.
Niezgodność domeny ciasteczka. Jeśli Twój sklep jest dostępny zarówno pod www.example.com, jak i example.com, ale domena ciasteczka jest ustawiona na www.example.com, klienci uzyskujący dostęp do witryny bez prefiksu www nie będą mieli ciasteczka. Zapewnij spójne użycie domeny za pomocą przekierowania i zweryfikuj domenę ciasteczka w ustawieniach PrestaShop.
Zgodność ciasteczek z RODO
Ogólne rozporządzenie o ochronie danych (RODO) oraz dyrektywa ePrivacy wymagają świadomej zgody przed ustawieniem nieistotnych ciasteczek w przeglądarce użytkownika. Sklepy PrestaShop muszą przestrzegać tych przepisów, a ich nieprzestrzeganie może skutkować znacznymi karami finansowymi.
Ciasteczka istotne vs nieistotne
RODO rozróżnia ciasteczka, które są ściśle niezbędne do funkcjonowania witryny, od ciasteczek, które służą innym celom, takim jak analityka, marketing czy personalizacja. Ciasteczko sesji PrestaShop jest istotne, ponieważ sklep nie może funkcjonować bez niego. Klient nie może dodać produktów do koszyka ani zakończyć zakupu bez ciasteczka sesji. Ciasteczka istotne nie wymagają zgody na mocy RODO.
Jednak wiele innych ciasteczek powszechnie spotykanych w sklepach PrestaShop jest nieistotnych i wymaga wyraźnej zgody przed ich ustawieniem. Obejmują one ciasteczka śledzenia Google Analytics (_ga, _gid), ciasteczka Facebook Pixel, ciasteczka reklamowe z platform remarketingowych, ciasteczka widżetów czatu na żywo, ciasteczka przycisków udostępniania w mediach społecznościowych oraz wszelkie ciasteczka ustawiane przez moduły firm trzecich do celów śledzenia lub personalizacji.
Implementacja zgody na ciasteczka
PrestaShop nie zawiera wbudowanego mechanizmu zgody na ciasteczka, który spełnia wymagania RODO. Potrzebujesz albo modułu PrestaShop zaprojektowanego do zgody na ciasteczka, albo integracji z platformą zarządzania zgodami (CMP) firm trzecich, taką jak Cookiebot, Osano czy Usercentrics.
Prawidłowa implementacja zgody na ciasteczka musi przedstawić użytkownikowi jasny wybór przed ustawieniem jakichkolwiek nieistotnych ciasteczek. Musi umożliwić użytkownikowi akceptację lub odrzucenie poszczególnych kategorii ciasteczek (analityka, marketing itd.), a nie oferować tylko wybór wszystko albo nic. Musi zapamiętać wybór użytkownika i nie pytać ponownie do momentu wygaśnięcia zgody. Musi faktycznie zapobiegać ustawieniu zablokowanych ciasteczek, a nie tylko rejestrować preferencję, nadal ładując kody śledzenia.
Ostatni punkt jest kluczowy i często nieprawidłowo obsługiwany. Baner zgody, który się wyświetla, ale i tak ładuje Google Analytics niezależnie od wyboru użytkownika, nie zapewnia żadnej ochrony prawnej. Implementacja musi warunkowo ładować zasoby śledzenia i marketingu na podstawie zgody użytkownika.
Techniczna implementacja zgody
Techniczne podejście do zarządzania ciasteczkami opartego na zgodzie polega na opakowaniu nieistotnego kodu w kontrole zgody. Dla wbudowanego JavaScript, który ustawia ciasteczka lub ładuje piksele śledzenia, należy zastąpić bezpośrednie wykonanie ładowaniem warunkowanym zgodą. Kod śledzenia jest przechowywany, ale nie wykonywany, dopóki użytkownik nie wyrazi zgody.
Dla modułów firm trzecich, które ustawiają ciasteczka, implementacja jest bardziej złożona. Niektóre moduły oferują hooki lub opcje konfiguracji do integracji ze zgodami. Inne ładują swoje ciasteczka bezwarunkowo i muszą być zmodyfikowane lub zastąpione. Przeanalizuj każdy moduł w swoim sklepie pod kątem użycia ciasteczek i określ, które z nich ustawiają nieistotne ciasteczka.
Zgoda na ciasteczka a cachowanie
Cachowanie pełnych stron tworzy konflikt ze zgodą na ciasteczka. Jeśli strona jest cachowana z załadowanym Google Analytics i serwowana użytkownikowi, który nie wyraził zgody, naruszasz RODO. Istnieją dwa podejścia do rozwiązania tego problemu.
Pierwsze podejście polega na cachowaniu strony bez żadnych nieistotnych zasobów i dynamicznym wstrzykiwaniu ich przez JavaScript po sprawdzeniu zgody. Działa to dobrze z systemem CCC (Combine, Compress, Cache) PrestaShop i z Varnish lub innymi reverse proxy cache.
Drugie podejście polega na niechachowaniu stron dla użytkowników, którzy jeszcze nie dokonali wyboru zgody (odwiedzający po raz pierwszy). Pogarsza to wydajność dla nowych odwiedzających, ale zapewnia zgodność. Większość platform zarządzania zgodami stosuje pierwsze podejście, ponieważ zachowuje korzyści z cachowania.
Kwestie bezpieczeństwa związane z ciasteczkami
Poza już omówionymi atrybutami HttpOnly i Secure, istnieją dodatkowe kwestie bezpieczeństwa dotyczące ciasteczek PrestaShop.
Kradzież ciasteczek i przejęcie sesji
Jeśli atakujący uzyska ważne ciasteczko sesji PrestaShop, może podszyć się pod klienta lub administratora. Główna ochrona to HTTPS wszędzie (zapobiega przechwyceniu), ciasteczka HttpOnly (zapobiega kradzieży przez XSS) i atrybut Secure (zapobiega przesyłaniu przez HTTP). PrestaShop w niektórych konfiguracjach wiąże również sesje z adresami IP, co zapewnia dodatkową warstwę ochrony, ale może powodować problemy dla użytkowników, których adresy IP się zmieniają (użytkownicy mobilni, użytkownicy VPN).
Bezpieczeństwo klucza ciasteczka
_COOKIE_KEY_ w konfiguracji PrestaShop to główny klucz do szyfrowania ciasteczek. Jeśli ten klucz zostanie skompromitowany, atakujący może odszyfrować dowolne ciasteczko PrestaShop i sfałszować ważne ciasteczka sesji. Chroń ten klucz, ograniczając dostęp do plików konfiguracyjnych, nigdy nie commitując go do publicznych repozytoriów i nigdy nie udostępniając go w zgłoszeniach wsparcia.
Zapobieganie utrwalaniu sesji
Ataki typu session fixation polegają na tym, że atakujący ustawia znany identyfikator sesji w przeglądarce ofiary, zanim ofiara się zaloguje. Gdy ofiara się loguje, wcześniej ustawiony identyfikator sesji atakującego staje się uwierzytelniony. PrestaShop łagodzi ten problem, regenerując identyfikator sesji przy logowaniu. Upewnij się, że regeneracja identyfikatora sesji działa prawidłowo i nie została wyłączona przez żaden moduł ani zmianę konfiguracji.
Rozwiązywanie typowych problemów z ciasteczkami
Pętla logowania panelu administracyjnego
Objaw polega na wprowadzeniu prawidłowych danych logowania w back office PrestaShop, krótkim zobaczeniu pulpitu nawigacyjnego i przekierowaniu z powrotem na stronę logowania. Jest to niemal zawsze problem z ciasteczkiem. Sprawdź, czy domena ciasteczka jest prawidłowa, czy nazwa katalogu administracyjnego nie uległa zmianie, czy HTTPS jest prawidłowo skonfigurowany (mieszana zawartość może zapobiec wysłaniu ciasteczka Secure) oraz czy katalog przechowywania sesji jest zapisywalny przez serwer WWW.
Opróżnianie koszyka przy nawigacji po stronach
Jeśli koszyk się opróżnia, gdy klient przechodzi na inną stronę, ciasteczko sesji nie jest utrzymywane. Typowe przyczyny obejmują brakujące lub nieprawidłowe ustawienie domeny ciasteczka, nieprawidłowo skonfigurowany session.cookie_lifetime w PHP (ustawienie 0 oznacza, że ciasteczko wygasa po zamknięciu przeglądarki, co jest poprawne, ale niektóre konfiguracje ustawiają to na bardzo krótki czas), lub warstwa CDN lub cachowania, która usuwa nagłówek Set-Cookie z odpowiedzi.
Niepowodzenie realizacji zamówienia po płatności
Gdy klienci realizują płatność, ale widzą błąd lub pusty koszyk po powrocie do Twojego sklepu, polityka ciasteczek SameSite jest zazwyczaj przyczyną, jak opisano w sekcji dotyczącej bramek płatności powyżej. Przetestuj pełny przepływ realizacji zamówienia z otwartymi narzędziami deweloperskimi przeglądarki, obserwując ciasteczka na każdym etapie, aby zidentyfikować, gdzie sesja jest tracona.
Wiele sklepów w tej samej domenie
Jeśli prowadzisz wiele instalacji PrestaShop w tej samej domenie (na przykład w podkatalogach), ich ciasteczka mogą wchodzić w konflikt. Każda instalacja używa podobnej nazwy ciasteczka, a jeśli ścieżka ciasteczka jest ustawiona na /, ciasteczko jednego sklepu nadpisuje ciasteczko drugiego. Ustaw unikalne nazwy ciasteczek dla każdej instalacji poprzez _COOKIE_KEY_ (co wpływa na nazwę ciasteczka) lub skonfiguruj ścieżkę ciasteczka, aby pasowała do podkatalogu każdej instalacji.
Optymalizacja konfiguracji ciasteczek pod kątem wydajności
Dobrze zoptymalizowana konfiguracja ciasteczek PrestaShop minimalizuje narzut przy zachowaniu funkcjonalności. Użyj domeny bez ciasteczek lub CDN dla zasobów statycznych, aby uniknąć wysyłania ciasteczek z zapytaniami o obrazy, CSS i JavaScript. Utrzymuj mały rozmiar ciasteczka, zapobiegając przechowywaniu niepotrzebnych danych przez moduły. Ustaw odpowiednie timeouty sesji, które balansują bezpieczeństwo (krótsze jest bezpieczniejsze) z doświadczeniem użytkownika (dłuższe oznacza mniej ponownych logowań). Użyj Redis do przechowywania sesji, aby połączyć szybki dostęp ze współdzielonym stanem między instancjami serwera. Włącz atrybuty Secure i HttpOnly, aby chronić integralność ciasteczek bez wpływu na wydajność. Wdróż prawidłową zgodę na ciasteczka, aby uniknąć ładowania niepotrzebnych ciasteczek śledzenia, które dodają narzut i ryzyko prawne.
Każda z tych optymalizacji jest indywidualnie niewielka, ale razem tworzą znaczącą poprawę zarówno wydajności, jak i zgodności. Zarządzanie ciasteczkami nie jest efektowną pracą, ale stanowi podstawę każdej interakcji między Twoim sklepem a Twoimi klientami, co sprawia, że warto zrobić to dobrze.
Why Database Performance Matters in PrestaShop
PrestaShop is a database-heavy application. Every product page, category listing, search result, cart update, and checkout step involves multiple database queries. A typical product page can generate 50 to 200 or more SQL queries depending on the number of modules installed, the complexity of the product (combinations, features, attachments), and the theme. When any of these queries run slowly, the entire page slows down, and the effect compounds under load.
The challenge is identifying which queries are actually slow. With hundreds of queries per page load, you cannot simply guess. You need data. The MySQL slow query log is the most direct and reliable tool for collecting this data. It records every query that exceeds a time threshold you define, giving you a clear picture of where your database spends the most time.
This guide covers how to enable and configure the slow query log, how to analyze the results, how to interpret query execution plans, and how to apply the most common optimizations for PrestaShop databases.
Enabling the Slow Query Log
The slow query log is a MySQL feature that writes queries exceeding a specified execution time to a log file. It is disabled by default on most installations because it adds a small amount of I/O overhead, but the performance cost is negligible compared to the diagnostic value it provides.
Configuration via my.cnf
To enable the slow query log permanently, add the following lines to your MySQL configuration file. On most Linux systems, this file is located at /etc/mysql/my.cnf, /etc/my.cnf, or in a directory like /etc/mysql/conf.d/:
slow_query_log = 1 enables the feature.
slow_query_log_file = /var/log/mysql/slow-query.log specifies where the log is written. Make sure the MySQL process has write permissions to this directory.
long_query_time = 1 sets the threshold in seconds. Any query that takes longer than this value is logged. Start with 1 second to catch the most egregious offenders, then lower it to 0.5 or even 0.1 seconds as you optimize the worst queries and want to find more subtle bottlenecks.
log_queries_not_using_indexes = 1 logs queries that do not use any index, regardless of how long they take. This is extremely useful for PrestaShop because many performance problems are caused by full table scans on large tables. However, this can generate a lot of log entries on a busy store, so you may want to enable it temporarily during analysis and disable it afterward.
After editing the configuration file, restart MySQL for the changes to take effect.
Enabling at Runtime
You can also enable the slow query log without restarting MySQL by running SQL commands. Connect to MySQL as root and execute:
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SET GLOBAL log_queries_not_using_indexes = 1;
Runtime changes take effect immediately but do not persist across MySQL restarts. This approach is useful for temporary analysis sessions where you want to collect data for a specific period and then disable logging.
Choosing the Right Threshold
The long_query_time value determines what gets logged. Setting it too high means you miss moderately slow queries that collectively impact performance. Setting it too low floods the log with entries that are not individually problematic.
For an initial analysis, start at 1 second. This catches queries that are clearly too slow. After optimizing those, lower the threshold to 0.5 seconds, then 0.2 seconds. On a well-optimized PrestaShop database, the goal is for no query to take longer than 0.1 seconds, but reaching that level requires significant optimization work.
Keep in mind that query execution time varies with server load. A query that takes 0.3 seconds under normal load might take 2 seconds during a traffic spike because of CPU contention, disk I/O bottlenecks, or lock contention. The slow query log captures actual execution times, so analyzing logs from peak traffic periods gives you the most realistic picture.
Analyzing the Slow Query Log
The raw slow query log is a text file with entries that look like this:
# Time: 2024-03-15T14:22:33.456789Z# User@Host: prestashop[prestashop] @ localhost []# Query_time: 3.456123 Lock_time: 0.000234 Rows_sent: 1 Rows_examined: 847293SET timestamp=1710511353;SELECT * FROM ps_product WHERE active = 1 AND id_product NOT IN (SELECT id_product FROM ps_category_product WHERE id_category = 2);
The key fields are Query_time (how long the query took), Lock_time (how long it waited for a lock), Rows_sent (how many rows were returned), and Rows_examined (how many rows MySQL had to look at to find the result). A query that examines 847,293 rows to return 1 row is a clear sign of a missing index or inefficient query structure.
Using mysqldumpslow
Reading the raw log file is impractical for busy stores that generate thousands of slow query entries. The mysqldumpslow tool, included with MySQL, aggregates and summarizes slow query log entries. It groups identical queries together (abstracting away specific values) and sorts them by various criteria.
To find the 10 slowest queries by average time: mysqldumpslow -s at -t 10 /var/log/mysql/slow-query.log
To find the queries with the most total execution time: mysqldumpslow -s t -t 10 /var/log/mysql/slow-query.log
To find the queries that examined the most rows: mysqldumpslow -s r -t 10 /var/log/mysql/slow-query.log
The -s flag specifies the sort order: at for average time, t for total time, c for count (how many times the query appeared), r for rows examined. The -t flag limits the output to the top N queries.
The most useful sort for initial analysis is by total time (-s t), which shows you which queries consume the most database time overall. A query that takes 0.5 seconds but runs 1000 times per hour consumes more total time than a query that takes 5 seconds but runs once per hour.
Using pt-query-digest
For more detailed analysis, Percona Toolkit's pt-query-digest is the industry standard tool. It provides far more detailed statistics than mysqldumpslow, including percentile distributions of query times, variance analysis, and table-level statistics.
Basic usage: pt-query-digest /var/log/mysql/slow-query.log
The output starts with a profile section that ranks queries by total time, similar to mysqldumpslow but with more detail. Each query then gets a detailed section showing the minimum, maximum, mean, median, and 95th percentile execution times, plus the distribution of rows examined and rows sent.
The 95th percentile is particularly important for PrestaShop performance. It tells you the execution time that 95% of executions fall below. If the average is 0.3 seconds but the 95th percentile is 2.5 seconds, you have a consistency problem: most of the time the query is acceptable, but 5% of users experience a much slower response.
You can install Percona Toolkit on Debian and Ubuntu with apt install percona-toolkit or download it from the Percona website. It is worth installing on any server where you run PrestaShop.
Common Slow Queries in PrestaShop
Certain query patterns appear repeatedly in PrestaShop slow query logs. Knowing these patterns helps you diagnose issues faster.
Full Table Scans on ps_product
Queries against the ps_product table without proper index usage are among the most common slow queries. As your catalog grows beyond a few thousand products, any query that scans the entire product table becomes problematic. Look for queries with WHERE clauses on columns that are not indexed, or queries that join ps_product with ps_product_lang and ps_product_shop without using the primary keys efficiently.
Category Product Listings with Many Filters
When customers use layered navigation (faceted search) to filter products by attributes, features, or price ranges, PrestaShop generates complex queries that join multiple tables. The ps_layered_* tables used by the faceted search module can become performance bottlenecks if indexes are missing or if the indexing process has not run recently.
Search Queries
PrestaShop's built-in search uses the ps_search_word and ps_search_index tables. On stores with large catalogs and many search terms, these tables grow large and queries against them slow down. The search query typically involves a full-text operation or multiple LIKE conditions, both of which are inherently slower than index lookups.
Cart and Order Queries
Queries that aggregate cart or order data can be slow on stores with a long history. If your ps_cart table has millions of rows (which is common because PrestaShop creates a new cart for almost every visitor), queries that scan this table become slow. The same applies to ps_orders and ps_order_detail on high-volume stores.
Statistics and Reporting Queries
Back office statistics modules often run aggregate queries (SUM, COUNT, GROUP BY) across large tables like ps_orders, ps_connections, and ps_page_viewed. These queries can be extremely slow because they scan large datasets. On stores that have been running for years, these tables may contain millions of rows, and statistics queries that worked fine on a small dataset now take minutes.
Module-Generated Queries
Third-party modules frequently generate inefficient queries because module developers often test against small datasets. A module that works perfectly with 100 products may generate catastrophically slow queries with 10,000 products. The slow query log helps you identify which modules are responsible because the query text often includes table names or patterns that point to specific modules.
Using EXPLAIN to Analyze Queries
Once you have identified slow queries from the log, the next step is understanding why they are slow. The EXPLAIN statement shows you how MySQL plans to execute a query, including which indexes it uses, how many rows it expects to examine, and what join strategies it employs.
Reading EXPLAIN Output
Run EXPLAIN followed by the slow query. The output shows one row per table in the query, with these important columns:
type: How MySQL accesses the table. Values from best to worst: system/const (single row, essentially free), eq_ref (one row per join, using unique index), ref (multiple rows, using non-unique index), range (index range scan), index (full index scan), ALL (full table scan). If you see ALL on a table with more than a few thousand rows, that is almost certainly your bottleneck.
key: Which index MySQL actually chose for this table. If this is NULL, no index is being used, and MySQL is scanning the entire table.
rows: The estimated number of rows MySQL needs to examine. This is an estimate, not exact, but it gives you a sense of scale. If the estimated rows value is close to the total number of rows in the table, you have a full table scan.
Extra: Additional information about the execution plan. Watch for Using filesort (MySQL must sort results without an index, which is slow for large datasets), Using temporary (MySQL creates a temporary table, often for GROUP BY or DISTINCT operations), and Using where (MySQL is filtering rows after reading them, which means the index does not fully cover the WHERE clause).
EXPLAIN Example
Consider a slow query: SELECT p.id_product, pl.name FROM ps_product p LEFT JOIN ps_product_lang pl ON p.id_product = pl.id_product WHERE pl.id_lang = 1 AND p.active = 1 AND p.price > 100 ORDER BY p.date_add DESC LIMIT 20
Running EXPLAIN on this query might show that the ps_product table is accessed with type ALL (full table scan), no key is used, and the Extra column shows Using where; Using filesort. This tells you that MySQL is reading every row in the product table, filtering by active status and price, and then sorting the results by date. On a table with 50,000 products, this involves reading and sorting thousands of rows to return just 20.
The fix would be creating a composite index on (active, price, date_add) or restructuring the query to take better advantage of existing indexes.
Index Optimization for PrestaShop
Adding the right indexes is the most effective way to speed up slow queries. An index allows MySQL to find rows without scanning the entire table, similar to how a book's index lets you find a topic without reading every page.
When to Add an Index
Add an index when EXPLAIN shows a full table scan (type ALL) on a table with many rows, when a query runs frequently and consistently appears in the slow query log, and when the query's WHERE clause, JOIN condition, or ORDER BY clause references columns that are not currently indexed.
Do not add indexes blindly. Every index speeds up reads but slows down writes (INSERT, UPDATE, DELETE) because MySQL must update the index on every data modification. PrestaShop performs many writes (cart updates, order creation, statistics tracking), so excessive indexing creates its own performance problems.
Composite Indexes
For PrestaShop queries, composite (multi-column) indexes are often more effective than single-column indexes. A composite index on (id_shop, id_lang, active) lets MySQL efficiently handle queries that filter by all three columns. The order of columns in the index matters: MySQL uses the index from left to right, so the most selective column (the one that filters out the most rows) should generally come first.
PrestaShop's multishop and multilanguage architecture means many queries include id_shop and id_lang conditions. These columns appear in virtually every query against product, category, and CMS tables. If you are adding custom indexes, including these columns is often necessary for the index to be useful.
Covering Indexes
A covering index contains all the columns that a query needs, so MySQL can satisfy the entire query from the index without reading the actual table data. This is shown in EXPLAIN as Using index in the Extra column. Covering indexes provide the best possible performance because reading from an index is faster than reading from the table itself (indexes are smaller and more likely to fit in memory).
Common Index Additions for PrestaShop
Several indexes that are not present in a default PrestaShop installation can significantly improve performance on large stores. These include indexes on the date_add column in ps_cart and ps_orders for queries that filter or sort by date, composite indexes on ps_product_attribute for combination-heavy queries, and indexes on custom columns added by modules that run frequent queries against them.
Before adding any index, verify the improvement by running the slow query with and without the index. Use EXPLAIN to confirm that MySQL actually uses the new index. An unused index wastes disk space and slows down writes without providing any benefit.
Connection Management and Query Optimization
Connection Pooling
PrestaShop uses a single database connection per request by default. Each PHP process opens a connection to MySQL, executes its queries, and closes the connection when the request completes. On busy stores with many concurrent visitors, this creates a high rate of connection creation and teardown, which has overhead.
MySQL's max_connections setting limits how many simultaneous connections are allowed. If your store runs out of connections, visitors see "Too many connections" errors. The default value is often 151, which may be insufficient for high-traffic stores running many PHP-FPM workers.
To determine the right value, check the Max_used_connections status variable, which tells you the peak number of simultaneous connections since MySQL started. Set max_connections to at least 20% above this peak to provide headroom during traffic spikes.
Query Optimization Techniques
Beyond indexing, several query-level optimizations can improve PrestaShop database performance:
Avoid SELECT *: Queries that select all columns transfer more data than necessary between MySQL and PHP. PrestaShop core sometimes uses SELECT * for convenience, but custom queries should specify only the columns needed.
Limit subqueries: MySQL's optimizer handles subqueries less efficiently than JOINs in many cases. If you see slow queries with IN (SELECT ...) patterns, rewriting them as JOINs often improves performance. This applies particularly to queries generated by modules.
Use LIMIT wisely: For paginated listings, PrestaShop typically uses LIMIT offset, count. For large offsets (like page 500 of a product listing), this becomes slow because MySQL must read and discard all rows up to the offset. A more efficient approach is keyset pagination, where you filter by the last seen ID instead of using an offset.
Batch operations: Modules that process products in loops often execute one query per product. Rewriting these as batch queries (using IN clauses or CASE statements for updates) dramatically reduces the number of round trips to the database.
Monitoring and Ongoing Optimization
Database optimization is not a one-time task. As your catalog grows, traffic patterns change, and you install new modules, new slow queries emerge. Establish a routine for monitoring database performance.
Enable the slow query log permanently with a reasonable threshold (0.5 to 1 second). Review the log weekly or monthly using pt-query-digest. Pay attention to new queries that appear in the log and to existing queries whose execution time increases over time.
Monitor MySQL's key performance metrics: the buffer pool hit rate (should be above 99%), the number of slow queries per hour, the average query time, and the connection usage. These metrics give you early warning of performance degradation before it impacts users.
When you add or update modules, check whether they introduce new slow queries. Run the module's functionality while monitoring the slow query log to catch problems before they affect production traffic. A module that generates efficient queries on a test store with 50 products may create severe bottlenecks on a production store with 50,000 products. Testing with production-scale data is the only reliable way to verify module performance.
Summary
The MySQL slow query log is your most valuable tool for finding and fixing database bottlenecks in PrestaShop. Enable it, set an appropriate threshold, and use analysis tools like mysqldumpslow or pt-query-digest to identify the worst offenders. Use EXPLAIN to understand why specific queries are slow, and apply targeted indexes to eliminate full table scans. Monitor your database performance continuously, because optimization is an ongoing process as your store grows. The combination of slow query log analysis, EXPLAIN-driven optimization, and proper indexing can transform a sluggish PrestaShop store into one that handles large catalogs and high traffic with responsive page loads.
Gdy kombinacje PrestaShop zabijaja wydajnosc: limity i obejscia
System kombinacji PrestaShop pozwala tworzyc warianty produktow. Dziala doskonale dla produktow z kilkoma wariantami. Ale gdy produkty maja setki lub tysiace kombinacji, wydajnosc drastycznie spada.
Dlaczego kombinacje powoduja problemy z wydajnoscia
Architektura bazy danych
PrestaShop przechowuje dane kombinacji w wielu tabelach: ps_product_attribute, ps_product_attribute_combination, ps_stock_available, ps_specific_price. Produkt z 5 rozmiarami i 10 kolorami tworzy 50 kombinacji z ponad 350 wierszami w bazie.
Problem wzrostu wykladniczego
| Atrybuty | Wartosci | Kombinacje | Wiersze BD |
|---|---|---|---|
| 2 | 5 x 5 | 25 | ~175 |
| 3 | 10 x 15 x 8 | 1 200 | ~8 400 |
| 4 | 10 x 15 x 8 x 5 | 6 000 | ~42 000 |
Praktyczne limity
| Liczba | Front Office | Back Office | Ocena |
|---|---|---|---|
| 1-50 | Szybko | Szybko | Brak problemow |
| 50-200 | Akceptowalnie | Akceptowalnie | Do opanowania |
| 200-500 | Wolno (3-8s) | Wolno | Potrzebna optymalizacja |
| 500-1000 | Bardzo wolno | Bardzo wolno | Rozwazyc restrukturyzacje |
| 1000+ | Nieuzywalne | Czesto awarie | Restrukturyzacja wymagana |
Rozwiazanie 1 - Restrukturyzacja katalogu
Zamiast jednego produktu z 50 kombinacjami, stworz oddzielne produkty na kolor z 5 kombinacjami kazdy. Szybsze i lepsze dla SEO.
Rozwiazanie 2 - Optymalizacja bazy danych i serwera
ALTER TABLE ps_product_attribute
ADD INDEX idx_product_default (id_product, default_on);
ALTER TABLE ps_stock_available
ADD INDEX idx_product_attribute (id_product, id_product_attribute);Rozwiazanie 3 - Lazy loading kombinacji
Zamiast ladowac wszystkie kombinacje przy wczytywaniu strony, pobieraj dane przez AJAX gdy klient wybiera atrybut.
Rozwiazanie 4 - Strategie cachowania
Cache calej strony (Varnish, LiteSpeed) dla stron produktow. Redis lub Memcached zamiast cachowania plikowego.
Kiedy unikac kombinacji calkowicie
- Produkty konfigurowalne z 4+ atrybutami - Modul konfiguratora produktow
- Produkty wymiarowe - Modul niestandardowych wymiarow
- Produkty print-on-demand - Modul projektanta produktow
Rekomendacje wedlug liczby kombinacji
| Liczba | Zalecane dzialanie |
|---|---|
| Ponizej 100 | Brak potrzeby dzialania |
| 100-300 | Indeksy BD, OPcache, Redis |
| 300-1000 | Podzielic produkty, indeksy, lazy loading |
| Powyzej 1000 | Restrukturyzacja katalogu, modul konfiguratora |
Wydajnosc panelu administracyjnego PrestaShop: dlaczego Back Office jest wolny
Wolny panel administracyjny PrestaShop to jeden z najbardziej frustrujacych problemow. Ten przewodnik identyfikuje najczestsze przyczyny i podaje konkretne rozwiazania.
Najczestsze przyczyny
1. Polaczenie z API PrestaShop Addons
Przyczyna numer jeden. Back office wykonuje zapytania HTTP do addons.prestashop.com. Gdy to API jest wolne, caly back office czeka.
Rozwiazanie - Wyloguj sie z konta Addons lub wylacz wywolania API.
2. Wlaczony tryb debug
Wylacza wszystkie cache i rekompiluje szablony przy kazdym zadaniu.
define('_PS_MODE_DEV_', false);3. Za duzo zainstalowanych modulow
Kazdy modul dodaje narzut. Odinstaluj nieuzywane moduly, szczegolnie statystyki i gamifikacje.
4. Duza baza danych bez optymalizacji
DELETE FROM ps_cart WHERE id_cart NOT IN (
SELECT id_cart FROM ps_orders
) AND date_add < DATE_SUB(NOW(), INTERVAL 30 DAY);
OPTIMIZE TABLE ps_cart, ps_connections, ps_guest;5. Ograniczenia hostingu wspoldzielonego
Rekomendacja: VPS z 2+ CPU, 4 GB RAM, SSD i PHP 8.1+.
6. OPcache nie wlaczony
opcache.enable = 1
opcache.memory_consumption = 2567. Wolne widgety dashboardu
Uproscisc dashboard. Usunac niepotrzebne widgety.
8. Duzy katalog produktow
Zmniejszyc produkty na strone do 20-50. Uzywac wyszukiwania zamiast przegladania.
Checklista optymalizacji
- Wylacz tryb debug
- Kompilacja szablonow: "Nigdy nie rekompiluj"
- Wlacz cache (Redis preferowany)
- Wlacz OPcache
- Odlacz od API Addons
- Odinstaluj nieuzywane moduly
- Wyczysc baze danych
- Uproscisc dashboard
- Zmien hosting na VPS/dedykowany
- Uzyj PHP 8.1+
Inne kategorie
Masz jeszcze pytania?
Can't find what you're looking for? Send us your question and we'll get back to you quickly.