Moduły wielosklepowe PrestaShop 9: zapobieganie wyciekom zakresu danych

47 Views

Najgroźniejszy błąd wielosklepowości to często prawidłowe zapytanie bez jednego warunku. Zwraca rzeczywisty rekord, przechodzi zwykłe kontrole typów i poprawnie zapisuje dane — w stanie niewłaściwego sklepu. Deweloperska instalacja z jednym sklepem rzadko ujawnia ten błąd.

Niezawodne moduły wielosklepowe zaczynają się od własności danych. Zdecyduj, które wartości są globalne, które należą do grupy sklepów, a które do jednego sklepu. Następnie przenieś tę decyzję na klucze, odczyty, zapisy, zadania w tle i pamięci podręczne.

To ogólny artykuł o projektowaniu modułów PrestaShop 9. Nie opisuje nowych funkcji administracyjnych 9.2, a przykłady SQL używają celowo ilustracyjnej tabeli modułu zamiast zakładać produkcyjny prefiks lub schemat rdzenia.

Gdy praca o określonym zakresie działa w tle, zastosuj niezawodny projekt zadań cron przekazując jawną tożsamość sklepu do każdego wykonania.

Modeluj własność przed dodaniem kolumny id_shop

Dodanie id_shop do tabeli nie zapewnia bezpieczeństwa modułu w wielosklepowości. Każda operacja musi używać tej kolumny spójnie, a niektórych faktów w ogóle nie należy powielać dla każdego sklepu.

Rozważ mapowanie zewnętrznych referencji. Jeśli system zewnętrzny przypisuje inną referencję do tego samego produktu w każdym sklepie, zakres sklepu należy do tożsamości mapowania. Jeśli referencja jest naprawdę globalna, powielanie jej może tworzyć sprzeczne kopie. Najpierw ustal semantykę systemu zewnętrznego.

Oddziel powiązanie encji od własności wartości. Produkt może być powiązany z kilkoma sklepami, choć konkretna wartość modułu różni się między nimi. Odwrotnie, encja powiązana z jednym sklepem może odwoływać się do globalnego rekordu.

Napisz tabelę własności dla każdego zestawu danych modułu:

Zestaw danych Właściciel Zakres odczytu Zakres zapisu
Dane uwierzytelniające zewnętrznego celu Wybrany zakres konfiguracji Jawna efektywna konfiguracja Autoryzowany kontekst
Mapowanie produktu Zdefiniowane przez reguły tożsamości zewnętrznej Produkt i wymagany zakres Ta sama granica tożsamości
Postęp zadania Jedna logiczna partycja zadania Jawny klucz sklepu/zadania Proces roboczy będący właścicielem
Współdzielony słownik wyszukiwania Globalny, jeśli rzeczywiście współdzielony Globalny Kontrolowana czynność administratora

Tabela jest artefaktem projektowym. Powinna wyjaśniać, dlaczego zakres istnieje, a nie tylko odzwierciedlać kolumny najłatwiejsze do dodania.

Ograniczaj odczyty i zapisy tą samą tożsamością

Częsty błąd to poprawnie ograniczony odczyt, po którym następuje aktualizacja o zbyt szerokim zakresie. Inny to wyszukiwanie według produktu i sklepu, ale wymuszanie unikalności wyłącznie według produktu.

Poniższe zapytanie ilustruje odczyt mapowania należącego do modułu z wiązaniem parametrów. Dosłowna nazwa tabeli jest przykładem; prawdziwy instalator musi wyprowadzić zaufany prefiks z konfiguracji aplikacji i własnego zadeklarowanego schematu.

SELECT external_reference
FROM demo_product_mapping
WHERE id_shop = :shop_id
  AND id_product = :product_id;

Odpowiadający zapis musi używać tej samej granicy własności. Nie aktualizuj wyłącznie według id_product po odczycie z oboma warunkami. Wywołujący powinien przekazać zweryfikowany obiekt zakresu lub jawny identyfikator sklepu zamiast polegać na zmiennym globalnym kontekście wewnątrz repozytorium.

Identyfikatory dynamiczne wymagają osobnego traktowania niż wartości parametrów. Wiązane parametry chronią wartości, nie dowolne nazwy tabel. Nigdy nie przyjmuj nazwy tabeli ani prefiksu z parametru HTTP, aby uruchomić ogólne zapytanie wielosklepowe.

Przy odczycie wsadowym uwzględniaj zakres w złączeniach i w zewnętrznym predykacie. Złączenie tylko po produkcie może dołączyć wiersz modułu innego sklepu, nawet gdy główne zapytanie encji jest poprawnie ograniczone.

Jawnie przetestuj przypadek negatywny: poproś o wartość sklepu A, gdy ma ją tylko B. Brak lokalnego mapowania może być poprawny; ciche pożyczanie mapowania B nie jest bezpiecznym ustawieniem domyślnym.

Niech unikalność wyraża regułę biznesową

Jeśli model przewiduje jedno mapowanie na produkt i sklep, klucz powinien wyrażać tę parę. Unikalny klucz tylko na produkcie odrzuca prawidłowe rekordy innego sklepu. Brak unikalnego klucza pozwala na duplikaty przy współbieżnych wstawieniach.

Przykładowa definicja tabeli modułu to:

CREATE TABLE demo_product_mapping (
    id_shop INT UNSIGNED NOT NULL,
    id_product INT UNSIGNED NOT NULL,
    external_reference VARCHAR(191) NOT NULL,
    PRIMARY KEY (id_shop, id_product)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

To nie jest import do produkcyjnej bazy PrestaShop. Demonstruje wyłącznie klucz własności. Prawdziwy schemat wymaga konwencji instalacyjnych modułu, zweryfikowanych typów identyfikatorów, strategii migracji i dodatkowych ograniczeń relacji.

Nie dodawaj unikalności dla external_reference bez decyzji, czy wartość jest unikalna globalnie, lokalnie w sklepie czy lokalnie w celu. Jeśli kilka systemów zewnętrznych może przypisać ten sam ciąg, tożsamość celu również może należeć do klucza.

Przed dodaniem ograniczenia do istniejących danych sprawdź i rozwiąż duplikaty zgodnie z określoną polityką. Usunięcie wiersza, który przypadkiem jest drugi, nie jest strategią migracji. Zachowaj dowody, który rekord pozostawiono i dlaczego.

Ograniczenie bazy danych uzupełnia walidację aplikacji. Chroni niezmiennik, gdy dwa pozornie prawidłowe żądania konkurują.

Traktuj dziedziczoną konfigurację jako stan, a nie tylko wartość

Sklep może dziedziczyć wartość lub jawnie zapisać równą wartość. Zachowują się inaczej, gdy zmienia się rodzic. Moduł odczytujący efektywną wartość i bezwarunkowo zapisujący ją z powrotem może przypadkiem przekształcić dziedziczenie w lokalne nadpisanie.

Dokumentacja konfiguracji PrestaShop opisuje dostęp uwzględniający zakres za pomocą ShopConstraint, a wskazówki dotyczące formularzy rozróżniają lokalną konfigurację i odziedziczone wartości. Stosuj właściwy kontrakt usługi dla obsługiwanej wersji platformy. Konfiguracja sklepów, formularze konfiguracji.

Przy implementacji zapisu rozróżnij „ustaw lokalną wartość”, „usuń lokalne nadpisanie” i „pozostaw to pole bez zmian”. Tych operacji nie należy sprowadzać do jednego przypisania wartości.

Ta sama ostrożność dotyczy danych uwierzytelniających i zewnętrznych celów. Proces powinien wiedzieć, jakiej efektywnej konfiguracji użył i który sklep mógł przetwarzać. Logowanie identyfikatora celu może pomóc diagnozować problemy zakresu bez ujawniania samych danych uwierzytelniających.

Unikaj wymyślania id_shop = 0 jako uniwersalnej konwencji globalnego wiersza dla każdego zestawu danych. Modele przechowywania rdzenia i modułów różnią się. Stosuj konkretny schemat i semantykę usług zamiast rozpowszechniać nieudokumentowaną wartość specjalną w kodzie.

Przekazuj zakres do pracy w kolejce i harmonogramie

Zadanie w tle powinno zawierać dość tożsamości, by wykonać się bez sesji pracownika: sklep, operację, odpowiednie identyfikatory encji i stabilny klucz biznesowy. Zweryfikuj sklep przed załadowaniem danych lub konfiguracji.

Nie umieszczaj w kolejce tylko ID produktu, pozwalając późniejszemu procesowi ustalać sklep z dowolnego globalnego kontekstu, który akurat posiada. Długotrwałe procesy mogą obsługiwać kilka wiadomości, przez co wyciekły kontekst szczególnie trudno odtworzyć.

Gdy starszy kod wymaga otaczającego kontekstu, ostrożnie odizoluj adaptację i przywróć poprzedni stan nawet przy wyjątku. Preferuj jawny zakres na granicach własnych usług, aby starsza zależność nie rozprzestrzeniła się w całym module.

Zadanie dla wszystkich sklepów powinno iterować po celowo wybranym, autoryzowanym zbiorze, ustalając i czyszcząc odpowiedni zakres dla każdej partycji. „Wszystkie sklepy” powinny być jawną operacją o określonym wyniku, a nie przypadkowym skutkiem brakującego argumentu.

Uwzględniaj zakres w kluczach blokad i idempotencji, gdy praca jest niezależna dla poszczególnych sklepów. Globalna blokada może niepotrzebnie serializować niezwiązane prace, a klucz bez tożsamości celu może uznać dwa różne eksporty za duplikaty.

Nadaj danym w pamięci podręcznej te same wymiary co zapytaniu

Klucz pamięci podręcznej jest częścią modelu danych. Jeśli wynik zależy od sklepu, języka, waluty lub grupy klientów, klucz i strategia unieważniania muszą odzwierciedlać odpowiednie wymiary.

Dla etykiety produktu należącej do modułu koncepcyjny klucz może zawierać przestrzeń nazw modułu, ID produktu, ID sklepu, ID języka i wersję reprezentacji. To wzorzec projektowy, nie narzucony format klucza pamięci podręcznej PrestaShop.

Uwzględniaj tylko wymiary faktycznie wpływające na wartość, ale nie pomijaj żadnego dla wygody. Poprawne zapytanie do bazy danych, po którym następuje współdzielony wpis pamięci podręcznej, nadal może ujawnić wynik pierwszego sklepu w drugim.

Testuj, żądając tej samej encji w różnych kontekstach w obu kolejnościach: A, potem B oraz B, potem A. Jeśli wynik zmienia się z kolejnością żądań, podejrzewaj kontekst w pamięci podręcznej lub zachowany kontekst. Testy wyłącznie z wyczyszczoną pamięcią podręczną mogą ukryć tę klasę błędu.

Unieważnianie musi dotrzeć do każdej dotkniętej reprezentacji. Zmiana wartości globalnej może wymagać unieważnienia kilku wyników właściwych dla sklepów; zmiana lokalna nie powinna nadpisywać danych innych sklepów podczas odbudowy pamięci podręcznej.

Używaj konfliktowych danych testowych do testów izolacji

Utwórz dwa sklepy z celowo sprzecznymi wartościami współdzielonej encji. Nadaj im różne identyfikatory zewnętrznych celów i różne stany konfiguracji dziedziczonej/lokalnej. Następnie sprawdź każdy odczyt i zapis przez obsługiwane interfejsy modułu.

Przydatne asercje obejmują:

  • Zapis w sklepie A pozostawia wiersz i efektywną wartość sklepu B bez zmian.
  • Odczyt w A nigdy nie korzysta zastępczo z B bez jawnej reguły biznesowej.
  • Czynność obejmująca wszystkie sklepy wpływa dokładnie na wybrany autoryzowany zbiór.
  • Zadanie w tle przetwarza sklep nazwany w jego danych.
  • Wyniki pamięci podręcznej pozostają poprawne niezależnie od kolejności żądań.
  • Podwójne współbieżne zapisy zachowują zadeklarowaną unikalną tożsamość.
  • Usunięcie lokalnego nadpisania przywraca dziedziczenie zamiast kopiować wartość rodzica.

Testuj także brak powiązania i usunięte encje. Moduł powinien zwracać określony błąd lub brak, a nie wybierać dowolny pozostały wiersz, by kontynuować przepływ pracy.

W raporcie regresji zachowaj dwa ID sklepów, różne wartości testowe i operację, która przekroczyła granicę. Minimalny przypadek dwóch sklepów często wyjaśnia błąd jaśniej niż duży eksport produkcyjny.

Uczyń izolację nawykiem przeglądu

Podczas przeglądu kodu pytaj, gdzie zakres trafia do usługi, gdzie jest weryfikowany i czy każda operacja utrwalania oraz pamięci podręcznej go zachowuje. Przeglądaj razem predykaty zapytań i ograniczenia unikalności. Przeglądaj dane wiadomości w tle wraz z obsługującymi je mechanizmami.

W istniejących modułach zacznij od zapisów o największym wpływie i integracji zewnętrznych. Poprawienie ograniczonego odczytu nie wystarcza, jeśli odpowiadająca mu aktualizacja lub eksport nadal używa globalnych wartości domyślnych.

Poprawność wielosklepowa nie jest specjalnym trybem dodawanym pod koniec programowania. Jest zgodnością między znaczeniem danych a każdą granicą, która je obsługuje. Gdy ta zgodność jest jawna, wycieki między sklepami stają się testowalnymi błędami zamiast tajemniczych zgłoszeń klientów.

Kontekst platformy bazowej znajdziesz w naszym poradniku tworzenia modułów PrestaShop 9 i zastosuj powyższe kontrole właściwe dla wersji do ocenianej instalacji.

Wybierając rozszerzenie, przejrzyj moduły PrestaShop 9 od PrestaSuite i porównaj udokumentowaną obsługę wersji oraz wymagania integracji z własnymi wynikami testów.