PHP/Studium przypadku - Księga gości: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
Zyx (dyskusja | edycje)
Nie podano opisu zmian
Zyx (dyskusja | edycje)
napisana pierwsza część
Linia 2:
 
== Studium przypadku: Księga gości ==
Dotychczasowe rozdziały miały w sobie więcej teorii i nie ukazywały prawdziwej istoty tworzenia skryptów dla stron WWW. Najlepszym rodzajem nauki jest praktyczne stworzenie skryptu z prawdziwego zdarzenie i pokazanie w ten sposób, jak poszczególne elementy języka ze sobą się łączą. W tym rozdziale stworzymy samodzielnie funkcjonalną księgę w PHP. Wykorzystamy w niej pętle, tablice, instrukcje warunkowe, formularze oraz dołączanie plików zewnętrznych. Ponadto poznamy kilka interesujących funkcji.
 
=== Plan ===
{{TODO|Patrz: dyskusja}}
Księgę gości oprzemy o pliki tekstowe. Każdy wpis będzie charakteryzowany przez:
* Tytuł
* Autora
* Datę
* Adres WWW (opcjonalny)
* Treść
Wszystkie te dane zostaną zapisane w pliku w pojedynczym wierszu, a oddzielone będą znakiem "|". Aby wyeliminować sytuację, gdy ktoś wpisze np. w treść taki znak, albo (co gorsza) naciśnie enter, każda kolumna zostanie zakodowana w formacie Base64. Oczywiście nie będziesz musiał sam pisać odpowiedniego algorytmu - PHP posiada odpowiednie funkcje. Base64 został pierwotnie zaprojektowany do przesyłania 8-bitowych wiadomości w 7-bitowych protokołach. Do zapisu są tu używane wyłącznie litery, cyfry, ukośnik oraz znak równości, zatem nie ma obawy o uszkodzenie formatu pliku księgi. Zakodowana wiadomość jest o ok. 33% dłuższa od oryginału.
 
Księga nie będzie zapisywać i odczytywać z pliku bezpośrednio. W zewnętrznym pliku napiszemy sobie dwie funkcje zajmujące się wyłącznie tym. Księga będzie miała dostęp do danych jedynie za ich pomocą. Rozwiązanie to jest bardzo użyteczne. Kiedy poznasz już bazy danych, z pewnością zapragniesz przesiąść się właśnie na nie. Nie będziesz musiał przepisywać całej księgi. Po prostu napiszesz do tych dwóch funkcji nowy kod. Dzięki takiemu rozwiązaniu źródła skryptu będą uporządkowane i czytelne, a ponadto bardzo łatwe do modyfikacji.
 
=== dane.php ===
Plik ''dane.php'' zawierać będzie dwie funkcje: ''dodajWpis()'' oraz ''pobierzWpisy()'' zajmujące się wyłącznie operowaniem na danych. Będziemy go pisać po kawałku.
 
<nowiki><?php
define('WPISY', './wpisy.txt');
function dodajWpis($tytul, $autor, $www, $tresc)
{
// Ucinanie bialych znakow
$tytul = trim($tytul);
$autor = trim($autor);
$www = trim($www);
$tresc = trim($tresc);</nowiki>
 
Nazwę pliku zapisaliśmy za pomocą stałej. To na wypadek, gdyby zachciało nam się go kiedyś przenieść albo zmienić mu nazwę. Pierwszy etap obrabiania danych to ucięcie białych znaków (spacji, tabulatorów itp.) z początku i końca każdego ciągu. Nie są nam one do niczego potrzebne, a jedynie utrudniają nam sprawę.
 
<nowiki> // Kontrola danych
if(strlen($tytul) < 3)
{
return false;
}
if(strlen($autor) < 3)
{
return false;
}
if(strlen($tresc) < 10)
{
return false;
}
if(strlen($www) > 0)
{
// Jesli adres nie zaczyna sie od http:// to dodaj to
if(strpos($www, 'http://') !== 0)
{
$www = 'http://'.$www;
}
}</nowiki>
 
Tutaj zajmujemy się kontrolą danych. Tytuł i autor muszą mieć przynajmniej trzy znaki, a treść 10. Długość pobieramy funkcją ''strlen()''. Jeżeli podaliśmy adres WWW, za pomocą funkcji ''strpos()'' sprawdzamy, czy na jego początku jest na pewno dodany identyfikator protokołu. Zwróć uwagę na użyty operator: ''!==''. Wspomniana funkcja zwraca pozycję pierwszego znaku szukanego ciągu (liczoną od zera), a jeżeli go nie znajdzie, zwraca '''false'''. Normalnie ''0'' i '''false''' są równoważne, dlatego musimy wymusić sprawdzenie także typu, bowiem nam chodzi o ''0'' jako pozycję identyfikatora w adresie, a nie informację, że go nie ma.
 
Jeżeli któraś z informacji nie będzie prawidłowo podana, funkcja zwróci do skryptu wartość '''false'''.
 
<nowiki> // Dodawanie
$f = fopen(WPISY, 'a');
$dane = array(0 =>
base64_encode(htmlspecialchars($tytul)),
base64_encode(htmlspecialchars($autor)),
time(),
base64_encode(htmlspecialchars($www)),
base64_encode(nl2br(htmlspecialchars($tresc)))
);
fwrite($f, implode('|', $dane)."\r\n");
fclose($f);
return true;
} // end dodajWpis();</nowiki>
 
Ostatni akord to zapisanie wpisu w pliku. Na początek otwieramy go w trybie dopisywania (parametr ''a''), następnie budujemy tablicę z danymi wpisu. Parametry przybyłe z formularza kodujemy w Base64, środkowa kolumna to czas dodania wpisu w sekundach od 1.1.1970. Dzięki takiemu jego zapisowi, będziemy go mogli później dowolnie formatować funkcją ''date()''. Przy przetwarzaniu tekstu użyliśmy jeszcze kilku funkcji:
* ''htmlspecialchars()'' - wszystkie wprowadzone tagi HTML są zamieniane na zwykły tekst (ograniczniki są zastępowane odpowiadającymi im encjami, np. ''&lt;'' zmienia się w ''&amp;lt;''). W ten sposób nikt nie rozwali nam księgi złośliwym kodem.
* ''nl2br()'' - zamienia znaki nowej linii na znaczniki ''&lt;br/&lt;''.
* ''implode()'' - łączy tablicę w ciąg tekstowy, wstawiając pomiędzy poszczególne elementy podany w pierwszym parametrze znak. Na końcu utworzonego przez nią rekordu wpisu musimy dodać samodzielnie znaki zejścia do nowej linii: ''\r\n'', koniecznie w cudzysłowach, a nie w apostrofach.
 
Zwróć uwagę na rozbudowane wywołania funkcji:
 
''base64_encode(nl2br(htmlspecialchars($tresc)))''
 
Oznacza ona, że najpierw zawartość zmiennej ''$tresc'' trafia do funkcji najbardziej w prawo, tj. ''htmlspecialchars()''. Z niej przechodzi do ''nl2br()'', a z niej do ''base64_encode()''. Alternatywne kursy preferują w tym miejscu czytelną, ale mniej wydajną formę zapisu:
 
<nowiki>$tresc = htmlspecialchars($tresc);
$tresc = nl2br($tresc);
$tresc = base64_encode($tresc);</nowiki>
 
Nasz kod ma tę przewagę, że wynik jednej funkcji od razu trafia do drugiego, tymczasem powyżej po drodze trafia do zmiennej, co ma szczególnie negatywny wpływ na wydajność przy dużych danych. Ponadto zapis ten często nie jest opatrzony stosownym komentarzem i wyrabia złe nawyki tworzenia mnóstwa niepotrzebnych zmiennych tymczasowych, o czym już wspominaliśmy. Trzeba zapamiętać, że nawet podawany przez nas wariant konstrukcji księgi nie jest "tym jedynym słusznym". Istnieje jeszcze wiele innych sposobów jej zaprogramowania.
 
Przyszła kolej na funkcję pobierającą wpisy.
 
<nowiki> function pobierzWpisy()
{
$wpisy = array_reverse(file(WPISY));
$i = 1;
$rezultat = array();</nowiki>
 
Wpisy pobieramy funkcją ''file()'', która automatycznie rozbija nam plik na tablicę względem wierszy. Tam jednak najnowsze wpisy są na końcu, a my chcemy je wyświetlić w kolejności odwrotnej: najnowsze na górze. Dlatego od razu przepuszczamy wynik przez funkcję ''array_reverse()'' odwracającą tablicę. Następnie inicjujemy licznik wpisów ''$i'' oraz tablicę ''$rezultat'', do której będziemy pakować sformatowane odpowiednio wpisy. Ją później przekażemy księdze do wyświetlenia.
 
<nowiki> foreach($wpisy as $wpis)
{
$wpis = explode('|', trim($wpis));
$rezultat[] = array(
'id' => $i,
'tytul' => base64_decode($wpis[0]),
'autor' => base64_decode($wpis[1]),
'data' => date('d.m.Y, H:i', $wpis[2]),
'www' => base64_decode($wpis[3]),
'tresc' => base64_decode($wpis[4])
);
$i++;
}
return $rezultat;
} // end pobierzWpisy();
?></nowiki>
 
Po kolei formatujemy każdy wpis. Do ich pobierania wykorzystaliśmy pętlę ''foreach()''. Na wejściu przepuszczamy je przez funkcję ''trim()'', bowiem ''file()'' pozostawia w tablicach znaki zejścia do nowej linii. Dopiero po ich usunięciu możemy funkcją ''explode()'' rozbić ciąg z powrotem na tablicę (czyli wykonać operację odwrotną do ''implode()''). Wpis przepuszczamy przez ''base64_decode()'', aby zdekodować informacje, formatujemy datę i pakujemy to do tablicy ''$rezultat''. Później zwracamy ją.
 
=== ksiega.php ===
 
{{TODO|Napiszę w weekend}}
 
=== Co dalej? ===
 
{{TODO|Napiszę w weekend}}