Księga gości w oparciu o Smarty
Często na stronach można spodkać księgi gości. Są to bardzo proste skrypty, które umożliwiają zostawianie informacji o sobie oraz krótki komentarz. Z tego artykułu dowiemy się w jaki sposób w oparciu o Smarty napisać taki skrypt.
Smarty
Smarty jest biblioteką szablonów umożliwiającą oddzielenie kodu PHP od wyglądu strony. W tym artykule zakładam podstawową znajomość Smarty. Wszystkich, którzy pierwszy raz stykają się ze smarty odsyłam do artykułu: Smarty - Instalacja
Baza danych
W naszym skrypcie używać będziemy bazy mysql. W tej bazie utworzymy tylko jedną tabelę entries, w której przechowywać będziemy wpisy. Każdy wpis będzie składał się z tytułu i treści oraz autora. Opcjonalne będą pola e-mail oraz strona WWW. Polecenie SQL tworzące tę tabelę widzimy poniżej.
![]()
CREATE TABLE entries(
id integer PRIMARY KEY auto_increment,
title varchar(150),
body text,
author varchar(50),
website varchar(100),
email varchar(100),
publish_date integer
);
Kod PHP strony
Utworzymy teraz plik db.php. Będzie on odpowiedzialny za komunikacje z bazą. Dodatkowo zaimplementujemy funkcję pobierającą wszystkie wpisy z zapytania do tablicy. Kod tego pliku przedstawia poniższa ramka.
![]()
![]()
![]()
$dbconfig = array(
'host' =>'localhost',
'user' =>'root',
'pass' =>'',
'dbname'=>'guestbook'
);
![]()
$db = mysql_connect($dbconfig['host'], $dbconfig['user'], $dbconfig['pass']);
mysql_select_db($dbconfig['dbname'], $db);
![]()
function db_fetch_all($sql){
global $db;
![]()
$query = mysql_query($sql);
![]()
$rows = array();
![]()
while(($row = mysql_fetch_array($query))!= null){
$rows[] = $row;
}
![]()
return $rows;
![]()
}
![]()
![]()
W pliku index.php zawrzemy inicjacje obiektu smarty wraz z ustawieniem pewnych parametrów.
![]()
![]()
![]()
require_once('db.php');
![]()
![]()
require_once('smarty/Smarty.class.php');
![]()
$smarty = new Smarty();
if(isset($_POST['title'])){
$title = mysql_escape_string($_POST['title']);
$body = mysql_escape_string($_POST['body']);
$author = mysql_escape_string($_POST['author']);
$website = mysql_escape_string($_POST['website']);
$email = mysql_escape_string($_POST['email']);
mysql_query('Insert into entries(title, body, author, website, email, publish_date)
values("'.$title.'", "'.$body.'", "'.$author.'", "'.$website.'", "'.$email.'", '.time().')', $db);
$smarty->assign('entry_added', true);
}
![]()
$entries = db_fetch_all('SELECT * FROM entries');
![]()
$smarty->compile_dir = 'var/compile';
$smarty->cache_dir = 'var/cache';
$smarty->assign_by_ref('entries', $entries);
$smarty->display('index.tpl');
![]()
![]()
![]()
Na początku skryptu dołączamy odpowiednie pliki. Trzeba zwrócić uwagę, że ścieżka do pliku Smarty.class.php może się różnić, w zależności od tego gdzie zainstalujemy Smarty.
Dalej następuje sprawdzenie czy dane zostały przesłane metodą POST. Jeśli przesłano metodą post tytuł (zakładamy umownie, że tyle jest wymagane), to dodajemy wpis do bazy.
Przed sprawdzeniem czy powinniśmy dodać wpis do bazy nastąpiło stworzenie obiektu klasy Smarty. Po ewentualnym dodaniu wpisu do bazy następuje ustawienie zmiennej entry_added na wartość true. W ten sposób wyświetlimy informacje o dodaniu wpisu. Dalej pobieramy wszystkie wpisy z bazy do zmiennej $entries. Następnie ustawiamy katalogi kompilacji szablonów i cache'owania szablonów. Moglibyśmy ustawić także inny katalog przechowywania szablonów (zmienna template_dir), jednak w tym przypadku katalog templates jest dobrym wyborem. Na końcu następuje przypisanie przez referencje wpisów. Aby przypisać przez referencje używamy funkcji assign_by_ref. Dzięki temu oszczędzamy pamięć. Gdybyśmy, przekazywali zmienną $entries funkcją assign, skrypt musiałby utworzyć sobie lokalną kobie tej tablicy. W przypadku dużych tablic polecam używać funkcji assign_by_ref.
Tworzymy szablon
Teraz zajmiemy sie szablonem. Tutaj nauczymy się wykorzystywania pętli foreach, kilku modyfikatorów zmiennych i instrukcji warunkowej if. Popatrzmy na kod szablonu (plik templates/index.tpl).
![]()
<html>
<head>
<title>Moja księga gości</title>
<meta http-equiv="content-type" content="application/xhtml+xml; charset=iso-8859-2"/>
<style>
{literal}
p{
font-size: 12pt;
font-family: Verdana,Arial;
}
![]()
.small{
font:8pt bold Verdana;
color:rgb(144,144,144);
margin: 0 0 0 0;
}
.author{
color: rgb(54,54,54);
font-size:8pt;
font-style:italic;
}
h2{
background: rgb(200,200,200);
color: rgb(54,54,54);
font-variant:
margin-bottom: 0;
}
input, textarea{
border: 1px solid black;
margin: 1px 0 1px 0;
}
{/literal}
</style>
<body>
{if $entry_added}<p><b>Dodano wpis!</b></p>{/if}
{foreach from=$entries item=entry}
<h2>{$entry.title|escape:"htmlall"}</h2>
<p class="small">{if $entry.website != ''}<a href="{$entry.website|escape:"url"}">{$entry.website|escape:"htmlall"}</a>{/if}</p>
<p class="small">{$entry.email|escape:"mail"|default:"brak"}</p>
<p>{$entry.body|escape:"htmlall"}</p>
<p class="author">{$entry.author|escape:"htmlall"}, {$entry.publish_date|date_format:"%d-%m-%y %H:%M:%S"}</p>
<hr>
{foreachelse}
<p>Nie dodano żanych wpisów</p>
{/foreach}
![]()
<form action="#" method="post">
<input type="textbox" name="title" style="width:400px" /><br />
<textarea rows="8" style="width:400px" name="body"></textarea><br />
Autor: <input type="textbox" name="author" style="width:300px" /><br />
Strona WWW: <input type="textbox" name="website" style="width:300px" /><br />
E-mail: <input type="textbox" name="email" style="width:300px" /><br />
<input type="submit" value="Dodaj wpis">
</form>
</body>
</html>
Widzimy, że na samej górze, tuż po tagu <style> otwieramy blok {literal}. Blok ten zamykamy tuż przez tagiem </style>. Otwarcie tego boku powoduje zaniechania kompilacji tego kawałka i wstawienia go do szablonu jako tekst. Dzięki temu parser Smarty nie będzie stwierdzał błędu, gdy otwieramy wpisy css { i zamykamy }. Gdyby nie ten blok parser Smarty wskazałby błąd. Jeżeli na stronie musimy, często używać znaków { i }, łatwiej będzie zmienić znaki ograniczające wyrażenia Smarty. Aby to uczynić ustawiamy polom left_delim i right_delim inne wartości niż standardowe { i }.
Dalej widzimy wykorzystanie bloku if. Dzięki temu blokowi możemy wykonać instrukcje tylko gdy warunek jest spełniony. W tym przypadku wyświetlimy informacje o dodanym wpisie, tylko wówczas, gdy $entry_added zostało ustawione na true (patrz plik index.php). Poniżej warunku if znajduje się pętla foreach. Przyjmuje ona 2 parametry. Parametr from określa zmienną, którą chcemy iterować. Parametr item określa nazwę iteratora. W bloku foreach używamy iteratora jak normalną zmienną. Przy wypisywaniu tytułu używamy modyfikatora escape z parametrem "htmlall", dzięki czemu zabezpieczamy się przed atakami XSS. Podobnie postępujemy ze wszystkimi innymi zmiennymi. Warto zwrócić uwagę, na parametr modyfikatora "email", który zamienia @ na [AT] i . na [DOT]. O wszystkich parametrach można przeczytać w manualu. Ciekawym modyfikatorem jest default, który określa wartość domyślną, jeśl zmienna nie została ustawiona.
Bardzo istotnym i przydatnym modyfikatorem jest date_format, który zamienia uniksowy znacznik czasu (zwracany m.in. przez funkcje time) na postać tekstową. Modyfikator ten działa podobnie jak funkcja date, jednak należy uważać, ponieważ niektóre parametry mają inne znaczenie.
Ciekawą opcją Smarty jest możliwość umieszczenie bloku foreachelse. Jest on opcjonalny i umożliwia on wyświetlenie informacji, gdy tablica jest pusta. Dzięki temu nie trzeba przed każdym blokiem foreach wstawiać ifa sprawdzającego czy tablica jest pusta.
Stronicowanie danych
Każda dobra księga gości musi mieć stronicowanie. Dzięki stronicowaniu nauczymy się kilku ciekawych rzeczy. Oto kod PHP zmodyfikowanego pliku index.php
![]()
![]()
![]()
require_once('db.php');
![]()
![]()
require_once('smarty/Smarty.class.php');
![]()
$smarty = new Smarty();
if(isset($_POST['title'])){
$title = mysql_escape_string($_POST['title']);
$body = mysql_escape_string($_POST['body']);
$author = mysql_escape_string($_POST['author']);
$website = mysql_escape_string($_POST['website']);
$email = mysql_escape_string($_POST['email']);
mysql_query('Insert into entries(title, body, author, website, email, publish_date)
values("'.$title.'", "'.$body.'", "'.$author.'", "'.$website.'", "'.$email.'", '.time().')', $db);
$smarty->assign('entry_added', true);
}
![]()
![]()
$page = 1;
if(isset($_GET['page'])) $page = (int)$_GET['page'];
![]()
$perPage = 1;
$offset = ($page - 1)*$perPage;
![]()
$entries = db_fetch_all('SELECT * FROM entries LIMIT '.$offset.', '.$perPage);
$pages = mysql_result(mysql_query('SELECT count(*) from entries'),0,0);
$pages /= $perPage;
![]()
$smarty->compile_dir = 'var/compile';
$smarty->cache_dir = 'var/cache';
$smarty->assign('entries', $entries);
$smarty->assign('page', $page);
$smarty->assign('pages',$pages);
![]()
$smarty->display('index.tpl');
![]()
![]()
![]()
![]()
Nie ma tu nic nowego oprócz kilku przeliczeń dotyczących ilości stron i ograniczenia LIMITem ilości pobranych rekordów. Teraz zobaczmy fragment kodu odpowiadający za wyświetlenie stron. Należy go umieścić go w tym miejscu, gdzie chcemy wyświetlić listę stron (np. po {/foreach}).
![]()
{section name=p start=1 loop=$pages+1}
{assign var=i value=$smarty.section.p.index}
{if $i == $page}<b> {$page} </b>{else}
<a href="index.php?page={$i}"> {$i} </a>{/if}
{/section}
Używamy tutaj nowego bloku: section. Ten blok także pozwala iterować tablice, jednak tutaj wykorzystujemy go podobnie do pętli for. Parametrem name nadajemy mu nazwę p. Parametrem start określamy pierwszą wartość iteratora, a parametrem loop ilość przejść pętli. Wewnątrz bloku section wykorzystujemy funkcję assign, która przypisuje zmiennej i wartość iteratora (ze zmiennej $smarty.section.p.index). Dalej wyświetlamy link lub stały tekst, jeżeli jesteśmy już na tej stronie.
![]() |
|
| Działająca księga gości | ![]() |
Podsumowanie
Smarty zawiera jeszcze wiele ciekawych funkcji i nie sposób ich opisać w jednym artykule. Z tego artykułu nauczyliśmy się wykorzystywać kilka najważniejszych i najprzydatniejszych. Warto jeszcze doczytać o nich w manualu.
#1
Dobry artykuł, lecz sądzę, że nie ma sensu robić AŻ tyle dla zwykłej księgi gości, tym bardziej, że ta, jeśli się ją nie rozbuduje, jest dość mało efektywna. Smarty to kompletny bezsens przy takim czymś.
#2
Dla prostego systemu pewnie nie, ale chodziło mi przede wszystkim o idee i sposób działania :)












