Formularze są podstawą aplikacji internetowych. Mimo że na stronach internetowych nie widać ich zbyt wiele, w panelach administracyjnych wszelkiego rodzaju formularzy jest znacznie więcej. To właśnie dzięki formularzom można dodawać treści na strony bez konieczności ręcznej edycji plików czy zawartości bazy danych.
Sposoby wysyłania formularzy
Dane z formularzy mogą być wysyłane na dwa sposoby: za pomocą metody {stala}GET{/stala} oraz {stala}POST{/stala}. Metoda {stala}GET{/stala} jest prostsza w działaniu, ma jednak kilka minusów:
- dane wysyłane tą metoda dodawane są do adresu URL,
- długość wysyłanych danych jest ograniczona, bowiem ograniczona jest długość adresu URL.
Wady te nie zawsze jednak są wadami, ponieważ:
- dane przesyłane w adresie URL pozwalają na przekazanie takiego adresu osobom trzecim, co może być przydatne w przypadku wyszukiwarek,
- dane w adresie URL można formatować samemu bez konieczności korzystania z formularzy (o tym dalej), przekazując tym samym pewnie informacje do skryptu PHP.
Dane wysyłane metoda post przesyłane są w postaci specjalnie sformatowanego przez przeglądarkę zadania do skryptu PHP.
Przyjrzyjmy się w jaki sposób wysyłane są żądania {stala}GET{/stala} i {stala}POST{/stala} do serwera. Wiedza ta nie jest niezbędna do pracy z formularzami w PHP, może się jednak przydać w przyszłości przy bardziej złożonych aplikacjach (nie wszyscy, nawet zaawansowani programiści, wiedza jak wyglądają takie zadania).
Załóżmy, że mamy prosty formularz:
oraz:
Wypełniony formularz wysłany metoda {stala}GET{/stala} (czyli pierwszy) spowoduje wysłanie do serwera
zadania o postaci:
{stala}GET /logowanie.php?imie=Jan&nazwisko=Kowalski HTTP/1.1{/stala}
{stala}Host: localhost{/stala}
Dane te są to tak zwane nagłówki – informują one serwer o zadaniach przeglądarki. Tutaj zadanie brzmi: \”uruchom skrypt {stala}logowanie.php{/stala}, który znajduje się pod adresem {stala}localhost{/stala}, i przekaż do niego parametry\”. Zaś adres w przeglądarce internetowej będzie miał postać:
{stala}http://localhost/logowanie.php?imie=Jan&nazwisko=Kowalski{/stala}
Jak widać, w adresie URL znajdują się niemal wszystkie informacje z nagłówków wysłanych do serwera w zadaniu.
W przypadku formularza wysłanego metoda POST zadanie wygląda nieco inaczej:
{stala}POST /logowanie.php HTTP/1.1{/stala}
{stala}Host: localhost{/stala}
{stala}Content-Type: application/x-www-formurlencoded{/stala}
{stala}Content-Lenght: 27{/stala}
{stala}imie=Jan&nazwisko=Kowalski{/stala}
Adres URL wygląda tym razem następująco:
{stala}http://localhost/logowanie.php{/stala}
Różnice są znaczne. Tym razem żadne dane nie są umieszczane w adresie URL, zamiast tego wysyłane są w treści zadania (pod nagłówkami – zwróćmy uwagę na linie przerwy między nagłówkami a danymi wysyłanymi do skryptu, jest ona niezbędna).
Nagłówek {stala}Content-Type{/stala} określa typ danych (formularz WWW) i sposób ich zapisu ({stala}urlencoded{/stala} – czyli sposób analogiczny do tego stosowanego w adresach URL; poszczególne wartości oddzielone są znakami {stala}&{/stala}). Nagłówek {stala}Content-Lenght{/stala} określa długość przesyłanych danych (czyli ilość znaków). Wygląda to przerażająco? Nie, bo PHP znacznie ułatwia obsługę danych pochodzących z formularzy. Nie trzeba dbać o analizowanie żądań pochodzących z przeglądarki.
Sprawdzić, czy istnieje element o indeksie 0, można za pomocą funkcji {stala}isset(){/stala}:
if (isset($_POST[\'uzytkownik\'][1])) {
echo $_POST[\'uzytkownik\'][1];
}
Co można również zapisać jako:
echo isset($_POST[\'uzytkownik\'][1]) ? $_POST[\'uzytkownik\'][1] : \'\';
Funkcja {stala}isset(){/stala} sprawdza czy dana zmienna – w tym przypadku wartość pod konkretnym indeksem tablicy – istnieje. Jeśli istnieje, zwraca ona wartość {stala}true{/stala}, jeśli nie, zwraca wartość {stala}false{/stala}.
Bardzo istotne jest sprawdzanie poprawności danych wprowadzanych przez użytkowników w formularzu. Nigdy nie ufajmy użytkownikom i ograniczmy ich możliwości wprowadzania danych. Jeśli dane maja być cyframi, można sprawdzić czy zostały one poprawnie wprowadzone za pomocą funkcji {stala}is_numeric(){/stala}:
if (!is_numeric$_POST[\'wiek\']) {
echo \'Wiek musi być liczbą!\';
} else {
//wprowadzone dane są poprawne
}
Funkcja ta sprawdza czy dane podane jako jej parametr są cyfra. Jeśli tak, zwraca wartość {stala}true{/stala}, jeśli nie, zwraca wartość {stala}false{/stala}.
Jeśli użytkownik ma mieć możliwość wprowadzania danych ułamkowych, przed sprawdzeniem ich za pomocą {stala}is_numeric{/stala} zadbajmy o to, aby dane te miały odpowiedni format – PHP oczekuje, że cześć całkowita zostanie oddzielona od części ułamkowej kropka, użytkownicy mogą zaś używać naprzemiennie kropki i przecinka (w Polsce cześć ułamkowa oddziela się przecinkiem). Zamieńmy więc wszystkie przecinki w sprawdzanym ciągu znaków na kropki:
$_POST[\'cena\'] = str_replace (\',\', \'.\', $_POST[\'cena\']);
if (!is_numeric$_POST[\'cena\']) {
echo \'Wiek musi bycz liczbą!\';
} else {
//wprowadzone dane są poprawne
}
W przypadku napisów warto sprawdzić ich długość (funkcja {stala}strlen{/stala}) oraz wyeliminować z nich tagi HTML-a, za pomocą funkcji {stala}strip_tags{/stala}:
$_POST[\'opis\'] = strip_tags($_POST [\'opis\']);
Można także zamienić znaki specjalne HTML-a (takie jak < czy >) na postać, która może być bezpiecznie wyświetlona na stronie internetowej. Służy do tego funkcja {stala}htmlentities{/stala} (pamiętajmy, ze nie radzi sobie ona z kodowaniem ISO- 8859-2, nie ma na szczęście problemu z UTF-8):
$_POST[\'opis\'] = htmlentities ($_POST[\'opis\']);
Jeśli dane pewnego rodzaju mogą przybierać wyłącznie z góry określone wartości (na przykład dane pochodzące z listy rozwijanej), nie zapomnijmy sprawdzać czy na pewno użytkownik nie przemycił do skryptu niepoprawnych wartości.
Im dokładniej sprawdzimy dane pochodzące z formularzy (czy od użytkownika), tym lepiej. Gdy zapoznamy się już z wyrażeniami regularnymi, warto z nich korzystać przy sprawdzaniu nietypowych sytuacji – jak np. kod pocztowy. Ale już teraz mamy wiedze, która pozwoli na napisanie funkcji sprawdzającej poprawność kodu pocztowego – postarajmy się napisać ją za pomocą poznanych funkcji operujących na ciągach znaków oraz poznanej dziś {stala}is_numeric{/stala}.
PHP pozwala także na przekazywanie z formularza danych w postaci tablicy:
Jak widać, nazwa wszystkich pól formularza jest taka sama, została jednak zakończona nawiasem kwadratowym. Dzięki temu w przypadku zaznaczenia kilku pól wyboru informacje o wszystkich zostaną wysłane w postaci tablicy – skrypt {stala}tablica.php{/stala}:
W przypadku zaznaczenia użytkowników 1 i 3 uzyskamy w wyniku działania skryptu napis:
{stala}Wybrałeś użytkowników: 1 3{/stala}
Tak więc dane pochodzące z formularza miały postać tablicy:
$_POST = array (
\'uzytkownik\' => array (
1,
3,
)
);
Zamiast pętli {stala}foreach{/stala}, można było zastosować zwykła pętle {stala}for{/stala}:
Mimo że jest ona w tym miejscu mniej naturalna, lepiej prezentuje tablicową postać wysłanych danych. Funkcja count zwraca liczbę elementów tablicy – w tym przypadku podtablicy umieszczonej w tablicy {stala}$_POST{/stala} pod indeksem użytkownik. Oczywiście w razie potrzeby można dostać się bezpośrednio do konkretnego elementu tablicy:
echo $_POST[\'uzytkownik\'][1]; // użytkownik 2 - pamiętaj że tablice A indeksowane są od 0!
W takim przypadku musimy być jednak pewni, ze istnieje element o indeksie 0.
Formularze a PHP
Zacznijmy od prostego skryptu wypisującego dane przesłane do niego z formularza za pomocą metody {stala}GET{/stala}:
Skrypt wykonujący to zadanie jest bardzo prosty – {stala}test_get.php:{/stala}
A jak wyglądałoby to w przypadku metody {stala}POST{/stala}?
A oto skrypt PHP – test_post.php:
Na rys. 1 i 2 przedstawiono wynik działania skryptu.
Dane pochodzące z formularzy umieszczane są w tablicy asocjacyjnej – odpowiednio {stala}$_GET{/stala}i {stala}$_POST{/stala} – w której indeksami są nazwy pól formularza (rysunek 3).
Spróbujmy teraz w przeglądarce wpisać następujący adres:
{stala}http://localhost/test_get.php?tresc=test{/stala}
Spowoduje to wyświetlenie napisu test w przeglądarce – skrypt zadział tak, jak w przypadku wysłania tekstu test z poziomu formularza. Można sprobować tego samego dla skryptu {stala}test_post.php{/stala}, jednak w tym przypadku sposób ten się nie powiedzie.