Organizacja kodu PHP i interfejs użytkownika



Podobne dokumenty
Lekcja 10. Uprawnienia. Dołączanie plików przy pomocy funkcji include() Sprawdzanie, czy plik istnieje przy pmocy funkcji file_exists()

Wyrażenie include(sciezka_do_pliku) pozwala na załadowanie (wnętrza) pliku do skryptu php. Plik ten może zawierać wszystko, co może się znaleźć w

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

4. Pliki Informacje ogólne o dostępie do plików w PHP Sprawdzanie istnienia pliku file_exists()

Uwagi dotyczące notacji kodu! Moduły. Struktura modułu. Procedury. Opcje modułu (niektóre)

PHP: bloki kodu, tablice, obiekty i formularze

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Podstawy technologii WWW

Zajęcia 10 obsługa formularzy w PHP

Wysyłanie pliku na serwer. Plik na serwerze.

Umieszczanie kodu. kod skryptu

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie

Języki programowania wysokiego poziomu. PHP cz.3. Formularze

INFORMATYKA Studia Niestacjonarne Elektrotechnika

Dane - pobieranie, przekazywanie i przechowywanie. dr Beata Kuźmińska-Sołśnia

Programowanie w Sieci Internet Blok 2 - PHP. Kraków, 09 listopada 2012 mgr Piotr Rytko Wydział Matematyki i Informatyki

Pliki. Operacje na plikach w Pascalu

Wykład 5: PHP: praca z bazą danych MySQL

Argumenty wywołania programu, operacje na plikach

Obiektowy PHP. Czym jest obiekt? Definicja klasy. Składowe klasy pola i metody

Pracownia internetowa w każdej szkole (edycja Jesień 2007)

Zmienne powłoki. Wywołanie wartości następuje poprzez umieszczenie przed nazwą zmiennej znaku dolara ($ZMIENNA), np. ZMIENNA=wartosc.

Autor: Joanna Karwowska

1 Podstawy c++ w pigułce.

Rys.2.1. Drzewo modelu DOM [1]

Należy ściągnąć oprogramowanie Apache na platformę

Programowanie w języku Python. Grażyna Koba

wersja 1.0 ośrodek komputerowy uj cm ul. mikołaja kopernika 7e, Kraków tel

Kontrola sesji w PHP HTTP jest protokołem bezstanowym (ang. stateless) nie utrzymuje stanu między dwoma transakcjami. Kontrola sesji służy do

Pliki. Informacje ogólne. Obsługa plików w języku C

Rys.2.1. Trzy warstwy stanowiące podstawę popularnego podejścia w zakresie budowy stron internetowych [2]

Być może jesteś doświadczonym programistą, biegle programujesz w Javie,

Ćwiczenie: JavaScript Cookies (3x45 minut)

Wykład 8: klasy cz. 4

Wykład 5: Klasy cz. 3

Komunikacja między klientem, a skryptem PHP, oraz operacje na plikach

Instrukcja generowania certyfikatu PFRON i podpisywania dokumentów aplikacji SODiR w technologii JS/PKCS 12

Aplikacje WWW - laboratorium

Zakres tematyczny dotyczący kursu PHP i MySQL - Podstawy pracy z dynamicznymi stronami internetowymi

Sesje, ciasteczka, wyjątki. Ciasteczka w PHP. Zastosowanie cookies. Sprawdzanie obecności ciasteczka

Aplikacje internetowe - laboratorium

Widoczność zmiennych Czy wartości każdej zmiennej można zmieniać w dowolnym miejscu kodu? Czy można zadeklarować dwie zmienne o takich samych nazwach?

Ćwiczenie 1. Wprowadzenie do programu Octave

Instrukcja konfiguracji funkcji skanowania

Języki skryptowe - PHP. PHP i bazy danych. Paweł Kasprowski. pawel@kasprowski.pl. vl07

Przewodnik użytkownika (instrukcja) AutoMagicTest

Programowanie proceduralne INP001210WL rok akademicki 2018/19 semestr letni. Wykład 6. Karol Tarnowski A-1 p.

4. Funkcje. Przykłady

Komentarze w PHP (niewykonywane fragmenty tekstowe, będące informacją dla programisty)

Aplikacje WWW - laboratorium

Systemy internetowe. Wykład 3 PHP. West Pomeranian University of Technology, Szczecin; Faculty of Computer Science

Specyfikacja instalacji usługi SMS Premium w Przelewy24.pl

Podstawy JavaScript ćwiczenia

Szablon główny (plik guestbook.php) będzie miał postać:

Podstawy Pythona. Krzysztof Gdawiec. Instytut Informatyki Uniwersytet Śląski

Pobieranie komunikatów GIF

Tablice (jedno i wielowymiarowe), łańcuchy znaków

Rozdział 4 KLASY, OBIEKTY, METODY

VinCent Administrator

Zasady programowania Dokumentacja

Celem tego projektu jest stworzenie

Skrypty powłoki Skrypty Najcz ciej u ywane polecenia w skryptach:

Formy dialogowe w środowisku Gnome

Włączanie/wyłączanie paska menu

Podstawy programowania. Wykład: 9. Łańcuchy znaków. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

LABORATORIUM 2 WSTĘP DO SIECI TELEINFORMATYCZNYCH TABELE I FORMULARZE

SERWER AKTUALIZACJI UpServ

Skrypty i funkcje Zapisywane są w m-plikach Wywoływane są przez nazwę m-pliku, w którym są zapisane (bez rozszerzenia) M-pliki mogą zawierać

W przeciwnym wypadku wykonaj instrukcję z bloku drugiego. Ćwiczenie 1 utworzyć program dzielący przez siebie dwie liczby

Bazy Danych i Usługi Sieciowe

S P I S T R E Ś C I. Instrukcja obsługi

Laboratorium Wstawianie skryptu na stroną: 2. Komentarze: 3. Deklaracja zmiennych

Napisy w PHP. Drukowanie napisów instrukcją echo

Programowanie w językach wysokiego poziomu

Stałe, znaki, łańcuchy znaków, wejście i wyjście sformatowane

Niezwykłe tablice Poznane typy danych pozwalają przechowywać pojedyncze liczby. Dzięki tablicom zgromadzimy wiele wartości w jednym miejscu.

UNIFON podręcznik użytkownika

Laboratorium 1 Wprowadzenie do PHP

Programowanie CGI. Jolanta Bachan Informatyka

Rozdział ten zawiera informacje o sposobie konfiguracji i działania Modułu OPC.

Dodawanie operacji dodatkowych w WAPRO Mag.

Trochę o plikach wsadowych (Windows)

SSK - Techniki Internetowe

Dlaczego PHP? - zalety

INSTRUKCJA obsługi certyfikatów

2. Łańcuchy tekstowe w PHP

Opis: Instrukcja warunkowa Składnia: IF [NOT] warunek [AND [NOT] warunek] [OR [NOT] warunek].

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Przykłady zastosowań funkcji tekstowych w arkuszu kalkulacyjnym

1 Przygotował: mgr inż. Maciej Lasota

Dokument opisuje sposób postępowania prowadzący do wysłania deklaracji VAT, PIT lub CIT drogą elektroniczną za pomocą funkcji systemu ADA modułu FK.

Wprowadzenie do projektu QualitySpy

2 INSTALACJA OPROGRAMOWANIA. 3 3 GŁÓWNE OKNO PROGRAMU 3 4 MODUŁ OBSŁUGI ARCHIWUM 7

Laboratorium 3: Tablice, tablice znaków i funkcje operujące na ciągach znaków. dr inż. Arkadiusz Chrobot dr inż. Grzegorz Łukawski

Przekazywanie danych. Dane zewnętrzne mogą pochodzić z róŝnych źródeł:

Systemy operacyjne. System operacyjny Linux - wstęp. Anna Wojak

IIIIIIIIIIIIIIIMMIMMIII

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 12. Karol Tarnowski A-1 p.

Transkrypt:

Organizacja kodu PHP i interfejs użytkownika 1. Pobieranie danych od użytkowników 2. Funkcje 3. Include i require 4. Argumenty funkcji 5. Zasięg zmiennych 6. Operacje na plikach 7. Praktyczny przykład elektroniczne głosowanie 1

1. Pobieranie danych od użytkowników Programy PHP są ściśle związane z kodem HTML, nic więc dziwnego, że do pobierania danych od użytkowników stosujemy formularze HTML. Aby użyć skryptu PHP do obsługi formularza, należy najpierw odpowiednio ten formularz przygotować. W znaczniku FORM w parametrze ACTION należy podać adres dokumentu PHP, mającego obsłużyć ten formularz. Parametr METHOD może mieć wartość POST lub GET obie metody są obsługiwane przez PHP. Jednak należy pamiętać, że formularze wysyłane przez GET mają dość ograniczoną długość. Do ich zalet należy natomiast to, że użytkownik może zrobić sobie zakładkę do wyników formularza, co nie jest możliwe w przypadku formularzy POST. Przypomnijmy sobie podstawowe informacje na temat metod GET i POST. Obie należą do protokołu HTTP. Jest to protokół komunikacji typu klient serwer, obsługujący wymianę informacji w sieci WWW. Przeglądarki internetowe, takie jak Netscape Navigator czy Internet Explorer, są najbardziej typowymi przykładami klientów HTTP. Z kolei do najpopularniejszych serwerów HTTP można zaliczyć używany w tym kursie serwer Apache i serwer IIS Microsoftu. Transakcja protokołu HTTP składa się z żądania inicjowanego przez klienta (przeglądarkę WWW), po którym następuje odpowiedź serwera i zakończenie połączenia. Żądania i odpowiedzi są bezstanowe ani nie zawierają informacji o wcześniejszych połączeniach, ani nie pozostawiają żadnych wskazówek dla następnych połączeń. Protokół HTTP obsługuje pewną liczbę metod, które przesyłane są jako pierwszy wyraz w żądaniu. Najprostszą i najczęściej używaną jest metoda GET. Kod przedstawiony poniżej zawiera żądanie, w którym klient domaga się od serwera przesłania dokumentu strona.html, korzystając z wersji 1.0 protokołu HTTP: GET strona.html HTTP/1.0 Żądanie protokołu HTTP może zawierać jeden lub więcej nagłówków, czyli argumentów podanych w formacie "nazwa:wartość", które opisują żądanie wysłane przez przeglądarkę. Kolejne polecenie zawiera nagłówek User-Agent, który podaje zazwyczaj nazwę i wersję przeglądarki: GET strona.html HTTP/1.0 User-Agent: Mozilla 10.0 2

Żądanie GET działa w sposób bardzo charakterystyczny. Przesyła do serwera argumenty w ten sposób, że dodaje do adresu URL znak zapytania (?), po którym następuje jedna lub więcej definiujących wybrane parametry par "nazwa=wartość", oddzielonych od siebie znakami &. I tak na przykład polecenie: GET strona.html?imie=rafal&stankonta=2000 HTTP/1.0 żąda od serwera przesłania pliku strona.html, przekazuje jednocześnie do serwera dwa parametry: imie o wartości rafal oraz "stankonta" o wartości 2000. Zwróć uwagę, że zarówno wartości tekstowe, jak i liczby przekazywane są w wywołaniu jednakowo (tekst nie jest otoczony cudzysłowami, jak to ma miejsce w większości języków programowania). Z pracą polecenia GET protokołu spotykasz się podczas codziennego przeszukiwania zasobów internetowych. Wystarczy uruchomić popularną przeszukiwarkę Google, wpisać w pole poszukiwania dowolną frazę (np. test), aby po naciśnięciu klawisza Szukaj na ekranie pojawił się obraz, którego fragment przedstawia poniższy rysunek. Zwróć uwagę na linię adresową przeglądarki. Zawiera ona właśnie żądanie typu GET, wywołujące z serwera dokument search z parametrami q=test&ie=utf... itd. Drugim popularnym żądaniem protokołu HTTP jest polecenie POST. W przeciwieństwie do omówionego już GET, żądanie to nie przesyła danych w sposób jawny, w linii żądania (przekazywanych argumentów nie widać w linii adresowej przeglądarki). Pary 3

"nazwa=wartość" są tutaj podawane dopiero po pierwszym wierszu żądania i oddzielone od niego pustym wierszem: POST strona.html HTTP/1.0 imie=rafal&stankonta=2000 Ciąg przekazywany jako argumenty w przypadku obu metod nie może zawierać spacji i niektórych znaków specjalnych (np.? czy & nie mogą wystąpić w argumentach, gdyż pełnią specjalne funkcje). Znaki, takie jak znak spacji (Space) czy znak zapytania (?) nie mogą być więc w normalnej formie przesyłane w adresie URL. Zastępowane są one symbolem %, po którym następuje szesnastkowy kod odpowiedniego znaku (proces ten nosi nazwę kodowania URL). Tak więc znak spacji (kod ASCII 0x20) w adresie URL podawany będzie jako %20, a znak zapytania (kod ASCII Ox3F) jako %3F. Znasz już jeden element internetowy, korzystający z metod POST i GET. Są to formularze HTML. Formularz HTML, tworzony za pomocą znacznika <form>, pozwala użytkownikom na wysyłanie danych w formacie "nazwa=wartość" pod wybrany adres URL. Użytkownik wprowadza wartości, korzystając z graficznych elementów interfejsu, wyświetlanych na stronie przez jego przeglądarkę. Znasz dobrze te elementy to pola tekstowe, przyciski wyboru i klawisze. Każdy formularz musi zawierać przynajmniej jeden przycisk Submit (Zatwierdź). Gdy użytkownik naciśnie ten przycisk, przeglądarka wyśle zawartość formularza pod adres URL zdefiniowany w atrybucie "action" znacznika <form>, używając odpowiedniej metody żądania (GET lub POST), podanej w atrybucie "method". Na przykład przedstawiony tutaj formularz wywoła stronę test.php, używając do tego metody POST: <html> <head> <title>formularz testowy</title> </head> <body> <form action="test.php" method="post"> <input type="text" name="tekst"> <input type="submit" value="uruchom"> </form> </body> </html> 4

Jeżeli w tworzonym formularzu nie umieścisz atrybutu "method", określającego metodę przesyłania danych, Twoja przeglądarka w sposób domyślny wybierze metodę GET. Zauważ, że formularz zawiera też pole tekstowe o nazwie tekst. Zobaczmy, jak powinien wyglądać skrypt test.php, aby wyświetlał zawartość pola tekst. <html> <head> <title>test PHP</title> </head> <body> <?php echo $tekst;?> </body> </html> Zwróć uwagę, że skrypt zawiera tylko jedno polecenie echo $tekst, a wszystko działa bez zarzutu. Skrypt bezbłędnie wyświetla wartość, którą wpiszesz do pola tekstowego formularza. Większość pracy wykonuje za nas PHP po prostu w skrypcie od razu będą dostępne zmienne o nazwach takich, jak nazwy pól formularza, zawierające ich wartości. W przypadku pola tekstowego będzie to po prostu wpisany przez użytkownika tekst. Jeżeli pole jest typu CHECKBOX wartością będzie "on" jeśli pole jest zaznaczone lub zmienna będzie pusta jeśli pole nie zostało zaznaczone. Jeżeli w polu typu CHECKBOX podamy parametr VALUE, będzie on użyty zamiast "on". Tak samo wygląda obsługa pola typu RADIO. Wartością pola SELECT będzie wartość parametru VALUE zdefiniowanego w znaczniku OPTION. Takie działanie PHP jest bardzo wygodne, ale w niektórych sytuacjach spodziewane przez Ciebie zmienne nie są tworzone. Często zdarza się tak, gdy korzystasz z usług zewnętrznych dostawców Internetu. Aby zmienne te powstały, w pliku php.ini musi być ustawiony parametr konfiguracji o nazwie register_global. Jeżeli zainstalowałeś własny serwer, zgodnie z wytycznymi z rozdziału Instalacja środowiska, jest to ustawienie, które pozwala na dostęp do wszystkich pól formularza przez zmienne PHP. Jednak z powodu zwiększenia poziomu bezpieczeństwa niektórzy dostawcy Internetu decydują się na wyłączenie tej opcji poprzez przestawienie opcji konfiguracji register_global na off. W wyniku takiego działania zmienna skojarzona z przedstawionym powyżej polem formularza będzie pusta. 5

Gdy wyłączysz rejestry globalne, co jest zalecane i dużo bezpieczniejsze, nasz skrypt powinien wyglądać następująco: <html> <head> <title>test PHP</title> </head> <body> <?php $tekst = $_POST["tekst"]; echo $tekst;?> </body> </html> Dołączona została jedna linia, której zadaniem jest przypisanie do zmiennej $tekst zawartości tablicy asocjacyjnej _POST, zawierającej wszystkie wartości przekazywane metodą POST. Analogiczna tablica dla metody GET nazywa się _GET. Tablice te istnieją zawsze, niezależnie od ustawień rejestrów globalnych i dlatego zaleca się tworzenie oprogramowania przy ich użyciu. Kiedy już wiesz, w jaki sposób przekazywać parametry do skryptu, uruchom poniższy program. To prosta zgadywanka, która ilustruje sposób wykorzystania formularzy. <html> <head> <title>zgadywanka</title> </head> <body> <?php $a=$_get["a"]; print 'Ile to jest 2*2, hmm? '; if ($a!= 4) { echo "<form action=\"zgaduj.php\" method=\"get\">"; echo "<input type=\"text\" name=\"a\">"; echo "<input type=\"submit\" value=\"sprawdz\"> </form>"; if($a) {print "$a --- Niestety to zly wynik!\n"; else { print "Jakos Ci sie udalo.\n"; 6

?> </body> </html> Zwróć uwagę, że program dzięki formularzowi wywołuje sam siebie, przekazując za każdym razem wartość wpisaną do pola tekstowego o nazwie a. To do tego pola właśnie powinno się wpisać odpowiedź na zagadkę. Takie wielokrotne wywołanie skryptu przez siebie samego doskonale zastępuje pętlę, w której liczba iteracji jest ściśle kontrolowana przez użytkownika. Można więc powiedzieć, że jest to pętla dynamiczna. 7

2. Funkcje Podczas pisania programu zastanawiasz się zwykle, jakie funkcje musi wykonywać i w jaki sposób możesz podzielić je na mniejsze fragmenty. Pomyślmy o tych fragmentach jak o modułach. W nowoczesnych językach programowania programiści piszą moduły kodu i dołączają je do dużej aplikacji. Łatwiej jest przetestować fragment kodu realizujący tylko jedno zadanie. Mamy wtedy do czynienia z dużo mniejszą liczbą wartości wejściowych i wyjściowych. Jeżeli jesteśmy pewni, że moduł działa bezbłędnie, a program zwraca nieprawidłowe wyniki, możemy łatwiej wyizolować prawdziwe źródło problemu. Jeżeli moduł realizuje jakieś zadanie, może być wywoływany za każdym razem, gdy potrzebujesz wykonać to zadanie. Taki moduł można traktować jak czarną skrzynkę, do której wkładamy dane, a wyjmujemy wyniki i dopóki dane wejściowe są prawidłowe, nie musimy przejmować się tym, co jest we wnętrzu. W PHP (i innych językach) takie moduły kodu nazwano funkcjami. Funkcje są fragmentami kodu zdefiniowanymi przez użytkownika w celu realizacji określonego zadania. Pobierają one wartości wejściowe w postaci argumentów, wykonują jakieś operacje i mogą zwracać wartość. Funkcje kopiują wartości argumentów do nowych zmiennych, nazywanych parametrami, które stosowane są we wnętrzu funkcji. Aby zdefiniować funkcję, musisz nadać jej nazwę. Realizujemy to za pomocą słowa kluczowego function; po którym następuje nazwa funkcji. Nazwy parametrów podane są w nawiasach po nazwie funkcji. Kod tworzący ciało funkcji umieszczony jest w nawiasach klamrowych po parametrach. function test ($arg_1, $arg_2,..., $arg_n) { echo "Przykładowa funkcja.\n"; return $wartosc; Funkcja może mieć dowolną liczbę linii kodu, ale jeżeli chcesz, aby zwracała wartość, musisz umieścić końcowe wyrażenie lub obliczenie po słowie kluczowym return. Instrukcja ta wskazuje, że skończyliśmy pracę i funkcja kończy się w tym miejscu. Może to również oznaczać, że chcemy zwrócić wartość obliczoną w funkcji. Nie musisz jednak zwracać żadnej wartości. Słowo return może zostać użyte po prostu do oznaczenia końca funkcji. 8

Ważne: nie możesz zwracać wielu wartości z funkcji, ale podobny efekt możesz uzyskać przez zwrócenie tablicy. Wewnątrz funkcji może się pojawić dowolny poprawny kod PHP, także definicje innych funkcji. W PHP 3 funkcje muszą być zdefiniowane przed odwołaniem do nich. W PHP 4 nie ma takiego wymagania. PHP nie obsługuje przeciążania funkcji (przypomnij sobie z kursu o języku Java, na czym polega przeciążanie). Nie jest także możliwe oddefiniowanie lub przedefiniowanie wcześniej zadeklarowanych funkcji. 9

3. Include i require Programiści często przygotowują biblioteki najbardziej przydatnych funkcji, umieszczając je w osobnych plikach. W celu wykorzystania tak przygotowanych plików PHP udostępnia instrukcje include() i require(). Obydwie instrukcje są identyczne w każdym szczególe, z wyjątkiem obsługi błędów. include() generuje błąd typu Warning, podczas gdy require() generuje błąd Fatal Error. Innymi słowy, funkcji require() używa się, by zatrzymać przetwarzanie skryptu, gdy brakuje jakiegoś pliku. Jeżeli zostanie użyta funkcja include(), to w powyższej sytuacji skrypt będzie przetwarzany dalej. Aby pokazać zastosowanie tych instrukcji, wpisz następujący przykład do pliku owoce.php: <?php $kolor = 'zielone'; $owoc = 'jabłko';?> po czym utwórz plik dolacz.php i wpisz do niego następujący kod: <?php echo "Jedno $kolor $owoc"; // Jedno include 'owoce.php'; echo "Jedno $kolor $owoc"; // Jedno zielone jabłko?> Uruchom teraz przeglądarkę internetową i wywołaj plik dolacz.php. Jeżeli oba pliki znajdują się w tym samym katalogu, na ekranie zobaczysz napis "Jedno zielone jabłko". Jeżeli plik owoce.php umieściłeś w innym katalogu (np. katalogu bibliotecznym), na początku pliku dolacz.php musisz zdefiniować ścieżkę dołączania. Zrobisz to, dopisując na początku linię: include_path=".;c:\twoja_sciezka" Spróbuj wymienić include na require wszystko będzie działać identycznie. 10

4. Argumenty funkcji Jak już wspomniano w rozdziale poświęconym funkcjom, podczas deklaracji funkcji, można w nawiasach zadeklarować jej argumenty, oddzielając je przecinkami. Argumenty muszą być poprzedzone symbolem dolara. Stają się one wewnątrz funkcji zmiennymi. Kiedy funkcja jest wywoływana, spodziewa się wartości, które będą odpowiadały argumentom i występowały w tej samej kolejności, w jakiej zostały zadeklarowane. Istnieje kilka możliwości operowania na argumentach funkcji. Przeanalizujmy następujący kod: <html> <head> <title> Parametry funkcji </title> </head> <body> <?php function podatek ($pensja) { $pensja = $pensja - (($pensja/100)*30); return $pensja; $pensja = 2500; echo (podatek($pensja)); /* przekazanie przez wartość */ echo "<br>"; echo '$pensja ='. $pensja; echo "<br>"; echo '$pensja ='. $pensja; echo "<hr>"; echo (podatek(&$pensja)); /* przekazanie przez zmienną (referencję) */ echo "<br>"; echo '$pensja ='. $pensja; echo "<br>"; echo '$pensja ='. $pensja; echo "<hr>"; 11

function podatek1 ($pensja=2500) /* domyślna wartość parametru*/ { $pensja = $pensja - (($pensja/100)*20); return $pensja; echo "Wywolanie podatek():". podatek(); echo "<br>"; echo "Wywolanie podatek1():". podatek1(); echo "<hr>"; function podatek2 ($pensja=2500, $podatek) /* kolejność parametrów*/ { $pensja = $pensja - (($pensja/100)*$podatek); return $pensja; function podatek3 ($pensja, $podatek=20) /* kolejność parametrów*/ { $pensja = $pensja - (($pensja/100)*$podatek); return $pensja; echo "Wywolanie podatek2(3000, 20):". podatek2(3000, 20); echo "<br>"; echo "Wywolanie podatek2(3000):". podatek2(3000); echo "<br>"; /*echo "Wywolanie podatek2(,3000):". podatek2(,3000);*/ echo "<br>"; echo "Wywolanie podatek3(3000):". podatek3(3000); echo "<hr>";?> </body> </html> 12

Argumenty domyślnie kopiują przesłaną im wartość do zmiennej lokalnej. Tak działa pierwsze wywołanie funkcji podatek(). Nazywa się to przekazaniem przez wartość. Jeżeli jednak zmienną poprzedza operator &, staje się ona wskazaniem zmiennej przesłanej do funkcji. Zwykle nazywa się to odwołaniem przez zmienną (referencję). Zwróć uwagę na drugie wywołanie funkcji podatek to właśnie ten mechanizm. Zmiana wartości wskazywanej zmiennej zmienia wartość zmiennej, która się do niej odwołuje. Możliwe jest również deklarowanie argumentów opcjonalnych. Wiele z funkcji, w które standardowo wyposażono PHP wykorzystuje tę możliwość. Należy do nich np. funkcja date(). Można jej przesłać jeden lub dwa argumenty. Pierwszy z nich to format zwracanej daty, a drugi to datownik wyrażony w sekundach, które upłynęły od 1 stycznia 1970 roku. W przypadku, gdy drugi argument jest pominięty, użyta zostaje bieżąca data. Argumenty opcjonalne deklaruje się we własnych funkcjach poprzez przyporządkowanie im wartości domyślnej operatorem =. Po prawej stronie znaku = znajduje się konkretna wartość, jaka zostanie przyporządkowana zmiennej. W omawianym przykładzie, mechanizm ten reprezentują funkcje podatek1(), podatek2() i podatek3(). Ponieważ argumenty muszą odpowiadać sobie w kolejności, trzeba przyporządkować wartość domyślną każdemu argumentowi, który wystąpi po pierwszym argumencie z wartością domyślną. Dlatego też funkcja podatek2() jest niepoprawnie zdefiniowana i wywołana z niekompletną liczbą parametrów zwróci błąd. 13

5. Zasięg zmiennych Zasięg zmiennej to zakres od miejsca jej utworzenia do miejsca jej zniszczenia. Zwykle jest to cała strona WWW. Jeżeli jednak użyjemy zmiennej we wnętrzu funkcji, niekoniecznie musi być to prawda. Zmienna może na przykład istnieć jedynie we wnętrzu funkcji. Jeżeli funkcja zostaje wywołana, tworzone są zmienne w jej wnętrzu, natomiast gdy funkcja się kończy, zmienne są niszczone. Odwołania spoza funkcji do tych zmiennych są nieprawidłowe, ponieważ w momencie odwołania (poza funkcją) nie mają one żadnej wartości. Podobnie jak w poprzednim rozdziale do dokładnego zaprezentowania idei zasięgu zmiennych w PHP posłużymy się przykładem. Oto on: <html> <head> <title> Zasieg </title> </head> <body> <?php $tekst = "Witaj Swiecie"; /* zmienna globalna */ function tlumacz($tekst) { $Tekst = "Hello World"; /* zmienna lokalna */ echo "zmienna tekst wew. funkcji :". $tekst. "<br>"; return $Tekst; tlumacz($tekst); echo $tekst; echo $Tekst; echo "<hr>"; function tlumacz2($tekst) { global $tekst; $Tekst = "Hello World"; /* zmienna lokalna */ echo "zmienna tekst wew. funkcji :". $tekst. "<br>"; return $Tekst; 14

tlumacz2(); echo $tekst; echo $Tekst; echo "<hr>"; function tlumacz3($tekst) { $Tekst = "Hello World"; /* zmienna lokalna */ echo "zmienna tekst wew. funkcji :". $GLOBALS["tekst"]. "<br>"; return $Tekst; tlumacz3(); echo $tekst; echo $Tekst; echo "<hr>"; function licznik() { static $liczba_odwiedzin = 0; return $liczba_odwiedzin += 1 ; echo licznik(). "<br>"; echo licznik(). "<br>"; echo licznik(). "<br>"; echo licznik(). "<br>"; echo licznik(). "<br>"; echo "<hr>";?> </body> </html> Wszystkie zmienne utworzone poza funkcjami są widoczne na całej stronie i dlatego zwiemy je globalnymi. Taki zasięg rozciąga się na pliki dołączane funkcjami include() i require(). Przykładem zmiennej globalnej jest $tekst. Jednakże w funkcjach zdefiniowanych przez użytkownika zmienne mają zasięg lokalny, dlatego też zostały nazwane lokalnymi. Przykładem zmiennej lokalnej w naszym przykładzie jest $Tekst. 15

Aby zmienne globalne były widoczne we wnętrzu funkcji, w PHP muszą być one jawnie określone jako globalne wewnątrz funkcji, w której mają być użyte, do czego używamy słowa kluczowego global. Przykładem takiej deklaracji jest funkcja tlumacz2(). Drugim sposobem uzyskania dostępu do zmiennych globalnych wewnątrz funkcji jest użycie specjalnej, zdefiniowanej przez PHP tablicy $GLOBALS. W naszym przykładzie ten sposób prezentuje funkcja tlumacz3(). $GLOBALS jest tablicą asocjacyjną, w której nazwa zmiennej jest kluczem, a zawartość zmiennej wartością komórki tablicy. Co się dzieje, jeżeli wielokrotnie wywołujemy tę samą funkcję? Zmienne lokalne są tworzone na początku funkcji i niszczone podczas jej zakończenia. Istnieją przypadki, w których chciałbyś, aby wartość zmiennej utrzymywała się pomiędzy kolejnymi wywołaniami funkcji (np. licznik wywołań strony). Zmienna taka nie istnieje poza funkcją, ale jeżeli kolejny raz wykonamy funkcję, wartość zmiennej jest taka sama, jak w poprzednim wywołaniu. Popatrz na funkcję licznik() z naszego przykładu. Użyto w niej tzw. zmiennej statycznej. Zmienna taka może mieć wyłącznie zasięg lokalny, ale nie traci swojej wartości, kiedy program opuści ten zasięg lokalny, w którym dana zmienna statyczna się znajduje. Powtórne wywołanie funkcji licznik() nadaje zmiennej $liczba_odwiedzin wartość, z którą zakończyło się poprzednie wywołanie. Gdyby nie słowo kluczowe static, ta funkcja byłaby bezużyteczna, gdyż przy każdym jej wywołaniu zmienna $liczba_odwiedzin otrzymywałaby wartość 0, w związku z czym funkcja stale wyświetlałaby "1". Dzięki mechanizmowi statyczności za każdym wywołaniem funkcji licznik(), zostanie wyświetlona wartość zmiennej $liczba_odwiedzin, zwiększona o jeden. Zmienne statyczne pozwalają też na wykorzystanie funkcji rekurencyjnych, czyli takich, które wywołują same siebie. Funkcje rekurencyjne należy pisać bardzo rozważnie, gdyż łatwo jest wywołać nieskończoną rekurencję. Musisz być pewny, że masz odpowiednie mechanizmy do zatrzymania rekurencji w odpowiednim momencie. Poniższa funkcja rekurencyjnie liczy do 10, używając zmiennej statycznej $licznik, aby wiedzieć, kiedy ma się zatrzymać: 16

function rekurencja() { static $licznik = 0; $licznik++; echo $licznik; if ($licznik < 10) { rekurencja(); $licznik--; 17

6. Operacje na plikach Uchwyt do pliku Pisząc różne programy, bardzo często musimy przechować do następnego uruchomienia dużą ilość danych. Można oczywiście skorzystać z bazy danych, co będzie opisane w dalszej części skryptu. Najprostszą metodą jest jednak wykorzystywanie w tym celu zwykłych plików dyskowych. Plik nie jest niczym więcej jak uporządkowaną sekwencją bajtów przechowywanych na dysku, dyskietce, dysku CD-ROM lub na innym medium służącym do przechowywania danych. Za pomocą dostępnych standardowo funkcji PHP, programista ma możliwość: otwierania i zamykania plików, czytania i zapisywania plików, usuwania i zmiany nazwy plików, przemieszczania się po pliku, otwierania i zamykania katalogu, odczytywania wpisów w katalogu, usuwania i zmiany nazwy katalogu. Autor programu zwykle doskonale wie, z jakiego pliku chciałby korzystać, musi jednak powiedzieć o tym interpreterowi PHP. Stosowne polecenie to fopen(), przyjmujące trzy parametry (w tym jeden opcjonalny). Pierwszy z nich to nazwa pliku do otwarcia, która może być podana w postaci nazwy pliku względnej (na przykład: "./dane.txt") lub bezwzględnej (na przykład: "c:/pliki/dane.txt"). Możesz również podać ścieżkę do pliku na innym komputerze, otwierając go poprzez HTTP lub FTP ("http://www.domena.com/index.html"). Drugi parametr reprezentuje tryb dostępu do pliku. Może być on ustawiony na jedną z poniższych wartości: 'r' otwórz tylko do odczytu; ustawia wskaźnik pliku na początku pliku; 'r+' otwórz do odczytu i zapisu; ustawia wskaźnik pliku na początku pliku; 'w' otwórz tylko do zapisu; ustawia wskaźnik pliku na początku pliku i obcina plik (zeruje) do 0 długości. Jeśli plik nie istnieje, próbuje go utworzyć; 'w+' otwórz do odczytu i zapisu; ustawia wskaźnik pliku na początku pliku i obcina plik (zeruje) do 0 długości. Jeśli plik nie istnieje, próbuje go utworzyć; 'a' otwórz tylko do zapisu; ustawia wskaźnik pliku na końcu pliku. Jeśli plik nie istnieje, próbuje go utworzyć; 18

'a+' otwórz do odczytu i zapisu; ustawia wskaźnik pliku na końcu pliku. Jeśli plik nie istnieje, próbuje go utworzyć. Możesz też użyć opcjonalnego trzeciego parametru i ustawić go na "1", jeśli chcesz, aby twój plik był poszukiwany także w include_path. Efektem działania funkcji fopen() jest zwrócenie tzw. uchwytu do pliku. Jest to rodzaj wskaźnika, ułatwiającego programowi korzystanie z danych zapisanych na dysku. W momencie wywołania polecenia fopen(), interpreter PHP odszukuje plik w zadanej lokalizacji i tworzy w pamięci programu specjalną strukturę danych, reprezentującą dane zawarte w pliku. Po utworzeniu uchwytu, każde korzystanie z pliku odwołuje się właśnie do tej struktury i nie wymaga ponownego przeszukiwania dysku. Oprócz odwoływania się do pliku, uchwyt może posłużyć do sprawdzania, czy udało się otwarcie pliku. Jeżeli otwarcie było udane, jest dodatnią liczbą całkowitą. Jeżeli nie udało się ma wartość zero. Działania na plikach i katalogach są zawsze narażone na wystąpienie błędu, więc musisz mieć to na uwadze. Dobrze jest mieć procedurę obsługi błędów, która jest wywołana po wystąpieniu błędu (na przykład: nie mamy wystarczających uprawnień do pliku lub plik po prostu nie istnieje) i elegancko obsłuży błąd, wypisując odpowiedni komunikat. Rozwiązanie taki uzyskamy w opisany poniżej sposób. Ponieważ PHP może traktować liczby całkowite jako wartości logiczne, załóżmy na potrzeby wyrażenia if() że wskaźnik pliku, który jest przecież liczbą, posiada wartość TRUE, gdy operacja się powiodła i FALSE, jeżeli się nie udała. Pozwoli to na sprawdzenie poprawności otwarcia w następujący sposób: $fp=fopen("dane.txt", "r"); if (!$fp) die(" Nie mogę otworzyć wskazanego pliku"); Funkcja die() powoduje natychmiastowe przerwanie działania programu, wyświetlając na ekranie komunikat podany jako parametr jej wywołania. Po zakończeniu pracy ze skryptem trzeba go zamknąć. Do tego celu służy funkcja fclose(). Jako parametr przyjmuje ona uchwyt do otwartego pliku: fclose($fp); Mimo że PHP powinien automatycznie zamknąć pliki po zakończeniu pracy skryptu, dobrą praktyką jest ich własnoręczne zamykanie natychmiast po wykorzystaniu, ponieważ 19

dzięki temu można szybciej udostępnić je dla innych procesów i skryptów lub nawet dla tego samego skryptu. Przyjrzyjmy się teraz funkcjom, które umożliwiają odczyt i zapis danych do otwartego pliku o uchwycie $fp. fread() Jest to funkcja służąca do odczytywania ciągu znaków z pliku. Posiada dwa argumenty: uchwyt do pliku i długość odczytywanego ciągu w bajtach. Inaczej mówiąc fread() odczytuje długość bajtów ze wskaźnika pliku $fp. Czytanie kończy się, gdy odczytano już długość bajtów lub osiągnięto koniec pliku, cokolwiek nastąpi pierwsze. Oto przykład pozwalający na odczyt całej zawartości pliku do łańcucha znakowego. $filename = fopen("dane.txt", "r"); $fd = fopen ($filename, "r"); $contents = fread ($fd, filesize($filename)); fclose ($fd); Zastosowano w nim nową funkcję filesize() pozwalającą na odczyt długości pliku. Oprócz funkcji fread() do odczytywania plików (ale tym razem znakowo) służą także: fgetc() odczytuje jeden znak i posiada tylko jeden argument uchwyt do pliku, fgets() odczytuje określoną liczbę znaków z pliku. Posiada dwa argumenty: uchwyt do pliku i liczbę znaków przeznaczonych do odczytu. fwrite() Do zapisu danych do pliku używamy funkcji fwrite(). Wymaga ona dwóch argumentów, uchwytu pliku $fp i ciągu znaków do zapisu. Istnieje też trzeci, opcjonalny argument. fwrite ( uchwyt, łańcuch [, długość]) fwrite() zapisuje treść łańcuch do pliku wskazanego przez uchwyt. Jeśli argument długość został podany, zapis zatrzymywany jest po zapisaniu liczby bajtów określonej tym argumentem lub jeśli łańcuch skończy się którekolwiek ze zdarzeń nastąpi szybciej. W efekcie swojego działania, funkcja zwróci liczbę zapisanych bajtów (lub zwróci 1 w przypadku wystąpienia błędu). Oto przykład użycia tej funkcji: 20

<?php $nazwapliku = 'test.txt'; $trochetresci = "Dodaj to do pliku\n"; Następna linia sprawdza, czy plik istnieje i jest zapisywalny. Zapamiętaj sobie nową funkcję is_writable(), to ona właśnie sprawdza atrybut zapisywalności. if (is_writable($nazwapliku)) { Następnie otwieramy $nazwapliku w trybie dopisywania. if (!$uchwyt = fopen($nazwapliku, 'a')) { echo "Nie mogę otworzyć pliku ($nazwapliku)"; exit; if (fwrite($uchwyt, $trochetresci) === FALSE) { echo "Nie mogę zapisać do pliku ($nazwapliku)"; exit; echo "Sukces, zapisano ($trochetresci) do pliku ($nazwapliku)"; fclose($uchwyt); else { echo "Plik $nazwapliku nie jest zapisywalny";?> Synonimem funkcji fwrite() jest fputs(). Obie funkcje działają identycznie. flock() Co jednak stanie się, jeżeli jednocześnie zostaną uruchomione dwie kopie skryptu i obie będą próbowały zmienić ten sam plik? Sytuacja taka, jak łatwo się domyślić, może mieć przykre konsekwencje. Aby rozwiązać ten problem, należy użyć blokowania plików. Służy do tego funkcja flock(): flock($fp, tryb); Pierwszy argument funkcji flock() to uchwyt do pliku. Argument tryb określa typ dostępu, jaki chcemy uzyskać. Może mieć następujące wartości: 21

1 dostęp do odczytu, 2 dostęp do zapisu, 3 zwolnienie blokady. Jeżeli chcemy uzyskać dostęp do zapisu, najpierw wszystkie inne blokady muszą być zwolnione. Do uzyskania dostępu do odczytu wystarczy, że plik nie będzie zablokowany do zapisu w ten sposób wiele skryptów może jednocześnie czytać z pliku, ale tylko jeden może do niego zapisywać. Dodatkowo w trakcie zapisu żaden inny skrypt nie może odczytywać z pliku dzięki temu nie natrafi na niekompletne dane. Jeżeli określony rodzaj dostępu nie może być w danej chwili uzyskany, wykonanie skryptu zostanie wstrzymane do czasu, gdy będzie to możliwe. Plik powinien być blokowany na jak najkrótszy czas, aby nie wstrzymywać niepotrzebnie innych operacji. Jeżeli chcemy tylko sprawdzić, czy plik jest zablokowany, do argumentu tryb należy dodać 4 wtedy funkcja zwróci wartość TRUE, jeżeli plik nie jest zablokowany, lub FALSE gdy jest. Oto przykład zastosowania operacji blokowania: $file1=fopen("jakis.plik", "r"); $file2=fopen("jakis.plik", "r"); otwiera dwa razy ten sam plik, flock($file1, 2); blokuje pierwszą kopię, if(flock($file2, 6)) funkcja flock zwróci FALSE, ponieważ plik jest już zablokowany. { echo("plik nie zablokowany"); else{ echo("plik zablokowany"); flock($file, 3); odblokowuje plik. 22

7. Praktyczny przykład elektroniczne głosowanie Pora pokazać użyteczny program, wykorzystujący większość poznanych do tej pory umiejętności. Treść programu będę przeplatał komentarzem. Linie zawierające wyłącznie znaczniki HTML pozostawię bez komentarza. Kod programu oraz pliki pomocnicze znajdziesz na płycie zawierającej materiały poświęcone naszemu kursowi. Jeżeli wszystko uruchomisz zgodnie ze wskazówkami, powinieneś uzyskać w oknie przeglądarki prosty system głosowania z wynikami w postaci graficznej, jak na rysunku: A oto treść programu: <link rel="stylesheet" href="vince.css"> <body bgcolor="#c0c0c0"> <table width="150" border="0" cellspacing="0" cellpadding="1" bgcolor="#ff9933" align=left> <tr> <td> <table width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#660066"> <tr> <td><br><br> <table width="100%" border="0" cellspacing="0" cellpadding="0"> <tr> <td> <? 23

Rozpoczynamy kod PHP. if($vote == 1) Sprawdzenie, czy parametr przekazany podczas wywołania wynosił 1. Oznacza to głosowanie na tak (vote to nazwa pola typu radio-button na formularzu głosowania). Przy spełnieniu warunku zostaną wykonane poniższe instrukcje otoczone nawiasem klamrowym. { $fich="tak.txt"; $fp=fopen("$fich","r+"); Zdefiniowanie nazwy pliku przechowującego głosy na tak ("tak.txt") i otwarcie go w trybie odczyt/zapis. $oui=fgets($fp,10); Odczytanie 10 znaków z pliku tak.txt. Innymi słowy odczytanie liczby głosów na tak do zmiennej $oui. $oui++; zwiększenie liczby głosów na tak o jeden. fseek($fp,0); przesunięcie wskaźnika odczytu na początek. Wskaźnik odczytu przemieszcza się zawsze na koniec ostatnio odczytanego ciągu. Dzięki niemu każda następna operacja odczytu uzyska kolejne znaki. Wskaźnik ten definiuje także miejsce, od którego ma być rozpoczęty zapis do pliku. Po ostatnim odczycie liczby głosów, wskaźnik ten znajdował się za znakiem 10 (lub na końcu pliku, jeśli plik był krótszy). Powyższe polecenie ustawi wskaźnik na początku. Dzięki temu zapis nowej liczby głosów zamaże dotychczasowy wynik. Po takiej operacji plik będzie zawierał zawsze aktualną liczbę głosów. fputs($fp,$oui); fclose($fp); Zapisanie nowej liczby głosów do pliku tak.txt i zamknięcie go. 24

if ($vote == 2) Sprawdzenie, czy parametr przekazany podczas wywołania wynosił 2. Oznacza to głosowanie na nie (vote to nazwa pola typu radio-button na formularzu głosowania). Przy spełnieniu warunku zostaną wykonane poniższe instrukcje otoczone nawiasem klamrowym. { $fich="nie.txt"; $fp=fopen("$fich","r+"); Zdefiniowanie nazwy pliku przechowującego głosy na nie ("nie.txt") i otwarcie go w trybie odczyt/zapis. $non=fgets($fp,10); $non++; Odczytanie 10 znaków z pliku nie.txt. Innymi słowy odczytanie liczby głosów na nie do zmiennej $non, a następnie zwiększenie liczby głosów o jeden. fseek($fp,0); fputs($fp,$non); fclose($fp); Przesunięcie wskaźnika odczytu na początek pliku. Zapisanie nowej liczby głosów do pliku nie.txt i zamknięcie go. $fich="tak.txt"; $fp=fopen("$fich","r+"); $oui=fgets($fp,10); fclose($fp); $fich="nie.txt"; $fp=fopen("$fich","r+"); $non=fgets($fp,10); fclose($fp); 25

Powtórzenie operacji odczytu liczby głosów na tak i na nie z plików "tak.txt" i "nie.txt" do zmiennych $oui i $non. Odczyt tych wartości do zmiennych jest potrzebny w celu prawidłowego narysowania wykresu. Należy bowiem zwrócić uwagę, że powyższe instrukcje warunkowe uaktualniają w zależności od wywołania tylko jedną ze zmiennych $oui lub $non, a w przypadku wywołania skryptu bez parametrów (pierwsze wywołanie z danej lokalizacji) ani jedna z tych zmiennych nie będzie miała przypisanej wartości. Zauważmy też, że pliki są zamykane natychmiast po użyciu, co pozwala na ich natychmiastowe użycie przez innego głosującego. $result = (($oui*100)/($oui+$non)); $oui= $result; $non= 100 - $oui ; Przeliczenie liczby głosów na wartości procentowe (wyskalowanie wykresu).?> Chwilowe zakończenie kodu PHP, przejście do HTML. <table border="0" cellspacing=0 cellpadding=0 align="center"> <tr><td> <img src="images/graph_gh.gif" width="30" height="98"><img src="images/spacja.gif" width="15" height="10"><img src="images/tak.gif" width="10" height="<? echo $oui;?>"><img src="images/spacja.gif" width="15" height="10"><img src="images/nie.gif" width="10" height="<? echo $non;?>"></td></tr><tr><td><img src="images/graph_bs.gif" width="125" height="12" border=0></td></tr></table> Powyższy kod HTML rysuje wykres składający się z kilku gotowych obrazków. Zwróć uwagę, że w celu wyskalowania wysokości słupka, do kodu HTML wtrącono kod PHP height="<? echo $oui;?> podający aktualną wysokość słupka na podstawie zmiennej $oui. To samo uczyniono z wysokością drugiego słupka. Kod PHP można więc dowolnie zagłębiać w znacznikach HTML. <br> <form method="post" action="ankieta.php"> 26

Otwarcie formularza, który po zagłosowaniu wywołuje skrypt ankieta.php (czyli skrypt, który właśnie opisuję) z parametrami przekazanymi metodą POST. Dalsza część formularza HTML, niewymagająca komentarzy: <div align="center"> <font color="#ff9933"><b> <input type="radio" name="vote" value="1" > tak <input type="radio" name="vote" value="2"> nie </b></font> <br><br> <input type=image src="images/glosuj.gif" name="submit" value="envoyer"> </div> </form> </td></tr></table> Ponowny odczyt liczby głosów na tak i na nie, celem wykonania podpisu pod rysunkiem i obliczenia liczby głosujących: <? $fich="tak.txt"; $fp=fopen("$fich","r+"); $oui=fgets($fp,10); $pour = $oui ; fclose($fp); $fich="nie.txt"; $fp=fopen("$fich","r+"); $non=fgets($fp,10); $contre = $non ; fclose($fp); $result = (($oui*100)/($oui+$non)); $oui= $result; $non= 100 - $oui ; Zapewne zapytasz, po co ten odczyt? Przecież wykonywaliśmy go kilka linii temu. Faktycznie, ale podczas wykonywania tych linii ktoś inny (to przecież aplikacja internetowa) mógł zagłosować i zmienić wyniki. Na rysunku jeden głos nie sprawi wielkiej różnicy, ale liczby pod rysunkiem powinny być jak najbardziej aktualne. Stąd kolejne odczyty. 27

?> <center> <font color="#ff9933"><b> TAK [<span class=copyrightvp><? print(intval($oui));?>%</span>] NIE [<span class=copyrightvp><? print(100- (intval($oui)));?>%</span>]<br> GLOSOWALO[<span class=copyrightvp><? print($pour + $contre);?></span>]<br><br> </b> </font> </center> </td></tr></table> </td></tr></table> <body> I to już koniec kodu. Niezbyt trudne, prawda? Oczywiście, aplikacja ta posiada wiele wad i niedociągnięć. Ma jednak też zalety: można ją bardzo szybko uruchomić, jest stosunkowo łatwa do zrozumienia. A jeżeli dostrzegasz jej wady, spróbuj je poprawić. Będzie to świetne ćwiczenie. 28