Dodatkowe pola zamówienia w Prestashop

Bytomasz

Dodatkowe pola zamówienia w Prestashop

Celem tego artykułu jest przybliżenie sposobu, w jaki można zaprogramować obsługę dodatkowych pól zamówienia w sklepie Prestashop. Artykuł powstawał w trakcie realizacji zadań na wersji 1.6.1.4.

Prestashop umożliwia dodanie dodatkowych pól do poszczególnych produktów ale niestety nie udostępnia takiej możliwości w przypadku zamówienia.

Ale po co?

Otóż niektóre typy sklepów internetowych lub systemów zamówień opartych o Prestashop mogą wymagać dodania dodatkowych pól do zamówienia. Mogą to być np. sklepy internetowe z upominkami urodzinowymi, gdzie zamawiający chce np. dostarczyć prezent odbdarowywanej osobie konkretnego dnia a nawet o konkretnej godzinie czy przedziale godzin. Potrzeba wówczas dać możliwość zamawiającemu wyspecyfikować oczekiwaną datę realizacji zamówienia/dostawy.

Tutaj wspomnę, że szczególnym powodem zabrania się za ten typ rozszerzenia była sytuacja, gdzie istniejący sklep został rozszerzony o moduł w założeniach oferujący taką funkcjonalność. Niestety okazało się, że mechanizm nie działa.

Wymagania na dodatkowe pola w Prestashop

Załóżmy więc, że mamy zamiar wzbogacić nasz sklep internetowy o 3 dodatkowe pola, mianowicie:

  • oczekiwaną datę realizacji zamówienia/dostawy,
  • przedział godzin w jakim dostawa ma mieć miejsce,
  • awaryjny telefon kontaktowy (na wypadek perturbacji).

Czyli chcemy uzyskać coś takiego:
Dodatkowe pola zamówienia w Prestashop

W zbliżeniu:
Dodatkowe pola zamówienia w Prestashop

Pod pole daty chcielibyśmy podpiąć interaktywny kalendarzyk:
Kalendarzyk w polu typu data dla Prestashop

Dodanie takich pól do zamówienia wymaga walidacji wprowadzonych wartości:

  • oczekiwana data realizacji zamówienia nie może być datą wcześniejszą niż dzień składania zamówienia,
  • być może dostawca pozwoli na realizację zamówienia w przedziale godzin w dniu składania zamówienia,
  • jeśli dostawca pozwoli na realizację zamówienia w dniu składania zamówienia, to wybór przedziału czasowego może być ograniczony czasem koniecznym na przygotowanie dostawy.

Oczywiście może być szereg innych ograniczeń jak np. kwestie weekendów (praca w sobotę, niedzielę) itp.

Chcielibyśmy także, aby dodatkowe informacje wprowadzone do tych pól zapisywały się do bazy danych, pojawiały się ponownie w podsumowaniu zamówienia i były możliwe do podejrzenia w części administracyjnej sklepu na karcie szczegółów zamówienia.

Informacje z dodatkowych pól na ekranie podsumowania zamówienia:
Dodatkowe pola podsumowanie zamówienia dla Prestashop

Pomijam w tym artykule inne istotne zmiany, jakie byłyby potrzebne jak np. umieszczenie dodatkowej kolumny na liście zamówień będącej oczekiwaną datą realizacji zamówienia – właściciel sklepu mógłby np. sortować zamówienia względem pilności realizacji. W scenariuszu z życia wziętym klient mógłby sobie także zażyczyć podania tej informacji w treści maila potwierdzającego zamówienie czy też generowanego PDFa. Tych dodatkowych aspektów nie będę poruszać w artykule. Zainteresowanych zapraszam do ew. kontaktu.

Zakres modyfikacji sklepu Prestashop

Zanim przejdę do bardziej szczegółowego, sektorowego opisywania modyfikacji wraz z uzasadnieniem, przedstawię ich skrótową listę aby dać Czytelnikowi pogląd, z jakiego typu zmianami będzie mieć do czynienia.
Prestashop opiera się o bazę danych MySQL, ma własną, ciekawą i wygodną realizację architektury MVC, jest otwarty na nakładkowe modyfikacje jądra (override) i własne moduły, wykorzystuje system szablonów Smarty jak również wspiera np. bibliotekę jQuery czy jQueryUI i inne, co ułatwia wprowadzanie modyfikacji i rozszerzeń.

Ogólna lista zmian w celu wprowadzenia dodatkowych pól zamówienia wygląda tak:

  1. Dodanie nowych kolumn w bazie danych w tabelach ps_cart,ps_orders.
  2. Modyfikacja klas modelu CartCore (Cart.php) i OrderCore (Order.php) poprzez dodanie nowych cech i definicji kolumn.
  3. Dodanie kontrolek w szablonach Smarty frontu (order-carrier.tpl, order-payment-classic.tpl) i administratora (view.tpl).
  4. Dodanie klienckiej walidacji pól w kodzie javascript w pliku order-carrier.js.
  5. Dodanie obsługi walidacji i zapisu wartości nowych pól w OrderControllerCore (OrderController.php).
  6. Modyfikacja tworzenia obiektu klasy OrderCore na podstawie CartCore w PaymentModule.php (metoda validateOrder).
  7. Stylizacja pól w kaskadowym arkuszu styli np. global.css.

Modyfikacja bazy danych Prestashop

Informacje wprowadzone do dodatkowych pól zamówienia będziemy zapisywać do bazy danych. Do tego niezbędne jest dodanie odpowiednich kolumn do tabel ps_cart i ps_orders. Rozszerzenie dwóch a nie jednej tabeli Prestashop’a wynika z faktu, że lista koszyków jest przechowywana w tabeli ps_cart, natomiast dopiero w momencie zatwierdzenia zamówienia, dane są przepisywane m.in. do tabeli ps_orders.

Dodawane kolumny:
requested_delivery_date datetime
requested_delivery_time tinyint(1)
requested_delivery_phone varchar(32)

Polecenia SQL zakładające powyższe kolumny w tabelach ps_cart i ps_orders:

ALTER TABLE ps_cart ADD COLUMN requested_delivery_date datetime;
ALTER TABLE ps_cart ADD COLUMN requested_delivery_time tinyint(1);
ALTER TABLE ps_cart ADD COLUMN requested_delivery_phone varchar(32);
ALTER TABLE ps_orders ADD COLUMN requested_delivery_date datetime;
ALTER TABLE ps_orders ADD COLUMN requested_delivery_time tinyint(1);
ALTER TABLE ps_orders ADD COLUMN requested_delivery_phone varchar(32);

Modyfikacja klas modelu

Dodanie dodatkowych pól zamówienia wymaga modyfikacji klas CartCore i OrderCore, odpowiednio w plikach Cart.php i Order.php. Aby uniknąć różnych problemów związanych z utrzymaniem kastomizowanego oprogramowania, Prestashop oferuje mechanizm „overrides” czyli uruchamiania skastomizowanych klas w zastępstwie klas jądra sklepu. Wymaga to zakodowania i umieszczenia plików w folderze /override zachowując odpowiednią strukturę folderów.

W naszym przypadku interesujące nas pliki mają następującą lokalizację:

  • /classes/Cart.php
  • /classes/order/Order.php

Kopiujemy je więc odpowiednio do lokalizacji:

  • /override/classes/Cart.php
  • /override/classes/order/Order.php

Zmiany kodu będziemy dokonywać na plikach w folderze /override.

Zmiany w kodzie klas modelu

Niezbędne zmiany to:

  • dodanie publicznych pól (cech, properties) do klas modelu (CartCore, OrderCore),
  • dodanie wierszy w tabeli definicji modelu (CartCore, OrderCore),
  • dodanie metody zapisu wartości dodatkowych pól (CartCore).

Jak zauważymy, na początku kodu klas CartCore i OrderCore mamy deklarację pól (cech, properties). Dodajemy na ich końcu nasze nowe pola:

class CartCore extends ObjectModel
{
public $id;
public $id_shop_group;
public $id_shop;


/** @var string date */
public $requested_delivery_date;
/** @var int */
public $requested_delivery_time;
/** @var string */
public $requested_delivery_phone;


}

Takie same poprawki wstawiamy do definicji klasy OrderCore (Order.php).

Zaraz po deklaracji pól w kodzie znajdziemy tablicę (array) obiektowo-relacyjnego mapowania, a mówiąc prościej, opis tabeli w bazie relacyjnej MySQL odpowiadającej definiowanej klasie modelu. To taki prosty ORM jaki ma w sobie Prestashop. W momencie wywołania odpowiedniej metody dane zapisane w polach obiektu klasy modelu są automatycznie zapisywane do bazy danych. Poniżej fragment kodu z dodanymi przez nas polami:


/**
* @see ObjectModel::$definition
*/
public static $definition = array(
‚table’ => ‚cart’,
‚primary’ => ‚id_cart’,
‚fields’ => array(
  ‚id_shop_group’ => array(‚type’ => self::TYPE_INT, ‚validate’ => ‚isUnsignedId’),
  ‚id_shop’ => array(‚type’ => self::TYPE_INT, ‚validate’ => ‚isUnsignedId’),
  ‚id_address_delivery’ =>array(‚type’=>self::TYPE_INT, ‚validate’=>’isUnsignedId’),

  ‚date_upd’ => array(‚type’ => self::TYPE_DATE, ‚validate’ => ‚isDate’),

  ‚requested_delivery_date’ => array(‚type’ => self::TYPE_DATE),
  ‚requested_delivery_time’ => array(‚type’ => self::TYPE_INT),
  ‚requested_delivery_phone’ => array(‚type’ => self::TYPE_STRING)

),
);

Ponownie, w ten sam sposób poszerzamy listę pól w tablicy statycznej $definition w OrderCore (Order.php).

Zauważmy, że w definicji dodatkowych pól nie zdefiniowaliśmy atrybutu ‚validate’. Moglibyśmy wymusić walidację, jednakże tego nie zrobiliśmy.

Przyczyna ma dwojaki charakter.

Po pierwsze, w naszym sklepie podanie sztywnej daty dostawy zamówienia nie jest obligatoryjne. Podobnie podanie telefonu nie jest obligatoryjne, jeśli nie podaliśmy oczekiwanej daty dostawy (w przypadku wyboru przedziału czasowego to już zależy od nas, czy wprowadzimy pierwszą opcję wyboru odpowiadającą niewybranemu przedziału godzinowego).

Po drugie, co istotne, modyfikujemy w sposób minimalistyczny kod Prestashop. Gdybyśmy na poziomie definicji wymusili walidację naszych dodatkowych pól, to przy pierwszej próbie zapisu do bazy danych z istniejącego obiektu klasy CartCore/OrderCore Prestashop dokonałby sprawdzenia czy nasze dodatkowe pola zawierają wartość odpowiedniego typu. Tego nie możemy zagwarantować. Dodatkowe pola w naszym przypadku będą wypełniane dopiero w kroku przesyłki (shipping) procesu finalizowania zamówienia. W związku z tym pozwalamy, aby rekord w tabeli ps_cart został założony z pustymi wartościami dla naszych dodatkowych pól i dopiero na etapie zapisu formularza w kroku wyboru przesyłki były one wypełniane wartością wprowadzoną przez użytkownika. Gdybyśmy jednak zażądali walidacji, wówczas Prestashop zakończyłby wykonanie z błędem przy pierwszej próbie zapisu danych z obiektu CartCore do bazy.

Zapis wartości dodatkowych pól do bazy danych w Prestashop

Wartości wprowadzone przez zamawiającego do dodatkowych pól zamówienia musimy zapisać do bazy danych sklepu Prestashop. Kontrolerem odpowiedzialnym za proces finalizowania zamówienia jest OrderControllerCore (OrderController.php), natomiast rolę modelu pełni obiekt klasy CartCore (Cart.php).

Przyjmując ten model architektoniczny, wartości przesłanych (wysubmitowanych) pól zbierzemy w OrderControllerCore, natomiast sam dostęp do bazy danych zrealizujemy w klasie CartCore (zapis do tabeli ps_cart) poprzez metodę, która zostanie wywołana w OrderControllerCore.

Zauważmy, że moglibyśmy po prostu zmodyfikować cechy/pola obiektu klasy CartCore licząc na to, że ORM Prestashop sam dokona zapisu do bazy danych do tabeli ps_cart.

Bardziej ostrożnym podejściem po prostu posiadając identyfikator naszego koszyka dokonać uaktualnienia tylko naszych dodatkowych pól w kroku wyboru sposobu przesyłki w trakcie finalizowania zamówienia. Do klasy CartCore dodajemy nową metodę, więc także nasze zmiany są bardziej zauważalne i odseparowane od natywnego kodu sklepu. Wygląda ona tak:


public function saveRequestedDeliveryDateTime($par_rdd,$par_rdt,$par_rdf) {
  $sql = ‚UPDATE ‚._DB_PREFIX_.”cart SET requested_delivery_date='”.$par_rdd.”‚,”;
  $sql.=”requested_delivery_time=”.(int)$par_rdt.”,”;
  $sql.=”requested_delivery_phone='”.strip_tags(htmlspecialchars($par_rdf)).”‚”;
  $sql.=.” WHERE id_cart=”.(int)$this->id;
  Db::getInstance()->execute($sql);
}

W powyższym kodzie zauważamy użycie stałej zawierającej konfigurowalny prefiks nazw tabel w bazie danych Prestashop. Dla uzyskania dostępu do bazy danych budujemy sami ręcznie string zapytania SQL. Prestashop pozwala robić to w inny sposób. Zapis do bazy danych niesie ze sobą parę niebezpieczeństw jak próby ataku SQLInjection lub próby wprowadzenia do submitowanych pól np. fragmentów kodu Javascript. W powyższym kodzie zauważymy więc że parametr $par_rdf (telefon awaryjny) zostaje objęty wywołaniem funkcji strip_tags oraz htmlspecialchars, dzięki czemu tego typu ataki przez pole telefonu nie przejdą ale $par_rdd idzie ‚na golca’ – dlaczego? Ot, pretekst do dyskusji. W kontrolerze będziemy sprawdzać czy submitowana wartość daty oczekiwanej dostawy będzie odpowiednio sformatowaną datą (a więc nie będzie mogła być spreparowanym fragmentem SQLa). Poniżej jednak przedyskutujemy dokładniej inne możliwości Prestashop w zakresie dostępu do danych oraz aspekty walidacji i bezpieczeństwa.

(ciąg dalszy nastąpi, koniec 31 marca 2016)

Kilka słów o dostępie do bazy danych w Prestashop

Walidacja i bezpieczeństwo w Prestashop

Szukasz programisty Prestashop? Zapoznaj się z propozycją Programista Prestashop

Potrzebujesz szkolenia z programowania w Prestashop? Zapoznaj się z propozycją Programowanie Prestashop

About the author

tomasz administrator