Spis Treści
SPIS TREŚCI 1
WSTĘP 7
Dla kogo jest przeznaczona ta książka 7
Konwencje 7
Omówienie książki 7
Od autora 8
Przykłady kodu 8
CZYM JEST PHP 8
DLACZEGO POWINIENEŚ UŻYĆ PHP 9
GDZIE SZUKAĆ POMOCY 9
PODZIĘKOWANIA 10
O AUTORZE 10
ROZDZIAŁ 1. KOMPILACJA I INSTALOWANIE PHP 11
WSTĘP 11
POBIERANIE PHP 11
INSTALOWANIE WERSJI BINARNEJ 11
Binarna instalacja dla Windows 11
Instalowanie PHP w postaci modułu ISAPI 12
Użycie PHP jako CGI 14
Inne instalacje binarne 14
KOMPILOWANIE PHP 15
Kompilowanie PHP w Uniksach 15
Kompilacja modułu CGI 15
Kompilacja PHP jako statycznie dołączanego modułu Apache 17
Kompilacja PHP do postaci dynamicznie ładowanego modułu Apache 17
Podsumowanie kompilacji PHP w systemach Unix 18
Kompilowanie PHP w środowisku Windows 18
Podsumowanie kompilacji PHP 20
KONFIGUROWANIE PHP 20
Korzystanie z pliku php.ini 20
Inne metody zmiany konfiguracji PHP 21
PODSUMOWANIE 22
ROZDZIAŁ 2. JĘZYK 23
WSTĘP 23
OGÓLNE INFORMACJE NA TEMAT SKŁADNI 23
TYPY 24
Liczby - całkowite i zmiennoprzecinkowe 24
Ciągi 24
Tablice 25
ZMIENNE I STAŁE 26
Zmienne predefiniowane 26
Zasięg zmiennych 30
Stałe 31
OPERATORY I KOLEJNOŚĆ OPERATORÓW 31
PROGRAMOWANIE PRZEPŁYWU STEROWANIA 32
if, else, elseif 32
while 32
do .. while 32
for 33
foreach 33
switch 33
break i continue 35
include i require 36
FUNKCJE 36
Klasy i programowanie obiektowe 37
PORÓWNYWANIE WZORCÓW 39
Podsumowanie 39
ROZDZIAŁ 3. FORMULARZE I COOKIE 40
WSTĘP 40
OBSŁUGA FORMULARZY W PHP 41
Skalarne i wielowartościowe elementy formularza 41
Alternatywne metody odczytywania wartości z formularza 42
Użycie formularzy do przesyłania plików 45
Użycie rysunku jako przycisku wysłania danych 45
KONTROLA POPRAWNOŚCI DANYCH FORMULARZA 46
Kontrola danych za pomocą wyrażeń regularnych 46
Kontrola poprawności za pomocą sprawdzania typów 47
Klasa Validator 48
COOKIE 49
WAŻNE ZAGADNIENIA PROGRAMOWANIA DLA WWW 50
Obsługa nieprawidłowych danych 50
Obsługa i formatowanie wyświetlanych danych 52
PODSUMOWANIE 57
ROZDZIAŁ 4. OPERACJE NA PLIKACH 58
WSTĘP 58
ODCZYT I ZAPIS PLIKÓW 58
UŻYCIE GNIAZD 59
UŻYCIE POTOKÓW 60
KLASA FILE 61
PODSUMOWANIE 61
ROZDZIAŁ 5. WYSYŁANIE PLIKÓW PRZEZ FORMULARZ 62
WSTĘP 62
WYSYŁANIE POJEDYNCZEGO PLIKU 62
PUŁAPKI 64
PRZESYŁANIE WIELU PLIKÓW 64
BEZPIECZEŃSTWO 65
PODSUMOWANIE 66
ROZDZIAŁ 6. WSPÓŁPRACA Z BAZAMI DANYCH 67
WSTĘP 67
WPROWADZENIE 67
FUNKCJE BAZ DANYCH 67
MYSQL 68
Rozpoczynamy pracę z MySQL 68
Użycie MySQL 68
ODBC 71
Podstawy ODBC 71
Instalowanie i kompilowanie unixODBC 72
Kompilowanie PHP z obsługą unixODBC 72
Instalowanie sterownika OOB 72
Konfigurowanie OOB 72
Korzystanie z ODBC 73
PHPLIB 74
PRZECHOWYWANIE DANYCH Z FORMULARZY 75
WYKORZYSTANIE MOŻLIWOŚCI BAZY DANYCH 77
PODSUMOWANIE 78
ROZDZIAŁ 7. SESJE I STAN APLIKACJI 80
WSTĘP 80
PODSTAWY MECHANIZMU SESJI 80
WBUDOWANY W PHP MECHANIZM ZARZĄDZANIA SESJAMI 81
Rozpoczęcie pracy z sesjami w PHP 81
Przesyłanie identyfikatora sesji bez użycia cookie 83
Zapisywanie zmiennych sesji w bazie danych 85
Inne funkcje i opcje dotyczące sesji 89
UŻYCIE PHPLIB DO OBSŁUGI SESJI 90
TWORZENIE WŁASNEGO MECHANIZMU SESJI 92
INŻYNIERIA PROGRAMOWANIA A SESJE 92
PODSUMOWANIE 94
ROZDZIAŁ 8. UWIERZYTELNIANIE 95
WSTĘP 95
PODSTAWOWE UWIERZYTELNIANIE W APACHE 95
AKTUALIZACJA PLIKU .HTACCESS PRZY UŻYCIU PHP 97
PODSTAWOWE UWIERZYTELNIANIE ZA POMOCĄ PHP 99
KOMPLETNY SYSTEM UWIERZYTELNIANIA OPARTY O PHP 100
PODSUMOWANIE 104
ROZDZIAŁ 9. NIEZALEŻNOŚĆ OD PRZEGLĄDARKI 105
WSTĘP 105
ROZPOCZYNAMY 105
WEWNĘTRZNE FUNKCJE PHP 106
Dodatkowe informacje na temat Browscap 106
BROWSERHAWK 109
WYKORZYSTANIE DANYCH O PRZEGLĄDARCE 113
PODSUMOWANIE 114
ROZDZIAŁ 10. URUCHAMIANIE 115
WSTĘP 115
INŻYNIERIA PROGRAMOWANIA A URUCHAMIANIE 115
Projekt aplikacji 115
Definiowanie standardów programowania 116
Przegląd oprogramowania 116
Testowanie 117
Uruchamianie 117
PROGRAMOWANIE DEFENSYWNE 118
WŁASNA OBSŁUGA BŁĘDÓW 122
ZAAWANSOWANA OBSŁUGA BŁĘDÓW 125
PODSUMOWANIE 129
BIBLIOGRAFIA 130
ROZDZIAŁ 11. PONOWNE WYKORZYSTANIE KODU 131
WSTĘP 131
PONOWNE WYKORZYSTANIE KODU A INŻYNIERIA PROGRAMOWANIA 131
PONOWNE UŻYCIE ISTNIEJĄCEGO KODU 132
PHP 132
C/C++ 133
Java 138
Dodawanie obsługi Javy w PHP na *niksach 138
Dołączanie obsługi Javy w PHP dla Windows 139
Opcje konfiguracji Javy 139
COM 141
Inne metody 143
PODSUMOWANIE 144
BIBLIOGRAFIA 144
ROZDZIAŁ 12. ODDZIELANIE KODU HTML OD PHP 145
WSTĘP 145
WPROWADZENIE 145
ODDZIELENIE I INTEGRACJA PRZY UŻYCIU WBUDOWANYCH FUNKCJI PHP 146
Motywacja 146
Implementacja 147
Czego należy unikać 151
Podsumowanie: Oddzielanie i integracja przy wykorzystaniu funkcji PHP 151
WYKORZYSTANIE SYSTEMU SZABLONÓW 152
FastTemplate 152
Zaawansowane techniki użycia FastTemplate 157
PODSUMOWANIE 159
BIBLIOGRAFIA 159
ROZDZIAŁ 13. FAJNY PHP 160
WSTĘP 160
WYSYŁANIE DO PRZEGLĄDARKI PLIKÓW INNYCH NIŻ HTML 160
SKRYPTY AUTOMATYZUJĄCE 164
WDDX 168
MONITOROWANIE SIECI 172
PODSUMOWANIE 174
ROZDZIAŁ 14. WITRYNY OPARTE O SZABLONY 175
PODSTAWY WYKORZYSTANIA SZABLONÓW 175
ZAPOŻYCZANIE 183
PERSONALIZACJA WITRYNY 185
OBSŁUGA WIELU JĘZYKÓW 187
PODSUMOWANIE 189
ROZDZIAŁ 15. WITRYNY OPARTE O BAZĘ DANYCH 190
WSTĘP 190
PROJEKT BAZY DANYCH 190
ZARZĄDZANIE DANYMI APLIKACJI 192
WYŚWIETLANIE DANYCH 199
PODSUMOWANIE 204
ROZDZIAŁ 16. GENEROWANIE STATYCZNYCH STRON HTML W OPARCIU O DYNAMICZNE DANE 205
WSTĘP 205
KONCEPCJA 205
GENEROWANIE STRON STATYCZNYCH 205
Użycie buforowania 205
Użycie FastTemplate 207
TECHNIKI BUFOROWANIA 208
PODSUMOWANIE 210
ROZDZIAŁ 17. WITRYNY HANDLU ELEKTRONICZNEGO 211
WSTĘP 211
BEZPIECZEŃSTWO 211
Zastosowanie SSL 211
Certyfikaty 211
Bezpieczeństwo bazy danych 212
PRZETWARZANIE PŁATNOŚCI 212
DOSTARCZANIE PRODUKTÓW 219
PODSUMOWANIE 220
DODATEK A. FUNKCJE 221
DODATEK B. PREDEFINIOWANE ZMIENNE I STAŁE PHP 367
ZMIENNE 367
Zmienne Apache 367
Zmienne środowiska 369
Zmienne PHP 369
STAŁE 370
DODATEK C. OPCJE KOMPILACJI PHP 372
BAZY DANYCH 372
HANDEL ELEKTRONICZNY 374
GRAFIKA 374
RÓŻNE 375
--enable-inline-optimization 376
SIEĆ 379
DZIAŁANIE PHP 379
SERWER 380
TEKST I JĘZYK 380
XML 381
DODATEK D. OPCJE KONFIGURACJI PHP 382
OGÓLNE DYREKTYWY KONFIGURACJI 382
DYREKTYWY KONFIGURACJI POCZTY 385
DYREKTYWY KONFIGURACJI TRYBU BEZPIECZNEGO 385
DYREKTYWY KONFIGURACJI DEBUGGERA 385
DYREKTYWY ŁADOWANIA ROZSZERZEŃ 385
DYREKTYWY KONFIGURACJI MYSQL 386
DYREKTYWY KONFIGURACJI MSQL 386
DYREKTYWY KONFIGURACJI POSTGRESQL 386
DYREKTYWY KONFIGURACJI SYBASE 387
DYREKTYWY KONFIGURACJI SYBASE-CT 387
DYREKTYWY KONFIGURACJI INFORMIX 388
DYREKTYWY KONFIGURACJI BC MATH 389
DYREKTYWY KONFIGURACJI MOŻLIWOŚCI PRZEGLĄDAREK 389
DYREKTYWY KONFIGURACJI ZUNIFIKOWANEGO ODBC 389
DODATEK E. ZASOBY SIECI 390
Wstęp
Książka ta jest przeznaczona dla programistów tworzących aplikacje WWW za pomocą PHP. Należy zwrócić uwagę, że zostało użyte określenie aplikacje WWW a nie strony WWW lub witryny WWW. W przeszłości w Sieci znajdowały się w większości proste strony HTML o ograniczonej możliwości interakcji. Dzisiejszy obraz Sieci jest o wiele bardziej skomplikowany. Użytkownicy i firmy oczekują od Sieci coraz więcej. Powoduje to powstanie coraz większej ilości dynamicznych aplikacji WWW. PHP jest idealny do tworzenia takich aplikacji, ponieważ został zaprojektowany właśnie do realizacji tego zadania.
Dla kogo jest przeznaczona ta książka
Książka ta powinna być użyteczna dla szerokiego grona programistów WWW, ale pisana była z myślą o średnio zaawansowanych lub zaawansowanych programistach. PHP jest językiem programowania a nie językiem opisu strony, więc przydatne będzie doświadczenie w programowaniu. Programiści znający C lub Perla powinni uznać PHP za język bardzo przyjazny, natomiast programiści pracujący w ASP Microsoftu (Active Server Pages) uznają PHP za język o podobnej strukturze.
Ponieważ książka ta nie jest kierowana do początkujących programistów, podstawowe pojęcia dotyczące programowania zostaną przedstawione bardzo skrótowo. Zakłada się, że Czytelnik zna takie pojęcia programowania, jak funkcje, zmienne i stałe.
Konwencje
W książce przyjęto następujące konwencje:
* Kod programu i jego wyniki zaznaczone są czcionką o stałej szerokości.
* Nazwy plików i katalogów zaznaczone są czcionką pochyłą.
* Komendy i elementy języka zaznaczone są czcionką o stałej szerokości.
Omówienie książki
Książka zawiera zwięzłe wprowadzenie do PHP, oraz opis języka. Został w niej również przedstawiony sposób instalacji i konfiguracji PHP.
Druga część, "Specjalne wymagania przy programowaniu WWW", przeznaczona jest dla programistów tradycyjnych aplikacji rozpoczynających pracę przy aplikacjach WWW. W części tej przedstawione zostały takie zagadnienia jak: przetwarzanie formularzy, interakcję z użytkownikiem, utrzymywanie stanu oraz niezależność od przeglądarki.
Następna część, "Zarządzanie projektem aplikacji WWW" opisuje zalety modularności i powtórnego użycia kodu.
Część "Przykłady zastosowań" pokazuje użycie PHP na podstawie fragmentów działających już aplikacji. Część ta łączy zagadnienia przedstawione w poprzednich częściach i pokazuje przykłady pełnej wymiany informacji pomiędzy przeglądarką użytkownika i aplikacją zainstalowaną na serwerze WWW.
Na końcu książki znajduje się skorowidz zawierający wszystkie funkcje PHP4.
Od autora
Od około trzech lat tworzę aplikacje WWW przy użyciu PHP i ASP, jako niezależny przedsiębiorca. Fundamentem mojego sukcesu było użycie PHP, ponieważ pozwala on na szybkie budowanie prototypów, oraz jest wystarczająco wydajny i pewny nawet do tworzenia dużych aplikacji WWW.
Celem tej książki jest przekazanie innym programistów użytecznych informacji. Nie będę opisywał różnic pomiędzy PHP i innymi tego typu narzędziami i nie będę zajmował się historią PHP. Wszystkie te informacje można znaleźć na oficjalnej witrynie PHP, www.php.net. Zamiast tego pokażę zastosowanie PHP do stworzenia aplikacji WWW. Omówię również inżynierię programowania w projektach WWW, sposoby przeniesienia istniejącego kodu do nowych projektów WWW. Przedstawię również kilka przydatnych narzędzi napisanych dla PHP.
Przykłady kodu
Zamieszczone przykłady kodu były tworzone i testowane pzy użyciu PHP 4.0.1 (poprawka 2) na Apache 1.3.11 działającym w systemie RedHat 6.1. Do edycji plików HTML i PHP wykorzystuję edytor Allaire Homeite 4.5.1 zainstalowany na Windows NT.
Do testowania małych fragmentów kodu stosowałem następujący szablon HTML do którego wklejałem odpowiedni kod PHP:
Nazwa przykładu
Większe fragmenty kodu były tworzone od razu razem z kodem HTML.
Czym jest PHP
PHP to język programowania przeznaczony dla programistów WWW pozwalający na szybkie tworzenie dynamicznych aplikacji WWW. Oficjalnym rozwinięciem skrótu PHP jest "PHP: Hypertext Preprocessor" (preprocesor hipertekstu). Jest to język programowania osadzany w HTML składniowo podobny do C, Perla i Javy. Na wydruku 1. przedstawiony jest przykład kodu PHP.
Wydruk 1. Prosty przykład kodu PHP
Prosty przykład kodu PHP
Po uruchomieniu tego przykładu (poprzez odpowiednio skonfigurowany serwer WWW) generowany jest kod HTML zamieszczony na wydruku 2.
Wydruk 2. Wynik działania wydruku 1
Prosty przykład kodu PHP
Witajcie w PHP!
Preprocesor PHP wykonuje cały kod zawarty pomiędzy znacznikami umieszczonymi w kodzie HTML i zwraca wynik w postaci tekstu. Nie jest to szczególnie interesujący, ale pokazuje jak łatwo można umieszczać kod PHP w kodzie HTML. Należy pamiętać, że kod ten jest wykonywany na serwerze WWW a nie na kliencie. Oznacza to, że przeglądarka nie wie, że do stworzenia strony był używany PHP. Otrzymuje ona po prostu strumień kodu HTML, identycznie jak w przypadku zwykłych stron. Więcej na ten temat znajduje się w części "Specjalne wymagania przy programowaniu WWW".
Dlaczego powinieneś użyć PHP
PHP jest pełnowartościowym językiem programowania pozwalający na tworzenie aplikacji WWW z wszystkimi potrzebnymi funkcjami. PHP współpracuje z wieloma systemami baz danych. Pozwala to na bardzo łatwe tworzenie aplikacji WW korzystających z informacji zapisanych w bazie danych. Możliwy jest również dostęp do usług sieciowych takich jak IMAP, POP3, NNTP i TTP. Pozwala on również na otwieranie gniazd sieciowych i podłączanie się do innych protokołów TCP/IP.
PHP może być użyty we wielu konfiguracjach serwerów. Ponieważ PHP jest rozprowadzany głównie w postaci kodu źródłowego, może być skompilowany na wielu różnych platformach, na przykład na Linuksie, FreeBSD i nawet na Windows. Dostępne są również binarne dystrybucje dla Win32.
PHP może działać jako program CGI lub może być zainstalowany jako moduł Apache lub rozszerzenie ISAPI. Dzięki temu może on działać z praktycznie każdym serwerem WWW, od Apache na Linuksie do IIS na Windows NT. W celu utworzenia najbardziej elastycznego środowiska pracy należy samodzielnie skompilować i zainstalować PHP. Jeżeli wolisz szybko zacząć pracę, możesz zastosować binarną dystrybucję PHP.
Gdzie szukać pomocy
Pomoc można uzyskać na witrynie PHP oraz poprzez kilka grup dyskusyjnych i wysyłkowych. W lutym 2000 roku około 1400000 domen korzystało z PHP. Ponieważ jest on tak popularny, istnieje ogromna grupa programistów i konsultantów, którzy mogą odpowiedzieć na pytania. Więcej informacji na temat dostępnych zasobów Sieci znajduje się w części "Zasoby" na końcu książki.
Podziękowania
Na początku chciałbym podziękować wszystkim z wydawnictwa McGraw-Hill za umożliwienie mi zrealizowania tego zadania. Szczególne podziękowania należą się Rebece Young za wsparcie i pomoc w technicznych aspektach pisania książki. Dziękuję Johnowi Steele, mojemu redaktorowi technicznemu, który niezmiernie pomógł mi swoimi trafnymi uwagami i informacjami.
Oczywiście, należy podziękować całemu zespołowi tworzącemu PHP. Wiele osób z tego zespołu pomagało mi w pracy nad książką. Cała część zawierająca skorowidz funkcji jest ich zasługą. To oni spędzili setki lub tysiące godzin tworząc ten wspaniały język programowania i bogatą dokumentację.
Dziękuję Mattowi Wilson za umożliwienie mi wykorzystania w przykładzie do książki kodu MWeather. Dziękuję Nickowi Bradbury za pozwolenie wykorzystania informacji i rysunków z edytora TopStyle. Podziękowania dla Nate Weiss za pomoc przy użyciu deserializera WDDX dla JavaScript, dla Johna Kos za pomoc przy unixODBC i EasySoft ODBC-ODBC Bridge. Dla Martina Evans, głównego programisty ODBC-ODBC Bridge, za stworzenie tego świetnego produktu. Dziękuję Michaelowi Justin za pomoc przy konwerterze RTF do HTML firmy Scrooge. Dziękuję również Michaelowi C. Battilana za pomoc przy Cloanto Currency Server. Dla Sama Ockman za umożliwienie wykorzystania w książce rysunku serwera Penguin 1U. Dziękuję Richardowi Litofski za pomoc przy BrowserHawk. Podziękowania dla Ali Ersheid za umożliwienie wykorzystania w książce dokumentacji CyberCash. Dziękuję Josephowi Harris (znany jako CDI) za klasę FastTemplate oraz inne fantastyczne narzędzia dostępne na witrynie The Webmasters.net.
Dziękuję rodzicom i braciom za nieustanne wsparcie nawet, gdy w latach osiemdziesiątych spędzałem całe noce na pisaniu programów w Apple Basicu. Dziękuję pani Barton, pani Smith i panu Wakefield, moim nauczycielom angielskiego z liceum, którzy mieli ogromny wpływ na moje pisanie. Dziękuję Garemu Rogers i Jasonowi Wallin za wskazanie mi PHP i Linuksa w czasie gdy coraz bardziej pogrążałem się wykorzystując ASP i Windows. Dziękuję Tracy Ard za pożyteczne komentarze do tej pracy oraz za jego niezmienną przyjaźń.
Na koniec najważniejsze podziękowania należą się mojej żonie i córce za umożliwienie mi zakończenia tej pracy. Teraz znów możemy wieczorami chodzić skakać na trampolinie.
O autorze
Blake Schwendiman rozpoczął programowanie w 1980 roku rozpoczynając od Apple IIe i języka Basic. Zdobył licencjat na uniwersytecie Arizona State University w roku 1994. W chwili obecnej Blake zarządza firmą Intechra LLC, http://www.intechra.net/, firmą konsultingową specjalizującą się w oprogramowaniu, która ma siedzibę w Rexburg, Idaho. Intechra LLC specjalizuje się w tworzeniu oprogramowania dla WWW. Blake ma żonę Holy i trzyletnią córkę. Można się z nim skontaktować pod adresem blake@intechra.net.
Rozdział 1. Kompilacja i instalowanie PHP
Wstęp
Zanim rozpoczniemy naukę języka PHP, należy go poprawnie zainstalować i skonfigurować w używanym środowisku interpreter PHP. Ponieważ pakiet PHP może działać na wielu serwerach WWW i systemach operacyjnych, w rozdziale tym znajdą się szczegółowe opisy instalacji na jedynie kilku platformach, ale podane informacje są wystarczająco uniwersalne i mogą być wykorzystane przy konfigurowaniu środowiska pracy na innych platformach.
W rozdziale tym opisane zostaną szczegółowo Apache dla Linuksa oraz IIS dla Windows NT. Są to często spotykane konfiguracje serwerów WWW i są one na tyle różne, że ilustrują ogólne zasady instalacji pakietu PHP na większości platform. Szczegółowe dane na temat określonej platformy można również znaleźć na witrynie www.php.net.
Pobieranie PHP
Pierwszym krokiem do rozpoczęcia pracy z PHP jest zaopatrzenie się w kopię interpretera PHP. Na witrynie www.php.net umieszczone jest kilka wariantów tego pakietu. Najnowsza wersja zawsze znajduje się na górze listy. W przypadku serwerów uniksowych zaleca się pobranie pakietu zawierającego kompletny kod źródłowy i przeprowadzenie samodzielnej kompilacji. Platformy uniksowe to między innymi Linux, BSD, Solaris itp. W przypadku Windows zaleca się pobranie binarnej instalacji PHP.
Ze strony zawierającej pakiety instalacyjne można również pobrać poprzednie wersje programów, dokumentację i narzędzia pomocnicze. Poprzednie wersje mogą być potrzebne, jeżeli masz już gdzieś zainstalowane PHP i nie chcesz ryzykować niekompatybilności.
Instalowanie wersji binarnej
Po pobraniu binarnej dystrybucji PHP, instalacja jest banalna. Najczęściej binarna instalacja PHP jest przeznaczona dla Windows. Ponieważ jednak niektóre dystrybucje Uniksa zawierają binarną dystrybucję PHP, opisany zostanie również taki przypadek.
Binarna instalacja dla Windows
W PHP prawie wszystkie operacje można wykonać na kilka sposobów. Instalacja binarna dla Windows zawiera zarówno wersję CGI (Common Gateway Interface) PHP, jak również wersję ISAPI. Jeżeli korzystasz z serwera IIS (Internet Information Server) lub PWS (Personal Web Server) zalecane jest użycie modułu ISAPI. Wersja CGI powoduje, że PHP jest uruchamiany za każdym odwołaniem do strony, więc jest mniej efektywny od dynamicznego modułu jakim jest rozszerzenie ISAPI. Moduł ISAPI jest również ze swojej natury bezpieczniejszy od programu CGI.
Instalowanie PHP w postaci modułu ISAPI
Jeżeli korzystasz z serwera IIS, PWS lub innego serwera WWW obsługującego moduły ISAPI, najlepszym rozwiązaniem będzie użycie PHP w postaci modułu ISAPI. Aby zainstalować taką wersję, należy skopiować pliki php4ts.dll i msvcrt.dll do katalogu systemowego Windows (zwykle \windows\system w Windows 95 lub \winnt\system32 w Windows NT). Są to współdzielone biblioteki niezbędne do prawidłowej pracy każdej wersji PHP dla Windows. Dodatkowo można skopiować do katalogu systemowego inne pliki .dll, ale nie jest to konieczne do ich użycia.
Następnie należy tak skonfigurować IIS lub PWS, aby korzystał z modułu ISAPI do obsługi plików php. Serwer IIS można konfigurować za pomocą konsoli konfiguracji zainstalowanej w menu Option Pack. Na rysunku 1.1. znajduje jest rozwinięte menu pokazujące położenie tego programu w Windows NT.
Rysunek 1.1.
Uruchamianie aplikacji konfigurującej IIS
Po uruchomieniu konsoli Menedżer usług internetowych należy kliknąć prawym przyciskiem myszy na węźle serwera WWW (prawdopodobnie zatytułowany Domyślna witryna sieci Web) i wybrać Właściwości, tak jak jest to pokazane na rysunku 1.2. Następnie w oknie Właściwości należy przejść na zakładkę Katalog macierzysty i kliknąć przycisk Konfiguracja. Opcja ta pozwala na dodawanie i edycję skojarzeń.
Rysunek 1.2.
Konfigurowanie IIS
Teraz należy kliknąć przycisk Dodaj i wprowadzić potrzebne informacje. Na rysunku 1.3. pokazany jest proces dodawania mapowania rozszerzenia phtml do modułu ISAPI PHP.
Rysunek 1.3. Dodawanie mapowania dla rozszerzenia w IIS
Po dodaniu mapowania zmiany są od razu widoczne w oknie dialogowym Konfiguracja aplikacji. Czasami może być pożyteczne skojarzenie niektórych rozszerzeń z modułem ISAPI a niektórych z programem CGI. Na rysunku 1.4. pokazana jest konfiguracja mojego serwera WWW. Na rysunku widać mapowania dla PHP3, dla PHP4 jako CGI oraz PHP4 jako ISAPI. Jest to przydatne przy testowaniu różnic pomiędzy wersjami 3 i 4 PHP.
Rysunek 1.4.
Mapowanie rozszerzeń PHP
Po zakończeniu konfiguracji należy ponownie uruchomić serwer WWW. Można to zrobić przy użyciu modułu Usługi w Panelu sterowania, lub uruchamiając z linii poleceń następujące polecenia:
net stop iisadmin
net start w3svc
Po uruchomieniu serwera należy go przetestować tworząc prosty plik testowy, na przykład taki, jak pokazany na wydruku 1.1. i otwierając go poprzez twój serwer. Jeżeli wszystko jest skonfigurowane poprawnie, powinieneś zobaczyć ekran z informacjami na temat instalacji PHP.
Wydruk 1.1. Testowy skrypt PHP
phpinfo()
Trzeba pamiętać, że w pakiecie instalacyjnym PHP znajduje się uwaga na temat stanu modułu ISAPI która ostrzega, że nie powinien być stosowany w środowisku produkcyjnym. Sugeruje się, że w celu zapewnienia odpowiedniej stabilności powinna być użyta wersja CGI. Następna część rozdziału opisuje użycie PHP jako CGI.
Użycie PHP jako CGI
Jeżeli nie masz zainstalowanego serwera WWW obsługującego moduły ISAPI lub istnieją inne powody wyboru wersji CGI, należy przeprowadzić instalację PHP jako CGI. Instalacja jest bardzo podobna do tej przedstawionej powyżej, różnice występują jedynie przy mapowaniu rozszerzeń. Zamiast wybierać bibliotekę .dll ISAPI, należy wybrać plik php.exe. Serwer IIS lub PWS wysyła parametry do pliku wykonywalnego CGI, więc oprócz nazwy pliku wykonywalnego należy podać opcje linii poleceń %s %s. Jest to pokazane na rysunku 1.4. dla rozszerzenia .php4.
Różne serwery WWW mają różne metody określenia mapowania rozszerzeń. Do Apache dla Windows istnieje świetny podręcznik dostępny pod adresem www.php.net/manual/config-apache-nt.html. Zasoby sieci na temat instalacji PHP na różnych serwerach WWW dla Windows można odszukać za pomocą wyszukiwarki umieszczonej na witrynie www.php.net.
Inne instalacje binarne
Niektóre instalacje Uniksa posiadają instalację binarną PHP zintegrowaną z instalacją serwera WWW. Niektórzy dostawcy, na przykład Red Hat, udostępniają również binarną instalację na swoich witrynach. Instalacja taka jest wykonana w formie plików RPM (Red Hat Package Manager). Zaletą użycia plików RPM jest łatwość instalacji. Nie trzeba martwić się szczegółami procesu kompilacji, ponieważ plik RPM zawiera gotową do użycia odpowiednio skompilowaną wersję programu. Wadą jest to, że z powodu wielu możliwych wariantów platform dla Uniksa, problemem dla początkujących może być nawet wybór właściwego pliku. Poza tym w pliku RPM nie zawsze są ustawione wszystkie potrzebne opcje konfiguracji, niezbędne do prawidłowego działania programu.
Jeżeli masz plik RPM z PHP, możesz go zainstalować wydając polecenie rpm -i . Powoduje to zainstalowanie plików binarnych do katalogów określonych przez twórcę pliku RPM. Dla większości użytkowników katalogi te są prawidłowe. Po instalacji należy ręcznie skonfigurować serwer WWW tak, aby korzystał z zainstalowanych właśnie plików binarnych PHP. Poniżej przedstawimy sposób konfiguracji Apache. Inne serwery WWW wymagają przeprowadzenia podobnych czynności.
Niezależnie od tego, czy PHP będzie działało jako program CGI czy w postaci modułu, pierwszy krok konfiguracji jest zawsze taki sam. Trzeba utworzyć skojarzenie pomiędzy rozszerzeniem pliku a wewnętrznym typem stosowanym przez serwer. Robi się to dodając do pliku konfiguracyjnego następujące linie:
AddType application/x-httpd-php .php
AddType application/x-httpd-php .phtml
AddType application/x-httpd-php .inc
Dyrektywy te powodują, że Apache uważa wszystkie pliki z rozszerzeniami .php, .phtml i .inc jako pliki typu application/x-httpd-php. Do przetwarzania tego typu plików wykorzystywane jest PHP.
Zakładając, że masz zainstalowane PHP w postaci modułu Apache, kolejnym krokiem będzie modyfikacja pliku konfiguracyjnego httpd.conf tak, aby Apache załadował moduł PHP:
LoadModule php4_module libexec/libphp4.so
Jeżeli zainstalowana została wersja CGI, należy wprowadzić nieco inne zmiany do pliku konfiguracji httpd.conf. Dyrektywa konfiguracji jest podobna do poprzedniej, ale odwołuje się do programu w postaci pliku wykonywalnego.:
Action application/x-httpd-php /cgi-bin/php
Dyrektywa Action definiuje typ pliku powodujący uruchomienie PHP po otrzymaniu żądania ściągnięcia strony z serwera WWW. Oczywiście należy podać właściwą ścieżkę do pliku wykonywalnego.
Po wprowadzeniu zmian należy ponownie uruchomić serwer WWW, aby zaczęły działać nowe ustawienia. Serwer Apache można zrestartować za pomocą polecenia:
/ścieżka/do/apachectl restart
Aby przetestować konfigurację można wczytać za pomocą przeglądarki skrypt testowy, przedstawiony na wydruku 1.1.
Binarna dystrybucja PHP ułatwia szybkie rozpoczęcie pracy z PHP w Uniksach, ale może ona sprawiać problemy. Z powodu istnienia wielu wariantów Uniksów, znalezienie gotowej wersji działającej na określonym systemie może być czasami trudne. W wielu przypadkach będzie to bardziej czasochłonne niż ściągnięcie kodu źródłowego, skompilowanie i zainstalowanie PHP. Proces ten zostanie opisany w kolejnej części rozdziału.
Kompilowanie PHP
Jeżeli chcesz skorzystać z elastyczności własnej instalacji PHP lub jeżeli przewidujesz dodawanie własnych rozszerzeń do języka PHP (opisane w rozdziale 11. "Ponowne wykorzystanie kodu"), musisz dokładnie poznać proces kompilowania PHP. Jeżeli pracujesz na platformie, dla której nie ma instalacji binarnej, możesz nie mieć innego wyboru jak tylko samodzielnie kompilować PHP.
Kompilowanie PHP w Uniksach
W tej części rozdziału przedstawione zostaną informacje na temat kompilowania PHP na platformie Unix. Należy pamiętać, że Unix określa całą rodzinę systemów, np.: Linux, BSD, Solaris i inne. Oczywiście systemy te różnią się między sobą, ale wiele z kroków niezbędnych do kompilacji PHP jest identycznych. Więcej informacji na temat określonej platformy można odszukać za pomocą wyszukiwarki dostępnej na witrynie www.php.net.
Dla każdej platformy istnieje kilka sposobów kompilacji PHP. Jeżeli serwerem WWW jest Apache, można skompilować PHP jako plik wykonywalny, jako moduł ładowany dynamicznie lub jako statyczną bibliotekę. Jeżeli nie korzystasz z Apache, należy odszukać w dokumentacji PHP i serwera WWW szczegóły postępowania. Przy okazji możemy zarekomendować korzystanie z PHP w postaci dynamicznie ładowanego modułu, jako najlepsze rozwiązanie dla większości aplikacji. Jeżeli PHP zostanie statycznie dołączony do Apache, każda zmiana konfiguracji wymaga większego nakładu pracy. W przypadku modułu CGI, występują problemy z bezpieczeństwem.
W kolejnych częściach zakładamy, że ściągnąłeś już źródła PHP i rozpakowałeś je. Proces kompilacji jest właściwie taki sam dla każdego typu pliku wynikowego. Na początku trzeba uruchomić skrypt configure, który ustawia opcje kompilacji. Następnie przy pomocy narzędzia make przeprowadza się kompilację. Na koniec trzeba zainstalować gotowe PHP i zrestartować serwer WWW. Informacje na temat skryptu konfiguracyjnego są przedstawione w części poświęconej kompilowaniu modułu CGI, więc zaleca się przeczytanie tego fragmentu jako wprowadzenia.
Kompilacja modułu CGI
Kompilacja PHP do postaci wykonywalnego modułu CGI jest najprostszą metodą kompilacji i dobrym rozwiązaniem, jeżeli nigdy wcześniej nie kompilowałeś programów dla Uniksa. Poniżej przedstawiona jest kompletna lista operacji jakie należy wykonać. Niektóre z nich nie są obowiązkowe. Operacje opcjonalne są zaznaczone czcionką pochyłą. Odwołanie do powinno być zamienione na nazwę twojego katalogu bazowego PHP.
cd
rm config.cache
make clean
./configure
make
make install
Wykonanie tych operacji spowoduje usunięcie podręcznych danych konfiguracji, usunięcie plików wynikowych a następnie skompilowanie PHP do postaci CGI. Jest to najprostsza metoda kompilacji, przytoczona jedynie jako przykład. W prawdziwej kompilacji do skryptu konfiguracyjnego dołącza się opcje określające atrybuty PHP.
Druga i trzecia linia jest nieobowiązkowa, ponieważ polecenia w nich umieszczone są używane jedynie do wyczyszczenia poprzedniej konfiguracji i pozostałości po poprzedniej kompilacji. Jeżeli wcześniej nie konfigurowałeś ani nie kompilowałeś PHP, nie są one potrzebne. Można również nie korzystać z tych opcji przy kompilacji PHP, choć czasami ich wykonanie jest niezbędne. Jeżeli wprowadzane są poważne zmiany w konfiguracji lub zmieniasz typ kompilacji z CGI na inny, może okazać się, że wykonanie czyszczenia jest niezbędne, aby kompilacja przebiegła prawidłowo. W zależności od szybkości komputera, na którym wykonywana jest kompilacja, przeprowadzenie całej konfiguracji i kompilacji może zająć dosyć dużo czasu. Pozostawienie zapisanych opcji konfiguracji oraz obiektów binarnych spowoduje znaczne skrócenie czasu tworzenia PHP.
Wszyscy, którzy nigdy nie przeprowadzali takiego procesu powinni wiedzieć, że skrypt konfiguracyjny poszukuje w systemie narzędzi, plików i innych danych systemowych. Następnie na podstawie tych danych tworzy specyficzny dla systemu skrypt za pomocą można skompilować kod. Jeżeli w czasie działania skryptu konfiguracyjnego nastąpi awaria, często zdarza się, że wymagany plik lub narzędzie nie jest odnajdywane lub niewłaściwie skonfigurowane. Po zakończeniu działania skryptu konfiguracyjnego tworzony jest plik tymczasowy config.cache zawierający szczegóły na temat systemu, więc badanie systemu nie musi być powtarzane przy ponownym uruchomieniu konfiguracji. Jeżeli wprowadzisz duże zmiany do konfiguracji systemu, musisz usunąć plik tymczasowy przed kolejnym uruchomieniem skryptu konfiguracyjnego. W ten sposób upewniamy się, że zmiany te zostaną wykryte.
Po wykonaniu wszystkich podanych poleceń zostanie utworzony nowy plik wykonywalny - php. Można przetestować poprawność kompilacji za pomocą następującego polecenia:
php < /dev/null
Jeżeli zobaczysz wynik podobny do poniżej przedstawionego, udało ci się poprawnie skompilować i zainstalować PHP w postaci CGI.
X-Powered-By: PHP/4.0.2
Content-type: text/html
Trzeba zauważyć, że skompilowana właśnie wersja PHP nie posiada funkcji, które być może będziemy chcieli wykorzystywać w aplikacjach, ponieważ została skompilowana z użyciem tylko ustawień domyślnych. Trzeba ponownie uruchomić skrypt konfiguracyjny, ustawić opcje potrzebne w aplikacji a następnie ponownie skompilować i zainstalować PHP.
Pożyteczną cechą zestawu domyślnych ustawień jest to, że dołączone jest do niego wiele często używanych opcji konfiguracji, w tym obsługa bazy danych MySQL, sesji i wiele, wiele innych. Oznacza to, że przytoczone polecenia umożliwiają skompilowanie PHP, który pozwala na rozpoczęcie nauki języka.
Jeżeli potrzebujesz obsługi innej bazy danych lub innego rozszerzenia, trzeba dodać odpowiednią opcję konfiguracji. Lista dostępnych opcji jest wyświetlana po wpisaniu:
./configure --help
Większość opcji konfiguracji wpływających na dostępne funkcje PHP ma postać --enable-FUNKCJA lub --with-PAKIET. Aby dodać funkcję do PHP należy użyć jednej z poniższych form:
--enable-FUNKCJA
--enable-FUNKCJA=yes
Aby usunąć funkcję z PHP, należy użyć:
--disable-FUNKCJA
--enable-FUNKCJA=no
Pełna lista opcji konfiguracji znajduje się w skorowidzu na końcu książki. Funkcje korzystające ze składni --enable są to zwykle wbudowane opcje PHP, takie jak możliwość wykorzystywania krótkich znaczników lub obsługa protokołu FTP. Pakiety są to zwykle moduły zewnętrzne, które mogą być dołączone do PHP, na przykład obsługa bazy danych Oracle lub Javy. Te własności wymagają zwykle wskazania zewnętrznego pliku i do jego włączania korzysta się z następującego zapisu:
--with-PAKIET=/ścieżka/do/pakietu
Aby wyłączyć pakiet należy użyć poleceń:
--with-PAKIET=no
--without-PAKIET
Jako przykład przedstawimy następującą konfigurację:
./configure --with-apxs=/www/bin/apxs --with-java --with-cybercash=/home/blake/mck-3.2.0.6-i586-pc-linux-gnulibc2.1 --withunixODBC=/usr/local/unixODBC --disable-debug --enabletrack-vars -- enable-fin-funcs --with-snmp=/home/blake/ucd-snmp-4.1.2 --enable-ucd-snmp-hack
Powyższe wywołanie konfiguracji powoduje dodanie do PHP obsługi Javy, CyberCash, SNMP (Simple Network Management Protocol) oraz unixODBC. Nie zostało podane położenie katalogu Javy, więc skrypt konfiguracyjny użyje domyślnej ścieżki do katalogu z tym pakietem. Dodatkowo została dodana opcja -with-apxs, która powoduje, że PHP jest kompilowane do postaci dynamicznie ładowanego modułu Apache a nie jako program typu CGI. Później omówimy to zagadnienie dokładniej. W przedstawianej konfiguracji wyłączono informacje dla debuggera oraz włączono opcje track-vars, fin-funcs oraz ucd-snmp-hack. Opcja fin-funcs powoduje dodanie własnego modułu rozszerzeń opisanego w dalszej części książki (rozdział 11.), natomiast pozostałe są standardowymi elementami konfiguracji opisanymi w skorowidzu na końcu książki.
Wiele z pakietów oprogramowania jakie chcemy dodać do PHP musi być osobno zainstalowane. Więcej informacji na temat tego, gdzie można zaopatrzyć się w potrzebne pakiety, można znaleźć w dokumentacji na witrynie www.php.net.
Po utworzeniu PHP w postaci CGI, należy skonfigurować serwer WWW do współpracy z nowym programem. Aby skonfigurować serwer Apache należy dodać następujące dyrektywy do pliku httpd.conf:
AddType application/x-httpd-php .php
AddType application/x-httpd-php .phtml
AddType application/x-httpd-php .inc
Action application/x-httpd-php /cgi-bin/php
Pierwsze trzy dyrektywy definiują zawartość plików z rozszerzeniami php, phtml i inc jako typ application/x-httpd-php. Ostatnia dyrektywa powoduje wysłanie wszystkich plików tego typu do pliku wykonywalnego php. Zakładamy, że plik ten jest umieszczony w katalogu cgi-bin serwera WWW.
Dyrektywy te są minimum wymaganym do konfiguracji PHP w Apache, ale ta sama czynność może być zrealizowana jeszcze na kilka sposobów. Więcej szczegółów można znaleźć w dokumentacji do Apache.
Kompilacja PHP jako statycznie dołączanego modułu Apache
Apache pozwala na statyczne dołączanie modułów bezpośrednio do pliku binarnego Apache. W porównaniu z wersją CGI użycie modułu pozwala poprawić wydajność aplikacji oraz zwiększyć bezpieczeństwo systemu,. Wadą tej metody jest konieczność powtórnej kompilacji Apache po każdej kompilacji PHP. Może być to czasochłonne i frustrujące, ponieważ w przypadku wystąpienia kłopotów z konfiguracją PHP, Apache może również przestać działać. Jednak niektóre aplikacje wymagają zastosowania statycznie dołączanego modułu Apache, opiszemy teraz sposób jego tworzenia.
Przed skonfigurowaniem i skompilowaniem PHP niezbędne jest skonfigurowanie Apache. Zakładamy, że na dysku jest już katalog z kodem źródłowym Apache. Aby skonfigurować Apache, należy użyć następujących poleceń:
cd
./configure
Po zakończeniu działania tego skryptu można zająć się konfigurowaniem i kompilowaniem PHP.
cd
./configure --with-apache=
make
make install
Opcja --with-apache powoduje kompilację do postaci statycznej biblioteki oraz pozwala podać katalog z plikami źródłowymi Apache. Następnie należy skompilować serwer Apache za pomocą poleceń:
cd
./configure --prefix=/www --activate-module=src/modules/php4/libphp4.a
make
make install
Dyrektywa prefix może być inna w twoim systemie, ponieważ wskazuje ona katalog gdzie zostaną zainstalowane pliki zależne od architektury. Teraz należy uruchomić serwer Apache i przy wykorzystaniu skryptu testowego z wydruku 1.1. sprawdzić poprawność konfiguracji.
Aby Apache prawidłowo przetwarzał pliki PHP należy odpowiednio zmodyfikować plik httpd.conf. W zależności od rozszerzeń jakie zostały wybrane do reprezentowania plików PHP, należy wprowadzić odpowiednie zmiany. I tym razem standardowa konfiguracja wygląda następująco:
AddType application/x-httpd-php .php
AddType application/x-httpd-php .phtml
AddType application/x-httpd-php .inc
Przedstawiony opis przedstawia jedynie bardzo prostą wersję PHP, która zawiera jedynie opcje domyślne. Więcej informacji o zmianie konfiguracji kompilacji PHP znajduje się w części na temat kompilacji wersji CGI.
Kompilacja PHP do postaci dynamicznie ładowanego modułu Apache
Sposób kompilacji PHP do postaci dynamicznie ładowanego modułu Apache nie różni się zbytnio od innych przedstawionych do tej pory metod. Zaletą tej metody jest możliwość kompilacji PHP bez konieczności równoczesnej kompilacji Apache. Również niektóre moduły rozszerzeń (na przykład Java) wymagają do poprawnej pracy, aby PHP był skompilowany do postaci dynamicznie ładowanego modułu. Aby Apache obsługiwał dynamicznie ładowane moduły należy go przekompilować z następującymi opcjami konfiguracji:
cd
make clean
./configure --enable-module=so --enable-rule=SHARED_CORE --prefix=/www
make
make install
Oprócz kompilacji Apache przedstawione polecenia przygotowują skrypt apxs, który jest niezbędny do kompilacji dynamicznego modułu PHP. Jeżeli wystąpią kłopoty ze skryptem apxs można powtórnie wykonać przedstawione polecenia, co spowoduje ponowne wygenerowanie prawidłowo skonfigurowanego skryptu. Po skompilowaniu Apache z obsługą dynamicznie ładowanych modułów, należy skompilować PHP w następujący sposób:
cd
make clean
rm config.cache
./configure --with-apxs=/www/bin/apxs (pozostałe opcje)
make
make install
Polecenia porządkujące są zalecane, jeżeli PHP był już kompilowany w innej konfiguracji. Ścieżka podana w dyrektywie konfiguracji --with-apxs powinna być pełną ścieżką do skryptu apxs na serwerze.
Tak jak w przypadku poprzednich sposobów kompilacji należy prawidłowo skonfigurować Apache, aby przetwarzał pliki PHP. Po zmodyfikowaniu konfiguracji należy uruchomić Apache i wywołać skrypt testowy.
Podsumowanie kompilacji PHP w systemach Unix
Celem tego fragmentu książki nie było podawanie szczegółowego i wyczerpującego opisu wszystkich możliwych opcji konfiguracji, ale pokazanie podstawowych metod kompilowania PHP do różnych postaci. Jeżeli nie kompilowałeś wcześniej PHP, powinieneś na początku spróbować skompilować podstawową konfigurację, a później uzupełniać potrzebne opcje. Po zapoznaniu się z procesem kompilacji jest już bardzo łatwo testować różne konfiguracje i dodawać niestandardowe rozszerzenia.
Po skompilowaniu PHP i sprawdzeniu, czy działa z Apache, można zapoznać się z opcjami konfiguracji, które można ustawiać bez potrzeby ponownej kompilacji. Zostały one opisane w dalszej części rozdziału.
Kompilowanie PHP w środowisku Windows
Kompilowanie PHP dla Windows jest na początku bardziej skomplikowanym procesem niż kompilacja PHP dla Uniksa. Dokumentacja zaleca użycie Visual C++ wersja 6, choć wersja 5 również powinna działać. Próbowałem sprawdzić, czy można użyć pakietu Borland C++ Builder, ale nie udało mi się tego zrobić. Problem stanowiły prekompilowane pliki lib, ponieważ Microsoft i Borland korzystają z różnych formatów tych plików. Prawdopodobnie można zastosować kompilator Borlanda, ale trzeba wcześniej przekompilować wszystkie biblioteki. W poniższym opisie zakładamy użycie Visual C++.
Przed rozpoczęciem pracy należy się zaopatrzyć w kilka programów i plików pomocniczych. Tabela 1.1. zawiera wszystkie dodatkowe programy oraz adresy w Internecie, gdzie były dostępne w czasie pisania książki.
Tabela 1.1. Dodatkowe pliki pomocnicze i ich adresy w Sieci
Program
Położenie
Kod źródłowy PHP
www.php.net/download.php
Pakiet Cygwin
http://sources.redhat.con/cygwin/
Narzędzia do kompilacji PHP dla Win32
www.php.net/extra/win32build.zip
Obsługa BCMath
www.php.net/version4/downloads/number.tar.gz
Zastępnik pliku resolv.lib
www.php.net/version4/downloads/bindlib_w32.zip
Pakiet Cygwin zawiera popularne narzędzia GNU, takie jak gcc, make i bison. Niektóre z tych programów są wykorzystywane w procesie kompilacji, więc trzeba wcześniej zainstalować ten pakiet. Inne potrzebne pliki są integralną częścią dystrybucji PHP. Kod źródłowy PHP jest identyczny jak ten, który jest używany do utworzenia wersji dla Uniksa.
Potrzebny jest również program do rozpakowywania plików. Ja używam programu Winzip, ponieważ bez problemu radzi sobie z plikami .tar.gz. Również inne programy posiadają takie możliwości. Na początku należy zainstalować narzędzia Cygwin. Trzeba ręcznie dodać zmienną środowiska wskazując na położenie plików Cygwin. Jeżeli pracujesz w Windows 95, trzeba dodać tą zmienną ręcznie do pliku autoexec.bat. W Windows NT należy kliknąć prawym przyciskiem myszy ikonę Mój komputer i wybrać z menu Właściwości. Teraz trzeba kliknąć zakładkę Środowisko i dodać nową zmienną, tak jak jest to pokazane na rysunku 1.5. Zmienna nazywa się CYGWIN a jej wartością jest ścieżka do katalogu, gdzie zainstalowane są narzędzia Cygwin.
Rysunek 1.5. Ustawienie zmiennej środowiskowej CYGWIN
Następnie utwórz katalog i rozpakuj do niego zawartość pliku win32build.zip. Uruchom Visual C++ i wybierz Options z menu Tools. Teraz wybierz zakładkę Directories (rysunek 1.6.) i przy użyciu listy rozwijalnej opisanej Show directories for, wybierz opcję Executable files i dodaj katalog z plikami Cygwin. Teraz z listy rozwijalnej wybierz Include files i dodaj katalog z win32build\include (rysunek 1.6.). Na koniec wybierz Library files i dodaj katalog win32build\lib. Od tej pory kompilator Visual C++ będzie mógł korzystać z zainstalowanych narzędzi i plików.
Rysunek 1.6.
Ustawienie katalogów w Visual C++
Kolejnym krokiem będzie skompilowanie nowej wersji pliku resolv.lib. Najpierw utwórz nowy katalog i rozpakuj do niego pliki z archiwum bindlib_w32.zip. W Visual C++ otwórz projekt bindlib.dsp. Z menu Build wybierz Set Active Project Configuration i wybierz wersję handlową biblioteki lub wersję do uruchamiania. Naciśnij klawisz F7, aby skompilować projekt. Po zakończeniu kompilacji należy skopiować plik resolv.lib do katalogu win32build\lib.
Następnie rozpakuj źródła PHP i plik number.tar.gz za pomocą zewnętrznego programu lub narzędzia tar z pakietu Cygwin. Skopiuj rozpakowane pliki number.c i number.h do katalogu ext/bcmath w katalogu z kodem źródłowym PHP.
Jeżeli wykonałeś wszystkie opisane wcześniej czynności, jesteś gotowy do kompilacji PHP. Uruchom Visual C++ i otwórz plik projektu php4ts.dsp, znajdujący się w podkatalogu win32 katalogu z kodem źródłowym PHP. Projekt ten zawiera kilka konfiguracji. Najłatwiej jest rozpocząć od skompilowania wersji CGI wybierając wersję handlową lub wersję z danymi dla debuggera, tak jak jest to pokazane na rysunku 1.7.
Rysunek 1.7.
Wybór konfiguracji dla wersji CGI
Skompiluj projekt i jeżeli wszystko pójdzie dobrze posiadasz już własną wersję PHP. Jeżeli potrzebujesz wersji PHP jako ISAPI lub NSAPI, wystarczy wybrać odpowiednią konfigurację dla kompilacji i ponownie skompilować projekt. Jak wspomniałem wcześniej, najtrudniejszą częścią było wstępne przygotowanie środowiska. Gdy wszystko jest już gotowe, cała reszta jest tak samo prosta jak w Uniksie.
Podsumowanie kompilacji PHP
Kompilowanie wersji PHP dla Windows jest za pierwszym razem dużo trudniejsze od wersji dla Uniksa, ale gdy wszystkie potrzebne dodatki zostaną odpowiednio skonfigurowane, jest już proste. Gdy poznałeś już proces kompilowania PHP dla obu platform możesz tworzyć wysoce specjalizowane wersje PHP, spełniających precyzyjnie potrzeby konkretnej witryny. Dokładna wiedza na temat procesu kompilacji PHP jest również niezbędna, aby móc tworzyć rozszerzenia PHP. Zagadnienie to zostało opisane w rozdziale 11.
Konfigurowanie PHP
Niezależnie od platformy na której działa PHP, sposób jego konfigurowania jest taki sam. Wykorzystuje się w tym celu plik php.ini. Plik ten jest dostarczany w dystrybucji PHP jako php.ini-dist i php.ini-optimized. Jeżeli nie znasz dobrze opcji konfiguracji, powinieneś rozpocząć do podstawowych ustawień z pliku php.ini-dist. Pierwszym krokiem będzie skopiowanie i zmiana nazwy pliku. Plik powinien być nazwany php.ini i skopiowany do katalogu zależnego od używanej platformy. W tabeli 1.2. zamieszczone są podstawowe warianty.
Tabela 1.2. Platformy PHP i położenie pliku php.ini
Platforma
Położenie pliku php.ini
Windows
Katalog zwykle \windows w Windows 95 i \winnt w Windows NT
Unix
Można to sprawdzić za pomocą funkcji phpinfo(), ale zwykle jest to /usr/local/lib.
Po umieszczeniu pliku konfiguracyjnego w odpowiednim katalogu, należy do niego wprowadzić odpowiednie zmiany. Plik php.ini jest podzielony na sekcje, rozpoczynające się od linii [nazwa_sekcji] podobnie, jak w standardowych plikach ini systemu Windows. Plik ten zawiera obszerne komentarze opisujące przeznaczenie sekcji i opcji konfiguracji. W pozostałej części książki czasami będą przytaczane opcje niezbędne do uruchomienia przykładów. Zwykle przykład taki zawiera nazwę sekcji, nazwę opcji oraz wartość. Aby wprowadzić zmiany najczęściej zmienia się plik php.ini i ponownie uruchamia Apache, ale istnieją również inne mechanizmy zmiany opcji. Mechanizmy te opisane zostaną w późniejszej części rozdziału.
Korzystanie z pliku php.ini
Zalecaną metodą zmiany konfiguracji jest modyfikacja pliku php.ini i ponowne uruchomienie serwera WWW. Jeżeli korzystasz z PHP w postaci programu CGI nie musisz restartować serwera, ponieważ plik php.ini jest odczytywany za każdym uruchomieniem programu CGI. Dla przykładu można zmienić sposób raportowania błędów przez PHP, korzystając z odpowiednich opcji konfiguracji. Opcje te mają następujące wartości domyślne:
error_reporting = E_ALL & ~E_NOTICE ; Pokaż wszystkie błędy oprócz informacji
display_errors = On ; Wypisuj błędy (jako część wynikowego HTML)
log_errors = Off ; Zapisuj błędy do pliku błędów
error_log = syslog ; Zapisuj błędy do dziennika systemowego
Pierwsza opcja powoduje generowanie komunikatów dla wszystkich typów błędów poza typem E_NOTICE. Następna linia powoduje wstawianie komunikatów błędów do wynikowego kodu HTML. Następne dwa wiersze powodują zapisywanie komunikatów błędów w pliku. Załóżmy, że w instalacji produkcyjnej nie chcemy wyświetlać błędów, a zamiast tego błędy będą zapisywane do określonego pliku. Można to zrealizować zmieniając konfigurację w następujący sposób:
error_reporting = E_ALL ; Pokaż wszystkie błędy
display_errors = Off ;
log_errors = On ; Zapisuj błędy
error_log = /tmp/php_log ; Zapisuj błędy do pliku /tmp/php_log
Taka konfiguracja powoduje, że wszystkie komunikaty błędów, w tym informacje, będą zapisywane w pliku /tmp/php_log. Oczywiście plik ten powinien mieć odpowiednio ustawione prawa dostępu, aby serwer WWW mógł zapisać w nim dane.
Z powodu dużej ilości opcji konfiguracji, nie zostaną tu przedstawione wszystkie możliwe opcje. Pełna lista znajduje się w skorowidzu na końcu książki. Tutaj przedstawione zostaną jedynie ogólne sposoby wykorzystywania tych opcji. Aby zmienić opcję konfiguracji, należy otworzyć w edytorze plik php.ini i odszukać opcję. Zwykle znajduje się tam sporo komentarzy opisujących możliwe wartości danej opcji.
Inne metody zmiany konfiguracji PHP
Istnieją dwie metody zmiany konfiguracji PHP bez konieczności modyfikacji pliku php.ini. Pierwszym sposobem jest wstawienie tych opcji do pliku konfiguracyjnego Apache httpd.conf lub do pliku .htaccess. Pierwsza metoda jest użyteczna, jeżeli chcemy mieć różne ustawienia PHP dla różnych serwerów wirtualnych lub różnych katalogów. Druga metoda jest wykorzystywana, gdy nie jest możliwy dostęp do plików php.ini i httpd.conf. Jest to częsta sytuacja, witryna jest umieszczona na dzierżawionym serwerze zewnętrznej firmy. Jest to jednak najmniej zalecana metoda, ponieważ plik .htaccess jest wczytywany i analizowany za każdym odwołaniem do stron znajdujących się w tym katalogu. Powoduje to znaczne spowolnienie serwera WWW.
W obu tych przypadkach sposób zmiany konfiguracji PHP jest tak sam. Należy użyć dyrektyw konfiguracji php_value i php_flag do ustawienia potrzebnych opcji. Na przykład, aby ustawić poprzednio opisane opcje konfigurujące sposób raportowania błędów, należy użyć następujących dyrektyw Apache:
ServerAdmin admin@server.net
DocumentRoot /www/hosts/wwwprojects/
ServerName www.testserver.com
php_value error_reporting 2047
php_flag display_errors off
php_flag log_errors on
php_value error_log /tmp/php_log
Umieszczenie tych ustawień w pliku httpd.conf spowoduje, że zostanie ustawiony sposób raportowania błędów dla serwera wirtualnego o nazwie www.testserver.com. Jeżeli na tej samej maszynie istnieją inne serwery wirtualne, używają one konfiguracji określonej przez plik php.ini. Pozwala to na posiadanie różnych konfiguracji PHP dla różnych serwerów wirtualnych lub katalogów.
Jeżeli musisz zmienić konfigurację PHP a nie masz dostępu do pliku php.ini ani do httpd.conf, możesz wykorzystać pliki Apache .htaccess. Jest to również użyteczne, jeżeli określony katalog musi mieć inne ustawienia konfiguracji niż reszta witryny. Na przykład, można zmienić sposób raportowania błędów dla jednego katalogu na czas uruchamiania skryptów w nim się znajdujących. W tym celu należy stworzyć plik .htaccess z następującą zawartością:
php_value error_reporting 2039
php_flag log_errors off
php_flag display_errors on
Należy zauważyć, że w obu przykładowych plikach konfiguracyjnych Apache wartość zmiennej konfiguracji error_reporting jest ustawiana za pomocą wartości numerycznej a nie stałej. Jest o jedyny sposób poprawnego ustawienia wartości. Należy pamiętać, że konfigurując PHP poprzez dyrektywy Apache nie można używać jako wartości żadnych stałych PHP. W przeciwnym wypadku efekty mogą być niespodziewane.
Aby zilustrować potęgę dostępnego mechanizmu konfiguracji na rysunku 1.8. przedstawiony został schemat możliwości konfiguracji środowiska PHP.
Rysunek 1.8. Elastyczność konfiguracji z zastosowaniem php.ini oraz plików konfiguracyjnych Apache
Podsumowanie
W tym rozdziale przedstawiono kilka informacji niezbędnych do rozpoczęcia pracy z PHP. Z powodu elastyczności i dużej ilości obsługiwanych platform niemożliwe jest szczegółowe opisanie wszystkich dostępnych konfiguracji. Korzystając jednak z informacji umieszczonych w tej książce, oraz na witrynie www.php.net powinieneś być w stanie zainstalować i skonfigurować PHP na twojej platformie.
Trzeba zauważyć, że PHP posiada wiele własnych funkcji zmieniających ustawienia konfiguracji. Przykładami takich funkcji są error_reporting() oraz set_time_limit(). Więcej informacji na temat tych funkcji można znaleźć w skorowidzu na końcu książki.
Rozdział 2. Język
Wstęp
W rozdziale tym znajduje się zwięzły opis języka programowania PHP. Jak wspomniałem we wstępie do książki nie jest moją intencją poświęcać zbyt wiele czasu na omawianiu ogólnych koncepcji programowania. W tym rozdziale znajduje się opis składni podstawowych konstrukcji programowania, na przykład zmiennych, stałych i funkcji. Przykłady przytoczone w tym rozdziale nie pokazują najlepszych technik programowania a jedynie ilustrują składnię i użycie omawianych elementów. Pełny opis języka znajduje się w dokumentacji języka dostępnej na witrynie http://www.php.net.
Ogólne informacje na temat składni
Ponieważ PHP jest zwykle wbudowywany w kod HTML istnieją specjalne znaczniki ograniczające bloki PHP. Użycie tych znaczników jest nazywane czasem wyjściem z trybu HTML.
Wydruk 2.1. Sposoby oznaczania bloku kodu PHP w HTML
echo "użycie krótkich znaczników PHP do wyjścia z trybu HTML "; ?>
"; ?>
<% echo "można stosować również znaczniki w stylu ASP "; %>
Pierwsza metoda oznaczania bloków PHP jest dostępna jedynie wtedy, gdy uaktywnione są krótkie znaczniki. Aby to zrobić należy użyć funkcji short_tags(), włączyć w pliku konfiguracyjnym opcję short_tag_open lub skompilować PHP z opcją -enable-short-tags. Znaczniki w stylu ASP są dostępne jedynie wtedy, gdy uaktywniona jest opcja konfiguracji asp_tags. Więcej informacji na temat kompilowania i konfiguracji PHP znajduje się w rozdziałach "Kompilacja i instalowanie PHP" oraz dodatku D - "Opcje konfiguracji".
PHP jest syntaktycznie bardzo podobny do C. Na przykład, instrukcje są oddzielone średnikiem. Znacznik ?> jest niejawnym końcem instrukcji, więc poniższe przykłady są poprawne składniowo:
Wydruk 2.2. Koniec instrukcji
";
?>
"
?>
Komentarze w PHP można oznaczać symbolami komentarzy pochodzącymi z C, C++ lub stosowanych w skryptach Uniksa. Komentarze jednoliniowe komentują tekst do końca linii lub do końca bieżącego bloku PHP w zależności od tego, co będzie pierwsze. Nie można zagłębiać wielowierszowych komentarzy w stylu C.
Wydruk 2.3. Komentarze
"; // To jest jednowierszowy komentarz w stylu C++
/* To jest wielowierszowy
blok komentarza */
echo "Witamy ponownie. "; # To jest komentarz w stylu skryptów Uniksa
?>
To wyświetli nic.
Typy
PHP posiada następujące typy: liczby zmiennoprzecinkowe, liczby całkowite, ciągi, tablice i obiekty. Typ zmiennej jest ustalany w oparciu o kontekst w jakim jest użyta zmienna i nie jest on jawnie ustalany przez programistę. Jest to ważna cecha o której należy pamiętać podczas programowania aplikacji PHP, ponieważ niejawna konwersja typów może spowodować trudne do odnalezienia błędy. Na przykład poniższa instrukcja jest prawidłowa i spowoduje wyświetlenie liczby 9:
print( 3* "3 małe świnki");
Aby można było zapanować nad typami, PHP posiada funkcje gettype() i settype() oraz kilka funkcji przeznaczonych dla określonych typów, na przykład is_integer() lub is_array(). W skorowidzu funkcji na końcu książki znajduje się pełne omówienie tych funkcji. Teraz zostanie opisany każdy z typów zmiennych (oprócz obiektów). Obiekty PHP zostaną opisane w dalszej części rozdziału.
Liczby - całkowite i zmiennoprzecinkowe
Liczby całkowite można podawać używając notacji dziesiętnej, ósemkowej i szesnastkowej. Liczby zmiennoprzecinkowe można podawać używając notacji zwykłej lub zapisu naukowego. Na poniższym wydruku pokazana jest składnia PHP dla wszystkich tych notacji.
Wydruk 2.4. Reprezentacja liczb
" );
?>
Ciągi
Ciągi w PHP są ograniczane apostrofami (') lub cudzysłowami ("). Zapisy te różnią się sposobem interpretacji ciągu. Jeżeli ciąg jest otoczony cudzysłowami, zmienne zapisane w ciągu zostają zamienione na ich wartości. Aby zapisać znaki specjalne w ciągach otoczonych cudzysłowami, należy użyć znaku lewego ukośnika (\), tak jak zostało to pokazane w tabeli 2.1.
Tabela 2.1. Znaki specjalne w ciągach otoczonych cudzysłowami
Sekwencja znaków
Znaczenie
\n
nowa linia
\r
powrót karetki (CR)
\t
tabulacja
\\
lewy ukośnik
\"
cudzysłów
\$
znak dolara
W ciągach otoczonych apostrofami zmienne nie są zastępowane. Jedynymi dopuszczalnymi sekwencjami sterującymi są te oznaczające lewy ukośnik (\\) i apostrof (\'). Sekwencje te pozwalają na wpisanie do ciągu znaku apostrofu i lewego ukośnika. Ciągi mogą być łączone przy użyciu operatora kropki (.). Dokładniej jest to opisane w części rozdziału na temat operatorów. Podobnie jak w języku C, mamy dostęp do poszczególnych znaków ciągu, traktując go jak tablicę znaków.
Wydruk 2.5. Przykład operacji na ciągach
" );
$aStr2 = "Thatcher";
print( "$aStr2 " );
$aStr3 = "Nazywam się $aStr2";
// $aStr3 = "Nazywam się Thatcher"
print( "$aStr3 " );
$aStr4 = "Nazywam się \$aStr2";
// $aStr4 = "Nazywam się $aStr2"
print( "$aStr4 " );
$aStr5 = 'Nie rozwijaj \'$aStr2\'';
// $aStr5 = "Nie rozwijaj '$aStr2'"
print( "$aStr5 " );
// wypisuje "Nazywam się Thatcher i Nazywam się $aStr2"
print( "$aStr3" . " i " . "$aStr4" );
?>
Z powodu ulotnej natury typów w PHP, zmienne mogą zmieniać swój typ w zależności od kontekstu w jakim występują. Liczby mogą być konwertowane niejawnie na ciągi, jeżeli zostaną użyte jako argument operatora operującego na ciągach. Ciągi mogą również zostać skonwertowane na liczby, jeżeli będą użyte w wyrażeniach matematycznych. Jeżeli PHP próbuje skonwertować ciąg na liczbę, korzysta z następujących zasad:
* Jeżeli ciąg zaczyna się od danych numerycznych, zostaną one skonwertowane na liczbę.
* Jeżeli ciąg nie zaczyna się prawidłowymi danymi liczbowymi, wartością ciągu będzie zero (0).
* Jeżeli dane numeryczne zawierają jeden ze znaków .,e lub E, wartość będzie liczbą zmiennoprzecinkową a w przeciwnym przypadku liczbą całkowitą.
Prawidłowymi danymi numerycznymi są: opcjonalny znak po którym następuje jedna lub więcej cyfr, opcjonalna kropka dziesiętna oraz opcjonalny znak wykładnika. Znakiem wykładnika jest "e" lub "E", po którym następuje jedna lub więcej liczb.
Wydruk 2.6. Niejawna konwersja pomiędzy ciągiem i liczbą
" );
$aVar2 = $aVar . " niejawnie skonwertowane do ciągu";
print( "\$aVar2 = $aVar2, typ = " . gettype( $aVar2 ) . " " );
$aVar3 = $aVar2 + 1; // niejawna konwersja na liczbę całkowitą
print( "\$aVar3 = $aVar3, typ = " . gettype( $aVar3 ) . " " );
$aVar3 = $aVar2 * 1.1; // niejawna konwersja na liczbę zmiennoprzecinkową
print( "\$aVar3 = $aVar3, typ = " . gettype( $aVar3 ) . " " );
$aNotNumber = "abc";
$aVar4 = $aNotNumber * 1; // próba konwersji na liczbę, zwracane jest 0
print( "\$aVar4 = $aVar4, typ = " . gettype( $aVar4 ) . " " );
$aIsNumber = "3 małe świnki";
$aVar5 = $aIsNumber + 1; // konwersja $aIsNumber na liczbę 3
print( "\$aVar5 = $aVar5, typ = " . gettype( $aVar5 ) . " " );
?>
Tablice
Tablice w PHP zachowują się zarówno tak jak tablice indeksowane (wektory) oraz jak tablice mieszające (asocjacyjne). PHP pozwala również na tworzenie tablic wielowymiarowych. Z powodu unikalnej konstrukcji tablic w PHP, można indeksować jeden wymiar tablicy wielowymiarowej liczbami a inny w sposób asocjacyjny.
Tablice mogą być tworzone przy użyciu funkcji list() lub array() albo poprzez jawne podanie każdej z wartości. W skorowidzu funkcji na końcu książki zostały opisane wszystkie funkcje do manipulacji tablicami.
Jednowymiarowe tablice mogą zamieniane w ciągach przez mechanizm zastępowania zmiennych na wartości w sposób identyczny jak wszystkie inne zmienne. W przypadku tablic wielowymiarowych należy użyć nawiasów klamrowych do zaznaczenia indeksów. Poniższy wydruk pokazuje przykłady użycia różnych typów tablic.
Wydruk 2.7. Inicjowanie i użycie tablic
" );
// Tworzenie tablicy asocjacyjnej
$color["niebieski"] = "#0000FF";
$color["zielony"] = "#00FF00";
$color["czerwony"] = "#FF0000";
print( "Wartość szesnastkowa koloru czerwonego wynosi {$color['czerwony']} " );
// Tworzenie tej samej co poprzedniej tablicy asocjacyjnej
// tylko nieco prościej
$color = array( "niebieski" => "#0000FF",
"zielony" => "#00FF00",
"czerwony" => "#FF0000" );
print( "Wartość szesnastkowa koloru zielonego wynosi {$color['zielony']} " );
// Ręczne tworzenie tablicy wielowymiarowej
$m[0][0] = "Zero Zero";
$m[0][1] = "Zero Jeden";
print( "Wartością \$m[0][1] jest {$m[0][1]} " );
// Ręczne tworzenie asocjacyjnej tablicy wielowymiarowej
$counties["Idaho"][0] = "Ada";
$counties["Idaho"][1] = "Adams";
$counties["Idaho"][2] = "Bannock";
$counties["Arizona"][0] = "Apache";
$counties["Arizona"][1] = "Cochise";
$counties["Arizona"][2] = "Coconino";
print( "\$counties['Idaho'][0] = {$counties['Idaho'][0]} " );
?>
Zmienne i stałe
Zmienne PHP są oznaczane znakiem dolara ($), po którym następuje nazwa zmiennej. Wielkość liter w nazwach zmiennych jest rozróżniana. Prawidłowe nazwy zmiennych muszą zaczynać się literą lub znakiem podkreślenia, po których może nastąpić litera, liczba lub znak podkreślenia. Prawidłowymi literami w zmiennych są a-z, A-Z lub dowolne znaki ASCII z zakresu 127-255 (0x7f-0xff).
Wydruk 2.8. Nazwy zmiennych
" ); // wypisuje "Ryan, Scott"
$1variable = 123; // nieprawidłowa nazwa zmiennej
$_test = "test"; // prawidłowo, rozpoczyna się podkreśleniem
$_ąęć = "test2"; // prawidłowo
?>
Wartości mogą być przypisywane do zmiennych przez wartość lub przez referencję. Gdy przypisanie jest realizowane przez wartość, obliczona wartość wyrażenia jest przepisywana do docelowej zmiennej. Po przypisaniu zmienne są niezależne i zmiana wartości w jednej nie wpływa na wartość drugiej zmiennej.
Gdy wartości są przypisywane przez referencję, nowa zmienna staje się odwołaniem do oryginalnej zmiennej. Zmiana wprowadzona do dowolnej zmiennej powoduje zmianę drugiej. Aby wykonać przypisanie przez referencję, należy poprzedzić nazwę znakiem &.
Wydruk 2.9. Przypisywanie zmiennych
" ); // wypisuje "Ryan, Ryan"
$variable2 = "Scott";
print( "$variable1, $variable2 " ); // wypisuje "Ryan, Scott"
$variable3 = &$variable1; // przypisanie przez referencję
print( "$variable1, $variable3 " ); // wypisuje "Ryan, Ryan"
$variable3 = "Katie";
print( "$variable1, $variable3 " ); // wypisuje "Katie, Katie"
?>
Zmienne predefiniowane
Oprócz zmiennych definiowanych przez użytkownika, w PHP istnieją zmienne tworzone przez system. Lista tych zmiennych zależy od kontekstu wykonania skryptu (na przykład, czy jest uruchamiany samodzielnie, czy poprzez serwer WWW), wersji PHP i typu serwera WWW. Ponieważ lista zmiennych jest zależna od wielu czynników, niektóre z nich mogą nie być nigdy dostępne.
PHP generuje również zmienne dla cookie i danych formularzy przesyłanych za pomocą metod GET i POST. Szczegółowe omówienie tych zmiennych zawarte jest w rozdziale 3 "Formularze i cookie".
Część ta zawiera podzbiór dostępnych zmiennych dostępnych w czasie pracy PHP4 wraz z serwerem Apache 1.3.11. Aby zobaczyć wszystkie zmienne dostępne w środowisku można użyć funkcji phpinfo(). Kompletniejsza lista predefiniowanych zmiennych znajduje się w skorowidzu na końcu książki. Tabela 2.2. zawiera podzbiór zmiennych środowiska Apache, tabela 2.3., podzbiór zmiennych środowiska systemu a tabela 2.4. zawiera zmienne generowane przez PHP. W tabeli 2.5. zebrane są operatory arytmetyczne, natomiast operatory bitowe w tabeli 2.6. Tabela 2.7. zawiera operatory porównania, tabela 2.8 operatory zwiększania i zmniejszania a tabela 2.9. zawiera operatory logiczne. Ostatnia tabela, 2.10. zawiera operatory przypisania.
Tabela 2.2. Zmienne środowiska serwera Apache
Zmienna
Definicja
HTTP_HOST
Zawartość nagłówka Host: o ile został wysłany przez przeglądarkę.
HTTP_USER_AGENT
Zawartość nagłówka User Agent: wysłanego przez przeglądarkę. Nagłówek ten opisuje przeglądarkę żądającą strony, na przykład: "Mozilla/4/0 (compatible; MSIE 5.01; Windows NT)". Więcej na temat wykorzystania tej zmiennej znajduje się w rozdziale 9 "Niezależność od przeglądarki".
REMOTE_ADDR
Adres IP użytkownika oglądającego stronę.
SERVER_PROTOCOL
Nazwa i wersja protokołu za pomocą którego zostało wysłane żądanie strony, na przykład HTTP/1.1.
GATEWAY_INTERFACE
Wersja specyfikacji CGI używanej przez serwer, na przykład CGI/1.1.
Tabela 2.3. Zmienne środowiska systemu
Zmienna
Definicja
HOSTNAME
Nazwa komputera serwera.
HOSTTYPE
Typ komputera, na przykład i386.
PATH
Systemowa ścieżka serwera.
OSTYPE
System operacyjny działający na serwerze, na przykład Linux.
Tabela 2.4. Zmienne generowane przez PHP
Zmienna
Definicja
PHP_SELF
Nazwa pliku z wykonywanym skryptem.
HTTP_COOKIE_VARS
Tablica asocjacyjna zmiennych przekazanych do skryptu poprzez cookie HTTP.
HTTP_GET_VARS
Tablica asocjacyjna zmiennych przekazanych do skryptu za pomocą metody GET.
HTTP_POST_VARS
Tablica asocjacyjna zmiennych przekazanych do skryptu za pomocą metody POST.
Tabela 2.5. Operatory arytmetyczne
Operator
Nazwa
Przykład
Wynik
+
Dodawanie
$a + $b
Suma $a i $b
-
Odejmowanie
$a - $b
Różnica $a i $b
*
Mnożenie
$a * $b
Iloczyn $a i $b
/
Dzielenie
$a / $b
Iloraz $a i $b
%
Reszta z dzielenia
$a % $b
Reszta z dzielenie $a przez $b
Tabela 2.6. Operatory bitowe
Operator
Nazwa
Przykład
Wynik
&
Iloczyn bitowy
$a & $b
Bity ustawione w $a i $b są ustawione
|
Suma bitowa
$a | $b
Bity ustawione w $a lub $b są ustawione
^
Różnica symetryczna
$a ^ $b
Bity ustawione w $a lub $b, ale nie w obu na raz są ustawione
~
Negacja
~$a
Bity ustawione nie są teraz ustawione i odwrotnie
<<
Przesunięcie w lewo
$a << $b
Przesunięcie bitów w $a w lewo o $b kroków
>>
Przesunięcie w prawo
$a >> $b
Przesunięcie bitów w $a w prawo o $b kroków
Tabela 2.7. Operatory porównania
Operator
Nazwa
Przykład
Wynik
==
Równy
$a == $b
True, jeżeli $a jest równe $b
===
Identyczny
$a === $b
True, jeżeli $a jest równe $b i są one tych samych typów
!=
Różny
$a != $b
True, jeżeli $a jest różne od $b
<
Mniejszy
$a < $b
True, jeżeli $a jest mniejsze od $b
>
Większy
$a > $b
True, jeżeli $a jest większe od $b
<=
Mniejszy lub równy
$a <= $b
True, jeżeli $a jest mniejsze lub równe $b
>=
Większy lub równy
$a >= $b
True, jeżeli $a jest większe lub równe $b
Tabela 2.8. Operatory zwiększania i zmniejszania
Operator, przykład
Nazwa
Wynik
$a++
Postinkrementacja
Zwraca $a, a następnie zwiększa $a o jeden
++$a
Preinkrementacja
Zwiększa $a o jeden i zwraca $a
$a--
Postdekrementacja
Zwraca $a, a następnie zmniejsza $a o jeden
--$a
Predekrementacja
Zmniejsza $a o jeden i zwraca $a
Tabela 2.9. Operatory logiczne
Operator
Nazwa
Przykład
Wynik
and
Iloczyn logiczny
$a and $b
True, jeżeli $a i $b mają wartość True
or
Suma logiczna
$a or $b
True, jeżeli $a lub $b mają wartość True
xor
Różnica symetryczna
$a xor $b
True, jeżeli $a lub $b mają wartość True, ale nie razem
!
Negacja
!$a
True, jeżeli $a nie jest True
&&
Iloczyn logiczny
$a && $b
True, jeżeli $a i $b mają wartość True
||
Suma logiczna
$a || $b
True, jeżeli $a lub $b mają wartość True
Tabela 2.10. Operatory przypisania
Operator
Przykład
Wynik
=
$a = $b
Przypisuje wartość $b do $a.
+=
$a += $b
Przypisuje wartość ($a+$b) do $a. Jest to identyczne z $a=$a+$b.
-=
$a -= $b
Przypisuje wartość ($a-$b) do $a. Jest to identyczne z $a=$a-$b.
*=
$a *= $b
Przypisuje wartość ($a*$b) do $a. Jest to identyczne z $a=$a*$b.
/=
$a /= $b
Przypisuje wartość ($a/$b) do $a. Jest to identyczne z $a=$a/$b.
.=
$a .= $b
Przypisuje wartość ($a.$b) do $a. Jest to identyczne z $a=$a.$b.
%=
$a %= $b
Przypisuje wartość ($a%$b) do $a. Jest to identyczne z $a=$a%$b.
|=
$a |= $b
Przypisuje wartość ($a|$b) do $a. Jest to identyczne z $a=$a|$b.
&=
$a &= $b
Przypisuje wartość ($a&$b) do $a. Jest to identyczne z $a=$a&$b.
^=
$a ^= $b
Przypisuje wartość ($a^$b) do $a. Jest to identyczne z $a=$a^$b.
<<=
$a <<= $b
Przypisuje wartość ($a<<$b) do $a. Jest to identyczne z $a=$a<<$b.
>>=
$a >>= $b
Przypisuje wartość ($a>>$b) do $a. Jest to identyczne z $a=$a>>$b.
Zasięg zmiennych
Ogólnie rzecz ujmując, zmienne globalne PHP mają taki sam zasięg. Rozciąga się on również na pliki dołączane. Wewnątrz funkcji definiowanych przez użytkownika zmienne mają zasięg lokalny. Zmienne globalne muszą być deklarowane jako globalne, aby mogły być wykorzystywane wewnątrz funkcji. PHP posiada również zmienne statyczne, które deklarowane wewnątrz funkcji zapewniają utrzymywanie swojej wartości pomiędzy kolejnymi wywołaniami funkcji.
Wydruk 2.10. Zasięg zmiennych
ponieważ zmienna $aGlobal1 wewnątrz funkcji
jest poza zasięgiem.
*/
print( "$aGlobal1 " );
}
DoPrint();
function DoPrint2( )
{
global $aGlobal1;
/*
Poniższa instrukcja wypisze wartość zmiennej
ponieważ została zadeklarowana jako globalna.
*/
print( "$aGlobal1 " );
}
DoPrint2();
function StaticFunc( )
{
static $aVal = 0;
print( "$aVal " );
$aVal++;
}
// Poniższe wywołania spowodują wypisanie 0, a następnie 1
StaticFunc();
StaticFunc();
?>
--- Zawartość pliku example10_inc.php3 ---
" );
?>
Stałe
PHP posiada kilka predefiniowanych stałych oraz pozwala na definiowanie własnych. Pełna lista stałych znajduje się w skorowidzu na końcu książki. Aby zdefiniować nową stałą używa się funkcji define(). Zauważ, że stałe PHP nie są makrami w stylu C i dlatego muszą być wartościami skalarnymi.
Wydruk 2.11. Stałe
" );
print( "Jej wartością jest '" . aString . "' " );
?>
Operatory i kolejność operatorów
PHP posiada zestaw operatorów znanych programistom C i C++. W tabelach od 2.5. do 2.10. zamieszczone zostało zestawienie dostępnych operatorów.
Oprócz operatorów umieszczonych w tabelach istnieje jeszcze kilka operatorów, ale są one trudniejsze do klasyfikacji. Operator trójskładnikowy, zapisywany jako ?: jest dostępny zarówno w PHP jak i w C. Wyrażenie $wart = (wyrażenie1) ? (wyrażenie2) : (wyrażenie3); przypisuje do zmiennej $wart wartość wyrażenie2, jeżeli wyrażenie1 będzie miało wartość True, natomiast w przeciwnym przypadku $wart będzie miało wartość wyrażenie3.
Operator wykonania oznaczany przez znak ` (na jednym klawiszu ze znakiem ~) jest podobny do operatora dostępnego we wielu językach programowania powłoki. Wyrażenie otoczone znakami ` jest wykonywane na serwerze a zwracana wartość przekazywana do zmiennej.
PHP posiada również operator kontroli błędów @. Gdy operator ten jest umieszczony przed wyrażeniem, nie są generowane komunikaty błędów powodowanych przez to wyrażenie. Użycie tego operatora pozwala na stworzenie lepszej obsługi błędów, o ile uaktywniona jest opcja track_errors. Gdy opcja ta jest aktywna, komunikaty błędów zatrzymane przez operator @ są zapamiętywane w zmiennej globalnej $php_errormsg. Zmienna ta jest nadpisywana przez kolejne błędy, więc aby kontrola błędów działała poprawnie, zmienna ta powinna być sprawdzana możliwie szybko.
Wydruk 2.12. Niektóre działania z operatorami
" ); // drukuje "Wartości są różne"
$aVal = ( 1 == "1" ) ? "Wartości są równe" :
"Wartości są różne";
print( "$aVal " ); // drukuje "Wartości są równe"
$aVal = ( 1 === "1" ) ? "Wartości są identyczne" :
"Wartości nie są identyczne";
print( "$aVal " ); // prints "Wartości nie są identyczne"
/*
Poniższy fragment powoduje przypisanie do $aListing
zawartości bieżącego katalogu serwera,
a następnie konwersję znaków nowej linii
na znaczniki I wypisanie wyników
*/
$aListing = `ls -l`;
$aFmtList = nl2br( $aListing );
print( " Zawartość katalogu: $aFmtList " );
?>
Programowanie przepływu sterowania
PHP posiada standardowe instrukcje programowania przepływu sterowania takie jak if oraz pętle while i for. Programiści C nie będą mieli kłopotu ze składnią tych instrukcji. Dodatkowo PHP posiada dwie funkcje dołączania plików z kodem źródłowym: include() i require().
if, else, elseif
Jest to oczywiście najważniejszy element języka. Instrukcja if organizuje przepływ sterowania poprzez tworzenie rozgałęzień na podstawie wyrażeń logicznych.
Wydruk 2.13. Przykład użycia if, else i elseif
" );
else
print( "To nie zostanie wydrukowane. " );
$aValue = 2;
if ( $aValue == 1 )
{
// Używamy nawiasów klamrowych do otaczania bloków instrukcji
print( "\$aValue == 1 " );
}
elseif ( $aValue == 2 )
{
print( "\$aValue == 2 " );
}
elseif ( $aValue == 3 )
{
print( "\$aValue == 3 " );
}
else
{
print( "\$aValue nie jest 1, 2 ani 3 " );
}
?>
while
Jest to najprostszy typ pętli w PHP, która zachowuje się identycznie jak w C i innych językach wysokiego poziomu.
do .. while
Mimo, że jest to pętla podobna do while, to w pętli do..while warunek pętli jest sprawdzany po pierwszym przebiegu pętli. Gwarantuje to, że ciało pętli zostanie wykonane co najmniej raz.
Wydruk 2.14. Przykład użycia while i do..while
while. " );
$nIndex = 0;
// wypisuje liczby od 0 do 9
while ( $nIndex < 10 )
{
print( "$nIndex " );
$nIndex++;
}
print( "Liczenie w dół przy użyciu do..while. " );
// wypisuje liczby od 10 do 1
do
{
print( "$nIndex " );
$nIndex--;
} while ( $nIndex > 0 );
?>
for
Pętla for jest najbardziej złożoną instrukcją pętli w PHP, ale jest ona składniowo identyczna z instrukcją for w języku C. Jej składnia jest następująca:
for (wyr1; wyr2; wyr3) instrukcja
Wartość pierwszego wyrażenia (wyr1) jest obliczana raz, na początku pętli. Wartość drugiego (wyr2) jest obliczana na początku każdego przebiegu pętli. Jeżeli będzie ono miało wartość True, pętla będzie się nadal wykonywała i zostaną wykonane instrukcje ciała pętli. Jeżeli drugie wyrażenie jest puste, przyjmowane jest, że ma ono wartość True. Na końcu każdego przebiegu pętli wykonywane jest trzecie wyrażenie (wyr3). Każde z tych trzech wyrażeń może być puste.
Wydruk 2.15. Przykład użycia for
" );
}
/*
$nIndex ma wartość 10. Pokażemy teraz, że
każde z trzech wyrażeń może zostać opuszczone.
Nie jest to zalecane ze względu na czytelność kodu.
Pętla powoduje wypisanie liczb od 10 do 1
*/
for ( ; $nIndex > 0; $nIndex-- )
{
print( "$nIndex " );
}
?>
foreach
Wyrażenie foreach jest wygodnym sposobem na przeglądanie tablic. Podobne konstrukcje znajdują się w VBScript, Perl i innych językach. PHP posiada dwa warianty składni:
foreach ( tablica as zmienna_wartosc) instrukcja
foreach ( tablica as zmienna_klucz => zmienna_wartosc) instrukcja
Pierwsza postać pętli przebiega po podanej tablicy i w każdym przebiegu wartość bieżącego elementu tablicy jest przypisywana do zmiennej (zmienna_wartosc) a wskaźnik bieżącego elementu tablicy jest przesuwany. Druga postać realizuje to samo, ale dodatkowo do zmiennej (zmienna_klucz) jest przypisywany klucz bieżącej pozycji.
Wydruk 2.16. Przykład użycia foreach
" );
}
$aColorArray = array( "Czerwony" => "#FF0000",
"Zielony" => "#00FF00",
"Niebieski" => "#0000FF" );
foreach( $aColorArray as $aKey => $aValue )
{
print( "Wartość szesnastkowa $aKey to $aValue " );
}
?>
switch
Instrukcja switch upraszcza tworzenie wielokrotnych warunków. Jest ona często używana zamiast skomplikowanych konstrukcji if...elseif...else zawierających wiele wystąpień elseif. Składnia i implementacja tej instrukcji jest identyczna jak w C. Korzystnym ulepszeniem w PHP jest możliwość używania ciągów jako wyrażeń instrukcji switch.
Programiści Delphi i Pascala mają zwykle kłopoty z zapamiętaniem, że w konstrukcji switch w C występują instrukcje break. Czasami opuszczenie tej instrukcji jest wygodne. Poniższy przykład ilustruje częste zastosowania instrukcji switch.
Wydruk 2.17. Przykłady użycia switch
" );
break;
case 1:
print( "jeden " );
break;
case 2:
print( "dwa " );
break;
}
// Użycie frazy 'default'
$nIndex = 17;
switch ( $nIndex )
{
case 0:
print( "zero " );
break;
case 1:
print( "jeden " );
break;
case 2:
print( "dwa " );
break;
default:
print( "Nie jest to zero, jeden ani dwa " );
break;
}
// Switch z użyciem ciągu
$aColor = "niebieski";
switch( $aColor )
{
case "czerwony":
print( "#FF0000 " );
break;
case "zielony":
print( "#00FF00 " );
break;
case "niebieski":
print( "#0000FF " );
break;
default:
print( "inny " );
break;
}
/*
Opuszczenie instrukcji break spowoduje
wykonanie wszystkich wyrażeń po pasującej pozycji.
Jeżeli $nIndex jest 0, zostaną wykonane wszystkie
trzy instrukcje print. Jeżeli $nIndex jest 1, wykonane zostaną
ostatnie dwie instrukcje print.
*/
$nIndex = 0;
switch ( $nIndex )
{
case 0:
print( "zero " );
case 1:
print( "jeden " );
case 2:
print( "dwa " );
}
/*
opuszczenie instrukcji break może być czasami przydatne
*/
$aColor = "Czerwony";
switch( $aColor )
{
case "czerwony":
case "Czerwony":
// Poniższa instrukcja zostanie wykonana, jeżeli $aColor
// będzie miał wartość "Czerwony" lub "czerwony"
print( "#FF0000 " );
break;
case "zielony":
case "Zielony":
print( "#00FF00 " );
break;
case "niebieski":
case "Niebieski":
print( "#0000FF " );
break;
default:
print( "inny " );
break;
}
?>
break i continue
PHP posiada również znane z C instrukcje break i continue, które pozwalają na dodatkowe sterowanie pętlami. Obie te instrukcje pozwalają na podanie im parametru numerycznego, który określa ilość zagłębionych pętli, które należy przerwać lub rozpocząć od początku.
Wyrażenie break kończy wykonanie bieżącej konstrukcji sterującej (pętli lub wyrażenia switch). Wyrażenie continue jest używane jedynie w pętlach. Powoduje ono opuszczenie pozostałych instrukcji ciała pętli i rozpoczęcie nowej iteracji.
Najczęściej instrukcje break i continue są stosowane w zagnieżdżonych pętlach. W przypadku pętli prostych, wyrażenia warunkowe są wystarczające do realizacji tych zadań.
Wydruk 2.18. Przykłady użycia break i continue
$aCurMax )
{
$aCurMax = $aValue;
break; // możemy napisać 'break 1;'
}
}
// wypisuje "Bieżącym maksimum jest 20"
print( " Bieżącym maksimum jest $aCurMax " );
// wypisuje liczby nieparzyste od 0 do 20
$nIndex = 0;
for ( $nIndex = 0; $nIndex < 20; $nIndex++ )
{
if ( ( $nIndex % 2 ) == 0 )
continue; // opcjonalnie 'continue 1;'
print( "$nIndex " );
}
?>
PHP osiada alternatywną składnię dla konstrukcji sterujących if, while, for i switch. W każdej z tych konstrukcji otwierająca klamra jest zamieniona na dwukropek (:) a zamykająca klamra na odpowiednio endif, endwhile, endfor i endswitch. Gdy tworzysz duże skrypty wbudowane w HTML, składnia alternatywna może być użyteczna, ponieważ zapewnia wyraźną identyfikację końca struktur sterujących.
Wydruk 2.19. Przykład użycia alternatywnej składni PHP na stronie HTML
Przykład 19
include i require
PHP posiada dwa mechanizmy dołączania plików zewnętrznych: include() i require(). Wyrażenie include() jest zwykłą funkcją PHP, natomiast require() jest konstrukcją językową, która posiada kilka ograniczeń. W obu przypadkach po dołączeniu pliku PHP przechodzi do trybu HTML na początku dołączanego pliku. Na końcu pliku analizator wraca do trybu PHP. Oznacza to, że dowolny kod zawarty w pliku dołączanym musi być otoczony prawidłowymi znacznikami PHP.
Funkcja include() jest wykonywana za każdym jej wywołaniem i może znajdować się wewnątrz pętli lub instrukcji warunkowych. Pozwala to warunkowo włączać pliki, lub włączać grupy plików przy pomocy odpowiednio skonstruowanej pętli. Funkcja include() pozwala również, aby dołączany plik zwracał wartość, którą można następnie przypisać do zmiennej. Przetwarzanie pliku w instrukcji include() kończy się, gdy zostanie napotkana instrukcja return.
Wyrażenie require() różni się tym od include(), że nie wchodzi w skład konstrukcji sterujących. Oznacza to, że pliki nie mogą być warunkowo dołączane za pomocą require(). Wyrażenie to jest wykonywane raz, jeżeli znajduje się w pętli lub nawet, jeżeli znajduje się w instrukcji warunkowej, której warunek ma wartość False. Inną różnicą jest to, że pliki dołączane za pomocą require() nie mogą zwracać wartości. Próba zwrócenia wartości w wyrażeniu require() powoduje błąd składni.
Funkcje
PHP pozwala na tworzenie funkcji definiowanych przez użytkownika. Funkcje nie muszą być deklarowane przed ich użyciem w kodzie PHP4. Funkcje w PHP mogą posiadać następujące cechy: zmienne nazwy funkcji, zmienna liczba argumentów, argumenty domyślne i argumenty przekazywane przez referencję. PHP pozwala na wykonywanie dowolnego kodu w ciele funkcji, włączając w to wywołania innych funkcji. Zdolność ta pozwala również na tworzenie funkcji rekurencyjnych. PHP nie pozwala na przeciążanie funkcji, nie ma również mechanizmu usuwania lub przedefiniowania wcześniej zdefiniowanych funkcji.
Domyślnie argumenty są przekazywane przez wartość. Aby przekazać argument przez referencję, należy poprzedzić nazwę zmiennej znakiem &. Używając argumentów domyślnych, muszą być one umieszczone po wszystkich argumentach obowiązkowych. W przypadku zmiennej listy argumentów, dostępne są funkcje func_num_args(), func_get_arg() i func_get_args(), za pomocą których można pobrać dane przekazane jako argumenty. Poniższe przykłady pokazują użycie funkcji w PHP.
Wydruk 2.20. Przykłady funkcji definiowanych przez użytkownika
$aText" );
}
else
{
print( "$aText" );
}
}
// zmienna lista argumentów
function PrintEverything( )
{
$aNumArgs = func_num_args();
for ( $nIndex = 0; $nIndex < $aNumArgs; $nIndex++ )
{
$aArgVal = func_get_arg( $nIndex );
print( "Argument $nIndex: $aArgVal " );
}
}
print( "ReturnSum( 3, 5 ): " . ReturnSum( 3, 5 ) . " " );
$aString = "Marysia miała ";
StringAppend( $aString, "małą owieczkę" );
print( "$aString " ); // wypisuje "Marysia miała małą owieczkę"
PrintAnchorTag( "example10.phtml",
"Zobaczmy jeszcze raz przykład 10" );
print( " " );
PrintAnchorTag( "example10.phtml",
"Zobaczmy jeszcze raz przykład 10 w nowym oknie",
"_blank" );
print( " " );
print( "Wywołanie PrintEverything( 1, 2, 3, 4, 5 ): " );
PrintEverything( 1, 2, 3, 4, 5 );
?>
Klasy i programowanie obiektowe
PHP posiada zdolność tworzenia klas za pomocą składni podobnej jak w C++. PHP posiada również bardzo prostą implementację programowania obiektowego, która jest jednak wystarczająca dla większości aplikacji WWW. Dostępne jest dziedziczenie jednobazowe, nie ma dziedziczenia wielobazowego. Istnieją konstruktory klas, ale nie ma destruktorów. PHP posiada (i wymaga używania) wskaźnik $this, który jest stosowany do odwoływania się do metod i zmiennych obiektu. Poniższy przykład pokazuje tworzenie prostej klasy. Więcej przykładów na ten temat znajdzie się w późniejszych rozdziałach książki.
Wydruk 2.21. Przykłady użycia klas w PHP
fCurValue = $aInitialValue;
}
// Dodanie określonej ilości przedmiotów
function AddItem( $aName, $aValue, $aQuantity = 1 )
{
$this->fItems[$aName]["Quantity"] += $aQuantity;
$this->fItems[$aName]["Value"] = $aValue;
$this->fCurValue += $aValue * $aQuantity;
return True;
}
function RemoveItem( $aName, $aQuantity = 1 )
{
// Usuwamy określoną ilość przedmiotów
// jedynie, gdy była dostępna wystarczająca ich ilość
if ( $this->fItems[$aName]["Quantity"] > $aQuantity )
{
$this->fItems[$aName]["Quantity"] -= $aQuantity;
$this->fCurValue -= $this->fItems[$aName]["Value"] *
$aQuantity;
}
else
{
return False;
}
}
function PrintBasket( )
{
if ( count( $this->fItems ) > 0 )
{
print( "Zawartość koszyka:
" );
}
}
}
/*
Tworzenie nowego obiektu ShoppingBasket. Dodanie kilku przedmiotów
usunięcie kilku przedmiotów i wypisanie zawartości koszyka
*/
$aBasket = new ShoppingBasket( 3.50 );
$aBasket->PrintBasket();
$aBasket->AddItem( "gizmo", 1.50 ); // dodanie 1 gizmo
$aBasket->PrintBasket();
$aBasket->AddItem( "foobar", 2.10, 6 ); // dodanie 6 foobarów
$aBasket->PrintBasket();
$aBasket->RemoveItem( "foobar", 15 );
$aBasket->PrintBasket();
$aBasket->RemoveItem( "foobar", 3 );
$aBasket->PrintBasket();
?>
Porównywanie wzorców
PHP posiada dwa typy funkcji do porównywania wzorców (lub wyrażeń regularnych). Pierwszy typ jest zgodny ze specyfikacją POSIX i są to funkcje ereg(), eregi(), ereg_replace(), eregi_replace() oraz split(). Każda z tych funkcji jako pierwszego argumentu wymaga wyrażenia regularnego. PHP korzysta z rozszerzonych wyrażeń regularnych zdefiniowanych przez POSIX 1003.2. PHP zawiera w katalogu regex strony podręcznika, które w pełni opisują wyrażenia regularne POSIX.
Drugi typ funkcji porównywania wzorców jest zgodny z wyrażeniami regularnymi Perl. Nazwy tych funkcji są poprzedzone ciągiem preg_. Pełna lista tych funkcji znajduje się w skorowidzu na końcu książki. Składnia tych wyrażeń jest taka sama jak w Perl 5 z kilkoma różnicami. Bieżąca implementacja tych funkcji odpowiada Perl 5.005. Różnica pomiędzy implementacją w Perl 5.005 i w PHP jest dokładnie opisana w dokumentacji PHP dostępnej z witryny http://www.php.net.
Podsumowanie
Rozdział ten jest zwięzłym opisem języka PHP i nie zawiera szczegółowo opisanych podstaw programowania. Dlatego nie zawiera on dyskusji na temat tego kiedy lub dlaczego należy używać określonych konstrukcji. Zamieszczone zostały za to przykłady ilustrujące składnię i dostępne funkcje. PHP zawiera wszystkie własności potrzebne do tworzenia złożonych i łatwych do zarządzania aplikacji WWW. Język jest wystarczająco sprawny do realizacji większości zadań, ale jest przygotowany do tworzenia aplikacji dla WWW, co zostanie pokazane w kolejnych rozdziałach.
Rozdział 3. Formularze i cookie
Wstęp
W czasie tworzenia dowolnego typu aplikacji utworzenie dobrego mechanizmu interakcji z użytkownikiem jest jednym z najważniejszych zadań programisty. HTML posiada elementy formularzy, które są używane do zbierania danych od użytkownika, natomiast PHP zapewnia prosty mechanizm przetwarzania tych formularzy. Ponieważ PHP został zaprojektowany jako język programowania dla WWW, obsługuje on automatycznie wiele szczegółów przetwarzania formularzy. Rozdział ten zawiera informacje nie tylko na temat sposobu użycia formularzy HTML w PHP, ale również na temat kontroli poprawności i przetwarzania danych formularza. Dla programistów, którzy przechodzą od pisania zwykłych aplikacji do tworzenia aplikacji WWW przeznaczona jest część zatytułowana "Ważne zagadnienia programowania dla WWW", która sygnalizuje niektóre problemy jakie powstają gdy jako urządzenie wyjściowe używana jest przeglądarka WWW. W rozdziale tym znajduje się również omówienie mechanizmu cookie, ponieważ jest ono składniowo podobne do obsługi elementów formularzy. Cookie mogą również pomóc w zrealizowaniu mechanizmu utrzymywania stanu, który jest zwykle potrzebny w czasie dialogu z użytkownikiem.
Konwencje nazw plików
We wszystkich przykładach oraz w mojej aktualnej pracy do oznaczania skryptów PHP które generują strony HTML używam rozszerzenia .phtml oraz rozszerzeń .php lub .php3 do plików dołączanych. Nie używam najczęściej używanych rozszerzeń .php i .php3 do stron wyświetlających dane jedynie dlatego, że uważam że rozszerzenie .phtml lepiej wygląda. Jest to jedyny powód. Do plików dołączanych używam innego rozszerzenia i chcemy zaznaczyć, że jest to kod PHP. Nie używam typowego rozszerzenia inc.
Możesz używać dowolnego rozszerzenia dla skryptów PHP. Wszystkie rozszerzenia jakich używasz do skryptów PHP i plików dołączanych powinny zostać dołączone do konfiguracji serwera WWW. Rozszerzenia te konfiguruje się używając opcji konfiguracji, które zostały opisane w rozdziale 1, "Kompilacja i instalowanie PHP". Na przykład, jeżeli używasz rozszerzeń php i inc do oznaczania skryptów PHP i plików dołączanych, powinieneś się upewnić, że serwer WWW został tak skonfigurowany, że będzie traktował oba te rozszerzenia jako pliki PHP i przetwarzał je przed wysłaniem do przeglądarki użytkownika. Jeżeli nie zrobisz tego, użytkownik może zapisać twoje skrypty. Rozważmy następujący przykład:
Przykład: błędny plik dołączany otwiera dziurę
w systemie zabezpieczeń
" );
?>
W przykładzie tym do głównego pliku, securityhole.phtml, dołączany jest plik bogus.inc. Dołączany plik zawiera dane na temat połączenia z bazą danych, w tym nazwę użytkownika i hasło. Zawiera on również błąd syntaktyczny. Gdy otwarty zostanie plik securityhole.phtml, wyświetlony zostanie błąd: "Parse error: parse error in bogus.inc on line 12".
Dociekliwy użytkownik może spróbować obejrzeć plik bogus.inc wpisując odpowiedni URL w pasku adresu. Jeżeli serwer WWW jest skonfigurowany taj aby traktować pliki .inc jako tekst (tak jak mój), cały tekst pliku pojawi się w przeglądarce. Jeżeli serwer WWW jest tak skonfigurowany, aby traktować pliki .inc jak każdy inny skrypt PHP, użytkownik zobaczy jedynie wcześniej wspomniany komunikat błędu.
Podsumowując. W trakcie tworzenia aplikacji PHP możesz użyć dowolnego rozszerzenia, ale aby uniknąć potencjalnego zagrożenia bezpieczeństwa należy tak skonfigurować serwer WWW, aby analizował wszystkie pliki posiadające używane przez ciebie rozszerzenia.
Obsługa formularzy w PHP
Do pobierania danych od użytkownika w HTML stosuje się formularze. W domyślnej konfiguracji PHP po przesłaniu danych formularza do skryptu PHP, konwertuje wszystkie elementy formularza na zmienne PHP. Poniższa strona HTML zawiera prosty formularz, do którego należy wpisać nazwę użytkownika i jego hasło. Po przesłaniu formularza do skryptu post1.phtml, zmienne $UserName i $Password będą zawierały wartości wpisane jako nazwę użytkownika i hasło.
Wydruk 3.1. Strona HTML i skrypt PHP ilustrujące procedurę logowania się użytkownika.
Wydruk 3.1 - listing1.htmlWydruk 3.1: post1.phtml
" );
print( "Hasło: $Password " );
?>
Skalarne i wielowartościowe elementy formularza
Elementy formularzy HTML zawierają zwykle wartości skalarne. Zamieszczony na wydruku 1 przykład zawiera formularz z dwoma wartościami skalarnymi - nazwą użytkownika i hasłem. Można również tworzyć elementy formularza zawierające wiele wartości, na przykład listę wielokrotnego wyboru. Aby użyć nieskalarnych elementów formularza w PHP, należy dodać do nazwy nawiasy kwadratowe oznaczające zmienną tablicową. Formularz na wydruku 2 pokazuje takie wielowartościowe elementy formularza.
Wydruk 3.2. Formularz HTML z elementami wielowartościowymi
Po przesłaniu danych formularza z wydruku 2 do skryptu PHP, każda z tablic $Colors[] i $adress[] będzie zawierać zero lub więcej wartości.
Alternatywne metody odczytywania wartości z formularza
PHP posiada alternatywną metodę dostępu do danych przesłanych do skryptu. Predefiniowane zmienne tablicowe HTTP_GET_VARS i HTTP_POST_VARS zawierają tablice asocjacyjne elementów przesłanych do skryptu przy pomocy metod odpowiednio GET i POST. Skrypt wyświetlający dane z wydruku 1 może zostać przepisany w następujący sposób:
Wydruk: post2.phtml
" );
print( "Hasło: {$HTTP_POST_VARS['Password']} " );
?>
W niektórych przypadkach preferowane jest użycie zmiennych HTTP_GET_VARS lub HTTP_POST_VARS zamiast korzystania ze zmiennych globalnych. Na przykład możesz chcieć wyświetlić w czasie uruchamiania skryptu wartości wszystkich danych wysłanych z formularza. Jeżeli bardzo przejmujesz się wydajnością serwera WWW, można tu nieco zyskać, ponieważ PHP nie będzie musiał tworzyć zmiennych globalnych dla każdego z elementów formularza. Można więc tak skonfigurować PHP, aby nie udostępniał tych zmiennych globalnych i tak pisać skrypty, aby korzystały z wartości zawartych w tablicach HTTP_GET_VARS i HTTP_POST_VARS. Więcej na temat tej dyrektywy konfiguracji napisane zostało na końcu książki przy opisie opcji konfiguracji register_globals.
Poniższa funkcja demonstruje użycie tablic HTTP_GET_VARS i HTTP_POST_VARS do wyświetlenia wszystkich danych przekazanych z formularza do skryptu:
function DisplayGetVars()
{
global $HTTP_GET_VARS;
DisplayArray( $HTTP_GET_VARS );
}
function DisplayPostVars()
{
global $HTTP_POST_VARS;
DisplayArray( $HTTP_POST_VARS );
}
Obie z tych funkcji opierają się o funkcję DisplayArray przedstawioną na wydruku 3.3. Jest to prosta funkcja wyświetlająca wszystkie elementy tablicy w tablicy HTML. Obsługuje ona rekurencyjnie elementy tablicy, które same są tablicami.
Wydruk 3.3. Funkcja DisplayArray
function DisplayArray( $aArray )
{
// Upewniamy się, czy $aArray jest na pewno tablicą
if ( is_array ($aArray ) && (count( $aArray ) > 0 ))
{
// Rozpoczęcie tabeli
print ("
");
// Wyświetlenie nagłówka tabeli
print ( "
Klucz
Wartość
");
// Wyświetlenie wszystkich par klucz/wartość z tabeli
foreach( $aArray as $aKey => $aValue )
{
print( "
" );
// Jeżeli bieżąca wartość jest tablicą
// wywołujemy rekurencyjnie funkcję
// w przeciwnym wypadku wyświetlamy wartość
if (!is_array( $aValue ))
{
// jeżeli wartość jest pusta, poinformujmy o tym
if (empty( $aValue ))
{
print( "
$aKey
pusty
");
}
else
{
print( "
$aKey
$aValue
");
}
}
else
{
print( "
$aKey(array)
");
DisplayArray( $aValue );
print ("
" );
}
print ("
");
}
print ("
");
}
else
{
print("pusty lub nieprawidłowy");
}
}
Używając tej funkcji można pisać własne skrypty PHP wyświetlające wartości wszystkich przesłanych elementów formularza. Poniższy skrypt, displayall.phtml powoduje wyświetlenie wszystkich danych przesłanych przez HTTP GET, HTTP POST i cookie odesłane przez przeglądarkę (cookie zostaną omówione w dalszej części tego rozdziału).
Wydruk 3.4. Skrypt displayall.phtml.
Wyświetlenie wszystkich elementów formularza
Cała zawartość HTTP_GET_VARS
Cała zawartość HTTP_POST_VARS
Cała zawartość HTTP_COOKIE_VARS
Na rysunkach 3.1. i 3.2. korzystając z formularza z wydruku 2. przedstawiono formularz wprowadzania danych i wyniki wysłania danych do skryptu displayall.phtml. Zauważmy, że na rysunku 3.2, tablica HTTP_POST_VARS zawiera trzy elementy: Colors, Address i Submit. Wartości dwóch pierwszych elementów są, jak się tego można było spodziewać, tablicami. Wartością elementu Submit jest napis umieszczony na przycisku. Pisząc skrypt obsługujący te wartości należy pamiętać, że element Submit jest zawsze umieszczany w tablicy HTTP_POST_VARS.
Rysunek 3.1. Przykład wielowartościowych elementów formularza
Rysunek 3.2. Wynik przesłania formularza wielowartościowego do displayall.phtml
Użycie formularzy do przesyłania plików
Większość nowoczesnych przeglądarek posiada zdolność przesyłania plików z dysku komputera użytkownika na serwer WWW. PHP posiada obsługę przesyłania plików wbudowaną bezpośrednio w język. Jest ona dokładniej opisana w rozdziale 5 "Wysyłanie plików przez formularz".
Użycie rysunku jako przycisku wysłania danych
Jeżeli projekt aplikacji WWW tak przewiduje, możesz użyć rysunku w miejsce przycisku HTML wysyłającego dane formularza do serwera. Dla PHP nie ma znaczenia, czy jest to przycisk czy rysunek, ale jeżeli używasz rysunku oprócz danych do serwera zostaną wysłane dodatkowo współrzędne x i y (względem lewego górnego rogu rysunku) punktu gdzie został kliknięty rysunek. Nazwy zmiennych przechowujących współrzędne są tworzone poprzez dodanie _x i _y do nazwy elementu reprezentującego rysunek. Na przykład na wydruku 5 nazwą elementu rysunku jest SubmitImg. Zmienne reprezentujące współrzędne będą się nazywały SubmitImg_x i SubmitImg_y. Mechanizm ten jest wygodny do tworzenia map obrazów po stronie serwera.
Wydruk 3.5. Przykład użycia rysunku w formularzu
Użycie rysunku zamiast przycisku
Niektóre przeglądarki posiadają mechanizm pozwalający wykorzystać klawisz Enter zamiast klikania w przycisk na formularzu. Gdy użyjemy rysunku zamiast przycisku, mechanizm ten nadal będzie działał, ale nie zostaną wtedy przesłane dane na temat współrzędnych.
Kontrola poprawności danych formularza
Część ta jest poświęcona kontroli poprawności danych formularza przez mechanizmy umieszczone na serwerze a nie na komputerze klienta. Języki skryptowe działające na kliencie, takie jak JavaScript mogą być wykorzystywane do kontroli poprawności elementów formularza przez wysłaniem ich do serwera. Kontrola taka jest zalecana w przypadku tworzenia wysoce interaktywnych aplikacji WWW, ale nie jest ona całkowicie pewna, ponieważ może być niedostępna w wielu przeglądarkach i systemach operacyjnych. Dlatego dane muszą być kontrolowane na serwerze nawet, jeżeli były one już kontrolowane na komputerze klienta. PHP pozwala na stosowanie kilku metod kontroli poprawności danych, wykorzystując wyrażenia regularne, kontrolę typów danych lub przeszukiwanie słowników w bazie danych.
Kontrola danych za pomocą wyrażeń regularnych
Prawdopodobnie najskuteczniejszym mechanizmem kontroli danych jest użycie wyrażeń regularnych i funkcji wyrażeń regularnych w PHP. Wyrażenia te są potężnym narzędziem, ale jeżeli wcześniej nie miałeś z nimi doświadczenia, są dość skomplikowane w użyciu.
PHP obsługuje dwa rodzaje wyrażeń regularnych - w stylu POSIX i Perl. Skupimy się tutaj na wyrażeniach w stylu POSIX, ale wyrażenia w stylu Perl dają podobne możliwości. Nazwy funkcji wyrażeń w stylu Perl są poprzedzone przedrostkiem preg_ i są opisane w skorowidzu na końcu tej książki. Ponieważ lepiej znam wyrażenia regularne w stylu POSIX, są one używane we wszystkich przytoczonych tu przykładach, ale należy pamiętać, że funkcje wyrażeń w stylu Perl są szybsze i mają większe możliwości.
Funkcje wyrażeń regularnych w stylu POSIX to: ereg(), ereg_replace(), eregi(), eregi_replace() oraz split(). Do kontroli poprawności używa się funkcji ereg() i eregi(). Ogólna składnia tych funkcji jest następująca:
int ereg( string wzorzec, string ciag [, array dopasowanie] )
int eregi( string wzorzec, string ciag [, array dopasowanie] )
Obie funkcje wymagają wzorca wyrażenia regularnego, ciągu do przeszukania oraz opcjonalnej tablicy, która będzie zawierać dopasowania wzorca odnalezione w przeszukiwanym ciągu. Każda funkcja zwraca true, jeżeli wzorzec został odnaleziony w ciągu. Funkcja eregi() jest identyczna z ereg() poza tym, że przy przeszukiwaniu ignoruje ona wielkość liter.
Unikanie kontroli poprawności
Chociaż kontrola poprawności jest ważna, jeżeli nie musisz czegoś kontrolować, to nie rób tego. Zamiast tego można zastosować takie mechanizmy wprowadzania danych, które zmniejszają szansę pomyłki użytkownika. Na przykład zastosowanie listy rozwijalnej z miesiącami jest mniej pracochłonne niż kontrola poprawności wpisanych nazw. Zamiast wszędzie korzystać ze zwykłych pól tekstowych należy znaleźć miejsca, gdzie można zastosować listę, pole wyboru lub przyciski opcji.
Poniższy przykład pokazuje zastosowanie wyrażeń regularnych do kontroli poprawności amerykańskiego kodu pocztowego oraz dat w formacie ISO (YYYY-MM-DD). Zauważ, że w przykładach tych jest sprawdzany jedynie format a nie wartości.
Wydruk 3.6. Kontrola poprawności kodu pocztowego i daty ISO
Kontrola poprawności amerykańskiego kodu pocztowego i daty ISO
" );
else
print( "'$aCode1' nie jest poprawnym kodem pocztowym " );
if ( ereg( $aCodeFormat, $aCode2 ) == True )
print( "'$aCode2' jest poprawnym kodem pocztowym " );
else
print( "'$aCode2' nie jest poprawnym kodem pocztowym " );
if ( ereg( $aCodeFormat, $aCode3 ) == True )
print( "'$aCode3' jest poprawnym kodem pocztowym " );
else
print( "'$aCode3' nie jest poprawnym kodem pocztowym " );
if ( ereg( $aCodeFormat, $aCode4 ) == True )
print( "'$aCode4' jest poprawnym kodem pocztowym " );
else
print( "'$aCode4' nie jest poprawnym kodem pocztowym " );
$aDate1 = "2000-06-29";
$aDate2 = "2000-7-4";
$aDate3 = "June 29, 2000";
$aDate4 = "0000-99-99";
$aDateFormat = "[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}";
if ( ereg( $aDateFormat, $aDate1 ) == True )
print( "'$aDate1' jest poprawnym formatem daty ISO " );
else
print( "'$aDate1' nie jest poprawnym formatem daty ISO " );
if ( ereg( $aDateFormat, $aDate2 ) == True )
print( "'$aDate2' jest poprawnym formatem daty ISO " );
else
print( "'$aDate2' nie jest poprawnym formatem daty ISO " );
if ( ereg( $aDateFormat, $aDate3 ) == True )
print( "'$aDate3' jest poprawnym formatem daty ISO " );
else
print( "'$aDate3' nie jest poprawnym formatem daty ISO " );
if ( ereg( $aDateFormat, $aDate4 ) == True )
print( "'$aDate4' jest poprawnym formatem daty ISO " );
else
print( "'$aDate4' nie jest poprawnym formatem daty ISO " );
?>
Wyniki działania skryptu z wydruku 6 są następujące:
'83440' jest poprawnym kodem pocztowym
'83440-1607' jest poprawnym kodem pocztowym
'834' nie jest poprawnym kodem pocztowym
'M6K 3E3' nie jest poprawnym kodem pocztowym
'2000-06-29' jest poprawnym formatem daty ISO
'2000-7-4' jest poprawnym formatem daty ISO
'June 29, 2000' nie jest poprawnym formatem daty ISO
'0000-99-99' jest poprawnym formatem daty ISO
Programiści programujący wcześniej w języku Perl i ci, którzy używali już wyrażeń regularnych uważają taką kontrolę poprawności za łatwą i wydajną. Ci zaś, którzy nie znają wyrażeń regularnych mogą wybrać inne metody kontroli poprawności, opisane w następnych dwóch częściach.
Kontrola poprawności za pomocą sprawdzania typów
W niektórych przypadkach wystarczy sprawdzić typ wprowadzonej danej i nie przejmować się wprowadzoną wartością. Metoda ta jest odpowiednia do kontrolo prostych typów, takich jak liczby i ciągi, ale również pozwala na nieco więcej. Jeżeli zostanie użyta w połączeniu z dodatkowym kodem kontroli poprawności, będzie wystarczająca dla wielu aplikacji. Poniższy przykład sprawdza typy zmiennych, aby upewnić się, że zostały wprowadzone tylko liczby.
Kontrola liczb przy użyciu kontroli typów
" );
else
print( "'$aValue1' nie jest liczbą " );
if ( is_numeric( $aValue2 ) == True )
print( "'$aValue2' jest liczbą " );
else
print( "'$aValue2' nie jest liczbą " );
if ( is_numeric( $aValue3 ) == True )
print( "'$aValue3' jest liczbą " );
else
print( "'$aValue3' nie jest liczbą " );
if ( is_numeric( $aValue4 ) == True )
print( "'$aValue4' jest liczbą " );
else
print( "'$aValue4' nie jest liczbą " );
?>
Skrypt przedstawiony na wydruku 7 interpretuje pierwsze trzy wartości jako liczby natomiast ostatnią nie. Więcej na temat funkcji kontroli typów znajduje się przy opisie funkcji is_xxx() w części "Funkcje zmiennych" w skorowidzu funkcji na końcu książki.
Klasa Validator
Jedną z najpiękniejszych cech oprogramowania typu open-source jest dostępność świetnych narzędzi uzupełniających podstawowy produkt. Dodatkowe oprogramowanie dla PHP można pozyskać z wielu źródeł. Witryna Webmasters Net (http://www.thewebmasters.net) zawiera nieco świetnych klas i modułów z kodem źródłowym. Do kontroli poprawności przeznaczona jest klasa Validator zawierająca wiele funkcji upraszczających wiele zadań i oszczędzających czas. Przykładowymi funkcjami kontroli poprawności są is_email(), is_url() i is_phone() przeznaczone do sprawdzania adresów e-mail, URL i numerów telefonów. Więcej informacji na temat tej klasy i innych dostarczanych przez Webmasters Net znajduje się w części "PHP Tools and Extras" - ich witryny.
Wydruk 3.8. Kontrola poprawności danych przy użyciu klasy Validator
is_phone( $aPhoneNum1 ) == True )
print( "'$aPhoneNum1' jest prawidłowym numerem telefonu " );
else
print( "'$aPhoneNum1' nie jest prawidłowym numerem telefonu " );
if ( $aValidator->is_phone( $aPhoneNum2 ) == True )
print( "'$aPhoneNum2' jest prawidłowym numerem telefonu " );
else
print( "'$aPhoneNum2' nie jest prawidłowym numerem telefonu " );
if ( $aValidator->is_phone( $aPhoneNum3 ) == True )
print( "'$aPhoneNum3' jest prawidłowym numerem telefonu " );
else
print( "'$aPhoneNum3' nie jest prawidłowym numerem telefonu " );
/*
Funkcja is_email kontroluje nie tylko poprawność formatu adresu email
ale również sprawdza, czy istnieje w Internecie podany host
Oczywiście wymaga to podłączenia z Internetem.
W chwili pisania tego przykładu host 'invalidhost.com'
nie był zarejestrowany.
*/
$aEmail1 = "blake@intechra.net";
$aEmail2 = "john";
$aEmail3 = "nobody@invalidhost.com";
if ( $aValidator->is_email( $aEmail1 ) == True )
print( "'$aEmail1' jest prawidłowym adresem email " );
else
print( "'$aEmail1' nie jest prawidłowym adresem email " );
if ( $aValidator->is_email( $aEmail2 ) == True )
print( "'$aEmail2' jest prawidłowym adresem email " );
else
print( "'$aEmail2' nie jest prawidłowym adresem email " );
if ( $aValidator->is_email( $aEmail3 ) == True )
print( "'$aEmail3' jest prawidłowym adresem email " );
else
print( "'$aEmail3' nie jest prawidłowym adresem email " );
?>
Klasa Validator jest potężnym zestawem funkcji przyspieszających tworzenie oprogramowania, ale tak jak w przypadku wszystkich narzędzi zewnętrznych należy sprawdzić, czy spełnia twoje wymagania.
Cookie
Z powodu trwającej debaty na temat użycia cookie, większość programistów WWW i użytkowników jest zaznajomiona z koncepcją cookie. Cookie są plikami tekstowymi zapisanymi na komputerze klienta i są one ze swojej natury niewinne. Jednak wielu użytkowników nie przyjmuje cookie wysłanych do przeglądarek z powodu plotek na temat ich wykorzystania. Jeżeli twoja aplikacja opiera swoje działanie na cookie, niektórzy użytkownicy nie będą mogli jej używać. Jednak jeżeli korzystasz z cookie, ale nie wymagasz ich do prawidłowej pracy, twoja aplikacja będzie działała z większością przeglądarek.
PHP posiada tylko jedna funkcję przeznaczoną do tworzenia cookie, setcookie(). Ponieważ cookie są wysyłane jako część nagłówka HTTP, funkcja setcookie() musi być wywołana przed wysłaniem jakichkolwiek danych do przeglądarki lub należy zastosować buforowanie wyjścia w celu opóźnienia wysyłania danych do przeglądarki do chwili zdefiniowania wszystkich cookie. To samo ograniczenie obowiązuje również dla funkcji header().
Dowolne cookie odesłane do aplikacji przez przeglądarkę jest automatycznie konwertowane na zmienną PHP tak samo, jak dzieje się to w przypadku metod GET i POST. Cookie mogą przenosić wartości skalarne jak również tablice wartości. Funkcja setcookie() jest zdefiniowana w sposób następujący:
int setcookie( string nazwa, string wartość, int czas, string ścieżka,
string domena, int bezpieczny )
Wszystkie argumenty funkcji poza nazwą są opcjonalne. Jeżeli funkcja jest wywołana tylko z nazwą, cookie o podanej nazwie jest usuwane. Dowolny z ciągów może zostać opuszczony podając pusty ciąg (""). Dowolna wartość numeryczna może zostać opuszczona podając wartość zero. Argument czas jest standardowym czasem z systemu Unix w postaci liczby, którą można uzyskać jako wynik funkcji mktime() lub time(). Parametr bezpieczny wskazuje, że cookie może być przesyłane jedynie przez połączenie bezpieczne (HTTPS).
Należy pamiętać o następujących pułapkach i częstych błędach użycia cookie:
* Ustawione cookie nie będą widoczne w skrypcie do czasu jego powtórnego załadowania.
* Przeglądarki różnie obsługują cookie. Sprawdź aplikację na możliwie dużej ilości przeglądarek.
* Każda przeglądarka przechowuje cookie niezależnie. Oznacza to, że jeżeli użytkownik obejrzy witrynę przy użyciu jednej przeglądarki i zostanie ustawione cookie, to cookie nie będzie dostępne, jeżeli użytkownik ponownie obejrzy witrynę za pomocą innej przeglądarki.
Więcej ogólnych informacji na temat cookie można znaleźć w specyfikacji cookie firmy Netscape, która jest dostępna pod adresem http://www.netscape.com/newsref/std/cookie_spec.html.
Poniższe dwa przykłady pokazują użycie funkcji setcookie(). Wydruk 3.9 pokazuje jak ustawiać i wyświetlać cookie. Na wydruku 3.10 pokazane jest jak używać buforowania wyjścia w połączeniu z funkcją setcookie().
Wydruk 3.9. Użycie cookie
Użycie cookie " . $aValMessage );
?>
Wydruk 3.10. Użycie setcookie() razem z buforowaniem wyjścia
Użycie setcookie() wraz z buforowaniem wyjścia
Działa świetnie.
Ostatnia uwaga na temat cookie
W poprzedniej wersji PHP jeżeli chciałeś ustawić wiele cookie za pomocą jednego skryptu, musiałeś wywoływać setcookie() w odwrotnej kolejności do tej, w jakiej chciałeś obsługiwać cookie. Na przykład, jeżeli chciałeś usunąć cookie a następnie ustawić nowe o tej samej nazwie, należało najpierw wywołać setcookie(), aby ustawić nową wartość a następnie usunąć poprzednią wartość. W PHP4 zostało to usunięte. Należy wywoływać setcookie() w takiej kolejności jak się spodziewasz, że będą przetwarzane przez przeglądarkę. Proces ten jest pokazany na wydruku 3.9.
Mimo, że debata na temat tego, czy należy używać cookie będzie nadal trwała, ich tworzenie w PHP jest łatwe i proste. Dalsze rozważania na temat cookie będą kontynuowane w rozdziale 7 "Sesje i stan aplikacji".
Ważne zagadnienia programowania dla WWW
Część ta zawiera niektóre tematy, jakie muszą brać pod uwagę programiści przechodzący z pisania zwykłych aplikacji na aplikacje oparte o WWW. Problemy te powstają zwykle w czasie przetwarzania i wykorzystywania danych przesłanych z formularza HTML.
Obsługa nieprawidłowych danych
Pierwszym problemem jest sposób obsługi nieprawidłowych danych. W tradycyjnych aplikacjach dane wprowadzone przez użytkownika są często kontrolowane natychmiast po ich wprowadzeniu. Pozwala to natychmiast informować o nieprawidłowych danych. W aplikacjach WWW nie ma niezawodnego mechanizmu kontroli danych po wyjściu z poszczególnych pól, więc cała kontrola poprawności jest przeprowadzana na serwerze. Oznacza to, że jeżeli istnieje błąd w danych, użytkownik nie będzie o nim wiedział aż do chwili przesłania danych formularza. Dlatego w trakcie tworzenia aplikacji musisz się zdecydować, w jaki sposób reagować na błędy.
Istnieje kilka sposobów reagowania na błędy, przytoczymy tutaj dwa z nich. Pierwszą metodą jest wypisywanie błędów i nakazanie użytkownikowi, aby wrócił do poprzedniej strony i poprawił dane. Według mnie jest to najmniej pożądany sposób reakcji na błędy, ale jest najprostszy do zrealizowania. Jeżeli do formularza wpisywane jest bardzo mało danych (jedno lub dwa pola) metoda ta będzie do zaakceptowania. Jeżeli jednak tworzysz duży formularz nie należy używać tej metody, ponieważ może ona wymagać ponownego wprowadzenia wszystkich danych. Niektóre przeglądarki nie utrzymują wartości formularza po użyciu przycisku Wstecz.
Drugą metodą obsługi nieprawidłowych danych jest ponowne pokazanie strony formularza z zainicjowanymi wszystkimi polami i zaznaczonymi nieprawidłowymi pozycjami. Możesz utworzyć taki formularz przesyłając dane z formularza do tego samego skryptu. Metoda taka wymaga bardziej zaawansowanego projektowania, ale skutkuje powstaniem solidniejszej i bardziej użytecznej aplikacji, ponieważ ten sam skrypt może być użyty do pobierania nowych danych, zmiany danych istniejących i kontroli poprawności tych danych. Na wydruku 3.11 pokazane jest w jaki sposób można użyć jednego skryptu do zbierania i kontroli poprawności danych na prostym formularzu używanym do wpisywania adresów e-mail i numerów telefonów.
Wydruk 3.11. Inteligentna obsługa nieprawidłowych danych
is_phone( $Phone );
$aValidEmail = $aValidator->is_email( $Email );
if ( $aValidPhone && $aValidEmail )
{
// Dane są prawidłowe, przechodzimy do odpowiedniej strony
header( "Location:thanks.html\n" );
}
else
{
// Dane nieprawidłowe, wyróżniamy je
$aCurPhoneVal = $Phone;
$aCurEmailVal = $Email;
if ( $aValidPhone == False )
$aPhoneTextCol = "red";
if ( $aValidEmail == False )
$aEmailTextCol = "red";
}
}
?>
Inteligentna obsługa nieprawidłowych danych
Proszę wprowadzić numer telefonu i adres email.
We wprowadzonych danych wystąpiły błędy.
Sprawdź dane oznaczone kolorem czerwonym.
W skrypcie na wydruku 11, gdy strona jest otwierana bezpośrednio, zmienna $Submit jest pusta, więc formularz jest wyświetlany z pustymi polami. Gdy użytkownik kliknie przycisk Wyślij, strona jest ładowana po raz drugi, ale tym razem zmienna $Submit nie jest pusta, więc sprawdzana jest poprawność danych. Jeżeli oba pola mają poprawne dane, wywoływana jest funkcje header(), która powoduje przekierowanie przeglądarki do nowej strony zawierającej podziękowanie. Jeżeli któreś pole zawiera nieprawidłową wartość, formularz wywoływany jest ponownie, ale tym razem pola mają wartości wprowadzone poprzednio przez użytkownika. Dodatkowo, aby zaznaczyć wystąpienie błędu, nieprawidłowe dane są wyświetlane kolorem czerwonym.
Metoda ta pozwala na szybką identyfikację przez użytkownika danych, które wymagają poprawienia i nie wymaga ponownego wprowadzenia całej zawartości formularza. Jeżeli tworzysz aplikację WWW, która wymaga od użytkownika wprowadzania danych należy rozważyć użycie podobnej metody do obsługi błędnych danych. Jeżeli twoja aplikacja będzie niewygodna lub wymagać będzie ponownego wprowadzania danych, na pewno nie będzie lubiana.
Przedstawione metody nie są jedynymi stosowanymi do obsługi błędnych danych, ale ilustrują one podstawy tworzenia aplikacji WWW. Wybór metody obsługi błędów może być kluczową decyzją przy projektowaniu aplikacji.
Obsługa i formatowanie wyświetlanych danych
W zwykłej aplikacji wyświetlanie danych wprowadzonych przez użytkownika nie wymaga zwykle formatowania lub przetwarzania. Czasami formatowane są liczby, aby wyświetlać wartości walutowe lub dodać separatory tysięcy, ale zwykle nie ma zbyt dużo kłopotu przy wyświetlaniu danych wprowadzonych przez użytkownika. W przypadku programowania dla WWW wyświetlanie danych wprowadzonych do formularza w postaci strony WWW jest sprawą krytyczną. Dzieje się tak, ponieważ przeglądarka interpretuje cały tekst otrzymany z serwera WWW. Jeżeli dostarczysz użytkownikom formularz a następnie będziesz wyświetlał wpisane dane, niektórzy użytkownicy będą dodawać znaczniki HTML, aby sprawdzić co się stanie.
Pamiętając o tym pomyśl o formularzu, w którym użytkownicy będą mogli wpisywać swoje uwagi. Załóżmy, że stworzysz formularz w którym zapisywane będą: nazwa użytkownika, adres e-mail oraz treść uwagi. Po wprowadzeniu tekstu wyświetlasz komunikat w celu weryfikacji a następnie przetwarzasz ten komunikat. Pomysłowi lub złośliwi użytkownicy mogą próbować przetestować twój serwer WWW dodając znaczniki HTML lub kod JavaScript w treści komunikatu. Zwykle nie jest to niebezpieczne, ale na pewno skutkuje różnymi efektami ubocznymi.
Aby uniknąć tego problemu zawsze należy przetwarzać dane wprowadzone do formularza przed ich wyświetleniem. PHP posiada kilka funkcji pomagających w tym zadaniu. Są to funkcje strip_tags() i htmlentities(). Funkcja strip_tags() usuwa wszystkie znaczniki z ciągu oprócz tych, które zostały podane w dodatkowym opcjonalnym parametrze. Funkcja htmlentities() konwertuje specjalne znaki HTML na odpowiadające im symbole HTML. Na przykład znaki < i > są zastępowane przez < i >. Formularz i skrypt na wydruku 3.12 pokazuje obróbkę danych do ponownego wyświetlenia.
Wydruk 3.12. Obróbka danych do wyświetlenia.
Pobieranie danych do wyświetleniaBezpieczne wyświetlenie danych użytkownika
Rysunki 3.3. do 3.6. pokazują formularz wejściowy i wyniki działania skryptu. Rysunek 3.3. zawiera formularz wprowadzania danych. Rysunek 3.4. pokazuje co się dzieje, jeżeli nie ma filtrowania. Rysunki 3.5. i 3.6. pokazują wyniki filtrowania danych z formularza za pomocą funkcji odpowiednio strip_tags() i htmlentities().
Rysunek 3.3. Formularz wprowadzania danych
Rysunek 3.4. Wyświetlanie bez filtrowania
Rysunek 3.5. Wyświetlanie ze strip_tags()
Rysunek 3.6. Wyświetlanie z htmlentities()
Jeżeli dokładnie przyjrzysz się tym rysunkom zauważysz, że widać niespodziewane wyniki po wyświetleniu danych. Na przykład pojedynczy apostrof jest wyświetlany na stronie jako sekwencja \'. Również znaki końca linii wprowadzone w polu tekstowym nie są uwzględniane w wyświetlanym tekście.
Pierwsze z zakłóceń jest powodowane przez dyrektywę konfiguracji --enable-magic-quotes oraz opcje pliku php.ini magic_quotes_gpc, magic_quotes_runtime i magic_quotes_sybase. Jeżeli jest ona uaktywniona, wszystkie apostrofy, cudzysłowy, NUL1 i znaki backslash pochodzące z zewnętrznych źródeł, na przykład formularzy i bazy danych, są automatycznie poprzedzane ukośnikiem. Jest to szczególnie przydatne, jeżeli dane te będą zapisywane w bazie danych, ponieważ nie będziesz musiał ręcznie oznaczać tych znaków w ciągu SQL. Aby wyświetlić taki ciąg, należy wywołać funkcję strip_slashes(), która usuwa te dodatkowe znaki.
Jeżeli chodzi o problem ze znakami nowej linii, należy pamiętać, że HTML nie interpretuje znaku CR ani LF jako znaku podziału wiersza, chyba, że wystąpi on w bloku . PHP posiada funkcję nl2br(), która konwertuje znaki nowej linii na znaczniki .
Na wydruku 13 znajduje się ten sam formularz i skrypt co na wydruku 12, ale z dodatkowymi opcjami które powodują wywołanie funkcji strip_slashes() i nl2br().
Wydruk 3.13. Ulepszona obróbka danych do wyświetlenia
Pobieranie danych do wyświetleniaBezpieczne wyświetlenie danych użytkownika
Rysunek 3.7. Formularz wprowadzania danych
Rysunek 3.8. Wyświetlanie przefiltrowane przez strip_tags(), strip_slashes() i nl2br()
Po wprowadzeniu zmian pokazanych na wydruku 3.13, formularz wprowadzania danych i postać danych wynikowych jest taka, jak widać na rysunku 3.7. i 3.8.
Jeżeli wcześniej miałeś doświadczenie jedynie ze zwykłymi aplikacjami, musisz pamiętać o tych pułapkach stosowania przeglądarki jako warstwy prezentacji aplikacji. Oprócz pamiętania o wspomnianych problemach należy również zwrócić uwagę, że każda przeglądarka działa nieco inaczej. Szczegółowe omówienie tych problemów znajduje się w rozdziale 9 "Niezależność od przeglądarki".
Podsumowanie
Rozdział ten zawiera opis podstaw przetwarzania formularzy przy użyciu PHP. Ponieważ PHP został zaprojektowany jako język programowania dla WWW, upraszcza on znacznie proces interakcji z formularzami HTML. Ważniejsze od prostego pobierania danych od użytkowników jest prawidłowa obsługa tych danych i zabezpieczanie serwera i użytkowników przed nieprawidłowymi lub niebezpiecznymi danymi. W rozdziale tym omówiono niektóre narzędzia umożliwiające obsłużyć nieprawidłowe dane i zabezpieczyć przed szkodliwymi danymi. W rozdziale tym omówiono również proces zapamiętywania i odczytywanie cookie na komputerze klienta. Wszystkie te tematy razem stanowią podstawę do tworzenia interaktywnych aplikacji WWW.
Rozdział 4. Operacje na plikach
Wstęp
Obsługa plików jest zawarta we wszystkich nowoczesnych językach programowania. Zdolność do tworzenia, czytania, zapisu i innych operacji na plikach lub innych obiektach systemu plików jest niezbędna do zrealizowania obsługi sesji i serializacji. Do obsługi plików i innych obiektów systemu plików PHP posiada funkcje podobne do tych spotykanych w języku C. Tak jak C, w funkcjach służących do odczytu i zapisu, PHP używa uchwytów plików oraz pozwala na tworzenie uchwytów (pozwalających na operacje innymi typami strumieni danych, takimi jak gniazda i potoki). Zdolność ta powoduje, że równie łatwo można zapisać dane do pliku jak również wysłać je poprzez potok do innego programu.
Odczyt i zapis plików
Jedną z głównych różnic przy pisaniu aplikacji opartych o sieć WWW w stosunku do zwykłych aplikacji, jest sposób utrzymywania stanu aplikacji. W przypadku zwykłego programu, użytkownik uruchamia go, wykonuje kilka komend i kończy działanie programu. W czasie pracy programu stan aplikacji jest utrzymywany w pamięci. W aplikacjach opartych o sieć WWW stan musi być utrzymywany przez serwer WWW, ponieważ klientem jest zwykle prosta przeglądarka WWW. Szczegółowe przedstawienie zarządzania stanem aplikacji można znaleźć w rozdziale 7 "Sesje i stan aplikacji". W chwili obecnej wystarczy wiedzieć, że do utrzymywania stanu aplikacji i tworzenia innych mechanizmów przechowywania danych można użyć plików.
Ważne jest, aby używając plików, pamiętać o zagadnieniach bezpieczeństwa. Ponieważ aplikacja będzie działać w kontekście serwera WWW, pliki będą miały uprawnienia użytkownika przy pomocy którego uruchamiany jest serwer WWW. W przypadku Apache domyślnie jest to użytkownik nobody, którego uprawnienia ograniczają dostęp przez aplikację do obiektów systemu plików. Należy uważać, aby korzystając z plików nie naruszyć systemu bezpieczeństwa serwera WWW. W większości przypadków użycie bazy danych zamiast plików jest o wiele bardziej bezpieczne i praktyczne. Oczywiście istnieje wiele sytuacji gdy narzut czasowy wprowadzany przez bazę danych lub wymagania aplikacji powodują, że pliki są jedynym sensownym rozwiązaniem.
Na wydruku 4.1 pokazane zostało w jaki sposób można zrealizować liczniki dostępu do stron witryny. Do tego celu wykorzystane zostały podstawowe operacje na plikach, otwarcie, odczyt, zapis i zamknięcie prostego pliku śladu. W przykładzie tym nie zostały wykorzystane wszystkie dostępne w PHP funkcje operujące na plikach. Bardziej szczegółowy opis wszystkich funkcji znajdują się w skorowidzu funkcji na końcu książki.
Wydruk 4.1. Użycie plików do zliczania odwołań do stron witryny
$aValue )
{
fputs( $aFile, "$aKey\t$aValue\n" );
}
fclose( $aFile );
?>
Na wydruku 4.1 pokazujemy użycie jednego pliku do przechowywania liczników odwołań do dowolnej liczby stron witryny. Nie jest to efektywny sposób, ale pokazuje ideę takiego licznika. W skrypcie tym sprawdzamy za pomocą funkcji is_file() czy istnieje plik śladu. Jeżeli plik ten istnieje, jego kolejne linie są odczytywane i analizowane. Każda linia zawiera pełną ścieżkę dostępu do skryptu, znak tabulacji i wartość licznika. Linia taka jest dzielona przy pomocy funkcji explode() na nazwę skryptu i wartość licznika a następnie wartości te są zapisywane w tablicy asocjacyjnej. Jeżeli chcesz, możesz użyć tej tablicy do wyświetlenia liczników dla wszystkich stron witryny a nie tylko bieżącej strony. Po wypełnieniu tablicy uaktualniany jest licznik odwołań do bieżącej strony (rozpoznawanej przy użyciu zmiennej globalnej PHP $PATH_TRANSLATED) i wartość ta jest przypisywana do zmiennej $aPageAccessCount. Na koniec cała tablica jest zapisywana do pliku śladu.
Na wydruku 4.2 pokazane jest strona demonstrująca jak łatwo można użyć tego licznika. Jeżeli szukasz takiego mechanizmu do twojej witryny, należy pamiętać, że jest to bardzo nieefektywne rozwiązanie. Bardziej efektywne jest odczytywanie i zapis tylko jednej wartości a nie całego pliku.
Wydruk 4.2. Użycie skryptu z wydruku 4.1
Strona testowa 1
Strona ta była oglądana razy.
Użycie gniazd
PHP umożliwia dostęp do surowych gniazd TCP/IP, za pomocą których można komunikować się z innymi aplikacjami za pomocą dowolnego protokołu. Niektóre z bardziej znanych protokołów TCP/IP, na przykład HTTP, POP3 i SMTP posiadają swoje implementacje w PHP, więc nie musisz w tych przypadkach używać surowych gniazd.
Na wydruku 4.3 pokazano sposób dostępu za pomocą gniazd do serwera quotd, który zwraca cytat dnia. Protokół quotd jest bardzo prosty. Po zestawieniu połączenia serwer wysyła strumień danych tekstowych a następnie zamyka połączenie. Z perspektywy klienta wystarczy jedynie zestawić połączenie, odczytać dane a następnie zakończyć połączenie.
Wydruk 4.3. Użycie gniazd
Przykład wykorzystania serwera QOTD: Użycie gniazd w PHP
" );
}
fclose( $aFile );
?>
Użycie potoków
Tak jak w przypadku gniazd, potoki są traktowane jak kolejny uchwyt pliku. Jedyną różnicą pomiędzy plikiem i potokiem jest to, że potok jest jednokierunkowym strumieniem danych. Potok może być użyty do odczytu danych wyjściowych z programu lub skryptu. Na wydruku 4.4 pokazane jest użycie potoku do odczytania wyniku zapytania do polecenia whois, które jest dostępne w większości systemów Unix. Ten prosty skrypt i formularz pozwalają na wprowadzenie zapytania dla whois. Skrypt ten ilustruje również częstą praktykę używania tego samego skryptu do wyświetlenia formularza i przetworzenia jego danych.
Wydruk 4.4. Skrypt przetwarzający zapytanie whois
";
exit;
}
?>
Whois: Uzycie potoków w PHP
" );
}
pclose( $aFile );
}
else
{
echo "Nie mogę otworzyć $whois do odczytu! ";
}
print( "" );
}
?>
Klasa File
W poprzednim rozdziale wspominaliśmy, że do PHP dostępne są świetne narzędzia dodatkowe pochodzące z różnych źródeł. Klasa File dostępna z WebMasters Net (http://www.theWebMasters.net) jest przydatnym narzędziem, szczególne wtedy, gdy twoja aplikacja intensywnie wykorzystuje pliki. Klasa ta zawiera wiele często używanych funkcji PHP operujących na plikach i hermetyzuje kontrolę błędów, dzięki czemu możesz więcej czasu poświęcić logice aplikacji zamiast zajmować się pisaniem podstawowych konstrukcji kontroli błędów.
Na wydruku 4.5 pokazany jest skrypt wyświetlający nazwy wszystkich plików w bieżącym katalogu w postaci łączy. Gdy użytkownik kliknie łącze, skrypt zamieszczony na wydruku 4.6 wyświetla jego zawartość używając celu klasy File do odczytania jego zawartości.
Wydruk 4.5. Użycie klasy File do wyświetlenia zawartości bieżącego katalogu
Użycie klasy File
Poniżej znajduje się lista plików w bieżącym katalogu.
Kliknij nazwę pliku aby zobaczyć ich zawartość.
" );
?>
Podsumowanie
Zdecydowanie się na użycie plików w aplikacji opartej na WWW jest jedną z krytycznych decyzji w fazie projektowania aplikacji. Noe wszystkie aplikacje używają plików, ale aby efektywnie korzystać z różnych typów strumieni danych, na przykład gniazd i potoków, należy poznać sposoby korzystania z uchwytów plików i funkcji operujących na plikach. Rozdział ten zawiera nie tylko opis podstawowych operacji na plikach i systemie plików, ale również przedstawia dodatkową klasę ułatwiającą operacje na plikach. Opis operacji na plikach zawarty w tym rozdziale oraz opis formularzy zamieszczony w rozdziale poprzednim stanowią odpowiednią podstawę do następnego rozdziału, "Wysyłanie plików przez formularz".
Rozdział 5. Wysyłanie plików przez formularz
Wstęp
Poprzednie dwa rozdziały omawiały niezbędne podstawy dla tego rozdziału, ponieważ wysyłanie plików wymaga poznania zarówno formularzy HTML, jak i funkcji systemu plików. Obsługa przesyłania plików w PHP jest bardzo łatwa. PHP posiada wbudowany mechanizm pozwalający na odebranie pliku wysłanego z przeglądarki zgodnej z RFC 1867. Większość nowoczesnych przeglądarek jest zgodnych z tym dokumentem, ponieważ został on włączony do standardu HTML 3.2.
Jeżeli pozwolisz użytkownikom na wysyłanie plików za pomocą formularza, musisz rozważyć dopuszczalne typy plików oraz ich wielkości. Mechanizm wbudowany w PHP działa świetnie dla małych plików, ale jeżeli masz zamiar przesyłać duże pliki należy się zastanowić nad zastosowaniem innego mechanizmu, a przykład anonimowego FTP. Możesz również pomyśleć o stworzeniu dodatkowego mechanizmu przesyłania plików, jeżeli są one niezbędne do działania aplikacji.
Wysyłanie pojedynczego pliku
Formularz przy pomocy którego można przesyłać pliki różni się kilkoma szczegółami od zwykłego formularza HTML. Znacznik
Po wysłaniu danych formularza z wydruku 5.1, PHP tworzy automatycznie cztery zmienne globalne, które opisują przesłany plik:
* $thefile - Zmienna zawiera nazwę pliku tymczasowego w którym znajduje się plik przesłany na serwer.
* $thefile_name - Zmienna ta zawiera nazwę pliku na komputerze z którego został wysłany.
* $thefile_size - Zmienna zawiera wielkość przesłanego pliku w bajtach.
* $thefile_type - Zmienna ta zawiera typ MIME przesyłanego pliku (o ile przeglądarka udostępnia taką informację).
Nazwy tych zmiennych są tworzone w oparciu o nazwę znacznika w formularzu, tak jak jest to pokazane na Wydruku 5.1. Pisząc skrypt obsługujący przesyłanie pliku należy pamiętać, że PHP automatycznie usuwa plik tymczasowy po zakończeniu skryptu, więc jeżeli nie skopujesz go, plik zostanie stracony.
Skrypt na wydruku 5.2 zawiera kod obsługi przesyłania pliku poprzez formularz z Wydruku 1 i jeżeli plik jest rysunkiem (w formacie GIF lub JPEG) mniejszym od 100 kB, jest on wyświetlany. Jeżeli przesłany plik nie ma właściwego typu lub jest większy, wyświetlany jest komunikat błędu.
Wydruk 5.2. Obsługa przesyłania pliku
Wyświetlenie przesłanego pliku
Wystąpił błąd: $aErrors " );
}
else
{
print( "Przesłany plik:
" );
print( "" );
}
?>
W przykładzie zamieszczonym na wydruku 5.2. nie wzięto pod uwagę, że nie wszystkie przeglądarki wysyłają typu MIME pliku. Opuszczono również inne zagadnienia kontroli błędów, na przykład kontrolę poprawności wykonania funkcji copy. Jednak przykład ten miał za zadanie pokazanie jak łatwo można obsłużyć za pomocą PHP operacje przesyłania pliku.
W przykładzie tym na początku sprawdzane jest, czy został wybrany plik do przesyłania. Jeżeli nie został wybrany plik, zmienna $thefile_name jest pusta. Następnie sprawdzane jest, czy plik ma odpowiednią wielkość i typ MIME. Jeżeli obie wartości zostaną zaakceptowane, przy pomocy wyrażenia dirname($PATH_TRANSLATED) odczytywany jest bieżący katalog na serwerze WWW. Funkcja dirname() zwraca nazwę katalogu z podanej ścieżki. Zmienna $PATH_TRANSLATED jest zmienną PHP i zawiera pełną ścieżkę do bieżącego skryptu. Dodając /uppics/ i oryginalną nazwę pliku na komputerze lokalnym, tworzymy nową ścieżkę. Na koniec, przesłany plik jest kopiowany z katalogu tymczasowego do katalogu określonego przez przed chwilą skonstruowaną ścieżkę. Należy pamiętać, że aby operacja kopiowania się udała, docelowy katalog musi posiadać odpowiednio ustawione uprawnienia. Korzystając z Apache w systemie Linux oznacza to, że uprawnienia do katalogu muszą pozwolić na zapis przez użytkownika nobody.
PHP posiada mechanizm pozwalający na ograniczanie w skrypcie wielkości przesyłanych plików. Jest to realizowane przez dodanie do formularza ukrytego pola o nazwie MAX_FILE_SIZE. Na wydruku 5.3 pokazany jest formularz identyczny z tym z wydruku 5.1, ale dodane zostało pole MAX_FILE_SIZE ograniczające wielkość przesyłanych plików do 100 kB.
Wydruk 5.3. Ograniczenie wielkości przesyłanego pliku za pomocą MAX_FILE_SIZE
Formularz do przesyłania plików
Pułapki
PHP domyślnie ogranicza wielkość plików, jakie można przesyłać używając tego mechanizmu, do 2 megabajtów. Ta wielkość jest ważniejsza od zmiennej formularza MAX_FILE_SIZE. Wartość ta może być zmieniona przez ustawienie wartości upload_max_filesize w pliku php.ini, lub ustawienie dyrektywy w pliku Apache.conf (więcej szczegółów znajduje się w rozdziale o opcjach konfiguracji, który znajduje się na końcu książki). Gdy osiągnięta zostanie graniczna wielkość pliku (zarówno ustawiona w formularzu jak i globalne maksimum), PHP generuje błąd, przerywa przesyłanie i ustawia nazwę pliku na none.
Mimo tego, że ta graniczna wielkość pliku jest ustawiana w celu chronienia serwera WWW, sieje ona zniszczenie w twoich aplikacjach. Ponieważ błąd przekroczenia wielkości przesyłanego pliku występuje przed wykonaniem jakiejkolwiek linii skryptu, nie ma możliwości przechwycenia generowanego ostrzeżenia generowanego przez mechanizm przesyłania plików. Oznacza to, że jeżeli opcja konfiguracji display_errors ma wartość On (domyślnie) w przeglądarce będzie się pojawiał komunikat błędu.
Jeżeli nie chcesz aby pojawiał się ten komunikat, musisz ustawić w pliku php.ini opcję konfiguracji display_errors na Off. Możesz następnie ustawić opcję log_errors na On a error_log na wartość odpowiednią dla twojego środowiska. Jeżeli używasz Linuksa i Apache, ustawienie error_log na stderr spowoduje, że wszystkie błędy PHP trafią do dziennika błędów Apache. Aplikacja twoja może sprawdzać zmienne przesyłu plików i odpowiednio obsługiwać błędy. Jeżeli użytkownikowi nie uda się przesył pliku, zmienna $thefile będzie miała wartość none, a $thefile_name będzie zawierała odpowiednią wartość.
Innym problemem, nad jakim należy się zastanowić w trakcie pisania skryptu obsługi przesyłania plików jest to, że zanim rozpocznie się wykonywanie skryptu musi zostać przesłany cały plik lub maksymalna określona ilość bajtów. Jeżeli więc twoja aplikacja dopuszcza przesyłanie dużych plików, ale akceptuje jedynie niektóre typy plików, twoi użytkownicy mogą dosyć długo czekać zanim zobaczą komunikat o odrzuceniu przesyłanego pliku.
Przesyłanie wielu plików
Jeżeli chcesz przesłać kilka plików używając jednego formularza możesz skorzystać z tablicy PHP do przesłania danych o przychodzących plikach. Poniższy przykład pokazuje użycie tablicy do przesłania czterech plików.
Wydruk 5.4. Przesyłanie czterech plików
Formularz do przesyłania plików
Proszę podać cztery pliki rysunków do przesłania:
Wydruk 5.5. Obsługa czterech przesyłanych plików
Wyświetlanie przesłanego rysunku
$aCount rysunki:
" );
foreach( $aNewNames as $aNewName )
{
print("
");
}
?>
Bezpieczeństwo
Jeżeli dopuszcza się dostarczanie jakichkolwiek danych do aplikacji, należy brać pod uwagę każdą ewentualność. Jeżeli pozwalasz na przesyłanie plików musisz się upewnić, że pliki te zostaną właściwie obsłużone na serwerze. Na przykład, jeżeli tworzysz witrynę do której programiści mogą przesyłać własne skrypty nie należy pozwalać na wykonywanie tych skryptów na serwerze. Można je jedynie odebrać i wyświetlić w postaci czystego tekstu i nie można zakładać, że można je bezpiecznie uruchomić.
Nawet pozwolenie na wyświetlenie przesłanych plików niesie ze sobą potencjalne zagrożenie. Na wydruku 5.6. pokazany jest prosty przykład w jaki sposób mechanizm wyświetlania plików może spowodować dziurę w systemie bezpieczeństwa.
Wydruk 5.6. Naruszenie bezpieczeństwa podczas obsługi przesłanych plików
Naruszenie bezpieczeństwa przy przesyłaniu pliku
$aNewName:
" );
?>
Jest to oczywiście wymyślony przykład. W przykładzie tym przesłany plik jest kopiowany do nowego katalogu, ale wyświetlając plik odczytywany i wysyłany do przeglądarki jest plik tymczasowy. W rzeczywistości prawdopodobnie odczytasz i wyświetlisz plik znajdujący się na ścieżce zapamiętanej w $aNewName. Dla potrzeb tej prezentacji poprzedni plik pokazuje w jaki sposób źle napisany skrypt narusza system bezpieczeństwa.
Aby wykorzystać niedoskonałość skryptu ktoś może wpisać do przeglądarki nazwę skryptu i podać nazwę dowolnego pliku na serwerze. Na przykład wprowadzenie takiego adresu URL spowoduje wyświetlenie zawartości pliku /etc/passwd (zakładając, że będzie on wykonywany na systemie Uniksowym):
http://serwer.com/sciezka/upload_flaw.phtml?thefile=/etc/passwd
Można przetestować to na komputerze z Uniksem, że niebezpieczeństwo jest rzeczywiste. Nawet mimo tego, że serwer WWW pracuje jako użytkownik nobody, plik /etc/passwd musi być możliwy do odczytania przez wszystkich użytkowników.
W rozdziale o formularzach kładłem nacisk na to, że nie wolno zakładać, że wszyscy użytkownicy aplikacji będą używali jej zgodnie z twoimi zamiarami. Tak samo jest i teraz. Niektórzy użytkownicy będą chcieli rozmyślnie wykorzystać słabości aplikacji a inni nieświadomie spowodują jej awarię. Należy dokładnie przemyśleć wszystkie możliwe skutki uboczne pozwolenia na przesyłanie plików na serwer WWW.
Podsumowanie
W rozdziale tym pokazane zostały sposoby odczytywania i wykorzystania plików przesłanych przez przeglądarki zgodne z dokumentem RFC 1867. Zostały przytoczone przykłady obsługi jednego pliku jak również tablicy plików. Na końcu rozdziału znajduje się mała część ilustrująca w jaki sposób źle napisany skrypt może stworzyć dziurę w systemie bezpieczeństwa serwera.
Dopuszczenie do przesyłania plików do aplikacji może być w wielu przypadkach użyteczne, ale należy pamiętać, że niektórzy użytkownicy mogą nie posiadać dostatecznie szybkiego łącza aby efektywnie korzystać z tego mechanizmu, więc dobrym pomysłem jest zapewnienie jeszcze jednego sposobu na dostarczanie plików do aplikacji.
Rozdział 6. Współpraca z bazami danych
Wstęp
Jedną z najważniejszych cech nowoczesnych języków programowania lub narzędzi programistycznych jest zdolność współpracy z bazą danych. Jest to spowodowane tym, że systemy zarządzania relacyjnymi bazami danych (SZRBD) posiadają wiele bardzo wydajnych i niezwykle użytecznych mechanizmów zarządzania danymi, jak na przykład indeksowanie, relacje pomiędzy danymi, obsługa transakcji, kaskadowe operacje wykonywane na danych i wiele innych. PHP pozwala na dostęp do danych przy użyciu bogatego zestawu funkcji związanych z bazami danych.
Wprowadzenie
Jak można wywnioskować na podstawie dokumentacji, autorzy PHP uważają obsługę baz danych za jedną z najważniejszych i najsilniejszych cech PHP. Obsługiwane są między innymi takie bazy danych:
Adabas D
InterBase
Solid
dBase
mSQL
Sybase
Empress
MySQL
Velocis
FilePro
Oracle
Unix dbm
Informix
PostgreSQL
Mictosoft SQL Server
ODBC
Obsługując ODBC, PHP może zostać użyty do prawdopodobnie dowolnej istniejącej bazy danych. Z powodu ogromnej ilości obsługiwanych baz danych jest niemożliwe szczegółowe omówienie obsługi każdej z nich w tej książce. Dodatkowo, język SQL jest sam w sobie niezwykle bogatym i wydajnym narzędziem, które również nie zostanie odpowiednio dokładnie opisane w tej książce. Najlepiej posiłkować się dokumentacją odmiany SQL zaimplementowanej w używanej przez ciebie bazie danych. Zakładamy w tym rozdziale, że czytelnicy znają podstawy SQL w stopniu wystarczającym do zrozumienia przykładów zamieszczonych na wydrukach.
W rozdziale tym skupimy się na przykładach użycia MySQL i ODBC. Wybrałem MySQL ponieważ jest to wydajna baza danych dostępna na zasadach licencji GNU General Public License (GPL) i jest powszechnie używana do współpracy z PHP. ODBC wybrałem, ponieważ do większości baz danych dostępne są sterowniki tego standardu. Przykłady ilustrują zastosowanie języka PHP i nie zawsze pokazują najlepsze zastosowania SQL oraz działania na bazach danych.
Funkcje baz danych
Każda z obsługiwanych baz danych posiada własny zestaw funkcji PHP. Nazwy funkcji związanych z MySQL rozpoczynają się od mysql_ i podobna zasada obowiązuje w przypadku innych baz (W skorowidzu funkcji na końcu książki znajduje się kompletna lista funkcji związanych z bazami danych). Mimo, że każda z baz danych ma własny zestaw funkcji, istnieje wspólny model dostępu do każdego z typów baz danych. Pseudokod opisujący pobieranie danych z dowolnego systemu bazy danych przedstawiony jest na wydruku 6.1.
Wydruk 6.1. Pseudokod opisujący pobieranie danych z bazy
Następne dwie części zawierają szczegóły konfiguracji i użycia MySQL i ODBC.
MySQL
MySQL jest świetną bazą danych dla większości projektów. Oficjalną witryną MySQL jest http://www.mysql.com. Na tej witrynie znajduje się najnowsza wersja systemu oraz dokumentacja opisująca instalację i konfigurację MySQL w różnych środowiskach.
Rozpoczynamy pracę z MySQL
W zależności od twoich potrzeb i typu serwera, możesz albo ściągnąć źródła MySQL, dystrybucję binarną albo RPM. Najszybszą metodą zainstalowania MySQL na systemie Linux działającym na platformie Intel jest ściągnięcie pliku RPM i zainstalowanie go. Przy użyciu tej metody instalowane są wszystkie elementy serwera, więc możesz od razu zaczynać pracę. Jeżeli używasz systemu działającego w oparciu o Win32, najszybszą metodą pozyskania serwera jest ściągnięcie skompresowanej instalacji binarnej.
PHP4 posiada wbudowaną obsługę MySQL, więc nie musisz ponownie kompilować PHP aby używać funkcji mysql_. Jednak jeżeli korzystasz z wbudowanej obsługi MySQL, nie można używać innych modułów odwołujących się do MySQL, na przykład mod_auth_mysql i mod_perl. Jeżeli potrzebujesz modułów używających MySQL, musisz przekompilować PHP podając opcję konfiguracji --with_mysql=/ścieżka/do/mysql.
Użycie MySQL
Po zainstalowaniu i uruchomieniu MySQL można rozpocząć pisanie skryptów PHP, które korzystają z danych umieszczonych w bazie danych. Skrypt zamieszczony na wydruku 6.2 pokazuje jak proste jest użycie MySQL do pobrania danych z bazy. Tabela której będę używał w dwóch kolejnych przykładach została utworzona za pomocą następującego kodu SQL:
CREATE TABLE employees
(
id tinyint(4) DEFAULT '0' NOT NULL auto_increment,
first varchar(20),
last varchar(20),
adress varchar(255),
position varchar(50),
PRIMARY KEY (id),
UNIQUE id (id)
)
Wydruk 6.2. Pobieranie danych z bazy danych MySQL
Pobieranie danych z MySQL
" );
}
mysql_free_result( $aQResult );
}
else
{
print( "Błąd wykonania zapytania " );
}
}
else
{
print( "Błąd wyboru bazy danych " );
}
}
else
{
print( "Błąd przy podłączaniu do bazy danych " );
}
?>
Po uruchomieniu skryptu z wydruku 6.2, próbuje się on podłączyć do serwera bazy danych MySQL działającego na komputerze db.serer.com podając nazwę użytkownika i hasło. Symbol @ umieszczony przed funkcją mysql_connect() powoduje zablokowanie wypisywania błędów i ostrzeżeń. Podczas testowania możesz opuścić ten symbol, ale w normalnej pracy należy go używać i stosować własne procedury obsługi błędów. Następną czynnością wykonywaną przez skrypt jest wybranie odpowiedniej bazy danych, w naszym przypadku mydb. Jeżeli się to powiodło, przy pomocy funkcji mysql_query() zadawane jest zapytanie do bazy danych. W naszym przykładzie jest to zapytanie SELECT, które powoduje pobranie rekordów z bazy danych. Może być to dowolne zapytanie, na przykład: INSERT, UPDATE, ADD TABLE lub dowolne inne zapytanie SQL. Wynik funkcji jest różny od zero w przypadku powodzenia i zero w przypadku błędu. Dodatkowo, jeżeli zapytanie jest typu SELECT, wynik funkcji jest identyfikatorem wyniku przekazywanym do funkcji mysql_result(), mysql_fetch_array(), mysql_fetch_lengths(), mysql_fetch_object(), i mysql_fetch_row(), które są używane do odczytania wynikowych danych. W naszym przykładzie używamy funkcji mysql_fetch_array() do odczytania wiersza z wynikowych danych a następnie wyświetlane są dane z odpowiednich pól.
Funkcje mysql_fetch_array() i mysql_fetch_row() są podobne do siebie i zwracają jeden wiersz wyniku w postaci tablicy. Funkcja mysql_fetch_array() zwraca wynik w postaci tablicy asocjacyjnej indeksowanej nazwami kolumn. Wywołanie funkcji mysql_fetch_row() zwraca tablicę indeksowaną liczbami. Wywołanie jednej z tych funkcji zwraca kolejny wiersz danych zwracanych przez zapytanie i przesuwa wewnętrzny wskaźnik do następnego wiersza. Jeżeli nie ma więcej danych, funkcja zwraca False. Wywołanie funkcji mysql_fetch_array() nie jest zauważalnie wolniejsze niż wywołanie mysql_fetch_row(), a dostarcza o wiele więcej danych.
Używając skryptu z wydruku 6.2 jako podstawy, można napisać wszystkie możliwe aplikacje oparte na bazie danych. Funkcje MySQL posiadają dodatkowo kilka cech, które nie są dostępne dla wszystkich baz obsługiwanych przez PHP. Dostarczone są specjalizowane funkcje do tworzenia i usuwania baz danych oraz funkcje umożliwiające odczytanie struktury bazy danych. Na przykład za pomocą funkcji mysql_list_tables() można uzyskać listę wszystkich tabel w bazie danych.
Jedną z moich ulubionych funkcji dla MySQL jest mysql_insert_id(). Używając pól o atrybucie auto_increment można po prostu zapisać dane do tabeli a następnie odczytać unikalny identyfikator rekordu za pomocą funkcji mysql_insert_id(). Na wydruku 6.3 mamy formularz, który pozwala na wprowadzenie danych nowego pracownika do bazy używanej na wydruku 6.2. Skrypt korzysta z funkcji mysql_insert_id() w celu zrealizowania potwierdzenia operacji wstawienia danych.
Wydruk 6.3. Wstawianie rekordu do bazy danych MySQL
" );
$aResult = -1;
}
}
else
{
// print( "Błąd wyboru bazy danych " );
$aResult = -2;
}
}
else
{
// print( "Błąd przy podłączaniu do bazy danych " );
$aResult = -3;
}
return $aResult;
}
?>
Przykład MySQL: Wstawianie danych do bazy
0 )
{
print( "Dodano nowy wiersz, ID = $aResult " );
}
else
{
print( "Błąd funkcji InsertRecord. Kod błędu = $aResult " );
}
print( "" );
}
?>
Proszę wpisać dane nowego pracownika:
W skrypcie z wydruku 6.3, funkcja IndertRecord() zawiera całą logikę wstawienia nowego rekordu do bazy danych. Zwraca on identyfikator nowego rekordu (wartość przypisywana przez MySQL do kolumny id) lub wartość ujemną oznaczającą jedną z trzech obsługiwanych sytuacji błędnych. Realistycznie patrząc, Ten typ aplikacji powinien zawierać o wiele więcej kodu odpowiedzialnego za obsługę błędów, na przykład sprawdzanie pustych pól, ale dla naszych potrzeb kod ten nie został rozmyślnie wprowadzony. Ponieważ pole id w tabeli employees jest polem typu auto_increment, MySQL automatycznie generuje jednoznaczne wartości tego pola przy każdym wstawieniu rekordu. W naszym przykładzie wartość ta jest odczytywana za pomocą funkcji mysql_insert_id().
Przykład ten miał na celu pokazanie prostoty korzystania z baz danych w PHP. Więcej przykładów użycia baz danych w aplikacjach WWW można znaleźć w rozdziale 15 "Witryny oparte o bazę danych". Znajdują się tam bardziej złożone przykłady zawierające obsługę błędów i skomplikowane zapytania.
MySQL jest wydajną bazą danych posiadającą funkcje wystarczające do tworzenia większości typów aplikacji WWW. Jest ona szybka, solidna i zawiera większość funkcji dostępnych w komercyjnych bazach danych. Jednak w czasie pisania tej książki MySQL nie zawierał mechanizmu transakcji. Niedostępne są również niektóre elementy SQL, na przykład podzapytania. Jeżeli jeszcze nie wybrałeś swojego systemu bazy danych, spisz swoje wymagania i porównaj ze specyfikacją dostępnych systemów. W przypadku tworzenia aplikacji o wysokiej jakości koszt bazy nie jest jedynym czynnikiem jaki należy brać pod uwagę. Jeżeli twoja firma posiada system bazy danych inny niż MySQL, następna część zawiera informacje na temat ODBC, które pomogą podłączyć się do twoich istniejących danych.
ODBC
Open Database Connectivity (ODBC) to powszechnie stosowany interfejs API (application programming interface) służący do łączenia się z bazami danych. Jest on oparty na specyfikacji Call Level Interface pochodzącym z X/Open oraz ISO/IEC i jako języka dostępu do danych używa SQL. Istnieje kilka implementacji ODBC API dla systemów Uniksowych. W systemie Windows ODBC jest zwykle instalowany razem z systemem.
Podstawy ODBC
PHP może obsługiwać praktycznie każdą implementację ODBC, ale musi być w tym celu odpowiednio skonfigurowany, ponieważ ODBC nie jest w chwili obecnej domyślną opcją. W PHP istnieją cztery opcje konfiguracji związane z ODBC: --with-unixODBC, --with-custom-ODBC, --with-iodbc oraz --with-openlink. Opcje te są lepiej opisane w skorowidzu na końcu książki. W rozdziale tym przykłady korzystają z implementacji ODBC unixODBC (http://www.unixodbc.org/). Jest on dostępny na zasadach licencji GPL lub LGPL i jest bardzo łatwy do instalacji i konfigurowania.
ODBC tym różni się od MySQL i innych API baz danych tym, że wszystkie odwołania do bazy danych wykonuje za pośrednictwem sterownika bazy danych. Oznacza to, że najpierw musisz zainstalować program zarządzający sterownikami, na przykład unixODBC, a następnie sterownik do twojego systemu bazy danych. Na rysunku 6.1. pokazane są powiązania pomiędzy komponentami aplikacji PHP opartej o ODBC. Aplikacja wywołując funkcję, na przykład odbc_connect(), kontaktuje się z zarządcą sterowników. Zarządca ten jest odpowiedzialny za załadowanie odpowiedniego sterownika bazy danych i przekazanie do niego żądania. Sterownik bazy danych wywołuje odpowiednią funkcję bazy danych, która realizuje nasze żądanie.
Rysunek 6.1. Komponenty aplikacji PHP korzystającej z PHP
PHP Application - aplikacja PHP
Driver Manager - zarządca sterowników
Database Driver - sterownik do bazy danych
DBMS - SZRBD
Ponieważ ODBC wymaga zastosowania zarządcy sterowników oraz sterownika odpowiedniej bazy danych, instalacja i konfiguracja ODBC jest nieco bardziej skomplikowana niż konfiguracja MySQL. Również każdy z używanych sterowników baz danych musi zostać zainstalowany i skonfigurowany.
W książce tej zostanie opisana instalacja i konfiguracja zarządcy sterowników unixODBC oraz sterownika ODBC-ODBC Bridge (OOB), który można uzyskać z Easysoft Limited, http://www.easysoft.com/. Sterownik OOB powoduje wzrost komplikacji struktury, ale posiada tak dużo zalet, że jest wart zainteresowania. Sterownik ten pozwala na dostęp do baz danych zainstalowanych na różnych platformach za pomocą własnego modelu klient-serwer. NA rysunku 6.2. zilustrowano sposób użycia sterownika OOB.
Rysunek 6.2.
Dodajemy sterownik OOB
PHP Application - aplikacja PHP
Driver Manager - zarządca sterowników
The OOB driver - sterownik OOB
OOB Client - klient OOB
Network - sieć
OOB Server - serwer OOB
Driver Manager - zarządca sterowników
Database Driver - sterownik do bazy danych
DBMS - SZRBD
Zaletą stosowania sterownika OOB jest to, że możesz dzięki niemu używać ODBC w aplikacjach działających na serwerze WWW i korzystać z danych z bazy danych działającej na innym komputerze (który może działać na innym systemie operacyjnym). Dla przykładu w moim testowym systemie zainstalowałem Oracle 8i na serwerze Windows NT i utworzyłem prostą bazę danych. Następnie w moim linuksowym serwerze WWW dodałem sterownik OOB. Sterownika tego można używać do podłączania się do dowolnej bazy zgodnej z ODBC, działającej na dowolnej platformie.
Dodatkowym utrudnieniem jest to, że używając OOB należy kolejno zainstalować klienta i serwer OOB na oddzielnych komputerach. Na szczęście na witrynie Easysoft bardzo łatwo jest odszukać i załadować odpowiednie programy.
Kolejne trzy części omawiają instalowanie zarządcy sterowników unixODBC, kompilację PHP z obsługą unixODBC oraz instalowanie sterownika OOB. Części te są przeznaczone dla użytkowników Linuksa i zakładamy, że potrafisz kompilować programy dla tego systemu oraz, że masz zainstalowane wszystkie niezbędne kompilatory i narzędzia.
Instalowanie i kompilowanie unixODBC
Po ściągnięciu i rozpakowaniu plików unixODBC, musisz skompilować zarządcę sterowników. W instalacji unixODBC znajduje się standardowy skrypt służący do konfigurowania środowiska kompilacji. W celu skompilowania mojej konfiguracji PHP użyłem następujących opcji:
./configure --disable--drivers --disable-threads --prefix=/usr/local/unixODBC --disable-gui
Ponieważ miałem już potrzebny sterownik, nie potrzebowałem aby unixODBC dodał swoje sterowniki wewnętrzne. Powodem wyłączenia wątków jest to, że moja instalacja PHP jest w postaci dynamicznie ładowanego modułu (--with-apxs) a Apache nie obsługuje domyślnie wątków. Skompilowanie tego modułu z obsługa wątków spowodowałoby awarię Apache w trakcie ładowania modułu. Wyłączyłem również obsługę graficznego interfejsu użytkownika, ponieważ nie mam na moim serwerze zainstalowanego środowiska XWindows.
Kompilowanie PHP z obsługą unixODBC
Po skompilowaniu i zainstalowaniu zarządcy sterowników unixODBC należy przekompilować PHP z włączoną obsługą unixODBC. Odpowiednią opcją konfiguracji jest --with-unixODBC=/sciezka/do/unixODBC. Użyta ścieżka musi być taka sama jak ścieżka użyta w opcji --prefix podczas kompilowania unixODBC. W moim przypadku jest to /usr/local/unixODBC.
Jeżeli statycznie łączysz PHP z Apache, musisz również przekompilować Apache. Jeżeli korzystasz z dynamicznego łączenia, wystarczy wyłączyć Apache, zainstalować nowy moduł PHP i powtórnie uruchomić Apache.
Instalowanie sterownika OOB
W moim przypadku musiałem zainstalować serwer OOB na komputerze z Windows NT i skonfigurować go tak, aby przyjmował żądania. Wykonałem to uruchamiając program instalacyjny i wykonując wszystkie kroki w programie instalacyjnym. Wszystko zadziałało bez problemów. Następnie ściągnąłem i zainstalowałem oprogramowanie klienta na serwerze z systemem Linux. Proces ten był niespodziewanie łatwy, ponieważ dostępny był program instalacyjny prowadzący użytkownika przez kolejne kroki procedury instalacyjnej. Można również skorzystać z witryny Easysoft, gdzie na podstawie konkretnej konfiguracji otrzymamy szczegółowy opis tego jak ściągnąć i zainstalować serwer i klienta OOB.
Konfigurowanie OOB
Po zainstalowaniu całego oprogramowania należy utworzyć nazwy źródeł danych (DSN) zarówno na kliencie jak i na serwerze. Źródła danych są mechanizmem specyficznym dla ODBC służącym do opisywania sposobu współpracy z systemem bazy danych. W Windows tworzy się DSN poprzez program Źródła danych ODBC dostępny w Panelu sterowania. OOB wymaga utworzenia systemowego DSN a nie DSN użytkownika. Program ten zawiera plik pomocy opisujący sposób tworzenia systemowych DSN.
Aby utworzyć DSN na Linuksie należy zmienić przy pomocy graficznego narzędzia unixODBC lub edytora tekstowego pliki odbcinst.ini i odbc.ini. Plik odbcinst.ini jest używany do opisu nazw sterowników i łączy nazwy z plikami sterowników. Mój plik wygląda następująco:
[OOB]
Driver = /usr/local/easysoft/oob/client/libesoobclient.so
Setup = /usr/local/easysoft/oob/client/libesoobsetup.so
FileUsage = 1
Plik odbc.ini zawiera opis źródeł danych. Swoje źródło skonfigurowałem następująco (serwer i hasło jest oczywiście zmyślone):
[localdsn]
Server=satabase.server.com
Driver=OOB
Port=8888
Transport=tcpip
LogonUser=prodplaner
LogonAuth=password
TargetDSN=LocalOracle
TargetUser=prodplaner
TargetAuth=password
Korzystanie z ODBC
Po zainstalowaniu i skonfigurowaniu wszystkich komponentów korzystanie z ODBC w PHP jest bardzo podobne do korzystania z MySQL. Na wydruku 6.4 znajduje się skrypt, który jest odpowiednikiem ODBC skryptu umieszczonego na wydruku 6.2. Tabela używana w tym przykładzie jest odpowiednikiem używanej w poprzednim przykładzie.
Wydruk 6.4. Odczytywanie danych z bazy ODBC
Pobioeranie danych z bazy danych ODBC
" );
$aRowNum++;
}
odbc_free_result( $aQResult );
}
else
{
print( "Błąd wykonania zapytania " );
}
}
else
{
print( "Błąd podłączenia do bazy danych " );
}
?>
Wydruk 6.4 jest właściwie taki sam jak wydruk 6.2. Mimo, że nazwy funkcji są inne, koncepcja jest nieomal identyczna. Jedyną zauważalną różnicą jest wywołanie putenv() na początku skryptu. Wywołanie to umieszcza w środowisku programu ścieżkę do pliku inicjalizującego ODBC. Nie jest to potrzebne, jeżeli w ten sam sposób ustawiłeś środowisko serwera WWW. Dodatkowo, na wydruku 6.4 do pól tabeli odwołujemy się dla uproszczenia za pomocą numer a nie nazwy. Dostępne są funkcje ODBC zapewniające obsługę transakcji, kursorów i wiele innych. W skorowidzu funkcji na końcu książki znajdują wszystkie funkcje do obsługi ODBC.
Uwaga na temat połączenia do baz danych
W poprzednim przykładzie połączenie do baz danych było realizowane za pomocą podstawowych funkcji xxx_connect(). PHP posiada również zdolność tworzenia trwałych połączeń za pomocą funkcji pxxx_connect(). Użycie połączenia trwałego poprawia wydajność aplikacji, ponieważ sam PHP utrzymuje połączenie z bazą danych, więc może być ono wielokrotnie używane. Po utworzeniu połączenia za pomocą odpowiedniej kombinacji host-użytkownik-hasło, PHP ciągle dostarcza tego samego połączenia do kolejnych wywołań połączenia. W bazach danych utworzenie połączenia trwa zwykle długo (na przykład w Oracle), więc użycie trwałych połączeń może mieć ogromny wpływ na ogólną wydajność aplikacji.
PHPLIB
Jak wspomniałem w poprzednich rozdziałach, dostępne są świetne biblioteki do wykorzystania przez programistów PHP. Jedna z najczęściej używanych bibliotek, PHP Base Library (PHPLIB) jest dostępna pod adresem http://phplib.netuse.de. Zawiera ona klasy dostęu do baz danych, obsługi sesji, narzędzi autoryzacji i wiele, wiele innych.
Klasy dostępu do bazy danych w PHPLIB tworzą warstwę abstrakcji dla kilku baz danych obsługiwanych przez PHP. Warstwa ta zapewnia wspólny interfejs dla bazowych funkcji baz danych, więc programiści mogą łatwo zmieniać typ bazy danych bez konieczności nauki nowego zestawu funkcji lub wielu zmian w kodzie. W czasie pisania książki PHPLIB obsługiwał MySQL, PostgreSQL, mSQL, Oracle 7, Oracle 8, Sybase, Microsoft SQL Sever i bazy ODBC.
Poniższy wydruk ilustruje siłę modułu obsługującego bazy danych z pakietu PHPLIB. W skrypcie umieszczonym na wydruku 6.5. pokazany został sposób uproszczenia skryptu z wydruku 6.2.
Wydruk 6.5. Użycie PHPLIB do powtórzenia wyników z wydruku 6.2
query( "select * from employees" );
while( $aDB->next_record() )
{
$aFName = $aDB->f( "first" );
$aPos = $aDB->f( "position" );
print( "$aFName, $aPos " );
}
?>
Dostarczona przez PHPLIB klasa DB_Sql ukrywa w sobie szczegóły procesu łączenia i wyboru bazy danych oraz zawiera kod obsługi błędów. Pozwala to osiągnąć w wyniku kod, który jest łatwiejszy do czytania, utrzymania i uruchamiania. Klasa DB_Sql nie jest przeznaczona do bezpośredniego używania. Zamiast tego powinna być tworzona klasa dziedzicząca po niej, w której ustawiane są zmienne specyficzne dla twojego środowiska pracy. Jeżeli PHP będzie obsługiwał klasy abstrakcyjne, jest to idealny kandydat do takiej właśnie implementacji. Na wydruku 6.5 definiowana jest klasa pochodna MySQLDBTest, w której zawarte są dane opisujące połączenie z MySQL. Następnie tworzony jest obiekt tej klasy, na którym wykonywane są operacje.
Największa zaleta korzystania z klas PHPLIB ujawnia się, gdy zachodzi potrzeba wymiany bazy danych. Poniższy wydruk pokazuje jak łatwo można zamienić skrypt z wydruku 6.5, aby zamiast z MySQL korzystał z Oracle poprzez sterownik ODBC.
Wydruk 6.6. Skrypt z wydruku 6.5 korzystający z Oracle i ODBC
query( "select * from employees" );
while( $aDB->next_record() )
{
$aFName = $aDB->f( "first" );
$aPos = $aDB->f( "position" );
print( "$aFName, $aPos " );
}
?>
Jedyną widoczną zmianą pomiędzy wydrukami 5 i 6 jest funkcja include(), ale znaczenie tej zmiany jest olbrzymie. Skrypt z wydruku 6.5 korzystał z danych z bazy MySQL działającej na tym samym komputerze co serwer WWW. Skrypt z wydruku 6.6 pobiera dane z bazy Oracle zainstalowanej na serwerze z Windows NT.
Z powodu prostoty projektu i implementacji PHPLIB może być on użyteczny dla programistów pracujących w złożonych, heterogenicznych środowiskach, jak również w prostych instalacjach składających się z jednego serwera. Biblioteka ta zapewnia jednakowy interfejs dostępu do różnych baz danych, co powoduje bardzo łatwe ponowne użycie istniejącego kodu. Więcej informacji na temat klas zawartych w PHPLIB można odnaleźć na witrynie http://phplib.netuse.de/.
Przechowywanie danych z formularzy
Omówienie formularzy HTML jest potrzebne w rozdziale dotyczących baz danych, ponieważ formularze są najczęściej używanym mechanizmem używanym do wprowadzania danych w aplikacjach WWW. Tak jak opisano w rozdziale 3, "Formularze i cookie", PHP dostarcza wielu funkcji potrzebnych przy używaniu formularzy i baz danych.
W przy domyślnych ustawieniach PHP automatycznie oznacza we wszystkich zmiennych GET, POST i COOKIE apostrofy, cudzysłowy, ukośniki i znaki NUL. Powoduje to, że wartość przekazana z formularza jest od razu gotowa do użycia w zapytaniu SQL. Jeżeli zablokowałeś tą opcję, musisz użyć funkcji addslashes() zanim skorzystasz w zapytaniu SQL z ciągu przekazanego z formularza. Dodatkowo, wszystkie wartości, które będą wyświetlane muszą zostać przed wyświetleniem przetworzone za pomocą funkcji stripslashes().
Tak jak we wszystkich aplikacjach, dane wpisane do formularza HTML muszą być sprawdzone przed ich zapisaniem do bazy danych. Mechanizmy kontroli poprawności danych były opisane w rozdziale 3. Wynikiem braku kontroli danych może być niezadowolenie użytkowników z aplikacji a nawet załamanie systemu bezpieczeństwa serwera. Na przykład, niektóre komunikaty błędów generowane przez bazę danych mogą zawierać takie informacje na temat używanej bazy danych, których na pewno nie chciałbyś pokazywać użytkownikom. Należy być przygotowanym na sytuacje, że niektórzy użytkownicy mogą próbować wyszukać słabe punkty w aplikacji.
Aby zabezpieczyć się przed niektórymi typami ataków należy zawsze używać atrybutu maxlength w polach tekstowych oraz kontrolować typ i postać danych. Jak wspomniano w rozdziale 3, tam gdzie jest to możliwe należy zastępować procedury kontroli danych przez takie mechanizmy, które ze swojej natury ograniczają pomyłki. Pola wyboru, przyciski opcji i inne tego typ elementy pozwalają na dużą elastyczność i ograniczają możliwość błędu przy wprowadzaniu danych.
Tworząc alternatywne mechanizmy wprowadzania danych należy pamiętać o możliwości korzystania z bazy danych przy tworzeniu początkowego zestawu danych. Umieszczenie takiego zestawu opcji w bazie danych skutkuje w dłuższym okresie stworzeniem aplikacji łatwiejszej do zarządzania. Na przykład na wydruku 6.7 pokazane zostało tworzenie listy wyboru zawierającej kraje oraz stany USA. Oczywiście można wybrać stan w USA a następnie Afrykę południową. Przykład ten pokazuje jedynie koncepcję. W skrypcie tym używane są tabele us_states oraz world_countries. Każda z tabel zawiera identyfikator oraz nazwę. Identyfikator jest przekazywany jako wartość formularza.
Wydruk 6.7. Użycie tabel słownikowych do generacji listy opcji
query( $aSQL );
while( $aDB->next_record() )
{
$aName = $aDB->f( "Name" );
$aID = $aDB->f( "ID" );
if ( $aID == $aCurSel )
{
$aResult .= "";
}
else
{
$aResult .= "";
}
}
return $aResult;
}
?>
Formularz wyboru stanu USA oraz kraju
To jest prosty kalkulator rat kredytu.
Wprowadź kwotę pożyczki, oprocentowanie i czas spłaty
Kwota:
Oprocentowanie ("7.5" == 7.5%):
Czas spłaty (w latach):
Skrypt ten wyświetla formularz do wprowadzenia danych kredytu, a następnie wysyła je do samego siebie. Po wywołaniu go poprzez wywołanie HTTP POST, wywoływane są funkcje finansowe i wyświetlane wyniki ich działania. Na rysunku 11.1. pokazany jest fragment strony będącej wynikiem typowego wykonania programu.
Rysunek 11.1. Wykorzystanie nowych funkcji finansowych
Jak wspomniano wcześniej, jeżeli masz dużą bibliotekę kodu C/C++ pochodzącą z istniejących aplikacji i zamierzasz przenieść je do środowiska WWW, PHP posiada prosty mechanizm integracji istniejącego kodu z nowymi aplikacjami. Zaletą tego rozwiązania jest możliwość ponownego wykorzystania dobrze przetestowanego kodu oraz dobra wydajność skompilowanego kodu. Dodatkowo, funkcje napisane w C lub C++ mogą realizować funkcje, których nie da się napisać wyłącznie w PHP. Na przykład implementacja bezpiecznych gniazd zapewnia możliwości, które nie mogą być w chwili obecnej zrealizowane przy pomocy funkcji PHP.
Rozważając integrację istniejącego kodu C/C++ z PHP należy wziąć pod uwagę, że koszt integracji może być wyższy od kosztu przepisania kodu na PHP. Przytoczony wcześniej przykład może być łatwo przepisany na PHP i zajmie to mniej czasu. Dodatkowo kroki podjęte w czasie integracji muszą być w części powtórzone dla każdej nowej wersji PHP. Jeżeli zamierzasz zawsze korzystać z najnowszej wersji PHP, powoduje to konieczność ciągłej konserwacji istniejącej witryny.
Inną możliwością wykorzystania istniejącego kodu C/C++ jest jego skompilowanie i wykonywanie na serwerze WWW poprzez PHP. Metoda ta zostanie opisana w dalszej części rozdziału.
Java
W rozdziale 9, "Niezależność od przeglądarki" przedstawiony został opis połączenia Javy z PHP. Możliwość używania klas Javy została wprowadzona w PHP4. Z powodu popularności Javy, dostępne jest wiele klas i modułów klas Javy, oferowanych przez wielu niezależnych dostawców. Obsługa Javy nie jest włączona domyślnie do PHP, więc należy przekompilować PHP, aby móc skorzystać z tego potężnego narzędzia.
Dodawanie obsługi Javy w PHP na *niksach
Jeżeli korzystasz z PHP na platformie *nix, musisz przekompilować PHP w celu dodania obsługi Javy. W podręczniku PHP znajdziemy, że nie można wykorzystać opcji konfiguracji --with-java, jeżeli posiadasz PHP statycznie włączone w Apache. Opcja ta działa, jeżeli PHP jest uruchamiany jako program CGI lub dynamicznie włączany moduł Apache. Z powodów bezpieczeństwa nie zaleca się korzystania z PHP w postaci CGI. Jeżeli serwer Apache nie posiada obsługi dynamicznych modułów, należy go wcześniej przekompilować.
Poniższy skrypt powoduje przekompilowanie Apache tak, aby korzystał z dynamicznie ładowanych modułów oraz tworzy właściwie skonfigurowany skrypt apxs, który będzie potrzebny do skompilowania PHP. W skrypcie tym zakładamy, że będzie on uruchomiony z głównego katalogu instalacji Apache.
make clean
./configure --enable-module=so --enable-rule=SHARED_CORE --prefix=/www
make
make install
Po przekompilowaniu Apache można uaktywnić obsługę Javy w PHP za pomocą następującego skryptu. Zakładamy w nim, że będzie uruchomiony z głównego katalogu instalacji PHP.
make clean
./configure --with-apxs=/www/bin/apxs --with-java ...
make
make install
Opcja --with-java może zawierać ścieżkę oznaczającą katalog instalacji używanej maszyny wirtualnej Javy. Po zakończeniu kompilacji można sprawdzić konfigurację PHP za pomocą funkcji phpinfo(). Należy również ustawić kilka opcji konfiguracji Javy w pliku php.ini. Pierwsza jest linia z dołączeniem rozszerzenia (extension=libphp_java.so). Pozostałe opcje zostaną omówione później.
Dołączanie obsługi Javy w PHP dla Windows
Zamiast kompilowania specjalnej wersji PHP dla Windows, rozszerzenie Javy jest dostępne do pobrania z www.php.net. Powinieneś sprawdzić która wersja JDK (Java Development Kit) jest zainstalowana na serwerze. Można to zrobić przy pomocy java -showversion. Należy pobrać odpowiedni plik rozszerzenia i skopiować php_java.dll do katalogu systemowego. W Windows 95 jest to zwykle \windows\system a Windows NT \winnt\system32.
Następnie należy uaktualnić plik php.ini. Należy doda linię ładującą rozszerzenie (extension=php_java.dll). Następnie należy dodać odpowiednio sekcję z opcjami konfiguracji. Są one kluczowe do prawidłowego działania Javy na każdej platformie.
Opcje konfiguracji Javy
Niezależnie od platformy, jeżeli obsługa Javy jest aktywna w PHP, musisz dodać kilka opcji konfiguracji do pliku php.ini. W Windows sekcja ta powinna wyglądać podobnie do następującej:
[java]
java.class.path="D:\php4\php_java.jar;D:\PHP4 book\other\RTF2HTML\lib\Scrooge_09b7.jar"
java.home="D:\Program Files\JavaSoft\JRE\1.3"
java.library="D:\Program Files\JavaSoft\JRE\1.3\bin\hotspot\jvm.dll"
W przypadku systemów *nix, sekcja ta jest następująca:
[java]
java.library.path=/usr/lib/kafee:/home/blake/php-4.0.1p12/modules
java.home=/usr/lib/kaffe
java.class.path=/usr/share/kaffe/Klasses.jar:/home/blake/php-4.0.1.p12/ext/java/php_java.jar:/home/blake/bhawk/lib/bhawk4j.jar:/home/blake/bhawk:/home/blake/java/numberspeller.jar:/home/blake/java/sax2.jar:/home/blake/java/servlet.jar:/home/blake/java/scrooge.jar
java.library=/www/libexec/libkaffevm.so
Po skonfigurowaniu obsługi Javy, w pliku php.ini musisz podać lokalizację klas Javy lub plików JAR. Należy to wykonać dla każdej używanej klasy Javy, której chcesz używać. Jak widać na zamieszczonych opcjach konfiguracji, java.class.path zawiera pełną ścieżkę do plików implementacji.
Tak jak jest to w przypadku każdego języka umożliwiającego tworzenie komponentów, dla Javy dostępne jest wiele narzędzi, z których można skorzystać za pomocą języka obsługującego API. Jednym z dostępnych komercyjnie modułów Javy jest konwerter RTH na HTML Scrooge, który można załadować z witryny www.betabeans.de. Moduł ten posiada prosty interfejs używany do konwertowania plików RTF na standardowy HTML. Funkcja ta może być wykorzystywana we wielu aplikacjach, w których użytkownicy mogą wysyłać takie pliki. Ponieważ RTF obsługuje różne czcionki i układy, wykorzystanie RTF pozwala użytkownikowi na dostarczanie plików bez niebezpieczeństwa bezpośredniego dodawania kodu HTML do witryny. Moduł Scrooge zawiera przykładowy plik RTF (pokazany na rysunku 11.2.) którego możemy użyć do sprawdzenia siły i elastyczności modułu.
Rysunek 11.2. Przykładowy plik RTF modułu Scrooge
Użycie modułu Scrooge jest łatwe i proste. Dołączona dokumentacja zawiera nazwę klasy Javy, oraz listę dostępnych metod i właściwości. W skrypcie z wydruku 11.8 pokazane jest wykorzystanie tego modułu.
Wydruk 11.8. Użycie modułu Javy Scrooge
Konwersja RTF na HTML
setOptWrapHTML( False );
$aOutput = $aR2H->convert( implode( "", $aArray) );
print( $aOutput );
}
else
{
print ("Wybrany plk nie jest plikiem RTF. ");
}
}
?>
Przesyłanie pliku:
Skrypt ten zawiera formularz przesyłania pliku, za pomocą którego użytkownik może przesłać plik RTF. Po przesłaniu danych formularza sprawdzany jest typ pliku i jeżeli jest prawidłowy tworzony jest obiekt Scrooge. Przesłany plik jest odczytywany do tablicy za pomocą funkcji file(), a następnie używając funkcji implode(), tablica jest konwertowana na ciąg, który jest przekazywany do obiektu Scrooge. Zwracaną wartością jest ciąg zawierający kod HTML utworzony na podstawie przesłanego pliku. Wynikowy kod HTML jest wysyłany do przeglądarki. Na rysunku 11.3. przedstawiony jest wynik uzyskany z przykładowego pliku RTF.
Rysunek 11.3. Wynik przetworzenia przykładowego pliku RTF na kod HTML
nie potrafię uruchomić tego przykładu
Java jest tylko jednym z języków umożliwiających tworzenie komponentów, które można wykorzystać w środowisku PHP. Następna część opisuje użycie obiektów COM w PHP.
COM
COM jest z natury oparty o Windows, więc dyskusja ta odnosić się będzie do PHP działającego na serwerze pracującym pod kontrolą systemu Windows. Standardowa instalacja PHP dla Windows posiada obsługę COM, więc nie jest potrzebna dodatkowa konfiguracja. Implementacja COM w PHP ewoluowała z opartego o funkcje API w wersji 3, do implementacji obiektowej w PHP 4. Powoduje to, że użycie COM w PHP jest bardzo naturalne.
W części tej omówimy serwer konwersji walut Cloanto Currency Server, dostępny z witryny http://cloanto.com. Obiekt ten pozwala na przeliczanie walut pomiędzy sobą i posiada wewnętrzną bazę danych kursów. Baza ta jest automatycznie uaktualniana, więc można użyć tego modułu w międzynarodowej aplikacji handlu elektronicznego w celu umożliwienia wyświetlania cen w lokalnej walucie.
Obiekt ten posiada bogaty zestaw metod, ale bardzo łatwo można użyć podstawowych funkcji w środowisku testowym. Na wydruku 11.9. zamieszczony jest przykład wykorzystania tego obiektu. Rysunki 11.4. i 11.5. pokazują formularz z cenami w dwóch różnych walutach.
Wydruk 11.9. Użycie serwera konwersji walut Cloanto
Użycie potoków
" );
}
else
{
$aLines = array();
if ( $aProgFile = popen( $aFreeProg . " -t", "r" ) )
{
$nIndex = 0;
$aLines = array();
while ( !feof( $aProgFile ) )
{
$aLine = fgets( $aProgFile, 1024 );
$aLines[$nIndex++] = $aLine;
}
pclose( $aProgFile );
$aCount = count( $aLines );
$aTotal = $aLines[$aCount - 2];
$aArray = split( "[ ]+", $aTotal );
$aTotalK = number_format( $aArray[1] );
$aUsedK = number_format( $aArray[2] );
$aFreeK = number_format( $aArray[3] );
?>
Całkowita ilość dostępnej pamięci =$aTotalK?> KB.
Wolna pamięć =$aFreeK?> KB.
Użyte =$aUsedK?> KB.
" );
}
}
?>
Rysunek 11.4. Przykład użycia serwera Cloanto, wyświetlana waluta: dolary amerykańskie
Rysunek 11.5. Przykład użycia serwera Cloanto, wyświetlana waluta: forinty węgierskie
W skrypcie umieszczonym na wydruku 11.9. utworzona jest prosta tabela cen dla trzech różnych towarów. Dodatkowo dostępny jest formularz do wyboru lokalnej waluty. Po przesłaniu danych formularza skrypt wykorzystuje serwer Cloanto do przeliczenia cen na wybraną walutę. Obiekt ten jest używany do uzyskania listy krajów, współczynników wymiany oraz wykonuje przeliczanie na bieżąco.
Jeżeli tworzona jest aplikacja handlu elektronicznego, przy pomocy tego obiektu można dodać niezwykle przydatną dla użytkowników funkcję, która eliminuje frustrujące pomyłki w liczeniu cen. Wykorzystując serwer Cloanto wraz z wykrywaniem typu przeglądarki można przeliczać ceny na lokalną walutę bez potrzeby pytania użytkownika o jej nazwę.
Z powodu dużej ilości programistów Windows oraz dojrzałości modelu COM, dostępne jest wiele komponentów dla wszystkich typów projektów. Używając obsługi COM w PHP można z łatwością wykorzystać istniejący kod we własnych projektach.
Inne metody
Prawdopodobnie posiadasz istniejący kod, którego nie da się wykorzystać przy użyciu żadnej z przedstawionych metod. Jeżeli tak się stanie, nadal można go wykorzystać w PHP. Jeżeli kod ten jest skryptem (na przykład skryptem Perla) lub można go skompilować do postaci wykonywalnej, da się go zastosować w skrypcie.
PHP posiada kilka funkcji służących do uruchamiania programów i skryptów na serwerze. Ponieważ tematem tego rozdziału jest integracja, najlepszą metodą wykorzystania programów na serwerze będzie skorzystanie z funkcji popen() do uruchamiania programów i skryptów oraz przechwytywania ich wyników. Technika ta była przedstawiona w rozdziale 4 "Operacje na plikach", na przykładzie programu whois, dostępnego na większości systemów *nix. Na wydruku 11.10. pokazany został przykład odczytywania bieżącej ilości użytej pamięci w systemach *nix.
Wydruk 11.10. Użycie potoków do integracji PHP z istniejącymi skryptami lub programami wykonywalnymi
Użycie potoków
" );
}
else
{
$aLines = array();
if ( $aProgFile = popen( $aFreeProg . " -t", "r" ) )
{
$nIndex = 0;
$aLines = array();
while ( !feof( $aProgFile ) )
{
$aLine = fgets( $aProgFile, 1024 );
$aLines[$nIndex++] = $aLine;
}
pclose( $aProgFile );
$aCount = count( $aLines );
$aTotal = $aLines[$aCount - 2];
$aArray = split( "[ ]+", $aTotal );
$aTotalK = number_format( $aArray[1] );
$aUsedK = number_format( $aArray[2] );
$aFreeK = number_format( $aArray[3] );
?>
Całkowita ilość dostępnej pamięci =$aTotalK?> KB.
Wolna pamięć =$aFreeK?> KB.
Użyte =$aUsedK?> KB.
" );
}
}
?>
Skrypt ten otwiera potok do standardowego programu free. Program zwraca dane na temat ilości dostępnej pamięci w komputerze. Skrypt otwiera potok, który powoduje uruchomienie programu. Skrypt odczytuje z potoku kolejne wiersze wyniku i wyświetla je w przeglądarce. W zależności od zwracanych danych może być niezbędna bardziej zaawansowana analiza, ale podstawowa idea jest ta sama.
Technika ta może być użyta dla każdego programu, który zwraca wyniki na standardowe wyjście. W przypadku systemów Unix oznacza to, że można w ten sposób użyć nieomal każdej komendy bezpośrednio z PHP. Pozwala to łatwo zrealizować odczytanie statusu systemu, zwracanie danych lub inne operacje. Jeżeli trzeba przenieść istniejący kod do PHP, pozwala to na szybkie prototypowanie, przed zastosowaniem wcześniej opisanych metod. Pozwala to na szybsze rozpoczęcie testowania funkcji aplikacji minimalizując ilość koniecznych prac programistycznych. Należy jednak zaznaczyć, że uruchamianie programów wymaga znacznej ilości zasobów serwera, co może powodować, że aplikacja będzie powolna i trudna do skalowania.
Podsumowanie
W PHP nie brakuje możliwości ponownego użycia kodu. Planując tworzenie biblioteki kodu w PHP przeznaczonej do wielokrotnego użytku lub przenosząc istniejący kod do aplikacji WWW, można znaleźć odpowiednie rozwiązanie. Z powodu olbrzymiej ilości istniejących komponentów (zarówno COM jak i Javy) może się okazać, że większość projektowanej aplikacji jest już napisana. Używając tych komponentów można znacznie zmniejszyć czas potrzebny na napisanie programu. Używając ich mądrze, można otrzymać aplikację łatwiejsza w konserwacji i skalowaniu.
Bibliografia
Steve McConnell, Rapid Development. Seattle: Microsoft Press. 1996.
Rozdział 12. Oddzielanie kodu HTML od PHP
Wstęp
Przy projektowaniu zwykłych aplikacji zwykle nie bierze się pod uwagę oddzielania tworzenia interfejsu użytkownika od tworzenia części wykonawczej programu. Jest to spowodowane tym, że standardowe aplikacje wykorzystują standardowe narzędzia tworzenia interfejsu użytkownika, dostępne dla większości programistów. Jedynymi fragmentami tworzonymi przez inne osoby są emblematy, rysunki przycisków i podobne elementy wpływające na graficzny wygląd produktu.
Programowanie dla WWW, pozwala na zastosowanie o wiele bogatszego interfejsu użytkownika i przez to bardzo często wymaga zatrudnienia projektantów specjalizujących się w tworzeniu strony graficznej aplikacji. Gdy tworzenie interfejsu i kodu jest rozdzielone pomiędzy zespołami lub osobami, oddzielenie kodu i HTML staje się naturalne a integracja wyników pracy ważna. Nawet w małych jednoosobowych projektach oddzielenie HTML od logiki aplikacji powoduje, że konserwacja aplikacji jest prostsza i bardziej efektywna.
Wprowadzenie
Programowanie dla WWW jest często nazywane tworzeniem aplikacji wielowarstwowej, ponieważ stosowane są tutaj oddzielne logiczne warstwy. Często używanymi nazwami warstw są: warstwa prezentacji, warstwa aplikacji (biznesowa) oraz warstwa bazy danych. Każda z tych warstw może być fizycznie oddzielona od drugiej. Najważniejszym zadaniem przy projektowaniu wielowarstwowym jest logiczne oddzielenie warstw a nie ich fizyczna implementacja.
Głównymi zaletami podejścia wielowarstwowego przy tworzeniu aplikacji WWW są:
* Możliwość przydzielenia zadań osobom najlepiej przygotowanym do ich realizacji. Na przykład: graficy i projektanci przygotowują stronę graficzną aplikacji, programiści tworzą logikę aplikacji a projektanci baz danych projektują i uruchamiają infrastrukturę bazy danych.
* Możliwość zmian w warstwie bez potrzeby modyfikacji innych. W praktyce nadal jest to trudne, ale wiele małych zmian ogranicza się do pojedynczej warstwy.
* Możliwość przeniesienia bądź replikacji określonych warstw na inny sprzęt w celu zapewnienia skalowania bądź nadmiarowości.
Tak jak w przypadku wszystkich aplikacji, podczas trwania projektu aplikacji dla WWW mogą pojawić się żądania wprowadzenia zmian. Jeżeli zmiany te są ograniczone do jednej warstwy, możliwe jest, że nie będzie konieczne ponowne kodowanie. Celem tego rozdziału jest pokazanie sposobów tworzenia aplikacji odpornych na zmiany w późnych stadiach rozwoju. Dodatkowo oddzielenie interfejsu użytkownika od logiki aplikacji jest jedną z technik programowania modularnego, które pozwala na łatwiejsze użycie istniejących modułów.
W programowaniu tradycyjnym projekt modularny jest zwykle postrzegany jako tworzenie modułów kodu, które mogą być używane w dowolnych aplikacjach. W przypadku projektowania dla WWW, moduły mogą zawierać dane będące częścią interfejsu, np. prawa autorskie lub mogą być modułami kodu.
Modularność więcej wnosi do łatwości utrzymania aplikacji niż strukturalność i jest najważniejszym czynnikiem zapobiegania konieczności tworzenia poprawek do aplikacji mających za zadanie usuwanie błędów. Według badań 89% użytkowników kodu zgłaszało poprawienie możliwości utrzymania aplikacji modularnej, a w rozległych testach programiści osiągali o 15% lepsze wyniki pracując nad programem modularnym niż nad niemodularnym (McConnell, 1993).
Jak wspomniano w poprzednim rozdziale, tworzenie aplikacji modularnej wymaga dodatkowych prac projektowych i podjęcia odpowiednich decyzji, ale w efekcie można otrzymać aplikację łatwiejszą do zrozumienia i konserwacji. W książce A Methodology for Client/Server and Web Application Development Roger Fournier sugeruje, że wspólne fragmenty lub moduły aplikacji zawsze powinny być najpierw projektowane, tworzone i testowane a następnie udostępniane dla całej korporacji. Komponenty te powinny zawierać nie tylko moduły kodu, ale również procedury przechowywane w bazie danych, wyzwalacze i zdalne procedury (Fournier, 1998).
W kolejnych częściach zostanie opisane kilka metod implementacji tych metod. Dodatkowo w tym rozdziale jak również w rozdziale 14 "Witryny oparte o szablony", dołączone są kompletne przykłady zastosowania tych technik. Niektóre przykłady w kolejnych częściach pokazują techniki jakich należy unikać.
Oddzielenie i integracja przy użyciu wbudowanych funkcji PHP
Ponieważ PHP zawiera bogaty zestaw funkcji i narzędzi, oddzielenie modułów kodu od modułów interfejsu może być zrealizowane bezpośrednio przy pomocy narzędzi języka. Część ta opisuje kilka sposobów zrealizowania tego zadania.
Motywacja
Pierwszą motywacją dla oddzielenia elementów HTML od kodu jest umożliwienie ponownego wykorzystania kodu oraz jego łatwiejszej konserwacji. W wszystkich przykładach umieszczonych do tej pory w książce, HTML i PHP były wymieszane w celu otrzymania krótkich i prostych przykładów. W przypadku tworzenia kodu prawdziwego kodu technika ta jest niewygodna i powoduje powstanie trudnych do analizy skryptów. Dla przykładu, skrypt z wydruku 12.1 zawiera fragment strony WWW ze zintegrowanym kodem PHP i HTML.
Wydruk 12.1. PHP i HTML w jednym skrypcie
SetSQL( $aSQL );
Oprócz tego, że przykład jest niekompletny, Wydruk 12.1 pokazuje jak skomplikowana może stać się strona HTML z wbudowanym PHP. Nawet pomocą edytorów wyróżniających składnię, zlokalizowanie bloków kodu może być trudne.
Problemy z utrzymaniem tego typu skryptów wykraczają jednak poza podstawowe problemy z czytelnością kodu. Równie trudno jest wprowadzać zmiany zarówno do kodu, jak i wyglądu strony bez wpływania na inne elementy. Na przykład, załóżmy, że projektanci uaktualnią wygląd przycisków nawigacji i muszą być one umieszczone w witrynie. Odpowiedź na pytanie kto powinien wprowadzić zmiany jest trudna, ponieważ projektanci mogą nie mieć wystarczająco dużo doświadczenia, aby nie popsuć kodu podczas wprowadzania zmian, a programiści mogą być zmuszeni uaktualniać fragmenty kodu jedynie w celu zmiany wyglądu. W obu przypadkach wynikiem są opóźnienia w projekcie. Można tego uniknąć stosując lepsze praktyki projektowe.
Jeżeli twoja firma zamierza dostarczać wysokiej jakości i łatwe do konserwacji aplikacje WWW, tworzenie stron za pomocą przedstawionej metody nie powinno być stosowane. Dodatkowo, jeżeli zainwestowano w projekt interfejsu, nie należy tego marnować tworząc aplikację utrudniającą wprowadzanie prostych zmian. Teraz zostaną zademonstrowane dostępne w PHP metody integrowania oddzielnych modułów kodu i projektu.
Implementacja
Najprostsza metodą integracji osobnych modułów jest wykorzystanie funkcji PHP include() lub require(). Metoda ta wymaga umieszczenia elementów projektu HTML w osobnych plikach, które są używane przez moduły kodu PHP w czasie ich wykonywania. Na przykład na wydruku 12.2 i 12.3 umieszczone są fragmenty projektu strony rozdzielonej na nagłówek i stopkę. Na wydruku 12.4 pokazano sposób integracji tych segmentów z dynamicznie tworzonym fragmentem strony.
Wydruk 12.2. Fragment z nagłówkiem HTML
Nowe książki wydawnictwa Helion
Wydruk 12.4. Skrypt łączący kod z projektem
Nowe książki wydawnictwa Helion
Nowości wydawnictwa Helion
Mimo, jest to bardzo prosty przykład, pokazuje on w jaki sposób można użyć funkcji include() w celu integracji HTML i kodu, co ułatwia tworzenie efektywnych i łatwych do modyfikacji aplikacji. Na wydruku 12.1 pokazany jest wygląd wynikowej strony w przeglądarce. Przykład ten pokazuje wartość oddzielenia kodu od HTML. Jeżeli projekt nagłówka lub stopki ulegnie modyfikacji, należy zmienić jedynie pliki HTML.
Rysunek 12.1. Łączenie HTML i kodu PHP przy użyciu include()
Zamiast funkcji include() lub reqiure(), można również wykorzystać standardowe funkcje obsługi plików dostępne w PHP w celu odczytania plików HTML i dołączenia ich do strony. Metoda ta pozwala na większą kontrolę nad obsługą plików, w tym odszukiwanie plików i obsługę błędów. Użycie własnych funkcji dołączania plików pozwala na to, aby w plikach HTML nie było żadnego kodu PHP.
Kolejne wydruki zawierają bardziej szczegółowy przykład wykorzystania poprzedniej techniki wykorzystując funkcje obsługi plików zamiast funkcji include(). Dodatkowo użyte zostały kaskadowe arkusze stylów (CSS) w celu zapewnienia większych możliwości zmiany wyglądu strony. Na wydruku 12.5. i 12.6. ponownie jest umieszczony nagłówek i stopka, natomiast na wydruku 12.7 znajduje się warstwa logiczna strony. Dla celów tej demonstracji utworzone zostały dwa osobne pliki CSS.
Wydruk 12.5. Nagłówek HTML
Nowe książki wydawnictwa Helion
Każdy z dodatkowych plików szablonów, które zostały do tej pory pokazane, zawierają swoje zmienne FastTemplate i aby szablony działały prawidłowo, muszą im zostać przypisane wartości. Jeżeli nie zostanie przypisana zmienna FastTemplate, wygenerowane zostaną następujące ostrzeżenia:
[Wed Sep 12 19:42:38 2001] [error] [FastTemplate] Warning: no value found for variable: {PAGE_HEADER}
[Wed Sep 12 19:42:38 2001] [error] [FastTemplate] Warning: no value found for variable: {PAGE_CONTENT}
[Wed Sep 12 19:42:38 2001] [error] [FastTemplate] Warning: no value found for variable: {YEARS}
Dodając nowe pliki szablonów należy również zmienić główny plik PHP. Na wydruku 12.12 pokazany jest nowy skrypt PHP używający zagnieżdżonych szablonów.
Wydruk 12.12. Zagnieżdżone pliki szablonów
define( array( 'basic' => 'sample_1.tpl',
'copyright' => 'copyright.tpl',
'body' => 'body.tpl' ) );
$aBodyText = "Bardzo krótka zawartość strony. ";
for ( $nIndex = 1; $nIndex <= 10; $nIndex++ )
{
$aBodyText .= "$nIndex ";
}
$aStartYear = 1997;
$aCurrentYear = GetCurrentYear();
$aYears = "$aStartYear";
for ( $nIndex = $aStartYear + 1; $nIndex <= $aCurrentYear; $nIndex++ )
{
$aYears .= ", $nIndex";
}
$aTemplate->assign( array( 'TITLE' => 'Lepszy przykład',
'BODY_COLOR' => 'white',
'YEARS' => $aYears,
'PAGE_HEADER' => 'Lepszy przykład',
'PAGE_CONTENT' => $aBodyText
) );
$aTemplate->parse( 'BODY', 'body' );
$aTemplate->parse( 'COPYRIGHT', 'copyright' );
$aTemplate->parse( 'PAGE', 'basic' );
$aTemplate->FastPrint( 'PAGE' );
?>
W przykładzie tym zdefiniowano dwa dodatkowe pliki szablonów nadając im nazwy copyright i body. Ponieważ te pliki szablonów zawierają własne zmienne FastTemplate, zmiennym tym należy przypisać wartości. Wartość zmiennej YEARS jest generowana automatycznie, więc dane o prawach autorskich są zawsze aktualne. Zmienna $aBodyText posiada identyczną wartość jak w poprzednim przykładzie. Należy zauważyć, że w tym rozdziale zmienne BODY i COPYRIGHT nie są ustawiane w metodzie assign(). Zamiast tego zmienne te otrzymują wartości przy wywołaniu metody parse() na końcu tego skryptu. Wynik działania tego skryptu jest pokazany na rysunku 12.5.
Rysunek 12.5. Wynik działania zagnieżdżonych szablonów FastTemplate
Klasa FastTemplate jest potężnym narzędziem, za pomocą którego można tworzyć bogate i złożone projekty interfejsu. Aby lepiej zilustrować tą technikę w kolejnym przykładzie wrócimy do przykładu aplikacji dostarczającej najnowszych wiadomości. Zamiast wykorzystywać do tego celu pliki dołączane, w kodzie tym wykorzystana zostanie siła klasy FastTemplate.
Na wydrukach 12.13, 12.14 i 12.15 umieszczony jest kod HTML szablonów tworzących podstawowy układ strony, treść i element wiadomości. W przykładzie tym użyty jest szablon zawierający prawa autorskie, wykorzystany w poprzednim przykładzie.
Wydruk 12.13. Podstawowy szablon dla aplikacji dostarczającej wiadomości (ft_news_base.tpl)
{TITLE}
{NEWS_BODY}
Wydruk 12.14. Szablon treści w aplikacji wiadomości (ft_news_body.tpl)
Nowości wydawnictwa Helion
{NEWS_ITEMS}
{COPYRIGHT}
Wydruk 12.15. Szablon elementu wiadomości (ft_news_item.tpl)
Na wydruku 12.16. zamieszczony jest skrypt generujący stronę z nowościami. Skrypt ten jest bardziej skomplikowany niż w poprzednim przykładzie, ale większość kodu pochodzi z poprzednich przykładów.
Wydruk 12.16. Główny skrypt aplikacji
define( array( "base" => "ft_news_base.tpl",
"body" => "ft_news_body.tpl",
"item" => "ft_news_item.tpl",
"copyright" => "copyright.tpl" ) );
// generowanie roku dla treści praw autorskich
$aStartYear = 1997;
$aCurrentYear = GetCurrentYear();
$aYears = "$aStartYear";
for ( $nIndex = $aStartYear + 1; $nIndex <= $aCurrentYear; $nIndex++ )
{
$aYears .= ", $nIndex";
}
$aTemplate->assign( array( "YEARS" => $aYears,
"TITLE" => "Nowości wydawnictwa Helion" ) );
// Tworzenie obiektu klasy news_db i generowanie elementów wiadomości
$aDB = new news_db;
$aDB->query( "select * from news order by date desc limit 5" );
while( $aDB->next_record() )
{
$aNewsID = $aDB->f( "news_id" );
$aAuthor = $aDB->f( "author" );
$aTitle = $aDB->f( "title" );
$aSynopsis = $aDB->f( "synopsis" );
$aURL = "full_story.phtml?news_id=$aNewsID";
$aTemplate->assign( array( "NEWS_TITLE" => $aTitle,
"NEWS_AUTHOR" => $aAuthor,
"NEWS_SYNOPSIS" => $aSynopsis,
"FULL_STORY_URL" => $aURL ) );
$aTemplate->parse( "NEWS_ITEMS", ".item" );
}
$aTemplate->parse( "COPYRIGHT", "copyright" );
$aTemplate->parse( "NEWS_BODY", "body" );
$aTemplate->parse( "BASE", "base" );
$aTemplate->FastPrint( "BASE" );
?>
W przykładzie tym funkcja generująca rok dla tekstu o prawach autorskich pochodzi z poprzednich przykładów, a obsługa bazy danych z poprzedniej realizacji aplikacji wiadomości. Zauważmy, że na początku skryptu wyłączone zostały ostrzeżenia PHP, ponieważ ostrzeżenie generowane przez FastTemplate zostaną omówione później.
W skrypcie tym zdefiniowane zostały cztery pliki szablonów. Na początku skryptu inicjowane są dwie główne zmienne FastTemplate, YEARS i TITLE reprezentujące odpowiednio rok praw autorskich i tytuł strony.
Kolejną główną funkcją skryptu jest dynamiczne dodawanie kolejnych wiadomości. Zostało to zrealizowane przez pobranie pięciu najnowszych wiadomości z bazy danych i wypisanie ich przy pomocy pętli. W każdym przebiegu pętli przetwarzany jest szablon item i dodawany do zmiennej FastTemplate NEWS_ITEMS. Dodawanie to jest zrealizowane poprzez dodanie kropki (.) przed nazwą szablonu. Dlatego właśnie w pierwszym przebiegu pętli FastTemplate generuje ostrzeżenie wskazujące, że zmienna NEWS_ITEMS nie jest zainicjowana. Po ustawieniu w pętli wartości zmiennej NEWS_ITEMS przetwarzana jest reszta szablonów a następnie drukowana strona.
Poprzedni przykład pokazuje w jaki sposób można wykorzystać klasę FastTemplate do generowania powtarzających się elementów, takich jak treść kolejnych wiadomości. Podobna konstrukcja może być wykorzystana do tworzenia wierszy tablicy lub listy łączy. Po poznaniu podstawowych założeń używanie FastTemplate staje się niezwykle naturalne.
Oczywistą zaletą klasy FastTemplate jak również innych systemów szablonów jest to, że elementy projektu strony mogą być tworzone i zmieniane niezależnie od kodu aplikacji. Mimo, że wykorzystanie systemu szablonów wymaga nieco innego myślenia w trakcie projektowania, jest ono warte zainteresowania.
Zaawansowane techniki użycia FastTemplate
W poprzednich rozdziałach dwa zagadnienia były z rozmysłem odsuwane aż do tego rozdziału. Pierwsze zostało wspomniane w rozdziale 7. "Sesje i stan aplikacji", w którym mówiono o lepszych sposobach przenoszenia identyfikatora sesji w aplikacji. Drugie znalazło się w rozdziale 9. "Niezależność od przeglądarki", gdzie znalazła się sugestia, że system szablonów może być alternatywną metodą dostarczania zawartości zależnej od typu przeglądarki. W tej części skupimy się na tych dwóch zagadnieniach.
Pierwsze zagadnienie, przesyłanie identyfikatora sesji, powinno być w tym momencie dosyć oczywiste. Wykorzystując szablony projekt może zawierać dynamiczne łącza URL generowane w kodzie PHP. Podstawowy przykład szablonu nawigacyjnego zamieszczony jest na wydruku 12.17.
Wydruk 12.17. Szablon nawigacji (navi.tpl)
począteknowościłącza
Właściwe adresy URL dla łączy mogą być tak generowane, aby zawierały identyfikator sesji, lub inny specyficzny dla aplikacji. Inną zaletą wykorzystania takich adresów jest łatwa modyfikacja położenia stron w czasie pracy aplikacji. Na wydruku 12.18 zamieszczony jest skrypt generujący dynamiczne adresy URL dla poprzedniego szablonu.
Wydruk 12.18. Szablon nawigacji
define( array( 'navi' => 'navi.tpl' ) );
$aTemplate->assign( array( 'HREF_INDEX' => MyGenURL( 'HREF_INDEX' ),
'HREF_NEWS' => MyGenURL( 'HREF_NEWS' ),
'HREF_LINKS' => MyGenURL( 'HREF_LINKS' ) ) );
$aTemplate->parse( 'NAVI', 'navi' );
$aTemplate->FastPrint( 'NAVI' );
?>
Funkcja MyGenURL() jest głównym elementem skryptu. Pobiera ona symboliczną nazwę łącza i zwraca prawdziwą lokalizację strony wraz z dołączonymi danymi sesji. Funkcja taka ma dodatkową możliwość obsługi nieznanych nazw łączy. Pozwala to unikać brzydkich komunikatów "HTTP 404: Page Not Found" spotykanych we wielu aplikacjach WWW.
Wykorzystanie szablonów do dostarczania treści zależnych od przeglądarki również jest korzystne. W rozdziale 9. zasugerowane były metody warunkowego dołączania plików lub przekierowania użytkownika do katalogu odpowiadającego używanej przeglądarce. Używając szablonów preferowana jest pierwsza metoda. Problemem z przekierowaniem jest to, że użytkownik może wysłać łącze do strony do osoby używającej innej przeglądarki. Przykład umieszczony na wydrukach 19., 20., 21. i 22. pokazuje w jaki sposób można zintegrować treści zależne od typu przeglądarki z szablonami. Na wydruku 12.19. pokazany jest główny szablon strony. Wydruk 12.20. i 12.21. to strony zależne od możliwości przeglądarki, natomiast wydruk 12.22 zawiera skrypt PHP.
Wydruk 12.19. Podstawowy szablon strony (base_basic.tpl)
{TITLE}
{NAVI}
Wydruk 12.20. Menu oparte o Flash (flash_menu.tpl)