Autor: Grzegorz Jasiński
Grzegorz Jasiński na Google+Front-end developer i freelancer, fan Star Wars i Terenca McKenny
Witaj w pierwszej z trzech części tutoriala, w którym od podstaw napiszemy moduł slidera do PrestaShop. Będzie nam potrzebne trochę ogólnej wiedzy o PHP i programowaniu obiektowym, znajomość JavaScript (jQuery) i Smarty. Wszystkie te elementy będą na bieżąco omawiane, więc w każdym momencie będziesz wiedział o co chodzi, nawet gdy jeszcze zupełnie nie orientujesz się w tym zakresie. Jeśli coś będzie niejasne lub znalazłeś błąd w tekście - zapraszam do dodawania komentarzy, z pewnością wszyscy z tego skorzystamy.
Na początek zajmiemy się stroną PHP i podstawami budowy modułów PrestaShop. Stopniowo rozbudowując testowe moduły przejdziemy się od "Witaj świecie" do napisania własnego modułu zmieniacza obrazków.
Pełna wersja Kinky Slider do ściągnięcia : Kinky Slider v0.1 (zip) / Kinky Slider v0.1 (tar.gz)
Oto wynik końcowy, nad jakim będziemy pracować. Nie zwracajcie uwagi na brak płynności video - mój komputer okazał się trochę za wolny. Sam slider działa bardzo płynnie :
Określamy nasz cel
Slider do PrestaShop, który automatycznie zmniejsza i zwiększa obrazki wgrywane przez obsługujących go administratorów
Powinien mieć ładny i konfigurowalny wygląd, ciekawe animacje, preload obrazków i nie może korzystać z Flasha ani HTML5 Canvas
Slider musi działać pod Internet Explorer 8
Ma dawać możliwość wpisywania tekstów - nagłówków zdjęć oraz ceny i linkować do wybranego towaru w sklepie lub dowolnej strony www
Potrzebne narzędzia
Oprócz silnika PrestaShop, na którym oparty będzie nasz slider, będziemy potrzebowali dwóch bibliotek jQuery, które ułatwią i przyśpieszą nam pracę:
jQuery 2d Transform plugin 0.9.3 (github.com/heygrady/transform/wiki) - biblioteka jQuery do obsługi transformacji i animacji 2d. Wszystkie nowe przeglądarki (Google Chrome, FireFox, Opera, Safari, Internet Explorer 9) dostają bonus dzięki wykorzystaniu CSS3. Starsze przeglądarki (IE8 i IE7) zostają z kolei potraktowane specjalnie, więc dostajemy mniej więcej to, czego oczekujemy.
jQuery Timers plugin (http://jquery.offput.ca/every/)- biblioteka na licencji WTFPL ułatwiająca obsługę zdarzeń czasowych, wykorzystamy ją do napisania preloadera obrazków oraz do innych rzeczy zależnych od czasu, jak np. cykliczne zmiany slajdów.
W trakcie kolejnych odsłon modułu wykorzystamy też parę gotowych funkcji PHP, o których napiszemy w następnych częściach tutoriala.
Podstawy
Jeśli jeszcze nigdy nie zetknąłeś się z programowaniem na zasadach MVC (Model, View, Controller), to będziesz miał okazję poznać je trochę pisząc nasz moduł. PrestaShop został stworzony przy wykorzystaniu założeń MVC* co oznacza, że składa się z 3 uzupełniających się warstw:
Model: Reprezentuje dane twojej aplikacji, odpowiada za jej strukturę. Modele w PrestaShop są zdefiniowane w katalogu /classes i zarządzają wszystkimi danymi trzymanymi w bazie danych. Jako podstawę do zbudowania naszego modułu wykorzystamy klasę Module, która znajduje sięw pliku /classes/Module.php
Widok (View): odpowiada za prezentację twoich danych w odpowiedni sposób - każdy model może mieć wiele widoków, dzięki czemu te same dane możesz przedstawiać w różnej formie. Widoki trzymane są w katalogu /themes i pisane są z wykorzystaniem języka Smarty (przyjrzymy się mu trochę później). Każdy moduł może posiadać własne widoki, które trzymane są w plikach o rozszerzeniu .tpl wewnątrz katalogu modułu
Kontroler (Controller): Zajmuje się obsługą zdarzeń. Odbiera żądania od użytkowników, odpowiednio je interpretuje a następnie wysyła dane do wartstwy Widoku. Począwszy od wersji 1.4, kontrolery PrestaShop trzymane są w katalogu /controllers
* PrestaShop nie trzyma się sztywno reguł MVC
Tworzymy pierwszy moduł testowy
Moduł będzie miał za zadanie pojawić się w zakładce w panelu administracyjnym. Wszystkie moduły PrestaShop trzymane są w katalogu /modules w głównym drzewku instalacji sklepu.
Będziemy trzymać się pewnej konwencji przy tworzeniu nazw plików i katalogów: będziemy nazywać je używając małych liter:
Stwórz katalog /modules/testone
Stwórz plik /modules/testone/testone.php
Skopiuj następującą zawartość do pliku testone.php:
class TestOne extends Module
{
function __construct()
{
$this->name = 'testone';
$this->tab = 'other';
$this->version = '0.1.0';
$this->author = 'You';
parent::__construct();
$this->displayName = $this->l('Our first module');
$this->description = $this->l('This module does nothing yet.');
}
} // End of: testone.phpMożesz sprawdzić teraz, czy moduł pojawił się w panelu administracyjnym. Wejdź do sekcji "Moduły" i odszukaj zakładkę "Pozostałe moduły" lub "Others" - jeśli używasz angielskojęzycznej wersji PrestaShop.
Dzięki klasie podstawowej Module, z której wywodzi się nasz moduł, dostajemy na start zestaw zawartych w niej metod oraz właściwości, do których możemy odwołać się pisząc moduł - zostały one już zdefiniowane wcześniej. Uwaga: w programowaniu obiektowym funkcje nazywa się zwykle metodami a zmienne - właściwościami.
Traktuj od tej chwili nasz moduł jako dziecko, a klasę Module jako rodzica, od którego dostajemy na start zestaw metod i właściwości, które możemy następnie używać, przerabiać i nadpisywać według naszych potrzeb.
W module Test One ustawione są następujące właściwości:
name - wewnętrzna nazwa modułu, nie może zawierać znaków specjalnych, spacji itp.
tab- nazwa jednej z dostępnych i odgórnie zdefiniowanych kategorii modułów w PrestaShop. Lista dostępnych kategorii znajduje się w referencjach na końcu tej części tutoriala. Uwaga: w starszych niż 1.4.x wersjach PrestaShop można było dowolnie ustalić nazwę kategorii modułu, w nowych musimy trzymać się określonych kategorii.
author- autor modułu
version- wersja modułu
displayName - nazwa wyświetlana na liście modułów w panelu administratora
description- opis modułu na liście w panelu administratora
Odnoszenie się do właściwości i metod danej klasy
Aby ustawić lub zmienić daną właściwość wewnątrz klasy użyj zmiennej $this . To samo dotyczy zawartych w naszej klasie metod:
$odczytajWartosc = $this->nazwaWlasciwosci; $rezultat = $this->nazwaMetody($parametr);
Konstruktory, rodzice, tłumaczenia
function __construct() i parent::__construct()
Na początek wyobraź sobie, że moduł w postaci klasy php nie jest jeszcze konkretnym przedmiotem którego można użyć, a formą, z której wyrabia się przedmioty. Aby uzyskać dostęp do przedmiotu (obiektu), PrestaShop musi go najpierw stworzyć na podstawie napisanej przez nas formy.
Funkcja __construct to specjalny rodzaj funkcji, która uruchamiana jest tuż po stworzeniu nowego obiektu. Odpowiada za różne startowe rzeczy, możesz o niej myśleć jak o rozruszniku.
Zamieszczając w naszym module metodę __construct() tak naprawdę zaczęliśmy nadpisywanie zawartości metody __construct() odziedziczonej po klasie Module. Pisząc więc parent::__construct jako moduł-dziecko komunikujesz klasie Module, żeby przejęła dalszą kontrolę nad daną funkcją, gdy ty już uzupełnisz ją odpowiednimi ustawieniami.
$this->l('Tekst po angielsku') :
Używamy metody l ( ) zamiast po prostu wpisywać tekst jako ciąg znaków, aby zapewnić możliwość dodawania tłumaczeń do wszystkich komunikatów, których użyjemy w module. Zasada działania jest prosta: jako parametr podajemy tekst po angielsku. Jeśli PrestaShop wykryje wersje językowe zdefiniowane przez ciebie lub administratora sklepu - użyje ich na stronie.
Moduł Test Two
Przejdźmy teraz do stworzenia trochę bardziej zaawansowanego modułu. Wyświetli on powitanie na stronie głównej PrestaShop. Powitanie to będziemy mogli ustawić w konfiguracji naszego modułu w panelu administratora i zostanie ono zapisane w bazie danych.
Stwórz katalog /modules/testtwo
Stwórz plik /modules/testtwo/testtwo.php
Stwórz plik /modules/testtwo/testtwo.tpl
Skopiuj następującą zawartość do pliku testtwo.php:
class TestTwo extends Module {
private $_html= '';
function __construct() {
$this->name = 'testtwo';
$this->tab = 'other';
$this->version = '0.2.0';
$this->author = 'You';
parent::__construct();
$this->displayName = $this->l('Our second module');
$this->description = $this->l('This module is a real hello world!.');
}
public function install() {
parent::install();
if(!$this->registerHook('leftColumn')) return false;
return true;
}
public function getContent() {
if(Tools::isSubmit('submit_text')) {
Configuration::updateValue(
$this->name.'_text_to_show',
Tools::getValue('the_text')
);
}
$this->_generateForm();
return $this->_html;
}
private function _generateForm() {
$textToShow=Configuration::get($this->name.'_text_to_show');
$this->_html .= '<form action="'.$_SERVER['REQUEST_URI'].'" method="post">';
$this->_html .= '<label>'.$this->l('Enter your text: ').'</label>';
$this->_html .= '<div class="margin-form">';
$this->_html .= '<input type="text" name="the_text" value="'.$textToShow.'" >';
$this->_html .= '<input type="submit" name="submit_text" ';
$this->_html .= 'value="'.$this->l('Update the text').'" class="button" />';
$this->_html .= '</div>';
$this->_html .= '</form>';
}
public function hookLeftColumn() {
global $smarty;
$smarty->assign('our_text',Configuration::get($this->name.'_text_to_show'));
return $this->display(__FILE__, 'testtwo.tpl');
}
} // End of: testtwo.phpA ten kod wklej do pliku testtwo.tpl :
<br />
And our message is: {$our_text}
<br />Po zainstalowaniu modułu widzisz teraz dodatkową opcję - Konfiguruj, a w środku czeka formularz do wypełnienia. Wpisz tu dowolny tekst i kliknij przycisk "Update the text". Sprawdź teraz stronę główną sklepu: na dole lewej kolumny powinieneś zobaczyć "And our message is: " a następnie tekst, który wpisałeś.
Trzy razy P
Jeśli chodzi o budowę modułu, to doszło nam kilka nowych metod oraz pojawiła się nowa właściwość: $_html. Będzie ona przechowywać kod html formularza, którego przed chwilą użyłeś. Zatrzymajmy się jeszcze na chwilę przy słowach kluczowych private, publici protected.
private $_html= '';
Za pomocą słów kluczowych private, public i protected możemy ustawić odpowiedni dostęp do właściwości i metod:
private: właściwości i metody będą dostępne tylko z wewnątrz danej klasy; Inne klasy nie odziedziczą prywatnych właściwości i metod
protected: właściwości i metody będą dostępne tylko z wewnątrz danej klasy i z wewnątrz klas pochodnych
public: publiczne właściwości i metody są dostępne zarówno z zewnątrz jak i z zewnątrz danej klasy. Jeśli inna klasa odziedziczy publiczną właściwość lub metodę, zostanie zachowana ta sama zasada działania.
Metoda getContent()
To właśnie przez dodanie do modułu metody getContent() sprawiliśmy, że PrestaShop wyświetlił automatycznie opcję konfiguracji, którą mogliśmy kliknąć. Funkcja ta będzie odpowiadała nam za wyświetlanie opcji konfiguracyjnych modułu i obsługę formularzy.
W obecnej formie rozwoju getContent() sprawdza, czy nastąpiło wysłanie formularza (submit) za pomocą przycisku o nazwie "submit_text" i jeśli tak - w bazie zostaje zapisana nowa wartość dla klucza o nazwie:
$this->name.'_text_to_show' // == testtwo_text_to_show
Przy zapisie rzeczy do bazy będziemy trzymać się konwencji, że każdą nazwę klucza poprzedzimy nazwą naszego modułu. Jako, że użyliśmy tutaj $this->name na początku, powstanie klucz o nazwie 'testtwo_text_to_show' , który będzie przechowywać treść naszego napisu do wyświetlenia na stronie głównej.
4 ważne funkcje użyte w przykładzie
Tools::isSubmit('nazwaPrzycisku')Służy do sprawdzania, czy nastąpiło wysłanie formularza w panelu konfiguracyjnym modułu. Jako parametr podajemy nazwę przycisku.
Tools::getValue('nazwaPola')Pobiera zawartość $_POST odpowiadającą zawartości danego pola w formularzu
Configuration::updateValue('nazwaKlucza', 'wartosc');Dzięki tej funkcji możemy w prosty sposób zapisać w bazie danych naszą konfigurację. Jako pierwszy parametr podajemy nazwę klucza, a jako drugi - wartość. Wszystkie stworzone przez nas konfiguracje lądują w bazie w tabelce ps_configuration (ps_ to standardowy przedrostek tabelek PrestaShop w bazie danych, ale w czasie instalacji sklepu mogłeś wybrać inny)
Configuration::get('nazwaKlucza');Funkcja get pobiera z kolei dane z bazy. Jako parametr użyj nazwy klucza, który użyłeś przy wprowadzaniu danych.
Wracamy do getContent()
Na końcu funkcji getContent() zwracamy zawartość $this->_html, która to zmienna zawiera kod wyświetlający nasz prosty formularz. Jako że getContent() z przykładu na przykład będzie nam się rozrastać - generowanie kodu html do wyświetlenia w panelu admina zostawiliśmy oddzielnej funkcji: _generateForm() . Funkcja ta wypełnia naszą zmienną _html już gotowym kodem formularza:
private function _generateForm() {
$textToShow=Configuration::get($this->name.'_text_to_show');
$this->_html .= '<form action="'.$_SERVER['REQUEST_URI'].'" method="post">';
$this->_html .= '<label>'.$this->l('Enter your text: ').'</label>';
$this->_html .= '<div class="margin-form">';
$this->_html .= '<input type="text" name="the_text" value="'.$textToShow.'" >';
$this->_html .= '<input type="submit" name="submit_text" ';
$this->_html .= 'value="'.$this->l('Update the text').'" class="button" />';
$this->_html .= '</div>';
$this->_html .= '</form>';
}Wykorzystaliśmy tu wspomnianą wcześniej funkcję Configuration::get() aby przy odświerzeniu strony admina nasz formularz zawierał wprowadzoną wcześniej treść.
Ostatni krok, punkt a : hooks
Moduły umiejscawiane są w odpowiednim miejscu na stronie przy pomocy tzw. hooks, czyli zaczepów lub haków - jak kto woli. Hooks pozwalają między innymi na łatwe rozmieszczanie modułów i późniejszą zmianę pozycji. PrestaShop daje też możliwość dodawania własnych, niestandardowych "zaczepów".
Aby nasz moduł był kompletny, musimy podczepić go teraz w odpowiednim miejscu na stronie. Podczepienie modułu wykonujemy w metodzie install() . W tym przypadku chcemy, aby moduł pojawił się w lewej kolumnie, więc napiszemy:
public function install() {
parent::install();
if(!$this->registerHook('leftColumn')) return false;
return true;
}Przekazując odpowiedni parametr funkcji registerHook wybierzemy lewą kolumnę jako miejsce pojawienia się modułu. Do wyboru mamy wiele różnych hooks związanych z pozycją modułów, oto niektóre z nich:
rightColumn - prawa kolumna
leftColumn - lewa kolumna
home - strona główna (środek)
header - nagłówek
top - szczyt strony
footer - stopka
Ostatni krok, punkt b : hookLeftColumn()
Aby podczepić moduł potrzebujmy jeszcze jednej funkcji, której nazwa musi być zgodna z konwencjąhook+nazwa hooka, czyli w tym przypadku hookLeftColumn() :
public function hookLeftColumn() {
global $smarty;
$smarty->assign('our_text',Configuration::get($this->name.'_text_to_show'));
return $this->display(__FILE__, 'testtwo.tpl');
}Już wyjaśniamy, co tu się dzieje. We wstępie wspomnieliśmy Smarty - jest to język templatów zaprojektowany by ułatwić komunikację między programistą front-end a developerem środka aplikacji. Minus jest taki, że jest to nowa rzecz do nauczenia się. Plus z kolei, że uczymy się czegoś nowego :) Na szczęście składnia Smarty nie jest trudna i podstawy można załapać w kilka chwil. PrestaShop używa Smarty w plikach widoku: na finiszu nie używamy już czystego PHP: wszystkie dane z naszego modułu przekazujemy dalej przypisując je do nowych zmiennych Smarty. Do tego celu służy właśnie funkcja $smarty->assign() :
$smarty->assign('nazwa_zmiennej','wartosc_zmiennej');Przypisaliśmy już do zmiennej Smarty our_text zawartość naszego tekstu do wyświetlenia, czas więc wskazać PrestaShop nazwę pliku widoku, który dokona naszego dzieła pokazania komunikatu. Umówy się jeszcze, że od tej chwili zmienne Smarty będziemy oznaczać w tekście kolorem zielonym.
Pliki widoku to te, które mają rozszerzenie .tpl ; jeśli szedłeś w/g kolejnych punktów instruckji, to twójplik jest już gotowy, nazywa się testtwo.tpli znajduje się znajduje się w katalogu /modules/testtwo :
<br/>
And our message is: {$our_text}
<br/>Jak widzisz, w pliku .tpl używamy zwykłego HTMLa. Różnica jest taka, że mamy też dostęp do zdefiniowanych wcześniej zmiennych Smarty. Oto jedno z najprostszych użyć Smarty - wydruk napisu na ekranie. W odpowiednim miejscu wstaw w nawiasie klamrowym nazwę zdefiniowanej wcześniej zmiennej poprzedzonej znakiem dolara, zupełnie jak w PHP.
Serdecznie dziękuję za uwagę. Mam nadzieję, że ten skromny tutorial zainspirował cię w jakiś sposób do zgłębienia tematu lub pomógł przy produkcji innego modułu. Jeszcze raz zapraszam do komentowania. W pierwszej wolnej chwili postaram się zamieścić drugą część tutoriala, w której pokażemy bardziej bezpośredni i szybszy dostęp do bazy danych, odczytywanie wielu wartości formularza na raz, napiszemy trochę więcej kodu używając Smarty oraz - jeśli wielkość nie przekroczy bezpiecznego poziomu uwagi - jak napisać prosty uploader plików wewnątrz PrestaShop.
Dla ciekawych przygotowaliśmy spis linków, które będą pomocne w nauce programowania z wykorzystaniem silnika PrestaShop:
Źródło wiedzy wszelakiej: www.google.pl
PrestaShop Development Guide - wszystko, co potrzeba wiedzieć: http://www.nethercottconstructions.com/en/content/32-prestashop-development-guide
Klasy, programowanie obiektowe: http://php.net/manual/en/language.oop5.visibility.php
Bardzo dobry tutorial o modułach PrestaShop: http://www.ecartservice.net/17072009/writing-your-own-prestashop-module-part-1/
Artykuł o Hooks: http://www.prestashop.com/blog/article/better_understand_and_use_hooks_by_julien_breux
Lista Hooks w Prestashop: http://www.techietips.net/prestashop-list-of-hooks-version-131.html







