Strona używa cookies (ciasteczek). Dowiedz się więcej o celu ich używania i zmianach ustawień. Korzystając ze strony wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki.    X

Smarty - Szablony w aplikacjach PHP #1

SPIS TREŚCI:Smarty - Szablony w aplikacjach PHP #1Smarty - Szablony w aplikacjach PHP #2

Kilka słów wstępu...

Każdy starszy programista wie, że aby projektem swobodnie mogło zarządzać kilka osób należy rozdzielić politykę biznesową od polityki prezentacji. Osoby, które same zajmują się pisaniem w PHPie, czy też innym języku programowania wiedzą, że można od razu przystąpić do pracy - na bieżąco pisać kod i rozmyślać co dodać dalej. Nie jest to najlepsze podejście, chyba że potrzebujemy zrobić małą stronę, która będzie np. wyświetlać rekordy z bazy danych i wpisywać je do tabeli. Do takich zastosowań nie potrzeba wielkich, obszernych, pamięcio i moco-żernych frameworków. Jednak jeżeli chcemy stworzyć stronę o dużo większych wymaganiach, warto na początku zaprojektować i przemyśleć z jakich komponentów będzie składać się nasza strona, oraz jakie opcje musimy zaprogramować, aby osiągnąć dobre rezultaty. Dzięki podzieleniu strony na komponenty możemy później w łatwy sposób wykorzystać je w innym projekcie.

Dzisiejszym tematem jest...

Dzisiaj chciałem przedstawić wam pokrótce nie framework do PHP, a małą klasę pozwalająca na oddzielenie warstwy prezentacji od warstwy reguły biznesu i warstwy dostępu do danych - SMARTY. Podstawowym zadaniem Smartiego, bo tak go dalej będę "przezywał", jest oddzielenie logiki aplikacji od logiki jej prezentacji. Wbrew pozorom Smarty zawiera pewne cechy logiki, która ułatwia odseparowanie PHP'a od szablonu i styczności z kodem HTML.

Co to jest warstwa dostępu do danych?

Są to dane, które chcemy zaprezentować użytkownikom. Dane te mogą być zapisane w postaci plików XML, w bazie danych SQL, w pliku, a nawet na sztywno zapisane w tablicy.

Co to jest warstwa reguł biznesu?

Tutaj prowadzimy cała logikę strony. Programujemy przypadki, które różnymi interakcjami narzuca nam użytkownik. Kliknięcie w button wyślij, a następnie obrobienie danych i wrzucenie do bazy danych, czy nawet proste sortowanie filtrowanie danych z warstwy dostępu do danych.

Co to jest warstwa prezentacji?

To jest wszystko, co widzi użytkownik. Cały układ strony, wyświetlane dane, CSS, obrazki...

Jak to wygląda w praktyce?

Smarty jest specjalną klasą, której obiekt tworzymy w logice aplikacji. Przetwarzamy potrzebne dane i przed wyświetleniem szablonu przekazujemy do logiki prezentacji. Ustawiamy żądany szablon i za resztę odpowiedzialna jest osoba kreująca wizerunek do naszej strony. W praktyce (przykład: firma w której odbywam praktyki) za to odpowiedzialny też jest programista. Jedynie poprawki nanosi projektant, oprócz odwalenia całej roboty stworzenia szablonu i podstawowej integracji.
Co dalej? Wywołując metodę display, na klasie Smarty, ustawiamy szablon, który wykorzystywany będzie do wyświetlenia naszej strony. Późniejszym zdaniem jest wyświetlić przekazane informacje. Więcej szczegółów zamieszczę niżej.

Smarty, a szybkość.

Smarty generuje z szablonów TPL, zwykły kod PHP i przetrzymuje go w pamięci cache. Przy kolejnych wywołaniach szablon, na który nie nanieśliśmy żadnych zmian brany jest z pamięci cache. Nie wpływa to znacznie na szybkość naszego kodu.

Smarty, a bezpieczeństwo.

Bezpieczeństwo. Kluczowa rzecz. Nie wiem, czy wcześniej udało mi się choć trochę naszkicować jak działa Smarty, warto tutaj wspomnieć, że nie ma on żadnego wpływu na pogorszenie bezpieczeństwa pisanej aplikacji. Ba, może nawet podnieść jej bezpieczeństwo zabraniając projektantom używać czystego PHP i nakazywać używanie wyłącznie wbudowanych funkcji, modyfikatorów i przesłanych przez programistę danych.

Jak stworzyć pierwszy szablon w Smartim?

Ponieważ nie będę zajmował się kwestią uruchomienia Smartiego, od tego jest dokumentacja, przejdę od razu do meritum sprawy - języka Smartiego!
Języka opracowanego specjalnie dla projektantów możemy używać w szablonach z rozszerzeniem 'tpl'. Czym różni się tpl od szablonu w HTML'u? A tym, że oprócz html'a, CSS, JS, może zawierać też tagi języka Smarty. Pisząc dalej zajmę się właśnie zagłębieniem się w ten język.

1. Zmienne - zmienne w Smartim przeplatane są przez kod HTML. Od innych tagów odróżnią je użyte klamry { }. Przykładowo szablon może wyglądać tak:<html> <body> Witaj świecie! Jestem {$imie}. </body> </html>Zmienną w tym wypadku jest imię, które zostało przekazane przez programistę w postaci zmiennej typu string zawierające, np. imię zalogowanego użytkownika.

Zmienne można też przypisywać w szablonie. Służy do tego funkcja assign. Przykład użycia: {assign var="imie" value="Paweł"} Witaj świecie! Jestem {$imie}.

2. Przekazywanie wartości do szablonów - w Smartim całą logikę tworzy się w plikach PHP. Jak przystało na dobry system oddzielenia logiki od treści mamy dostęp do określania, który szablon ma być dołączony pod aktualnie opracowywaną logikę. Smarty to także klasa, która ma zdefiniowane metody, służące do określania ustawień jak i przesyłania danych, oraz wyświetlania wyników (szablonów). Przykładowy kod napisany w języku PHP, do wyświetlenia przykładu z punktu pierwszego, może wyglądać tak:<?php include("libs/Smarty.class.php"); $smarty = new smarty(); $imie = Paweł; $smarty->assign("imie", $imie); $smarty->display("przyklad.tpl"); ?>

3. Warunki logiczne - tak jak w innych znanych językach programowanie, w Smartim istnieją warunki logiczne. Zasięg instrukcji if oznaczony jest za pomocą nawiasów klamrowych. Używa się tutaj nawiasów {if}{/if}, dostępne są także {else} oraz {elseif}. Smarty obsługuje operatory warunkowe dostępne w języku PHP jak i też dodaje własne operatory np. operator sprawdzający podzielność - $a is [not] div by $b - w PHP $a % $b == 0.{if $student->ocena >= 4} <p>Dobry uczeń!</p> {else} <p>Uczeń średni</p> {/if}

4. Pętle - w Smartim można tworzyć pętle za pomocą dwóch znaczników. {section} - tablice nieasocjacyjne. {foreach} - tablice asocjacyjne. Dlaczego taki podział? Ponieważ tam gdzie można, należy używać pętli foreach - łatwiejsza. Oczywiście tablice asocjacyjne można przeglądać funkcją section, ponieważ w PHP (nie wiem czy w innych językach także) można do każdej tablicy odwołać się przez jej indeks. Przykład dwóch rodzajów pętli.{section name=id loop=$titles} <p>Tytuł: {$titles[id]}</p> <p>Cena: {$price[id]}</p> {/section} {foreach item=book from=$books} <p>Tytuł: {$book.title}</p> <p>Cena: {$book.price}</p> {/foreach}W pierwszym wypadku użyliśmy dwóch tablic jednowymiarowych. Natomiast w drugim przykładzie użyliśmy tablicy asocjacyjnej o nazwie $books, która zawiera kolejne tablice asocjacyjne. Wygląda to mniej więcej tak:books: ....book0: ........title = Matematyka Dyskretna ........price = 100.99 ....book1: ........title = Wprowadzenie do teorii grafów ........price = 28.00

Dopowiedzenie. Jak by jakiś czytelnik nie wiedział, tablica asocyacyjna jest to tablica, do której możemy odwołać się podając klucz złożony ze znaków. Do tablic nieasocjacyjnych odwołujemy się używając ich kolejnych indeksów zaczynając od indeksu równego zero.

Ponadto używając funkcji section mamy do dyspozycji zmienne, które mogą być przydatne w modyfikowaniu logiki pętli:index - wyświetla bieżący indeks pętli. Przykład użycia: {section name=id loop=3} # indeksu: {$smarty.section.id.index}<br /> {section} first - zwraca true w trakcie pierwszej iteracji iteration - podobna do zmiennej index, ale zwraca numer bieżącej iteracji. Ważne, jeżeli pętla ma indeks startowy np. 15. total - zwraca całkowitą liczbę iteracji. JEDYNA ZMIENNA, KTÓRĄ MOŻNA UŻYĆ PO ZAKOŃCZENIU PĘTLI {section}. loop - zwraca numer ostatniego indeksu.

5. Przydatne funkcje - powiem tylko o części przydatniejszych funkcji. Jest ich naprawdę sporo. W kolejnych wpisach rozpiszę się na ich temat więcej.

5.1. Funkcja html_table - funkcja pobiera parametry w postaci tablicy oraz opcjonalnie liczby kolumn (domyślnie cols=3). Na przykładzie kalendarza: {html_table loop=$dni_tygodnia cols=7} 5.2. Funkcja cycle - funkcja, która cyklicznie przetwarza zbiór wartości i zwraca je jedną po drugiej. Funkcja cycle może mieć nieskończenie wiele wartości. Przykład dla 2 kolorów: <tr bgcolor='{cycle values="#EBEBEB, #ACABAB"}'> 5.3. Funkcja include - aby ułatwić nam edycje szablonu, trzeba rozłożyć go na komponenty. Po co pisać wielokrotnie stopkę, bądź menu? Edycja jednego elementu z takiego menu będzie trwała tyle razy dłużej, ile mamy stworzonych podstron. Funkcja include pozwala nam załączyć szablon we wskazanym miejscu. Przykład działania funkcji include. Plik stopka.tpl: <div id="stopka">Wszystkie prawa zastrzeżone 2009-2020</div> Plik index.tpl: <html> <body> <div id="naglowek">Nagłówek</div> <div id="tresc">TREŚĆ TREŚĆ TREŚĆ</div> {include file="stopka.tpl"} Warto pomyśleć, aby dobrać odpowiednią ilość komponentów. Nie za dużo, oraz nie za mało. W zależności od strony może to być od 4 do 6,10...
5.4. Funkcja literal - funkcja ta przydaje się, kiedy musimy dołączyć kod, w którym zawarliśmy niedozwolone znaki, źle interpretowane przez kompilator Smartiego. Przykładem może być kod JavaScript napisany między znacznikami script, a nie dołączony z oddzielnego pliku. W języku JavaScript do oznaczenia bloków (np. warunków logicznych, funkcji, pętli) używa się klamerek { }, co jest znakiem zastrzeżonym przez Smartiego. Dlatego taki blok najlepiej otoczyć funkcją literal, aby nie była interpretowana przez kompilator. Przykład: {literal}<a href="#" onclick="function js(){ alter('{/literal}{$argument}{literal}');}{/literal}">Click</a> 5.5. Funkcje ldelim i rdelim - funkcje służą do wyświetlania lewej klamerki - {ldelim} { oraz prawej klamerki - {rdelim} }. Dzięki czemu, szablon zostanie prawidłowo prze kompilowany, a wyświetleniem prawidłowych klamerek zajmie się Smarty, dzięki czemu możliwa będzie wewnętrzna (w szablonie) obsługa CSS i JavaScript.

Smarty, używać czy nie?

Nie ma co się zastanawiać! Oczywiście teraz po przeczytaniu takiej porcji informacji możesz nawet w czystym PHP spróbować oddzielić logikę prezentacji od aplikacji. Spójrzcie jak jeszcze miesiąc temu pisałem wyświetlanie prostej listy użytkowników. Widać, że źle nie jest (a może niektórzy powiedzą - tragicznie jest!), ale projekty trzeba pisać tak, aby umożliwić ich łatwiejszą edycję później, dużo później - kiedy już zapomnimy jak działał nasz skomplikowany kod przepleciony fragmentami HTML'a.$listOfContacts = PrepareContacts::getContactsFT($page); /* Sprawdzam czy zapytanie nie zwróciło false */ if ($listOfContacts !== false) foreach ($listOfContacts as $record) { echo '<div class="wiersz">'; echo '<div class="kolumna"><a href="?contact,' . $record->getContactID() . '">' . Config::cutSting($record->getName(), 20) . '</a></div> <div class="kolumna">' . Config::cutSting($record->getSName(), 20) . '</div> <div class="kolumna">' . Config::cutSting($record->getEmail(), 20) . '</div> <div class="kolumna">' . Config::cutSting($record->getPhoneNumer() , 20). '</div> <div class="kolumna">' . Config::cutSting($record->getDate(), 20) . '</div>'; echo '</div>'; }Moim zdaniem nie wygląda to źle. Ale jak by tak wszyscy pisali, to nie było by problemu, a jednak kody różnych ludzi wyglądają różnie. Smarty to standaryzuje. Po otrzymaniu od programisty tablicy z użytkownikami kod wyglądał by np tak (piszę z palca, przepraszam za wszelkie błędy), przy założeniu otrzymania tablicy obiektów User.{if $users} {foreach item=user from=$users} <div class="wiersz"> <div class="kolumna"><a href="?contact,{$user->getId()}">{$user->getName()|truncate:20:"...":true}</a></div> <div class="kolumna">{$user->getSName()|truncate:20:"...":true}</div> <div class="kolumna">{$user->getEmail()|truncate:20:"...":true}</div> <div class="kolumna">{$user->getPhoneNumer()|truncate:20:"...":true}</div> <div class="kolumna">{$user->getDate()|date_format:"%d %b, %Y"}</div> </div> {/foreach} {else} <div class="wiersz">W bazie nie ma żadnych użytkowników</div> {/if}To wszystko przepisałem w 4 minuty, zachowując ładne, czytelne formatowanie i prostotę. A przy tym nie napisałem żadnej funkcji (jak np. we wcześniejszym kodzie, obcinanie stringa).

Ponieważ, nie widać wcięć na blogu zamieściłem powyższy kod, wraz z wcięciami, na innej stronie http://ctrlv.it/id/MjQxNTk5.

Podsumowanie.

Wpis jak na mój pierwszy dość obszerny. Pewnie dało by się go napisać ładniej i zgrabniej. Wybaczcie. Mam tylko nadzieje, że ten wpis się komuś przyda. Jeżeli zajdzie taka potrzeba napiszę od postaw jak dodać Smartiego do projektu.
Następnych części można spodziewać się w odstępie tygodnia, w których poruszę inne ważne funkcje, metody klasy Smarty, używanie modyfikatorów (użyłem do formatowania daty, ucięcia tekstu) i innych zagadnień związanych ze Smartim. Miejmy nadzieje, że nie utracę weny i podam bardziej praktycznie przykłady zastosowania, bo nie można uczyć się na sucho.

Mile widziane wszelkie poprawki! Przede wszystkim literówki utrudniające czytanie, jak i błędy które wkradły się do kodów i niedomówienia. 

Komentarze

0 nowych
Sobak   2 #1 19.07.2011 12:20

Dobry wpis. Przy większych aplikacjach brak rozdzielenia warstwy prezentacji od biznesowej to strzał w stopę.

"Mile widziane wszelkie poprawki! Przede wszystkim literówki utrudniające czytanie, jak i błędy które wkradły się do kodów i niedomówienia."
W drugiej linijce ostatniego listingu:
{foreacch item=user from=$users}

ziggurad   11 #2 19.07.2011 13:18

W jednej firmie w której pracowałem korzystano z Smarty, w drugiej nie.

Nie wiem dlaczego ale mi wygodniej jest zastosować MVC i podzielić projekt na te trzy warstwy za pomocą PHP. Mam model w którym są wszystkie najważniejsze operacje czyli rozpoznanie gdzie użytkownik chce się dostać (z "ładnych" adresów), sprawdzenie czy użytkownik może otrzymać dostęp do tej części strony, łączenie z bazą, funkcje często wykorzystywane w projekcie no i wybór odpowiedniego kontrolera. Kontroler wykonuje już konkretne zadanie np dodanie newsa do bazy i po przetworzeniu danych wybiera odpowiedni widok do wyświetlenia. Widok to plik html który zawiera informacje o wyglądzie i odpowiednio wyświetla (przy pomocy PHP) dane dostarczone przez kontroler.

Na tym opierałem się pisząc swojego małego CMSa który był moją pracą inżynierską. Nie jest idealny, brakuje mu kilku rzeczy ale jest MÓJ :D

Co do twojego artykułu, jest bardzo fajny i z chęcią przeczytam dalsze wpisy na ten temat. Może mnie przekonasz do sprawdzenia jak w praktyce wygląda praca z tą klasą ;)

Przyczepie się tylko do includowania stopki. No fajnie mam stopkę w osobnym pliku i nie muszę jej poprawiać we wszystkich tpl'ach. Ale co się dzieje jak chcę zmienić główny układ strony?

Wiem że można to także rozdzielić i utworzyć index z głównym układem strony i później doczytywać tylko szablony kolejnych podstron ale jak to się robi? Za każdym razem wczytywany jest index i smarty w zależności od odebranych danych dopiera sobie jakiś "podwidok"? Czy to php wczytuje główny układ i podwidok?

underface   14 #3 19.07.2011 15:20

będzie więcej?

dingo12   3 #4 19.07.2011 19:40

@Sobak
Dzięki za poprawę i wypowiedź. Poprawione.

@ziggurad
Tak jak w prawie wszystkich frameworkach. Najważniejsze jest aby oddzielić logikę programisty od widoku, tak jak to napisałeś. W widoku robimy tylko minimum.
Co do stopki. Dzisiaj musiałem własny moduł dodać do do strony. Stworzyłem stronę, pod ten moduł no i trzeba było podpiąć linka. Jakie było moje zdziwienie, że strona miała 5 plików index (3 domeny, praktycznie taki sam wygląd strony, ale troszkę inna tematyka - jakieś dofinansowanie unijne). No i każdy plik musiałem ręcznie poprawiać. Fakt dużo roboty nie było bo potem CTRL+V i CTRL+C, ale zawsze.
Co do rozdzielnia. Aktualnie pracuje na autorskim CMS'ie gdzie wszystko jest już zaimplementowane. Ja jedynie wybieram sobie podszablon i doczepiam go w odpowiednie miejsce (cały moduł doczepiam). Nie wiem jak odpowiedzieć Ci na to pytanie. Spróbuje to opisać później, bo sam za bardzo się w to nie wgłębiałem. Spróbuje na to pytanie odpowiedzieć w następnym wpisie.

@underface
Tak jak napisałem. Będzie, a raczej ma być. Ale pewnie będzie.

Dzięki za komentarze.

Pozdrawiam

  #5 19.07.2011 21:36

W mojej opinii Smarty nie jest czymś, na czym powinno tworzyć się nowe projekty - jest to swego rodzaju przeżytek z czasów PHP4 - w czasach PHP5 i języków obiektowych powinno nauczać się młodych adeptów programowania bardziej nowoczesnych architektur (jakby chociaż wspomniane MVC, vide: Symfony, Zend Framework, CakePHP, ...).
Nie mówię, że nie należy w ogóle się Smarty zajmować - jego znajomość jest dobra TYLKO i WYŁĄCZNIE w jednym przypadku - bugfixing aplikacji używających tejże technologii.

kubut   17 #6 20.07.2011 03:19

Osobiście także używam MVC, jednak nie tyle ze świadomego wyboru, co z przymusu. Przy jednym ze zleceń miałem wprowadzić modyfikacje na portalu napisanym w MVC, co wymusiło na mnie "naukę" tego sposobu pisania aplikacji. O Smartach słyszałem nie raz, ale jakoś nigdy nie miałem czasu poczytać o tym. Teraz oczywiście go też nie mam (przyznam, ze przeleciałem tylko na szybko) ale zapiszę sobie ten art w zakładkach i chętnie przeczytam. Szczególnie, ze ja także niedługo planuję rozpocząć pracę nad własnym CMS'em będę musiał zaznajomić się z różnymi technikami, aby wybrać najlepszą dla mnie ;)

  #7 20.07.2011 08:27

Zgodziłbym się z ZKW :)
Autorzy Smarty powinni spłonąć w piekle ;) Smarty jest przeżytkiem. Dużo lepszy pod względem wydajności i kodu jest Twig. Jeśli nie jesteś grafikiem to Smarty po pewnym czasie staje się obciążeniem niż ułatwieniem.

dingo12   3 #8 21.07.2011 09:58

@up up up
No niestety, a ludzie ciągle go używają. Ja go poznałem, bo powiedzieli mi na rozmowie, że używają go więc coś tam ogarnąłem.

  #9 21.07.2011 11:48

MVC - tak!
Smarty jako dodatek do MVC - upraszczający tworzenie warstwy widoku może być, acz niekoniecznie.

marcin86s   4 #10 22.07.2011 14:38

Macie jakieś ciekawe artykuły na temat MVC, coś dla początkujących w tej dziedzinie? Próbowałem coś z Zendem ale to chyba zbyt duże bydle jak na początek.

dingo12   3 #11 23.07.2011 13:50

@marcin86s
Zend to super bydle. Ale bardzo dobry framework. Hmm co polecam? W symfony robiłem. Też bydle, i ma swoje humory. Nie wiem co jest dobre na początek. Niestety nie znam się, ale jak nie masz alternatywy to może jednak symfony. Moim zdaniem większość rzeczy jest naprawdę prosta.

  #12 25.07.2011 19:45

Bardzo często zdarza się, że funkcje systemu templat (weźmy dla przykładu omówione Smarty) są niewykorzystywane. Warto zainteresować się głębiej tematem szablonów i spróbować napisać swoją wersje - nierzadko upraszczającą wiele i odciążającą serwer www.

Tak, być może zaraz ktoś powie: "no ale smarty ma tak wiele możliwości, jest darmowe a serwery obecnie są takie szybkie, ma obsługę błędów, blablabla...". Wszystko to jest prawdą, tylko jak wspomniałem: jeśli coś jest nieużywane - po co istnieje? Odpowiedź zna każdy.