PHP/Formularze

Z Wikibooks, biblioteki wolnych podręczników.
< PHP
Poprzedni rozdział: Zmienne i tablice
Następny rozdział: Struktury kontrolne

Formularze[edytuj]

W tym rozdziale zajmiemy się podstawami komunikacji skryptu PHP z przeglądarką.

Protokół HTTP[edytuj]

Działanie protokołu HTTP.

Podstawą funkcjonowania stron WWW jest protokół HTTP, którego używa przeglądarka i serwer. Zasada jego działania jest bardzo prosta. Gdy chcemy obejrzeć dokument pod podanym adresem URL, wysyłamy do serwera tzw. żądanie HTTP zawierające lokalizację zasobu oraz garść informacji o nas samych. Serwer odnajduje lub generuje (np. przy pomocy PHP) odpowiedni dokument i odsyła wszystko jako odpowiedź HTTP. Odpowiedź zawsze zawiera pewną ilość nagłówków informacyjnych oraz opcjonalną treść, w której przesyłany jest dokument. Przeglądarka odbiera wszystko i rozpoczyna działanie. Protokół jest stosowany zarówno do pobierania kodu HTML strony, jak i znajdujących się na niej obrazków, ściągania plików i innych danych multimedialnych. Rodzaj pobieranej zawartości jest określany przez nagłówki.

Skrypty PHP zawsze pracują po stronie serwera, generując odpowiedzi HTTP na przychodzące do niego żądania. Przeważnie koncentrujemy się jedynie na budowaniu treści, ponieważ interpreter potrafi samodzielnie skonstruować podstawowy zestaw odpowiednich nagłówków, który co najwyżej uzupełniamy. Bardzo często do wygenerowania strony potrzebne są dodatkowe informacje, które najczęściej przechowywane są w bazie danych, a rzadziej - w plikach. Skrypty pobierają z nich dane, poddają je obróbce i osadzają w kodzie HTML, który jest odsyłany do klienta.

Istotną częścią protokołu HTTP są rodzaje żądań (zwane "metodami") informujące o tym, co próbujemy zrobić. Dwa podstawowe to:

  1. Żądania GET - zwyczajne pobieranie dokumentu z serwera.
  2. Żądania POST - wysłanie pewnych danych na serwer.

Istnieją jeszcze inne metody, które są coraz powszechniej stosowane w większych aplikacjach WWW, jednak na niektórych serwerach są one z nieznanych powodów poblokowane. Protokołem HTTP zajmiemy się dokładniej w dalszej części podręcznika, tymczasem na razie będą nas interesować te dwie metody. Pierwsza z nich jest wykorzystywana podczas zwykłego pobierania z serwera dokumentu, natomiast druga - przy formularzach.

Ogólnie o danych wejściowych[edytuj]

W żądaniu HTTP przenoszonych jest wiele informacji o tym, co użytkownik chce obejrzeć oraz o nim samym. Wielu danych dostarcza także sam serwer HTTP. Wszystkie one są podstawą dla aplikacji PHP do wygenerowania odpowiedzi. Mechanizm ich odbierania ewoluował stopniowo. Pierwsze wersje języka rejestrowały wszystkie nadesłane parametry, dane formularzy itd. jako zmienne, lecz było to wyjątkowo niebezpieczne. Dodając nowe parametry można było rejestrować nowe zmienne, które mogły nadpisać zmienne używane w kodzie aplikacji powodując jego błędne działanie (np. zyskanie praw administratora strony przez atakującego). Programista nie mógł także policzyć, ile danych właściwie trafiało do skryptu i gdzie są one zawarte.

Wszystko zmieniło się wraz z pojawieniem się PHP4. Obecnie wszystkie pola są rejestrowane w specjalnych, tworzonych przez skrypt tablicach asocjacyjnych posegregowane według miejsca, z którego nadeszły. PHP potrafi odbierać informacje:

  • Charakterystyczne dla metody GET (adresy URL)
  • Charakterystyczne dla metody POST (zawartość formularzy)
  • z serwera
  • z ciasteczek
  • z sesji (emulowanych przez PHP)

Tutaj zajmiemy się trzema pierwszymi pozycjami. Ciastka oraz sesje zostaną omówione w dalszych rozdziałach podręcznika.

Adresy URL[edytuj]

Do adresu URL można dołączać po znaku zapytania dodatkowe zmienne, np. www.example.com/strona.php?zmienna=wartosc&inna_zmienna=wartosc. Są one przechowywane w tablicy $_GET. Ten sposób przekazywania danych wykorzystujemy tylko, gdy skrypt nie wykonuje operacji mających efekty uboczne (np. może być wyszukiwanie, ale już nie dodawanie lub usuwanie rekordów) lub do przesyłania danych kontrolnych. W przeciwnym wypadku roboty indeksujące stronę i proxy ładujące strony z wyprzedzeniem mogą niechcący wykonywać operacje na serwerze. Ponadto cache przeglądarki i dostawców internetowych może spowodować zignorowanie zapytań.

Przyjrzymy się zawartości tablicy:

<?php
var_dump($_GET);

Wywołując skrypt normalnie: http://localhost/~programowanie_php/nazwaskryptu.php otrzymamy następujący rezultat:

array(0) { }

Oznacza to, że nie otrzymaliśmy tą drogą żadnych danych. Dodajmy teraz do adresu ciąg ?parametr=wartosc. Po odświeżeniu zobaczymy:

array(1) { ["parametr"]=> string(7) "wartosc" }

Tablica zawiera jeden element o nazwie parametr przechowujący wpisaną w adresie wartość.

Napiszemy teraz prosty skrypt wyświetlający informacje powitalne na podstawie danych z adresu:

<?php
if(sizeof($_GET) == 2)
{
   echo 'Witaj, '.$_GET['imie'].' '.$_GET['nazwisko'].'!';
}
else
{
   echo 'Nieprawidłowa liczba parametrów!';
}

Nie przejmuj się istnieniem konstrukcji, której jeszcze nie poznaliśmy. Niektórzy pewnie domyślili się, co ona robi, ale szczegóły będą podane już w następnym rozdziale. Na razie wpiszmy ją tak, jak jest. Funkcja sizeof() pojawiająca się w kodzie zwraca ilość elementów w tablicy. Sprawdzamy w ten sposób, czy użytkownik podał to, co trzeba. Kontrola nadchodzących danych jest niezwykle istotna i nigdy nie wolno jej zlekceważyć. Pominięcie tego aspektu zazwyczaj kończy się dla skryptu tragicznie, bo jeżeli coś jest do zepsucia, na pewno znajdzie się ktoś, kto tego dokona.

Wywołując skrypt z parametrami "imie" oraz "nazwisko" możemy wpływać na wyświetlane informacje: http://localhost/~programowanie_php/nazwaskryptu.php?imie=Adam&nazwisko=Kowalski. Dla lepszego efektu stwórzmy prosty formularz XHTML wysyłający dane metodą GET:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <title>Formularz XHTML</title>
 </head>
 <body>
  <form method="get" action="nazwaskryptu.php">
   <p>
    <label>Podaj imię: <input type="text" name="imie"/></label>
   </p>
   <p>
    <label>Podaj nazwisko: <input type="text" name="nazwisko"/></label>
   </p>
   <p>
    <input type="submit" value="OK"/>   
   </p>
  </form>
 </body>
</html>

Choć tworzenie formularzy teoretycznie pasuje do następnej sekcji, tak naprawdę w tym momencie zwyczajnie oszukujemy. Wypełnij ten formularz i wyślij go, a zobaczysz, że przeglądarka dokleiła do pliku podanego w znaczniku FORM parametry utworzone na podstawie pól! Tak więc nasz skrypt nawet nie ma możliwości stwierdzenia, skąd dane do niego przyszły! Poznajmy zatem metodę POST...

Formularze[edytuj]

Obsługa formularzy z prawdziwego zdarzenia, którymi można przesyłać setki informacji, odbywa się dosyć podobnie, jak w przypadku użycia w formularzu metody "get" do przesyłania adresów z parametrami. Różnica jest taka, że wszystko wysyła się wyłącznie z formularza, który posiada parametr "method" ustawiony na "post" oraz że korzysta się z tablicy $_POST wewnątrz samego skryptu. Przeróbmy nasze ostatnie dzieło tak, aby pracowało w ten sposób.

<?php
if(count($_POST) == 2)
{
   echo 'Witaj, '.$_POST['imie'].' '.$_POST['nazwisko'].'!';
}
else
{
   echo 'Nieprawidłowa liczba parametrów!';
}

W skrypcie podmieniamy jedynie nazwy tablic na $_POST. W formularzu musimy jeszcze zmienić metodę:

<html>
<head>
 <title>Formularz HTML</title>
</head>
<body>
  <form method="post" action="nazwaskryptu.php">
  Podaj imię: <input type="text" name="imie"/><br/>
  Podaj nazwisko: <input type="text" name="nazwisko"/><br/>
  <input type="submit" value="OK"/>   
  </form>
</body>
</html>

I gotowe. Wyślij teraz formularz. Zauważ, że żadna informacja nie jest doklejana do adresu, ponieważ transmisja odbywa się niejako innym kanałem.

Z kursów języka HTML wiadomo, że istnieją różne typy pól formularzy. Oto, jakie wartości otrzymuje od nich PHP:

  • <input type="text" name="nazwa"/>
    - skrypt otrzymuje $_POST['nazwa'] z wartością wpisaną w pole formularza.
  • <input type="hidden" name="nazwa" value="wartosc"/>
    - skrypt otrzymuje $_POST['nazwa'] z wartością wpisaną w danym znaczniku. Użyteczne do przesyłania formularzem ukrytych informacji, o których typowy użytkownik wiedzieć nie musi.
  • <input type="radio" name="nazwa" value="wartosc"/>
    - pozycje należące do tej samej grupy muszą mieć identyczną nazwę. $_POST['nazwa'] będzie zawierać wartość tej pozycji, która jest aktualnie zaznaczona.
  • <input type="checkbox" name="nazwa"/>
    - jeśli pole jest zaznaczone, $_POST['nazwa'] zawierać będzie słowo "on".
  • <select name="nazwa">...</select>
    - $_POST['nazwa'] zawierać będzie wartość wybranego z listy elementu.
  • <input type="submit" name="nazwa"/>
    - zmienna $_POST['nazwa'] zostanie utworzona, jeżeli akurat ten przycisk zostanie wciśnięty.

Dzięki temu można do formularzy wstawiać kilka przycisków "submit" i reagować inaczej w zależności od tego, który z nich został naciśnięty.

Serwer[edytuj]

Na sam koniec zostawiliśmy sobie kilka informacji przekazywanych interpreterowi przez serwer WWW (np. Apache). Zacznijmy od określenia adresu IP gościa:

<?php
echo 'Witaj, twój adres IP to '.$_SERVER['REMOTE_ADDR'].'!';

Ten skrypt pokaże nam adres IP komputera lub sieci, w której znajduje się internauta. W tym drugim przypadku dalsze informacje są niepewne. Serwerowi potrzebny jest wyłącznie ten adres, aby móc gdzieś wysłać rezultat, a pola $_SERVER['HTTP_X_FORWARDED_FOR'] lub $_SERVER['HTTP_CLIENT_IP'] są bardzo niepewne - generuje je właśnie serwer proxy, ale nic nie stoi na przeszkodzie, by podszył się pod nie hacker. Uznawanie ważności informacji tu zawartych było przyczyną wielu błędów bezpieczeństwa w popularnym skrypcie forów dyskusyjnych phpBB i jeżeli naprawdę zależy Ci na nim, pozostań przy REMOTE_ADDR, a resztę traktuj wyłącznie jako ciekawostkę.

Korzystając z funkcji gethostbyaddr() możemy uzyskać nazwę hosta, którego dotyczy adres IP:

<?php
echo 'Witaj, twój host to '.gethostbyaddr($_SERVER['REMOTE_ADDR']).'!';

Spróbujmy zidentyfikować przeglądarkę użytkownika:

<?php
echo 'Twoja przeglądarka została zidentyfikowana jako: '.$_SERVER['HTTP_USER_AGENT'].'!';

Pole to zawiera wyłącznie surowe informacje. Każda przeglądarka wpisuje tu co innego i dlatego wyciągnięcie ładnych i pogrupowanych w odpowiednie kategorie danych to zadanie na więcej, niż jeden artykuł. Pozostańmy zatem przy takiej postaci, a przetwarzaniem nagłówków przeglądarek zajmiemy się kiedy indziej.

Adres strony, z której przybyliśmy do naszego skryptu, znajduje się w zmiennej $_SERVER['HTTP_REFERER']. Można wykorzystać go do utworzenia linków "Cofnij" albo do detekcji, jakich słów kluczowych używają ludzie trafiający do nas z wyszukiwarek. Zauważ - szukane frazy zazwyczaj dołączane są właśnie do adresów URL i w ten sposób można je zdobyć.

Uwaga: nie można polegać na obecności i prawidłowości tej informacji. Istnieją przeglądarki i zapory ogniowe, które ją usuwają lub wstawiają tam dowolny adres podany przez użytkownika.

<?php
echo 'Przybyłeś do nas ze strony: '.$_SERVER['HTTP_REFERER'].'!';

W chwili obecnej to tyle, jeżeli chodzi o pobieranie danych. Dalszych informacji dowiemy się w trakcie następnych rozdziałów w miarę potrzeby.