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 2 Spis Treści

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 PHP – Kompendium wiedzy 3

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 4 Spis Treści

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 5 PHP – Kompendium wiedzy

DYREKTYWY KONFIGURACJI MOŻLIWOŚCI PRZEGLĄDAREK ................................................................................ 389 DYREKTYWY KONFIGURACJI ZUNIFIKOWANEGO ODBC ..................................................................................... 389 DODATEK E. ZASOBY SIECI.......................................................................................................................... 390

Spis Treści

6

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 • Nazwy plików i katalogów zaznaczone są czcionką pochyłą. • Komendy i elementy języka zaznaczone są czcionką o stałej
szerokości. 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.

Więcej na ten temat znajduje się w Wstęp 8 . Nie jest to szczególnie interesujący. Jest to język programowania osadzany w HTML składniowo podobny do C. Wydruk 1.11 działającym w systemie RedHat 6. ponieważ pozwala on na szybkie budowanie prototypów.Od autora Od około trzech lat tworzę aplikacje WWW przy użyciu PHP i ASP. Czym jest PHP PHP to język programowania przeznaczony dla programistów WWW pozwalający na szybkie tworzenie dynamicznych aplikacji WWW. przedstawiony jest przykład kodu PHP.5.net.1 zainstalowany na Windows NT. Nie będę opisywał różnic pomiędzy PHP i innymi tego typu narzędziami i nie będę zajmował się historią PHP. Oznacza to. identycznie jak w przypadku zwykłych stron. ?> </body> </html> Po uruchomieniu tego przykładu (poprzez odpowiednio skonfigurowany serwer WWW) generowany jest kod HTML zamieszczony na wydruku 2. że kod ten jest wykonywany na serwerze WWW a nie na kliencie. Do edycji plików HTML i PHP wykorzystuję edytor Allaire Homeite 4. Oficjalnym rozwinięciem skrótu PHP jest „PHP: Hypertext Preprocessor” (preprocesor hipertekstu). Celem tej książki jest przekazanie innym programistów użytecznych informacji. Zamiast tego pokażę zastosowanie PHP do stworzenia aplikacji WWW. sposoby przeniesienia istniejącego kodu do nowych projektów WWW. Omówię również inżynierię programowania w projektach WWW. ale pokazuje jak łatwo można umieszczać kod PHP w kodzie HTML. Fundamentem mojego sukcesu było użycie PHP. Prosty przykład kodu PHP <html> <head> <title>Prosty przykład kodu PHP</title> </head> <body> <?php echo "Witajcie w PHP!" . że do stworzenia strony był używany PHP. www.1 (poprawka 2) na Apache 1. Do testowania małych fragmentów kodu stosowałem następujący szablon HTML do którego wklejałem odpowiedni kod PHP: <html> <head> <title>Nazwa przykładu</title> </head> <body> <!-. jako niezależny przedsiębiorca.php. Wynik działania wydruku 1 <html> <head> <title>Prosty przykład kodu PHP</title> </head> <body> Witajcie w PHP! </body> </html> Preprocesor PHP wykonuje cały kod zawarty pomiędzy znacznikami <?php i ?> umieszczonymi w kodzie HTML i zwraca wynik w postaci tekstu. Przykłady kodu Zamieszczone przykłady kodu były tworzone i testowane pzy użyciu PHP 4. Otrzymuje ona po prostu strumień kodu HTML. Perla i Javy.1. że przeglądarka nie wie.Kod PHP wkleić poniżej --> </body> </html> Większe fragmenty kodu były tworzone od razu razem z kodem HTML.3. Wydruk 2. Wszystkie te informacje można znaleźć na oficjalnej witrynie PHP. Przedstawię również kilka przydatnych narzędzi napisanych dla PHP.0. Na wydruku 1. Należy pamiętać. oraz jest wystarczająco wydajny i pewny nawet do tworzenia dużych aplikacji WWW.

FreeBSD i nawet na Windows. Możliwy jest również dostęp do usług sieciowych takich jak IMAP.części „Specjalne wymagania przy programowaniu WWW”. PHP może działać jako program CGI lub może być zainstalowany jako moduł Apache lub rozszerzenie ISAPI. Ponieważ jest on tak popularny. od Apache na Linuksie do IIS na Windows NT. istnieje ogromna grupa programistów i konsultantów. W celu utworzenia najbardziej elastycznego środowiska pracy należy samodzielnie skompilować i zainstalować PHP. POP3. PHP współpracuje z wieloma systemami baz danych. na przykład na Linuksie. 9 PHP – Kompendium wiedzy . NNTP i TTP. może być skompilowany na wielu różnych platformach. Więcej informacji na temat dostępnych zasobów Sieci znajduje się w części „Zasoby” na końcu książki. Pozwala on również na otwieranie gniazd sieciowych i podłączanie się do innych protokołów TCP/IP. W lutym 2000 roku około 1400000 domen korzystało z PHP. PHP może być użyty we wielu konfiguracjach serwerów. możesz zastosować binarną dystrybucję PHP. Dostępne są również binarne dystrybucje dla Win32. którzy mogą odpowiedzieć na pytania. Gdzie szukać pomocy Pomoc można uzyskać na witrynie PHP oraz poprzez kilka grup dyskusyjnych i wysyłkowych. Dzięki temu może on działać z praktycznie każdym serwerem WWW. Ponieważ PHP jest rozprowadzany głównie w postaci kodu źródłowego. Jeżeli wolisz szybko zacząć pracę. Pozwala to na bardzo łatwe tworzenie aplikacji WW korzystających z informacji zapisanych w bazie danych. Dlaczego powinieneś użyć PHP PHP jest pełnowartościowym językiem programowania pozwalający na tworzenie aplikacji WWW z wszystkimi potrzebnymi funkcjami.

Dziękuję Michaelowi Justin za pomoc przy konwerterze RTF do HTML firmy Scrooge. Zdobył licencjat na uniwersytecie Arizona State University w roku 1994. Dziękuję również Michaelowi C. należy podziękować całemu zespołowi tworzącemu PHP. firmą konsultingową specjalizującą się w oprogramowaniu. Dziękuję pani Barton. Intechra LLC specjalizuje się w tworzeniu oprogramowania dla WWW. Na koniec najważniejsze podziękowania należą się mojej żonie i córce za umożliwienie mi zakończenia tej pracy. Battilana za pomoc przy Cloanto Currency Server. Cała część zawierająca skorowidz funkcji jest ich zasługą. Idaho. Szczególne podziękowania należą się Rebece Young za wsparcie i pomoc w technicznych aspektach pisania książki. Dziękuję rodzicom i braciom za nieustanne wsparcie nawet. Podziękowania dla Nate Weiss za pomoc przy użyciu deserializera WDDX dla JavaScript.net. dla Johna Kos za pomoc przy unixODBC i EasySoft ODBC-ODBC Bridge. która ma siedzibę w Rexburg. pani Smith i panu Wakefield. To oni spędzili setki lub tysiące godzin tworząc ten wspaniały język programowania i bogatą dokumentację. Dziękuję Josephowi Harris (znany jako CDI) za klasę FastTemplate oraz inne fantastyczne narzędzia dostępne na witrynie The Webmasters. który niezmiernie pomógł mi swoimi trafnymi uwagami i informacjami. Dziękuję Richardowi Litofski za pomoc przy BrowserHawk. gdy w latach osiemdziesiątych spędzałem całe noce na pisaniu programów w Apple Basicu. Teraz znów możemy wieczorami chodzić skakać na trampolinie.net/. Można się z nim skontaktować pod adresem blake@intechra.net.Podziękowania Na początku chciałbym podziękować wszystkim z wydawnictwa McGraw-Hill za umożliwienie mi zrealizowania tego zadania. http://www. Dziękuję Tracy Ard za pożyteczne komentarze do tej pracy oraz za jego niezmienną przyjaźń. Dziękuję Nickowi Bradbury za pozwolenie wykorzystania informacji i rysunków z edytora TopStyle. za stworzenie tego świetnego produktu. mojemu redaktorowi technicznemu. O autorze Blake Schwendiman rozpoczął programowanie w 1980 roku rozpoczynając od Apple IIe i języka Basic. Dziękuję Mattowi Wilson za umożliwienie mi wykorzystania w przykładzie do książki kodu MWeather. 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. głównego programisty ODBCODBC Bridge.intechra. W chwili obecnej Blake zarządza firmą Intechra LLC. którzy mieli ogromny wpływ na moje pisanie. Wstęp 10 . Dla Sama Ockman za umożliwienie wykorzystania w książce rysunku serwera Penguin 1U. Oczywiście. Wiele osób z tego zespołu pomagało mi w pracy nad książką. Dziękuję Johnowi Steele. Podziękowania dla Ali Ersheid za umożliwienie wykorzystania w książce dokumentacji CyberCash. Blake ma żonę Holy i trzyletnią córkę. Dla Martina Evans. moim nauczycielom angielskiego z liceum.

Jeżeli korzystasz z serwera IIS (Internet Information Server) lub PWS (Personal Web Server) zalecane jest użycie modułu ISAPI. W przypadku Windows zaleca się pobranie binarnej instalacji PHP. Szczegółowe dane na temat określonej platformy można również znaleźć na witrynie www. Ze strony zawierającej pakiety instalacyjne można również pobrać poprzednie wersje programów. Instalacja binarna dla Windows zawiera zarówno wersję CGI (Common Gateway Interface) PHP. Ponieważ pakiet PHP może działać na wielu serwerach WWW i systemach operacyjnych. ale podane informacje są wystarczająco uniwersalne i mogą być wykorzystane przy konfigurowaniu środowiska pracy na innych platformach. Solaris itp. Ponieważ jednak niektóre dystrybucje Uniksa zawierają binarną dystrybucję PHP. Wersja CGI powoduje. Binarna instalacja dla Windows W PHP prawie wszystkie operacje można wykonać na kilka sposobów. dokumentację i narzędzia pomocnicze.net.net umieszczone jest kilka wariantów tego pakietu. Poprzednie wersje mogą być potrzebne. że ilustrują ogólne zasady instalacji pakietu PHP na większości platform. w rozdziale tym znajdą się szczegółowe opisy instalacji na jedynie kilku platformach. jeżeli masz już gdzieś zainstalowane PHP i nie chcesz ryzykować niekompatybilności. że PHP jest uruchamiany za każdym odwołaniem do strony. więc jest mniej efektywny od dynamicznego modułu jakim jest rozszerzenie ISAPI. Instalowanie wersji binarnej Po pobraniu binarnej dystrybucji PHP. Najczęściej binarna instalacja PHP jest przeznaczona dla Windows. Są to często spotykane konfiguracje serwerów WWW i są one na tyle różne. należy go poprawnie zainstalować i skonfigurować w używanym środowisku interpreter PHP. Platformy uniksowe to między innymi Linux. W przypadku serwerów uniksowych zaleca się pobranie pakietu zawierającego kompletny kod źródłowy i przeprowadzenie samodzielnej kompilacji. Moduł ISAPI jest również ze swojej natury bezpieczniejszy od programu CGI. jak również wersję ISAPI. BSD. opisany zostanie również taki przypadek. Na witrynie www. Najnowsza wersja zawsze znajduje się na górze listy. Kompilacja i instalowanie PHP Wstęp Zanim rozpoczniemy naukę języka PHP. .Rozdział 1.php. instalacja jest banalna. Pobieranie PHP Pierwszym krokiem do rozpoczęcia pracy z PHP jest zaopatrzenie się w kopię interpretera PHP.php. W rozdziale tym opisane zostaną szczegółowo Apache dla Linuksa oraz IIS dla Windows NT.

Konfigurowanie IIS Teraz należy kliknąć przycisk Dodaj i wprowadzić potrzebne informacje.dll do katalogu systemowego Windows (zwykle \windows\system w Windows 95 lub \winnt\system32 w Windows NT). tak jak jest to pokazane na rysunku 1. ale nie jest to konieczne do ich użycia.3. należy skopiować pliki php4ts.1.2.dll i msvcrt. najlepszym rozwiązaniem będzie użycie PHP w postaci modułu ISAPI. pokazany jest proces dodawania mapowania rozszerzenia phtml do modułu ISAPI PHP. Następnie należy tak skonfigurować IIS lub PWS. Są to współdzielone biblioteki niezbędne do prawidłowej pracy każdej wersji PHP dla Windows. Rozdział 1 – Kompilacja i instalowanie PHP 12 . Rysunek 1.2. Następnie w oknie Właściwości należy przejść na zakładkę Katalog macierzysty i kliknąć przycisk Konfiguracja. Na rysunku 1. Aby zainstalować taką wersję. znajduje jest rozwinięte menu pokazujące położenie tego programu w Windows NT. Na rysunku 1. Dodatkowo można skopiować do katalogu systemowego inne pliki . Serwer IIS można konfigurować za pomocą konsoli konfiguracji zainstalowanej w menu Option Pack.1.Instalowanie PHP w postaci modułu ISAPI Jeżeli korzystasz z serwera IIS. aby korzystał z modułu ISAPI do obsługi plików php. 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. PWS lub innego serwera WWW obsługującego moduły ISAPI. Rysunek 1.dll. Opcja ta pozwala na dodawanie i edycję skojarzeń.

1.4.Rysunek 1. Rysunek 1. jak pokazany na wydruku 1. Dodawanie mapowania dla rozszerzenia w IIS Po dodaniu mapowania zmiany są od razu widoczne w oknie dialogowym Konfiguracja aplikacji. Na rysunku 1. Czasami może być pożyteczne skojarzenie niektórych rozszerzeń z modułem ISAPI a niektórych z programem CGI. powinieneś zobaczyć ekran z informacjami na temat instalacji PHP.4. ?> </body> </html> 13 PHP – Kompendium wiedzy . Wydruk 1. Testowy skrypt PHP <html> <head> <title> phpinfo() </title> </head> <body> <?php phpinho().1.3. 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. Jeżeli wszystko jest skonfigurowane poprawnie. na przykład taki. i otwierając go poprzez twój serwer. dla PHP4 jako CGI oraz PHP4 jako ISAPI. 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. Jest to przydatne przy testowaniu różnic pomiędzy wersjami 3 i 4 PHP. Na rysunku widać mapowania dla PHP3. pokazana jest konfiguracja mojego serwera WWW.

że nie powinien być stosowany w środowisku produkcyjnym. Różne serwery WWW mają różne metody określenia mapowania rozszerzeń.rpm>. ale odwołuje się do programu w postaci pliku wykonywalnego.php. Dyrektywa konfiguracji jest podobna do poprzedniej. należy przeprowadzić instalację PHP jako CGI. różnice występują jedynie przy mapowaniu rozszerzeń. kolejnym krokiem będzie modyfikacja pliku konfiguracyjnego httpd. Zaletą użycia plików RPM jest łatwość instalacji. Poniżej przedstawimy sposób konfiguracji Apache.Trzeba pamiętać. Inne instalacje binarne Niektóre instalacje Uniksa posiadają instalację binarną PHP zintegrowaną z instalacją serwera WWW. ale może ona sprawiać problemy. udostępniają również binarną instalację na swoich witrynach. Trzeba utworzyć skojarzenie pomiędzy rozszerzeniem pliku a wewnętrznym typem stosowanym przez serwer. Oczywiście należy podać właściwą ścieżkę do pliku wykonywalnego. Po instalacji należy ręcznie skonfigurować serwer WWW tak.php4.inc jako pliki typu application/x-httpd-php. Niektórzy dostawcy. 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. Niezależnie od tego. Zamiast wybierać bibliotekę . ponieważ plik RPM zawiera gotową do użycia odpowiednio skompilowaną wersję programu. Z powodu istnienia wielu wariantów Uniksów. Nie trzeba martwić się szczegółami procesu kompilacji.4. Wadą jest to. pierwszy krok konfiguracji jest zawsze taki sam.php. więc oprócz nazwy pliku wykonywalnego należy podać opcje linii poleceń %s %s. Jest to pokazane na rysunku 1. Następna część rozdziału opisuje użycie PHP jako CGI. na przykład Red Hat. przedstawiony na wydruku 1. aby Apache załadował moduł PHP: LoadModule php4_module libexec/libphp4. Binarna dystrybucja PHP ułatwia szybkie rozpoczęcie pracy z PHP w Uniksach. znalezienie gotowej wersji działającej na określonym Rozdział 1 – Kompilacja i instalowanie PHP 14 .conf. problemem dla początkujących może być nawet wybór właściwego pliku. że w pakiecie instalacyjnym PHP znajduje się uwaga na temat stanu modułu ISAPI która ostrzega.conf tak. Instalacja jest bardzo podobna do tej przedstawionej powyżej. że Apache uważa wszystkie pliki z rozszerzeniami . że w celu zapewnienia odpowiedniej stabilności powinna być użyta wersja CGI. Sugeruje się. dla rozszerzenia . Poza tym w pliku RPM nie zawsze są ustawione wszystkie potrzebne opcje konfiguracji. możesz go zainstalować wydając polecenie rpm -i <plikrpm. 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. aby korzystał z zainstalowanych właśnie plików binarnych PHP. należy wprowadzić nieco inne zmiany do pliku konfiguracji httpd. Robi się to dodając do pliku konfiguracyjnego następujące linie: AddType application/x-httpd-php . Serwer IIS lub PWS wysyła parametry do pliku wykonywalnego CGI. Zasoby sieci na temat instalacji PHP na różnych serwerach WWW dla Windows można odszukać za pomocą wyszukiwarki umieszczonej na witrynie www. należy wybrać plik php.exe. Do Apache dla Windows istnieje świetny podręcznik dostępny pod adresem www. niezbędne do prawidłowego działania programu. że masz zainstalowane PHP w postaci modułu Apache. Instalacja taka jest wykonana w formie plików RPM (Red Hat Package Manager). Dla większości użytkowników katalogi te są prawidłowe.html. czy PHP będzie działało jako program CGI czy w postaci modułu.1.: 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.php AddType application/x-httpd-php . Zakładając.php. .net.phtml i . Jeżeli masz plik RPM z PHP.net/manual/config-apache-nt.dll ISAPI. Do przetwarzania tego typu plików wykorzystywane jest PHP.phtml AddType application/x-httpd-php .inc Dyrektywy te powodują. aby zaczęły działać nowe ustawienia.so Jeżeli zainstalowana została wersja CGI. że z powodu wielu możliwych wariantów platform dla Uniksa. Inne serwery WWW wymagają przeprowadzenia podobnych czynności. Po wprowadzeniu zmian należy ponownie uruchomić serwer WWW. Powoduje to zainstalowanie plików binarnych do katalogów określonych przez twórcę pliku RPM.

15 PHP – Kompendium wiedzy .systemie może być czasami trudne. Można również nie korzystać z tych opcji przy kompilacji PHP. może okazać się. Operacje opcjonalne są zaznaczone czcionką pochyłą. Na koniec trzeba zainstalować gotowe PHP i zrestartować serwer WWW. należy odszukać w dokumentacji PHP i serwera WWW szczegóły postępowania. Jeżeli pracujesz na platformie. Druga i trzecia linia jest nieobowiązkowa. Kompilacja modułu CGI Kompilacja PHP do postaci wykonywalnego modułu CGI jest najprostszą metodą kompilacji i dobrym rozwiązaniem. W wielu przypadkach będzie to bardziej czasochłonne niż ściągnięcie kodu źródłowego. Dla każdej platformy istnieje kilka sposobów kompilacji PHP. Jeżeli nie korzystasz z Apache. Oczywiście systemy te różnią się między sobą. Proces kompilacji jest właściwie taki sam dla każdego typu pliku wynikowego. Solaris i inne. W zależności od szybkości komputera. Jeżeli wprowadzane są poważne zmiany w konfiguracji lub zmieniasz typ kompilacji z CGI na inny. Proces ten zostanie opisany w kolejnej części rozdziału. przeprowadzenie całej konfiguracji i kompilacji może zająć dosyć dużo czasu. Kompilowanie PHP w Uniksach W tej części rozdziału przedstawione zostaną informacje na temat kompilowania PHP na platformie Unix. jako najlepsze rozwiązanie dla większości aplikacji. który ustawia opcje kompilacji. jako moduł ładowany dynamicznie lub jako statyczną bibliotekę. że Unix określa całą rodzinę systemów. 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. ponieważ polecenia w nich umieszczone są używane jedynie do wyczyszczenia poprzedniej konfiguracji i pozostałości po poprzedniej kompilacji. ale wiele z kroków niezbędnych do kompilacji PHP jest identycznych. Odwołanie do <php_dir> powinno być zamienione na nazwę twojego katalogu bazowego PHP. możesz nie mieć innego wyboru jak tylko samodzielnie kompilować PHP. Jeżeli serwerem WWW jest Apache. występują problemy z bezpieczeństwem. W kolejnych częściach zakładamy. dla której nie ma instalacji binarnej.net. Informacje na temat skryptu konfiguracyjnego są przedstawione w części poświęconej kompilowaniu modułu CGI. Więcej informacji na temat określonej platformy można odszukać za pomocą wyszukiwarki dostępnej na witrynie www. nie są one potrzebne. Jeżeli wcześniej nie konfigurowałeś ani nie kompilowałeś PHP. Na początku trzeba uruchomić skrypt configure. jeżeli nigdy wcześniej nie kompilowałeś programów dla Uniksa. Niektóre z nich nie są obowiązkowe. na którym wykonywana jest kompilacja. że ściągnąłeś już źródła PHP i rozpakowałeś je. np. aby kompilacja przebiegła prawidłowo.php. można skompilować PHP jako plik wykonywalny. W przypadku modułu CGI. Należy pamiętać. musisz dokładnie poznać proces kompilowania PHP. cd <php_dir> rm config. BSD. Przy okazji możemy zarekomendować korzystanie z PHP w postaci dynamicznie ładowanego modułu. choć czasami ich wykonanie jest niezbędne. W prawdziwej kompilacji do skryptu konfiguracyjnego dołącza się opcje określające atrybuty PHP. Jeżeli PHP zostanie statycznie dołączony do Apache. Poniżej przedstawiona jest kompletna lista operacji jakie należy wykonać. Następnie przy pomocy narzędzia make przeprowadza się kompilację.: Linux. więc zaleca się przeczytanie tego fragmentu jako wprowadzenia./configure make make install Wykonanie tych operacji spowoduje usunięcie podręcznych danych konfiguracji. każda zmiana konfiguracji wymaga większego nakładu pracy. usunięcie plików wynikowych a następnie skompilowanie PHP do postaci CGI. „Ponowne wykorzystanie kodu”). przytoczona jedynie jako przykład.cache make clean . Jest to najprostsza metoda kompilacji. skompilowanie i zainstalowanie PHP. że wykonanie czyszczenia jest niezbędne.

natomiast pozostałe są standardowymi elementami konfiguracji opisanymi w skorowidzu na końcu książki. Lista dostępnych opcji jest wyświetlana po wpisaniu: . Funkcje korzystające ze składni --enable są to zwykle wbudowane opcje PHP./configure --help with-PAKIET. fin-funcs oraz ucd-snmp-hack. że zmiany te zostaną wykryte. że PHP jest kompilowane do postaci dynamicznie ładowanego modułu Apache a nie jako program typu CGI. Po zakończeniu działania skryptu konfiguracyjnego tworzony jest plik tymczasowy config. Można przetestować poprawność kompilacji za pomocą następującego polecenia: php < /dev/null Jeżeli zobaczysz wynik podobny do poniżej przedstawionego. że skrypt konfiguracyjny poszukuje w systemie narzędzi. Pożyteczną cechą zestawu domyślnych ustawień jest to.1.cache zawierający szczegóły na temat systemu. Dodatkowo została dodana opcja -withapxs.6-i586-pc-linuxgnulibc2. że skompilowana właśnie wersja PHP nie posiada funkcji. należy użyć: --enable-FUNKCJA --enable-FUNKCJA=yes --disable-FUNKCJA --enable-FUNKCJA=no Pełna lista opcji konfiguracji znajduje się w skorowidzu na końcu książki.1 --withunixODBC=/usr/local/unixODBC --disable-debug --enabletrack-vars -./configure --with-apxs=/www/bin/apxs --with-java --with-cybercash=/home/blake/mck-3. Opcja fin-funcs powoduje dodanie własnego modułu rozszerzeń opisanego w dalszej części książki (rozdział 11. Jeżeli wprowadzisz duże zmiany do konfiguracji systemu. które być może będziemy chcieli wykorzystywać w aplikacjach. X-Powered-By: PHP/4. Nie zostało podane położenie katalogu Javy. udało ci się poprawnie skompilować i zainstalować PHP w postaci CGI. 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ę: . takie jak możliwość wykorzystywania krótkich znaczników lub obsługa protokołu FTP. wiele innych. Później omówimy to zagadnienie dokładniej. które mogą być dołączone do PHP. Pakiety są to zwykle moduły zewnętrzne. Oznacza to. sesji i wiele.2.Pozostawienie zapisanych opcji konfiguracji oraz obiektów binarnych spowoduje znaczne skrócenie czasu tworzenia PHP.0. Trzeba ponownie uruchomić skrypt konfiguracyjny. plików i innych danych systemowych. ustawić opcje potrzebne w aplikacji a następnie ponownie skompilować i zainstalować PHP. Następnie na podstawie tych danych tworzy specyficzny dla systemu skrypt za pomocą można skompilować kod. więc skrypt konfiguracyjny użyje domyślnej ścieżki do katalogu z tym pakietem. Po wykonaniu wszystkich podanych poleceń zostanie utworzony nowy plik wykonywalny — php. CyberCash. że dołączone jest do niego wiele często używanych opcji konfiguracji. często zdarza się.). na przykład obsługa bazy danych Oracle lub Javy. musisz usunąć plik tymczasowy przed kolejnym uruchomieniem skryptu konfiguracyjnego. że wymagany plik lub narzędzie nie jest odnajdywane lub niewłaściwie skonfigurowane. trzeba dodać odpowiednią opcję konfiguracji. Wszyscy. Jeżeli w czasie działania skryptu konfiguracyjnego nastąpi awaria. który pozwala na rozpoczęcie nauki języka. Większość opcji konfiguracji wpływających na dostępne funkcje PHP ma postać --enable-FUNKCJA lub -Aby dodać funkcję do PHP należy użyć jednej z poniższych form: Aby usunąć funkcję z PHP. że przytoczone polecenia umożliwiają skompilowanie PHP. która powoduje. w tym obsługa bazy danych MySQL.0. którzy nigdy nie przeprowadzali takiego procesu powinni wiedzieć. Rozdział 1 – Kompilacja i instalowanie PHP 16 .enable-fin-funcs --withsnmp=/home/blake/ucd-snmp-4. W przedstawianej konfiguracji wyłączono informacje dla debuggera oraz włączono opcje track-vars. SNMP (Simple Network Management Protocol) oraz unixODBC.2 Content-type: text/html Trzeba zauważyć. W ten sposób upewniamy się. więc badanie systemu nie musi być powtarzane przy ponownym uruchomieniu konfiguracji.2 --enable-ucd-snmp-hack Powyższe wywołanie konfiguracji powoduje dodanie do PHP obsługi Javy. ponieważ została skompilowana z użyciem tylko ustawień domyślnych. Jeżeli potrzebujesz obsługi innej bazy danych lub innego rozszerzenia.

Może być to czasochłonne i frustrujące. należy skonfigurować serwer WWW do współpracy z nowym programem./configure --prefix=/www --activate-module=src/modules/php4/libphp4. że plik ten jest umieszczony w katalogu cgi-bin serwera WWW. Zakładamy./configure --enable-module=so --enable-rule=SHARED_CORE --prefix=/www make 17 PHP – Kompendium wiedzy . Po utworzeniu PHP w postaci CGI. Apache może również przestać działać. która zawiera jedynie opcje domyślne.a make make install Dyrektywa prefix może być inna w twoim systemie. Zakładamy.conf. sprawdzić poprawność konfiguracji. należy użyć następujących poleceń: cd <apache_dir> . Wadą tej metody jest konieczność powtórnej kompilacji Apache po każdej kompilacji PHP. Kompilacja PHP jako statycznie dołączanego modułu Apache Apache pozwala na statyczne dołączanie modułów bezpośrednio do pliku binarnego Apache. można znaleźć w dokumentacji na witrynie www. Teraz należy uruchomić serwer Apache i przy wykorzystaniu skryptu testowego z wydruku 1.phtml AddType application/x-httpd-php ./configure --with-apache=<apache_dir> make make install Opcja --with-apache powoduje kompilację do postaci statycznej biblioteki oraz pozwala podać katalog z plikami źródłowymi Apache. Więcej szczegółów można znaleźć w dokumentacji do Apache.php.Wiele z pakietów oprogramowania jakie chcemy dodać do PHP musi być osobno zainstalowane. I tym razem standardowa konfiguracja wygląda następująco: AddType application/x-httpd-php . aby PHP był skompilowany do postaci dynamicznie ładowanego modułu.. ponieważ w przypadku wystąpienia kłopotów z konfiguracją PHP. gdzie można zaopatrzyć się w potrzebne pakiety. Zaletą tej metody jest możliwość kompilacji PHP bez konieczności równoczesnej kompilacji Apache. cd <php_dir> .php AddType application/x-httpd-php .php AddType application/x-httpd-php ./configure Po zakończeniu działania tego skryptu można zająć się konfigurowaniem i kompilowaniem PHP.1. Aby skonfigurować Apache. Aby Apache obsługiwał dynamicznie ładowane moduły należy go przekompilować z następującymi opcjami konfiguracji: cd <apache_dir> make clean . Przed skonfigurowaniem i skompilowaniem PHP niezbędne jest skonfigurowanie Apache. Aby skonfigurować serwer Apache należy dodać następujące dyrektywy do pliku httpd. opiszemy teraz sposób jego tworzenia. W porównaniu z wersją CGI użycie modułu pozwala poprawić wydajność aplikacji oraz zwiększyć bezpieczeństwo systemu. W zależności od rozszerzeń jakie zostały wybrane do reprezentowania plików PHP.inc Action application/x-httpd-php /cgi-bin/php Pierwsze trzy dyrektywy definiują zawartość plików z rozszerzeniami php. Aby Apache prawidłowo przetwarzał pliki PHP należy odpowiednio zmodyfikować plik httpd. należy wprowadzić odpowiednie zmiany. Ostatnia dyrektywa powoduje wysłanie wszystkich plików tego typu do pliku wykonywalnego php.phtml AddType application/x-httpd-php .inc Przedstawiony opis przedstawia jedynie bardzo prostą wersję PHP. Następnie należy skompilować serwer Apache za pomocą poleceń: cd <apache_dir> . Więcej informacji na temat tego. ale ta sama czynność może być zrealizowana jeszcze na kilka sposobów. ponieważ wskazuje ona katalog gdzie zostaną zainstalowane pliki zależne od architektury.conf: AddType application/x-httpd-php . Więcej informacji o zmianie konfiguracji kompilacji PHP znajduje się w części na temat kompilacji wersji CGI. Dyrektywy te są minimum wymaganym do konfiguracji PHP w Apache. 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. Również niektóre moduły rozszerzeń (na przykład Java) wymagają do poprawnej pracy. że na dysku jest już katalog z kodem źródłowym Apache. Jednak niektóre aplikacje wymagają zastosowania statycznie dołączanego modułu Apache.net. phtml i inc jako typ application/x-httpd-php.

który jest niezbędny do kompilacji dynamicznego modułu PHP. powinieneś na początku spróbować skompilować podstawową konfigurację.net/version4/downloads/num ber. ale pokazanie podstawowych metod kompilowania PHP do różnych postaci. takie jak gcc.php. Ja używam programu Winzip. a później uzupełniać potrzebne opcje.net/version4/downloads/bind lib_w32. Potrzebny jest również program do rozpakowywania plików. choć wersja 5 również powinna działać.tar. ale trzeba wcześniej przekompilować wszystkie biblioteki. make i bison. W poniższym opisie zakładamy użycie Visual C++. Jeżeli pracujesz w Windows 95.cache . aby przetwarzał pliki PHP. 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. Tabela 1.con/cygwin/ Narzędzia do kompilacji PHP dla www. Dokumentacja zaleca użycie Visual C++ wersja 6. Po skompilowaniu Apache z obsługą dynamicznie ładowanych modułów.make install Oprócz kompilacji Apache przedstawione polecenia przygotowują skrypt apxs. Prawdopodobnie można zastosować kompilator Borlanda. ale nie udało mi się tego zrobić. który jest używany do utworzenia wersji dla Uniksa. Tak jak w przypadku poprzednich sposobów kompilacji należy prawidłowo skonfigurować Apache./configure --with-apxs=/www/bin/apxs (pozostałe opcje) make make install Polecenia porządkujące są zalecane. można zapoznać się z opcjami konfiguracji. należy skompilować PHP w następujący sposób: cd <php_dir> make clean rm config.1. ponieważ bez problemu radzi sobie z plikami . Tabela 1.lib www. co spowoduje ponowne wygenerowanie prawidłowo skonfigurowanego skryptu. Przed rozpoczęciem pracy należy się zaopatrzyć w kilka programów i plików pomocniczych.net/extra/win32build.tar. Po skompilowaniu PHP i sprawdzeniu. Jeżeli nie kompilowałeś wcześniej PHP. więc trzeba wcześniej zainstalować ten pakiet.bat. jeżeli PHP był już kompilowany w innej konfiguracji. Zostały one opisane w dalszej części rozdziału. Kod źródłowy PHP jest identyczny jak ten. Po zapoznaniu się z procesem kompilacji jest już bardzo łatwo testować różne konfiguracje i dodawać niestandardowe rozszerzenia. trzeba dodać tą zmienną ręcznie do pliku autoexec. Problem stanowiły prekompilowane pliki lib. które można ustawiać bez potrzeby ponownej kompilacji. Ścieżka podana w dyrektywie konfiguracji --with-apxs powinna być pełną ścieżką do skryptu apxs na serwerze. Na początku należy zainstalować narzędzia Cygwin.php Pakiet Cygwin http://sources. Inne potrzebne pliki są integralną częścią dystrybucji PHP. zawiera wszystkie dodatkowe programy oraz adresy w Internecie. Również inne programy posiadają takie możliwości. Dodatkowe pliki pomocnicze i ich adresy w Sieci Program Położenie Kod źródłowy PHP www. Trzeba ręcznie dodać zmienną środowiska wskazując na położenie plików Cygwin. Jeżeli wystąpią kłopoty ze skryptem apxs można powtórnie wykonać przedstawione polecenia. Próbowałem sprawdzić.gz Zastępnik pliku resolv. gdzie były dostępne w czasie pisania książki.redhat. W Windows NT należy kliknąć prawym przyciskiem myszy ikonę Mój komputer i wybrać z menu Właściwości.php. Niektóre z tych programów są wykorzystywane w procesie kompilacji.zip Win32 Obsługa BCMath www.gz. czy działa z Apache. ponieważ Microsoft i Borland korzystają z różnych formatów tych plików.1.php.net/download. Kompilowanie PHP w środowisku Windows Kompilowanie PHP dla Windows jest na początku bardziej skomplikowanym procesem niż kompilacja PHP dla Uniksa.zip Pakiet Cygwin zawiera popularne narzędzia GNU. czy można użyć pakietu Borland C++ Builder. Teraz trzeba Rozdział 1 – Kompilacja i instalowanie PHP 18 . Po zmodyfikowaniu konfiguracji należy uruchomić Apache i wywołać skrypt testowy.php.

aby skompilować projekt. Z menu Build wybierz Set Active Project Configuration i wybierz wersję handlową biblioteki lub wersję do uruchamiania. tak jak jest to pokazane na rysunku 1. Na koniec wybierz Library files i dodaj katalog win32build\lib.6.lib.) i przy użyciu listy rozwijalnej opisanej Show directories for. Od tej pory kompilator Visual C++ będzie mógł korzystać z zainstalowanych narzędzi i plików. Następnie rozpakuj źródła PHP i plik number.dsp.zip.tar. Zmienna nazywa się CYGWIN a jej wartością jest ścieżka do katalogu. Po zakończeniu kompilacji należy skopiować plik resolv. Teraz wybierz zakładkę Directories (rysunek 1. gdzie zainstalowane są narzędzia Cygwin. Ustawienie zmiennej środowiskowej CYGWIN Następnie utwórz katalog i rozpakuj do niego zawartość pliku win32build.c i number. Teraz z listy rozwijalnej wybierz Include files i dodaj katalog z win32build\include (rysunek 1.6.5.kliknąć zakładkę Środowisko i dodać nową zmienną. W Visual C++ otwórz projekt bindlib. Naciśnij klawisz F7.gz za pomocą zewnętrznego programu lub narzędzia tar z pakietu Cygwin. Skopiuj rozpakowane pliki number.). Rysunek 1.6.5.zip. Najpierw utwórz nowy katalog i rozpakuj do niego pliki z archiwum bindlib_w32.lib do katalogu win32build\lib. Rysunek 1. Uruchom Visual C++ i wybierz Options z menu Tools. 19 PHP – Kompendium wiedzy . wybierz opcję Executable files i dodaj katalog z plikami Cygwin.h do katalogu ext/bcmath w katalogu z kodem źródłowym PHP. Ustawienie katalogów w Visual C++ Kolejnym krokiem będzie skompilowanie nowej wersji pliku resolv.

ini jest odczytywany za każdym uruchomieniem programu CGI. W tabeli 1. zamieszczone są podstawowe warianty. jak w standardowych plikach ini systemu Windows. Jeżeli potrzebujesz wersji PHP jako ISAPI lub NSAPI.dsp. Opcje te mają następujące wartości domyślne: Rozdział 1 – Kompilacja i instalowanie PHP 20 . ale gdy wszystkie potrzebne dodatki zostaną odpowiednio skonfigurowane. Projekt ten zawiera kilka konfiguracji. aby móc tworzyć rozszerzenia PHP. Zwykle przykład taki zawiera nazwę sekcji.ini Windows Katalog <windows> zwykle \windows w Windows 95 i \winnt w Windows NT Unix Można to sprawdzić za pomocą funkcji phpinfo().ini i ponownie uruchamia Apache. wystarczy wybrać odpowiednią konfigurację dla kompilacji i ponownie skompilować projekt.ini i ponowne uruchomienie serwera WWW.ini jest podzielony na sekcje. tak jak jest to pokazane na rysunku 1. ale zwykle jest to /usr/local/lib. Mechanizmy te opisane zostaną w późniejszej części rozdziału. Plik ten jest dostarczany w dystrybucji PHP jako php. Jeżeli nie znasz dobrze opcji konfiguracji. Po umieszczeniu pliku konfiguracyjnego w odpowiednim katalogu. Plik powinien być nazwany php. sposób jego konfigurowania jest taki sam. jest już proste.ini Platforma Położenie pliku php. korzystając z odpowiednich opcji konfiguracji. Plik ten zawiera obszerne komentarze opisujące przeznaczenie sekcji i opcji konfiguracji. Tabela 1. Konfigurowanie PHP Niezależnie od platformy na której działa PHP. Korzystanie z pliku php. nazwę opcji oraz wartość. cała reszta jest tak samo prosta jak w Uniksie. Rysunek 1. W pozostałej części książki czasami będą przytaczane opcje niezbędne do uruchomienia przykładów. Dla przykładu można zmienić sposób raportowania błędów przez PHP. Jak wspomniałem wcześniej.ini-dist i php. Wybór konfiguracji dla wersji CGI Skompiluj projekt i jeżeli wszystko pójdzie dobrze posiadasz już własną wersję PHP. Pierwszym krokiem będzie skopiowanie i zmiana nazwy pliku. Plik php. Gdy wszystko jest już gotowe.ini-dist.ini.Jeżeli wykonałeś wszystkie opisane wcześniej czynności.7. ponieważ plik php. rozpoczynające się od linii [nazwa_sekcji] podobnie. Platformy PHP i położenie pliku php. najtrudniejszą częścią było wstępne przygotowanie środowiska. znajdujący się w podkatalogu win32 katalogu z kodem źródłowym PHP. należy do niego wprowadzić odpowiednie zmiany. Uruchom Visual C++ i otwórz plik projektu php4ts. powinieneś rozpocząć do podstawowych ustawień z pliku php. Aby wprowadzić zmiany najczęściej zmienia się plik php. Podsumowanie kompilacji PHP Kompilowanie wersji PHP dla Windows jest za pierwszym razem dużo trudniejsze od wersji dla Uniksa.ini Zalecaną metodą zmiany konfiguracji jest modyfikacja pliku php.7. Jeżeli korzystasz z PHP w postaci programu CGI nie musisz restartować serwera. Gdy poznałeś już proces kompilowania PHP dla obu platform możesz tworzyć wysoce specjalizowane wersje PHP.ini i skopiowany do katalogu zależnego od używanej platformy. Zagadnienie to zostało opisane w rozdziale 11. Dokładna wiedza na temat procesu kompilacji PHP jest również niezbędna.2. Wykorzystuje się w tym celu plik php. jesteś gotowy do kompilacji PHP. spełniających precyzyjnie potrzeby konkretnej witryny.2. ale istnieją również inne mechanizmy zmiany opcji. Najłatwiej jest rozpocząć od skompilowania wersji CGI wybierając wersję handlową lub wersję z danymi dla debuggera.ini-optimized.

Na przykład.1. że w instalacji produkcyjnej nie chcemy wyświetlać błędów. W przeciwnym wypadku efekty mogą być niespodziewane.htaccess. należy użyć następujących dyrektyw Apache: <VirtualHost 192. Następna linia powoduje wstawianie komunikatów błędów do wynikowego kodu HTML. Tutaj przedstawione zostaną jedynie ogólne sposoby wykorzystywania tych opcji. że w obu przykładowych plikach konfiguracyjnych Apache wartość zmiennej konfiguracji error_reporting jest ustawiana za pomocą wartości numerycznej a nie stałej.testserver. należy otworzyć w edytorze plik php.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ć. Druga metoda jest wykorzystywana.com php_value error_reporting 2047 php_flag display_errors off php_flag log_errors on php_value error_log /tmp/php_log </VirtualHost> Umieszczenie tych ustawień w pliku httpd. witryna jest umieszczona na dzierżawionym serwerze zewnętrznej firmy.conf spowoduje. Jest to również użyteczne. Pełna lista znajduje się w skorowidzu na końcu książki. jeżeli określony katalog musi mieć inne ustawienia konfiguracji niż reszta witryny. Następne dwa wiersze powodują zapisywanie komunikatów błędów w pliku.net DocumentRoot /www/hosts/wwwprojects/ ServerName www. aby serwer WWW mógł zapisać w nim dane.1. Jeżeli musisz zmienić konfigurację PHP a nie masz dostępu do pliku php. a zamiast tego błędy będą zapisywane do określonego pliku.1> ServerAdmin admin@server. nie zostaną tu przedstawione wszystkie możliwe opcje. Jest o jedyny sposób poprawnego ustawienia wartości. Z powodu dużej ilości opcji konfiguracji. że konfigurując PHP poprzez dyrektywy Apache nie można używać jako wartości żadnych stałych PHP. Załóżmy. Pierwsza metoda jest użyteczna.ini i httpd. Zapisuj błędy /tmp/php_log .ini. Jest to jednak najmniej zalecana metoda. będą zapisywane w pliku /tmp/php_log.testserver.conf lub do pliku . Należy użyć dyrektyw konfiguracji php_value i php_flag do ustawienia potrzebnych opcji.ini.conf. Jest to częsta sytuacja. gdy nie jest możliwy dostęp do plików php. używają one konfiguracji określonej przez plik php. W tym celu należy stworzyć plik . Wypisuj błędy (jako część wynikowego HTML) Off .8.ini ani do httpd. Jeżeli na tej samej maszynie istnieją inne serwery wirtualne. Pierwszym sposobem jest wstawienie tych opcji do pliku konfiguracyjnego Apache httpd. Na przykład.htaccess jest wczytywany i analizowany za każdym odwołaniem do stron znajdujących się w tym katalogu.ini i odszukać opcję.htaccess.error_reporting display_errors log_errors error_log = = = = E_ALL & ~E_NOTICE . Pokaż wszystkie błędy oprócz informacji On . Można to zrealizować zmieniając konfigurację w następujący sposób: error_reporting display_errors log_errors error_log = = = = E_ALL . możesz wykorzystać pliki Apache . w tym informacje. jeżeli chcemy mieć różne ustawienia PHP dla różnych serwerów wirtualnych lub różnych katalogów. Pozwala to na posiadanie różnych konfiguracji PHP dla różnych serwerów wirtualnych lub katalogów. Pokaż wszystkie błędy Off . Zapisuj błędy do pliku błędów syslog . Oczywiście plik ten powinien mieć odpowiednio ustawione prawa dostępu. Zapisuj błędy do pliku /tmp/php_log Taka konfiguracja powoduje. Powoduje to znaczne spowolnienie serwera WWW. Aby zilustrować potęgę dostępnego mechanizmu konfiguracji na rysunku 1. że wszystkie komunikaty błędów. Należy pamiętać.com. Zwykle znajduje się tam sporo komentarzy opisujących możliwe wartości danej opcji. Zapisuj błędy do dziennika systemowego Pierwsza opcja powoduje generowanie komunikatów dla wszystkich typów błędów poza typem E_NOTICE. ponieważ plik . W obu tych przypadkach sposób zmiany konfiguracji PHP jest tak sam.conf. aby ustawić poprzednio opisane opcje konfigurujące sposób raportowania błędów. że zostanie ustawiony sposób raportowania błędów dla serwera wirtualnego o nazwie www. 21 PHP – Kompendium wiedzy . można zmienić sposób raportowania błędów dla jednego katalogu na czas uruchamiania skryptów w nim się znajdujących. Aby zmienić opcję konfiguracji. Inne metody zmiany konfiguracji PHP Istnieją dwie metody zmiany konfiguracji PHP bez konieczności modyfikacji pliku php. przedstawiony został schemat możliwości konfiguracji środowiska PHP. On .

net powinieneś być w stanie zainstalować i skonfigurować PHP na twojej platformie. Przykładami takich funkcji są error_reporting() oraz set_time_limit().8. Trzeba zauważyć. oraz na witrynie www. Elastyczność konfiguracji z zastosowaniem php. Więcej informacji na temat tych funkcji można znaleźć w skorowidzu na końcu książki. że PHP posiada wiele własnych funkcji zmieniających ustawienia konfiguracji.Rysunek 1.php. Z powodu elastyczności i dużej ilości obsługiwanych platform niemożliwe jest szczegółowe opisanie wszystkich dostępnych konfiguracji. Rozdział 1 – Kompilacja i instalowanie PHP 22 . Korzystając jednak z informacji umieszczonych w tej książce.ini oraz plików konfiguracyjnych Apache Podsumowanie W tym rozdziale przedstawiono kilka informacji niezbędnych do rozpoczęcia pracy z PHP.

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<br>"; ?> <?php echo "wyjście przy użyciu pełnych znaczników PHP<br>"; ?> <script language="php"> echo "niektóre edytory HTML nie obsługują instrukcji przetwarzania<br>"; </script> <% echo "można stosować również znaczniki w stylu ASP<br>"; %>

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
<?php echo "Test, test...<br>"; ?> <?php echo "Test, test...<br>" ?>

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
<?php echo "Witaj świecie!<br>"; // To jest jednowierszowy komentarz w stylu C++ /* To jest wielowierszowy blok komentarza */ echo "Witamy ponownie.<br>"; # To jest komentarz w stylu skryptów Uniksa ?> <?php /* Poniższa linia spowoduje wypisanie "To wyświetli nic." */ ?> To wyświetli <?php # echo "coś"; ?> nic.<br> <?php

/* echo "A tutaj mamy problem."; /* Komentarz ten jest nieprawidłowy */ */ ?>

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
<?php $int1 = 523; // liczba dziesiętna $int2 = -523; // dziesiętna ujemna $int3 = 01013; // ósemkowa reprezentacja liczby 523 $int4 = 0x20B; // szesnastkowa reprezentacja liczby 523 $float1 = 523.197; // zwykły zapis liczby zmiennoprzecinkowej $float2 = 5.23197e2; // notacja naukowa liczby zmiennoprzecinkowej /* Wypisanie wszystkich liczb. Wyświetla "523, -523, 523, 523, 523.197, 523.197". */ print( "$int1, $int2, $int3, $int4, $float1, $float2<br>" ); ?>

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 ###BOT_TEXT###quot; 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
<?php

Rozdział 2 – Język

24

$aStr1 print( $aStr2 print( $aStr3

= "To jest zwykły ciąg."; "$aStr1<br>" ); = "Thatcher"; "$aStr2<br>" ); = "Nazywam się $aStr2"; // $aStr3 = "Nazywam się Thatcher" print( "$aStr3<br>" ); $aStr4 = "Nazywam się \$aStr2"; // $aStr4 = "Nazywam się $aStr2" print( "$aStr4<br>" ); $aStr5 = 'Nie rozwijaj

Related Interests

$aStr2

Related Interests

'; // $aStr5 = "Nie rozwijaj '$aStr2'" print( "$aStr5<br>" ); // 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ą
<?php $aVar = 123; print( "\$aVar = $aVar, typ = " . gettype( $aVar ) . "<br>" ); $aVar2 = $aVar . " niejawnie skonwertowane do ciągu"; print( "\$aVar2 = $aVar2, typ = " . gettype( $aVar2 ) . "<br>" ); $aVar3 = $aVar2 + 1; // niejawna konwersja na liczbę całkowitą print( "\$aVar3 = $aVar3, typ = " . gettype( $aVar3 ) . "<br>" ); $aVar3 = $aVar2 * 1.1; // niejawna konwersja na liczbę zmiennoprzecinkową print( "\$aVar3 = $aVar3, typ = " . gettype( $aVar3 ) . "<br>" ); $aNotNumber = "abc"; $aVar4 = $aNotNumber * 1; // próba konwersji na liczbę, zwracane jest 0 print( "\$aVar4 = $aVar4, typ = " . gettype( $aVar4 ) . "<br>" ); $aIsNumber = "3 małe świnki"; $aVar5 = $aIsNumber + 1; // konwersja $aIsNumber na liczbę 3 print( "\$aVar5 = $aVar5, typ = " . gettype( $aVar5 ) . "<br>" ); ?>

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
<?php // Jawne tworzenie prostej tablicy $a[0] = "Ryan"; $a[1] = "Scott"; $a[] = "Randall"; // jawne przypisanie do indeksu (klucza) 2 $a[] = "Sherie"; // jawne przypisanie do indeksu (klucza) 3

25

PHP – Kompendium wiedzy

print( "$a[3], $a[2], $a[1], $a[0]<br>" ); // Tworzenie tablicy asocjacyjnej $color["niebieski"] = "#0000FF"; $color["zielony"] = "#00FF00"; $color["czerwony"] = "#FF0000"; print( "Wartość szesnastkowa koloru czerwonego wynosi {$color['czerwony']}<br>" ); // 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']}<br>" ); // 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]}<br>" ); // 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]}<br>" ); ?>

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
<?php $variable1 = "Ryan"; $variable2 = "Scott"; print( "$variable1, $variable2<br>" ); // 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
<?php $variable1 = "Ryan"; $variable2 = $variable1; // przypisanie wartości print( "$variable1, $variable2<br>" ); // wypisuje "Ryan, Ryan" $variable2 = "Scott"; print( "$variable1, $variable2<br>" ); // wypisuje "Ryan, Scott" $variable3 = &$variable1; // przypisanie przez referencję print( "$variable1, $variable3<br>" ); // wypisuje "Ryan, Ryan" $variable3 = "Katie"; print( "$variable1, $variable3<br>" ); // 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, Rozdział 2 – Język 26

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
HOSTNAME HOSTTYPE PATH OSTYPE

Definicja Nazwa komputera serwera. Typ komputera, na przykład i386. Systemowa ścieżka serwera. System operacyjny działający serwerze, na przykład Linux.

na

Tabela 2.4. Zmienne generowane przez PHP Zmienna
PHP_SELF HTTP_COOKIE_VARS

HTTP_GET_VARS

HTTP_POST_VARS

Definicja Nazwa pliku z wykonywanym skryptem. Tablica asocjacyjna zmiennych przekazanych do skryptu poprzez cookie HTTP. Tablica asocjacyjna zmiennych przekazanych do skryptu za pomocą metody GET. Tablica asocjacyjna zmiennych przekazanych do skryptu za pomocą metody POST. PHP – Kompendium wiedzy

27

Tabela 2.5. Operatory arytmetyczne Operator Nazwa + Dodawanie Odejmowanie
* / %

Przykład
$a + $b $a - $b $b $a * $b $a / $b

Wynik Suma $a i $b Różnica $a i Iloczyn $a i $b Iloraz $a i $b Reszta z dzielenie $a przez $b Wynik Bity ustawione w $a i $b są ustawione Bity ustawione w $a lub $b są ustawione Bity ustawione w $a lub $b, ale nie w obu na raz są ustawione Bity ustawione nie są teraz ustawione i odwrotnie Przesunięcie bitów w $a w lewo o $b kroków Przesunięcie bitów w $a w prawo o $b kroków Wynik True, jeżeli $a jest równe $b True, jeżeli $a jest równe $b i są one tych samych typów True, jeżeli $a jest różne od $b True, jeżeli $a jest mniejsze od $b True, jeżeli $a jest większe od $b True, jeżeli $a jest mniejsze lub równe $b True, jeżeli $a jest większe lub równe $b

Mnożenie Dzielenie Reszta dzielenia

z

$a % $b

Tabela 2.6. Operatory bitowe Operator Nazwa & Iloczyn bitowy
|

Przykład
$a & $b $a | $b

Suma bitowa Różnica symetryczna Negacja Przesunięcie w lewo Przesunięcie w prawo

^

$a ^ $b

~

~$a

<<

$a << $b

>>

$a >> $b

Tabela 2.7. Operatory porównania Operator Nazwa == Równy
===

Przykład
$a == $b $a === $b

Identyczny Różny Mniejszy Większy Mniejszy równy Większy równy lub lub

!= < > <=

$a != $b $a < $b $a > $b $a <= $b

>=

$a >= $b

Tabela 2.8. Operatory zwiększania i zmniejszania Rozdział 2 – Język 28

Operator, przykład
$a++ ++$a $a---$a

Nazwa Postinkrementacja Preinkrementacja Postdekrementacja Predekrementacja

Wynik Zwraca $a, a następnie zwiększa $a o jeden Zwiększa $a o jeden i zwraca $a Zwraca $a, a następnie zmniejsza $a o jeden Zmniejsza $a o jeden i zwraca $a Wynik True, jeżeli $a mają wartość
True,

Tabela 2.9. Operatory logiczne Operator Nazwa and Iloczyn logiczny
or

Przykład
$a and $b

i
$a or $b

$b True $b

Suma logiczna Różnica symetryczna Negacja Iloczyn logiczny Suma logiczna

lub
True xor $a xor $b

jeżeli $a mają wartość

! &&

!$a $a && $b

jeżeli $a mają wartość True, ale nie razem True, jeżeli $a nie jest True True, jeżeli $a i $b mają wartość lub
$b True True,

True,

||

$a || $b

lub
True

$b

jeżeli $a mają wartość

Tabela 2.10. Operatory przypisania Operator Przykład
= += $a = $b

Wynik Przypisuje wartość do $a.

$b

$a += $b

-=

$a -= $b

*=

$a *= $b

/=

$a /= $b

.=

$a .= $b

%=

$a %= $b

|=

$a |= $b

Przypisuje wartość ($a+$b) do $a. Jest to identyczne z $a=$a+$b. Przypisuje wartość ($a-$b) do $a. Jest to identyczne z $a=$a-$b. Przypisuje wartość ($a*$b) do $a. Jest to identyczne z $a=$a*$b. Przypisuje wartość ($a/$b) do $a. Jest to identyczne z $a=$a/$b. Przypisuje wartość ($a.$b) do $a. Jest to identyczne z $a=$a.$b. Przypisuje wartość ($a%$b) do $a. Jest to identyczne z $a=$a%$b. Przypisuje wartość PHP – Kompendium wiedzy

29

$aVal++. */ print( "$aGlobal1<br>" ). PHP posiada również zmienne statyczne. Przypisuje wartość ($a>>$b) do $a. będzie dostępna w dołączanym pliku. POwyższa zmienna $aGlobal1. function DoPrint( ) { /* Poniższa instrukcja wydrukuje tylko <br> ponieważ zmienna $aGlobal1 wewnątrz funkcji jest poza zasięgiem. } DoPrint2(). } // Poniższe wywołania spowodują wypisanie 0. Przypisuje wartość ($a<<$b) do $a. Jest to identyczne z $a=$a^$b. ?> --. print( "$aVal<br>" ). */ print( "$aGlobal1<br>" ). które deklarowane wewnątrz funkcji zapewniają utrzymywanie swojej wartości pomiędzy kolejnymi wywołaniami funkcji. Wewnątrz funkcji definiowanych przez użytkownika zmienne mają zasięg lokalny. Jest to identyczne z $a=$a&$b.php3 --<?php print( "$aGlobal1<br>" ). } DoPrint().10. /* Poniższa instrukcja wypisze wartość zmiennej ponieważ została zadeklarowana jako globalna. ?> Rozdział 2 – Język 30 .Zawartość pliku example10_inc. Przypisuje wartość ($a&$b) do $a. Jest to identyczne z $a=$a|$b. StaticFunc(). zmienne globalne PHP mają taki sam zasięg. Zasięg zmiennych <?php $aGlobal1 = "To jest test". ($a|$b) Zasięg zmiennych Ogólnie rzecz ujmując.php" ). Jest to identyczne z $a=$a>>$b. function StaticFunc( ) { static $aVal = 0.&= $a &= $b ^= $a ^= $b <<= $a <<= $b >>= $a >>= $b do $a. Jest to identyczne z $a=$a<<$b. Rozciąga się on również na pliki dołączane. Zmienne globalne muszą być deklarowane jako globalne. aby mogły być wykorzystywane wewnątrz funkcji. a następnie 1 StaticFunc(). Przypisuje wartość ($a^$b) do $a. function DoPrint2( ) { global $aGlobal1. /* Dołączamy inny plik z kodem PHP. */ include( "example10_inc. Wydruk 2.

Oprócz operatorów umieszczonych w tabelach istnieje jeszcze kilka operatorów. Operator trójskładnikowy. Niektóre działania z operatorami <?php $aNum1 = 1. print( "$aVal<br>" ). aString . print( "$aVal<br>" ). a następnie konwersję znaków nowej linii na znaczniki <br> I wypisanie wyników */ $aListing = `ls -l`. Wydruk 2. Operator wykonania oznaczany przez znak ` (na jednym klawiszu ze znakiem ~) jest podobny do operatora dostępnego we wielu językach programowania powłoki. ?> $aVal $aVal 31 PHP – Kompendium wiedzy . ale są one trudniejsze do klasyfikacji. " stałych. zmienna ta powinna być sprawdzana możliwie szybko. // drukuje "Wartości są równe" = ( 1 === "1" ) ? "Wartości są identyczne" : "Wartości nie są identyczne". "'<br>" ). o ile uaktywniona jest opcja track_errors. komunikaty błędów zatrzymane przez operator @ są zapamiętywane w zmiennej globalnej $php_errormsg. aNumber . 1 ). Gdy opcja ta jest aktywna. $aNum2 = 2. $aVal = ( $aNum1 == $aNum2 ) ? "Wartości są równe" : "Wartości są różne". Pełna lista stałych znajduje się w skorowidzu na końcu książki. Użycie tego operatora pozwala na stworzenie lepszej obsługi błędów.10. print( "<br>Zawartość katalogu:<br><b>$aFmtList</b><br>" ). przypisuje do zmiennej $wart wartość wyrażenie2. Gdy operator ten jest umieszczony przed wyrażeniem. print( "Mamy tutaj zdefiniowane " .5. define( "aNumber". zamieszczone zostało zestawienie dostępnych operatorów. Wyrażenie $wart = (wyrażenie1) ? (wyrażenie2) : (wyrażenie3). Zmienna ta jest nadpisywana przez kolejne błędy. // prints "Wartości nie są identyczne" /* Poniższy fragment powoduje przypisanie do $aListing zawartości bieżącego katalogu serwera. // drukuje "Wartości są różne" = ( 1 == "1" ) ? "Wartości są równe" : "Wartości są różne".12. "To jest stały ciąg znaków" ). ?> Operatory i kolejność operatorów PHP posiada zestaw operatorów znanych programistom C i C++. Wydruk 2. więc aby kontrola błędów działała poprawnie. do 2. print( "$aVal<br>" ). że stałe PHP nie są makrami w stylu C i dlatego muszą być wartościami skalarnymi.<br>" ). zapisywany jako ?: jest dostępny zarówno w PHP jak i w C. jeżeli wyrażenie1 będzie miało wartość True. Aby zdefiniować nową stałą używa się funkcji define(). Zauważ. $aFmtList = nl2br( $aListing ).Stałe PHP posiada kilka predefiniowanych stałych oraz pozwala na definiowanie własnych. natomiast w przeciwnym przypadku $wart będzie miało wartość wyrażenie3. Stałe <?php define( "aString".11. PHP posiada również operator kontroli błędów @. nie są generowane komunikaty błędów powodowanych przez to wyrażenie. print( "Jej wartością jest '" . W tabelach od 2. Wyrażenie otoczone znakami ` jest wykonywane na serwerze a zwracana wartość przekazywana do zmiennej.

} elseif ( $aValue == 3 ) { print( "\$aValue == 3<br>" ). Dodatkowo PHP posiada dwie funkcje dołączania plików z kodem źródłowym: include() i require().. $nIndex = 0. else i elseif <?php if ( 1 < 2 ) print( "To zostanie wydrukowane.<br>" ). } print( "Liczenie w dół przy użyciu <b>do. if.13.14.<br>" ). że jest to pętla podobna do while. while Mimo. else print( "To nie zostanie wydrukowane.. Programiści C nie będą mieli kłopotu ze składnią tych instrukcji. // wypisuje liczby od 10 do 1 do { print( "$nIndex<br>" ).while warunek pętli jest sprawdzany po pierwszym przebiegu pętli. $nIndex++. if ( $aValue == 1 ) { // Używamy nawiasów klamrowych do otaczania bloków instrukcji print( "\$aValue == 1<br>" ). $aValue = 2.. która zachowuje się identycznie jak w C i innych językach wysokiego poziomu. do .while</b>. else. elseif Jest to oczywiście najważniejszy element języka. Przykład użycia if. } else { print( "\$aValue nie jest 1. to w pętli do.<br>" ). // wypisuje liczby od 0 do 9 while ( $nIndex < 10 ) { print( "$nIndex<br>" ). } ?> if organizuje przepływ sterowania poprzez while Jest to najprostszy typ pętli w PHP. } elseif ( $aValue == 2 ) { print( "\$aValue == 2<br>" ). ?> Rozdział 2 – Język 32 .while <?php print( "Liczenie w górę przy użyciu <b>while</b>. 2 ani 3<br>" ). że ciało pętli zostanie wykonane co najmniej raz. } while ( $nIndex > 0 ). Wydruk 2. Przykład użycia while i do.<br>" ). Wydruk 2. Gwarantuje to. Instrukcja tworzenie rozgałęzień na podstawie wyrażeń logicznych.Programowanie przepływu sterowania PHP posiada standardowe instrukcje programowania przepływu sterowania takie jak if oraz pętle while i for.. $nIndex--.

ale jest ona składniowo identyczna z instrukcją for w języku C.) { print( "$nIndex<br>" ).. foreach( $aColorArray as $aKey => $aValue ) { print( "Wartość szesnastkowa $aKey to $aValue<br>" ). Jeżeli będzie ono miało wartość True. } ?> switch Instrukcja switch upraszcza tworzenie wielokrotnych warunków. Wartość drugiego (wyr2) jest obliczana na początku każdego przebiegu pętli. Korzystnym ulepszeniem w PHP jest możliwość używania ciągów jako wyrażeń instrukcji switch.elseif. } /* $nIndex ma wartość 10. $nIndex < 10. } $aColorArray = array( "Czerwony" => "#FF0000". Perl i innych językach. "Niebieski" ). $nIndex > 0. $nIndex++ ) { print( "$nIndex<br>" ). 33 PHP – Kompendium wiedzy .. Każde z tych trzech wyrażeń może być puste. Jej składnia jest następująca: for (wyr1. że każde z trzech wyrażeń może zostać opuszczone. foreach( $aArray as $aValue ) { print( "Bieżąca wartość to $aValue<br>" ). przyjmowane jest. ale dodatkowo do zmiennej (zmienna_klucz) jest przypisywany klucz bieżącej pozycji. Przykład użycia foreach <?php $aArray = array( "Czerwony".15. wyr3) instrukcja Wartość pierwszego wyrażenia (wyr1) jest obliczana raz. Wydruk 2. "Zielony". na początku pętli. } ?> foreach Wyrażenie foreach jest wygodnym sposobem na przeglądanie tablic. 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. $nIndex-.else zawierających wiele wystąpień elseif. że ma ono wartość True. Na końcu każdego przebiegu pętli wykonywane jest trzecie wyrażenie (wyr3). Druga postać realizuje to samo.for Pętla for jest najbardziej złożoną instrukcją pętli w PHP. wyr2.. "Niebieski" => "#0000FF" ). Pokażemy teraz. Wydruk 2. "Zielony" => "#00FF00".. Pętla powoduje wypisanie liczb od 10 do 1 */ for ( . Przykład użycia for <?php // Wypisuje liczby od 0 do 9 for ( $nIndex = 0. Podobne konstrukcje znajdują się w VBScript. Jeżeli drugie wyrażenie jest puste. pętla będzie się nadal wykonywała i zostaną wykonane instrukcje ciała pętli. Nie jest to zalecane ze względu na czytelność kodu. Jest ona często używana zamiast skomplikowanych konstrukcji if.16. Składnia i implementacja tej instrukcji jest identyczna jak w C.

zostaną wykonane wszystkie trzy instrukcje print. case 1: print( "jeden<br>" ). case 1: print( "jeden<br>" ). break. Jeżeli $nIndex jest 1. switch ( $nIndex ) { case 0: print( "zero<br>" ). // Najprostsza instrukcja switch switch ( $nIndex ) { case 0: print( "zero<br>" ). break. case 1: print( "jeden<br>" ). Czasami opuszczenie tej instrukcji jest wygodne. break. } /* Opuszczenie instrukcji break spowoduje wykonanie wszystkich wyrażeń po pasującej pozycji. case "niebieski": print( "#0000FF<br>" ). break. } // Switch z użyciem ciągu $aColor = "niebieski". break. break. break. Wydruk 2. } // Użycie frazy 'default' $nIndex = 17. break. case 2: print( "dwa<br>" ).17. */ $nIndex = 0. Poniższy przykład ilustruje częste zastosowania instrukcji switch. Przykłady użycia switch <?php $nIndex = 2. wykonane zostaną ostatnie dwie instrukcje print. case 2: print( "dwa<br>" ). Jeżeli $nIndex jest 0. case "zielony": print( "#00FF00<br>" ). break. że w konstrukcji switch w C występują instrukcje break. break.Programiści Delphi i Pascala mają zwykle kłopoty z zapamiętaniem. } /* opuszczenie instrukcji break może być czasami przydatne */ $aColor = "Czerwony". jeden ani dwa<br>" ). default: print( "inny<br>" ). default: print( "Nie jest to zero. switch( $aColor ) { case "czerwony": print( "#FF0000<br>" ). switch( $aColor ) Rozdział 2 – Język 34 . case 2: print( "dwa<br>" ). switch ( $nIndex ) { case 0: print( "zero<br>" ). break.

który określa ilość zagłębionych pętli.19. Wyrażenie continue jest używane jedynie w pętlach. 12. case "niebieski": case "Niebieski": print( "#0000FF<br>" ). break. $nIndex++ ) { if ( ( $nIndex % 2 ) == 0 ) continue. endwhile. 15. składnia alternatywna może być użyteczna. 3. W przypadku pętli prostych. Przykłady użycia break i continue <?php $aArray = array( 4. // wypisuje liczby nieparzyste od 0 do 20 $nIndex = 0. for i switch. W każdej z tych konstrukcji otwierająca klamra jest zamieniona na dwukropek (:) a zamykająca klamra na odpowiednio endif. break. Wydruk 2. czy istnieje w tablicy wartość większa od bieżącej wartości maksymalnej. Powoduje ono opuszczenie pozostałych instrukcji ciała pętli i rozpoczęcie nowej iteracji. break. Przykład użycia alternatywnej składni PHP na stronie HTML <html> <head> <title>Przykład 19</title> 35 PHP – Kompendium wiedzy . endfor i endswitch. ponieważ zapewnia wyraźną identyfikację końca struktur sterujących. 20. 7. for ( $nIndex = 0. */ foreach( $aArray as $aValue ) { /* Wyrażenie będzie prawdziwe. Wydruk 2. default: print( "inny<br>" ). wyrażenia warunkowe są wystarczające do realizacji tych zadań. gdy osiągnięta zostanie wartość 20. while. 5. // opcjonalnie 'continue 1. case "zielony": case "Zielony": print( "#00FF00<br>" ). nie sprawdzamy wartości które są w tablicy po wartości 20 */ if ( $aValue > $aCurMax ) { $aCurMax = $aValue.' } } // wypisuje "Bieżącym maksimum jest 20" print( " Bieżącym maksimum jest $aCurMax<br>" ).{ case "czerwony": case "Czerwony": // Poniższa instrukcja zostanie wykonana. 11. Wyrażenie break kończy wykonanie bieżącej konstrukcji sterującej (pętli lub wyrażenia switch). $aCurMax = 17. Najczęściej instrukcje break i continue są stosowane w zagnieżdżonych pętlach. } ?> break i continue PHP posiada również znane z C instrukcje break i continue.18. jeżeli $aColor // będzie miał wartość "Czerwony" lub "czerwony" print( "#FF0000<br>" ). Ponieważ wykonujemy instrukcję break. Obie te instrukcje pozwalają na podanie im parametru numerycznego. 31 ). $nIndex < 20. Gdy tworzysz duże skrypty wbudowane w HTML. } ?> PHP osiada alternatywną składnię dla konstrukcji sterujących if. break. /* Sprawdzamy. które należy przerwać lub rozpocząć od początku. które pozwalają na dodatkowe sterowanie pętlami. break.' print( "$nIndex<br>" ). // możemy napisać 'break 1.

która posiada kilka ograniczeń. Wyrażenie to jest wykonywane raz. nie ma również mechanizmu usuwania lub przedefiniowania wcześniej zdefiniowanych funkcji. że pliki nie mogą być warunkowo dołączane za pomocą require(). którą można następnie przypisać do zmiennej. zmienna liczba argumentów. jeżeli znajduje się w instrukcji warunkowej. aby dołączany plik zwracał wartość. lub włączać grupy plików przy pomocy odpowiednio skonstruowanej pętli.Używamy PHP do utworzenia listy opcji --> <form action="someotherpage. Pozwala to warunkowo włączać pliki. że pomiędzy while i endwhile jest dużo więcej tekstu. której warunek ma wartość False. PHP pozwala na wykonywanie dowolnego kodu w ciele funkcji.phtml" method="post"> <table> <tr> <td> Wybierz swój rok urudzenia: </td> <td> <select name="BirthYear" size="1"> <?php /* Generujemy znaczniki dla lat 1920-2000 w odwrotnej kolejności */ $aCurYear = 2000. włączając w to wywołania innych funkcji. gdy zostanie napotkana instrukcja return. endwhile. że dowolny kod zawarty w pliku dołączanym musi być otoczony prawidłowymi znacznikami PHP. że pliki dołączane za pomocą require() nie mogą zwracać wartości. Funkcje w PHP mogą posiadać następujące cechy: zmienne nazwy funkcji. Próba zwrócenia wartości w wyrażeniu require() powoduje błąd składni. /* zakładając. Funkcja include() pozwala również. Przetwarzanie pliku w instrukcji include() kończy się. ?>"> <?php print( $aCurYear ). Zdolność ta pozwala również na tworzenie funkcji rekurencyjnych. PHP nie pozwala na przeciążanie funkcji. że nie wchodzi w skład konstrukcji sterujących. Funkcja include() jest wykonywana za każdym jej wywołaniem i może znajdować się wewnątrz pętli lub instrukcji warunkowych. Na końcu pliku analizator wraca do trybu PHP. W obu przypadkach po dołączeniu pliku PHP przechodzi do trybu HTML na początku dołączanego pliku. while( $aCurYear >= 1920 ): ?> <option value="<?php print( $aCurYear ). może być trudno znaleźć końcowy średnik. argumenty domyślne i argumenty przekazywane przez referencję. jeżeli użyjemy zwykłej składni. Rozdział 2 – Język 36 . Wyrażenie jest zwykłą funkcją PHP. Wyrażenie require() różni się tym od include(). */ ?> </select> </td> </tr> </table> </form> </body> </html> include i require PHP posiada dwa mechanizmy dołączania plików zewnętrznych: include() i require(). Oznacza to.</head> <body> <!-. Funkcje nie muszą być deklarowane przed ich użyciem w kodzie PHP4. ?> </option> <?php $aCurYear--. include() Funkcje PHP pozwala na tworzenie funkcji definiowanych przez użytkownika. Oznacza to. Inną różnicą jest to. natomiast require() jest konstrukcją językową. jeżeli znajduje się w pętli lub nawet.

"<br>" ).phtml". wartość // $BaseString może być zmieniona poza tą funkcją $BaseString . print( "Argument $nIndex: $aArgVal<br>" ). 5 ): " . ale nie ma destruktorów. } else { print( "<a href=###BOT_TEXT###quot;$aHREF###BOT_TEXT###quot; target=###BOT_TEXT###quot;$aTarg###BOT_TEXT###quot;>$aText</a>" ). func_get_arg() i func_get_args(). muszą być one umieszczone po wszystkich argumentach obowiązkowych. Poniższe przykłady pokazują użycie funkcji w PHP. print( "$aString<br>" ). Używając argumentów domyślnych. nie ma dziedziczenia wielobazowego. */ function PrintAnchorTag( $aHREF. PHP posiada (i wymaga używania) wskaźnik $this. $nIndex++ ) { $aArgVal = func_get_arg( $nIndex ).20.phtml". dostępne są funkcje func_num_args(). należy poprzedzić nazwę zmiennej znakiem &. print( "<br>" ). } // przekazanie argumentu przez referencję function StringAppend( &$BaseString. 5 ):<br>" ).Domyślnie argumenty są przekazywane przez wartość. 2. } // wartości domyślne /* Funkcja ta może być wywołana przy użyciu jednej z postaci: PrintAnchorTag( "href". "text". $aTarg = "" ) { if ( $aTarg == "" ) { print( "<a href=###BOT_TEXT###quot;$aHREF###BOT_TEXT###quot;>$aText</a>" ). Wydruk 2. za pomocą których można pobrać dane przekazane jako argumenty. "target" ). PrintAnchorTag( "example10. $AddString ) { // ponieważ jest to przekazane przez referencję. } } print( "ReturnSum( 3. która jest jednak wystarczająca dla większości aplikacji WWW. $b ) { return $a + $b. PrintAnchorTag( "href". ?> Klasy i programowanie obiektowe PHP posiada zdolność tworzenia klas za pomocą składni podobnej jak w C++. // wypisuje "Marysia miała małą owieczkę" PrintAnchorTag( "example10. 4. 4. Istnieją konstruktory klas. $aString = "Marysia miała ". 3. "_blank" ). W przypadku zmiennej listy argumentów. "małą owieczkę" ). który jest 37 PHP – Kompendium wiedzy . 3. "text" ). ReturnSum( 3. Przykłady funkcji definiowanych przez użytkownika <?php // prosta funkcja function ReturnSum( $a. Aby przekazać argument przez referencję. 5 ). 5 ) . print( "<br>" ).= $AddString. for ( $nIndex = 0. $nIndex < $aNumArgs. StringAppend( $aString. } } // zmienna lista argumentów function PrintEverything( ) { $aNumArgs = func_num_args(). "Zobaczmy jeszcze raz przykład 10" ). print( "Wywołanie PrintEverything( 1. PHP posiada również bardzo prostą implementację programowania obiektowego. $aText. 2. "Zobaczmy jeszcze raz przykład 10 w nowym oknie". Dostępne jest dziedziczenie jednobazowe. PrintEverything( 1.

. print( "</blockquote>" ). // dodanie 6 foobarów $aBasket->PrintBasket(). print( "<br>" ). } } } /* Tworzenie nowego obiektu ShoppingBasket. $aBasket->AddItem( "foobar". */ function ShoppingBasket( $aInitialValue = 0. } print( "Wartość całkowita: $" . number_format( $this->fCurValue.stosowany do odwoływania się do metod i zmiennych obiektu. return True. $aValue. $aBasket->AddItem( "gizmo". } else { return False. $aQuantity = 1 ) { // Usuwamy określoną ilość przedmiotów // jedynie. } } function PrintBasket( ) { if ( count( $this->fItems ) > 0 ) { print( "Zawartość koszyka:<blockquote>" ). Rozdział 2 – Język 38 . $this->fItems[$aName]["Value"] = $aValue. 1. } // Dodanie określonej ilości przedmiotów function AddItem( $aName. $aQuantity = 1 ) { $this->fItems[$aName]["Quantity"] += $aQuantity. Dodanie kilku przedmiotów usunięcie kilku przedmiotów i wypisanie zawartości koszyka */ $aBasket = new ShoppingBasket( 3. Więcej przykładów na ten temat znajdzie się w późniejszych rozdziałach książki. var $fCurValue.10. 15 ). Poniższy przykład pokazuje tworzenie prostej klasy. $this->fCurValue -= $this->fItems[$aName]["Value"] * $aQuantity.50 ). // dodanie 1 gizmo $aBasket->PrintBasket(). Może być to stała prowizja lub rabat. } function RemoveItem( $aName. gdy była dostępna wystarczająca ich ilość if ( $this->fItems[$aName]["Quantity"] > $aQuantity ) { $this->fItems[$aName]["Quantity"] -= $aQuantity. Wydruk 2. $this->fCurValue += $aValue * $aQuantity.50 ).0 ) { $this->fCurValue = $aInitialValue. foreach( $this->fItems as $aKey => $aValue ) { print( "{$aValue['Quantity']} $aKey<br>" ). 6 ). Przykłady użycia klas w PHP <?php // tworzenie prostej klasy class ShoppingBasket { var $fItems. 2 ) ). $aBasket->PrintBasket(). 2. /* jest to konstruktor klasy. $aBasket->RemoveItem( "foobar". } else { print( "<i>Koszyk jest pusty</i><br><br>" ). Tak samo jak w C++ konstruktor może posiadać argumenty W tym przypadku jest to początkowa wartość koszyka.21. ponieważ ma taką samą nazwę jak klasa.

ereg_replace().$aBasket->PrintBasket(). PHP zawiera wszystkie własności potrzebne do tworzenia złożonych i łatwych do zarządzania aplikacji WWW. Dlatego nie zawiera on dyskusji na temat tego kiedy lub dlaczego należy używać określonych konstrukcji. eregi(). eregi_replace() oraz split().005. $aBasket->PrintBasket(). PHP korzysta z rozszerzonych wyrażeń regularnych zdefiniowanych przez POSIX 1003. Pierwszy typ jest zgodny ze specyfikacją POSIX i są to funkcje ereg(). Zamieszczone zostały za to przykłady ilustrujące składnię i dostępne funkcje.php. Nazwy tych funkcji są poprzedzone ciągiem preg_. 3 ). co zostanie pokazane w kolejnych rozdziałach. Drugi typ funkcji porównywania wzorców jest zgodny z wyrażeniami regularnymi Perl. ale jest przygotowany do tworzenia aplikacji dla WWW. Bieżąca implementacja tych funkcji odpowiada Perl 5. PHP zawiera w katalogu regex strony podręcznika. 39 PHP – Kompendium wiedzy . $aBasket->RemoveItem( "foobar". ?> Porównywanie wzorców PHP posiada dwa typy funkcji do porównywania wzorców (lub wyrażeń regularnych).net. które w pełni opisują wyrażenia regularne POSIX. Podsumowanie Rozdział ten jest zwięzłym opisem języka PHP i nie zawiera szczegółowo opisanych podstaw programowania. Każda z tych funkcji jako pierwszego argumentu wymaga wyrażenia regularnego. Różnica pomiędzy implementacją w Perl 5. Składnia tych wyrażeń jest taka sama jak w Perl 5 z kilkoma różnicami. Język jest wystarczająco sprawny do realizacji większości zadań.2.005 i w PHP jest dokładnie opisana w dokumentacji PHP dostępnej z witryny http://www. Pełna lista tych funkcji znajduje się w skorowidzu na końcu książki.

php lub . natomiast PHP zapewnia prosty mechanizm przetwarzania tych formularzy. $aDatabasePass = "secretpassword".123". ?> </body> </html> <!-. która sygnalizuje niektóre problemy jakie powstają gdy jako urządzenie wyjściowe używana jest przeglądarka WWW. użytkownik może zapisać twoje skrypty.phtml lepiej wygląda. Ponieważ PHP został zaprojektowany jako język programowania dla WWW. gdy źle skonfigurowany zostanie serwer WWW. Dla programistów. Do plików dołączanych używam innego rozszerzenia i chcemy zaznaczyć. Rozdział ten zawiera informacje nie tylko na temat sposobu użycia formularzy HTML w PHP. Nie używam najczęściej używanych rozszerzeń . HTML posiada elementy formularzy. Jest to jedyny powód. Możesz używać dowolnego rozszerzenia dla skryptów PHP. ponieważ jest ono składniowo podobne do obsługi elementów formularzy. które zostały opisane w rozdziale 1.Plik: bogus. */ include( "bogus. Nie używam typowego rozszerzenia inc. /* .phtml oraz rozszerzeń . // powatającą.<br>" ). że jest to kod PHP.56. print( "Poznajmy dziurę w systemie bezpieczeństwa. 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 .Plik: securityhole.34. którzy przechodzą od pisania zwykłych aplikacji do tworzenia aplikacji WWW przeznaczona jest część zatytułowana „Ważne zagadnienia programowania dla WWW”. że uważam że rozszerzenie . zawiera błąd ale również znajduje się w nim nazwa użytkownika bazy danych i hasło. $aDatabaseIP = "12.php3 do plików dołączanych.inc" ).php i . Na przykład. Jeżeli nie zrobisz tego.php3 do stron wyświetlających dane jedynie dlatego.Rozdział 3. jeżeli używasz rozszerzeń php i inc do oznaczania skryptów PHP i plików dołączanych. który jest zwykle potrzebny w czasie dialogu z użytkownikiem. obsługuje on automatycznie wiele szczegółów przetwarzania formularzy. „Kompilacja i instalowanie PHP”. które są używane do zbierania danych od użytkownika. 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. że będzie traktował oba te rozszerzenia jako pliki PHP i przetwarzał je przed wysłaniem do przeglądarki użytkownika.inc --> <?php // Jest to dołączany plik PHP demonstrujący // potencjalną dziurę w systemie zabezpieczeń.inc.phtml --> <html> <head> <title>Przykład: błędny plik dołączany otwiera dziurę w systemie zabezpieczeń</title> </head> <body> <?php /* Plik dołączany bogus. że serwer WWW został tak skonfigurowany. powinieneś się upewnić. Cookie mogą również pomóc w zrealizowaniu mechanizmu utrzymywania stanu. $aDatabaseUser = "secretuser". Wszystkie rozszerzenia jakich używasz do skryptów PHP i plików dołączanych powinny zostać dołączone do konfiguracji serwera WWW. W rozdziale tym znajduje się również omówienie mechanizmu cookie. Rozważmy następujący przykład: <!-. Rozszerzenia te konfiguruje się używając opcji konfiguracji. ale również na temat kontroli poprawności i przetwarzania danych formularza.

Formularz na wydruku 2 pokazuje takie wielowartościowe elementy formularza.To jest strona HTML. W trakcie tworzenia aplikacji PHP możesz użyć dowolnego rozszerzenia.inc jako tekst (tak jak mój).phtml" method="post"> <table> <tr> 41 PHP – Kompendium wiedzy .html --> <html> <head> <title>Wydruk 3. Wydruk 3. konwertuje wszystkie elementy formularza na zmienne PHP. Poniższa strona HTML zawiera prosty formularz. Gdy otwarty zostanie plik securityhole.listing1. Dociekliwy użytkownik może spróbować obejrzeć plik bogus. Aby użyć nieskalarnych elementów formularza w PHP. Po przesłaniu formularza do skryptu post1. ale aby uniknąć potencjalnego zagrożenia bezpieczeństwa należy tak skonfigurować serwer WWW.phtml.1. w tym nazwę użytkownika i hasło. Zawiera on również błąd syntaktyczny. zmienne $UserName i $Password będą zawierały wartości wpisane jako nazwę użytkownika i hasło. securityhole.phtml.inc on line 12”. Wydruk 3. Jeżeli serwer WWW jest tak skonfigurowany. Można również tworzyć elementy formularza zawierające wiele wartości. Jeżeli serwer WWW jest skonfigurowany taj aby traktować pliki . ?> </body> </html> Skalarne i wielowartościowe elementy formularza Elementy formularzy HTML zawierają zwykle wartości skalarne. aby analizował wszystkie pliki posiadające używane przez ciebie rozszerzenia. Podsumowując. post1. dołączany jest plik bogus. Obsługa formularzy w PHP Do pobierania danych od użytkownika w HTML stosuje się formularze. na przykład listę wielokrotnego wyboru. cały tekst pliku pojawi się w przeglądarce.html</title> </head> <body> <form action="post1.inc. Dołączany plik zawiera dane na temat połączenia z bazą danych. /* właśnie tutaj */ */ ?> W przykładzie tym do głównego pliku.html --> <html> <head> <title>Wydruk 3. <!-.To jest skrypt PHP. Zamieszczony na wydruku 1 przykład zawiera formularz z dwoma wartościami skalarnymi — nazwą użytkownika i hasłem.1: post1.phtml" method="post"> Nazwa użytkownika: <input type="text" name="Username"><br> Hasło: <input type="password" name="Password"><br> <input type="submit" name="Submit" value="Wyślij"> </form> </body> </html> <!-. do którego należy wpisać nazwę użytkownika i jego hasło.Zagnieżdżony komentarz powoduje błąd. print( "Hasło: $Password<br>" ).inc wpisując odpowiedni URL w pasku adresu. aby traktować pliki .2.phtml. listing1. W domyślnej konfiguracji PHP po przesłaniu danych formularza do skryptu PHP. należy dodać do nazwy nawiasy kwadratowe oznaczające zmienną tablicową. użytkownik zobaczy jedynie wcześniej wspomniany komunikat błędu. wyświetlony zostanie błąd: „Parse error: parse error in bogus. Formularz HTML z elementami wielowartościowymi <form action="displayall.inc jak każdy inny skrypt PHP.1 .phtml</title> </head> <body> <?php print( "Nazwa użytkownika: $Username<br>" ). Strona HTML i skrypt PHP ilustrujące procedurę logowania się użytkownika.

Nazwy są indeksami tablicy --> <select name="Colors[]" size="5" multiple> <option value="Red">Czerwony</option> <option value="Green">Zielony</option> <option value="Blue">Niebieski</option> <option value="Purple">Purpurowy</option> <option value="Yellow">Żółty</option> </select> </td> </tr> <tr> <td valign="top"> Wprowadź twój adres: </td> <td valign="top"> <!-. ?> </body> </html> W niektórych przypadkach preferowane jest użycie zmiennych HTTP_GET_VARS lub HTTP_POST_VARS zamiast korzystania ze zmiennych globalnych. post2. aby korzystały z wartości zawartych w tablicach HTTP_GET_VARS i HTTP_POST_VARS. każda z tablic będzie zawierać zero lub więcej wartości. } function DisplayPostVars() { Rozdział 3 – Formularze i cookie 42 .<td valign="top"> Wybierz kolory które lubisz: </td> <td valign="top"> <!-. ponieważ PHP nie będzie musiał tworzyć zmiennych globalnych dla każdego z elementów formularza.html --> <html> <head> <title>Wydruk: post2. print( "Hasło: {$HTTP_POST_VARS['Password']}<br>" ).Trzy linie na dane adresowe. DisplayArray( $HTTP_GET_VARS ). Więcej na temat tej dyrektywy konfiguracji napisane zostało na końcu książki przy opisie opcji konfiguracji register_globals. 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. $Colors[] i $adress[] Alternatywne metody odczytywania wartości z formularza PHP posiada alternatywną metodę dostępu do danych przesłanych do skryptu. aby nie udostępniał tych zmiennych globalnych i tak pisać skrypty. print( "Nazwa użytkownika: {$HTTP_POST_VARS['Username']}<br>" ). 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.phtml</title> </head> <body> <?php error_reporting( 255 ). Na przykład możesz chcieć wyświetlić w czasie uruchamiania skryptu wartości wszystkich danych wysłanych z formularza.To jest skrypt PHP. Można więc tak skonfigurować PHP. można tu nieco zyskać. Skrypt wyświetlający dane z wydruku 1 może zostać przepisany w następujący sposób: <!-. Jeżeli bardzo przejmujesz się wydajnością serwera WWW. Używamy notacji tablicowej aby zaznaczyć użycie wielu wierszy tablicy --> <input type="text" name="address[]"><br> <input type="text" name="address[]"><br> <input type="text" name="address[]"><br> </td> </tr> <tr> <td colspan="2"> <input type="submit" name="Submit" value="Wyślij"> </td> </tr> </table> </form> Po przesłaniu danych formularza z wydruku 2 do skryptu PHP.

Obsługuje ona rekurencyjnie elementy tablicy. // Wyświetlenie wszystkich par klucz/wartość z tabeli foreach( $aArray as $aKey => $aValue ) { print( "<tr>" ). ?> <h2>Cała zawartość HTTP_GET_VARS</h2> <?php DisplayGetVars(). Wydruk 3. } print ("</tr>"). <html> <head> <title>Wyświetlenie wszystkich elementów formularza</title> </head> <body> <?php error_reporting( 255 ). // Wyświetlenie nagłówka tabeli print ( " <tr><th>Klucz</th><th>Wartość</th></tr>"). } } else { print( "<td>$aKey(array)</td><td>").phtml. Skrypt displayall. } print ("</table>").. czy $aArray jest na pewno tablicą if ( is_array ($aArray ) && (count( $aArray ) > 0 )) { // Rozpoczęcie tabeli print ("<table border = ###BOT_TEXT###quot;1###BOT_TEXT###quot;>").3. DisplayArray( $aValue ). displayall. Funkcja DisplayArray function DisplayArray( $aArray ) { // Upewniamy się. } } Używając tej funkcji można pisać własne skrypty PHP wyświetlające wartości wszystkich przesłanych elementów formularza. } else { print( "<td>$aKey</td><td><i>$aValue</i></td>")./include/gen_form_funcs. // 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.global $HTTP_POST_VARS. Poniższy skrypt. HTTP POST i cookie odesłane przez przeglądarkę (cookie zostaną omówione w dalszej części tego rozdziału).phtml powoduje wyświetlenie wszystkich danych przesłanych przez HTTP GET. ?> <br><br> <h2>Cała zawartość HTTP_COOKIE_VARS</h2> <?php 43 PHP – Kompendium wiedzy . poinformujmy o tym if (empty( $aValue )) { print( "<td>$aKey</td><td><i>pusty</i></td>"). print ("</td>" ). które same są tablicami. } Obie z tych funkcji opierają się o funkcję DisplayArray przedstawioną na wydruku 3. DisplayArray( $HTTP_POST_VARS ). } else { print("<i>pusty lub nieprawidłowy</i>"). Wydruk 3.3.4. Jest to prosta funkcja wyświetlająca wszystkie elementy tablicy w tablicy HTML. include( ". ?> <br><br> <h2>Cała zawartość HTTP_POST_VARS</h2> <?php DisplayPostVars().php" ).

1. Wartości dwóch pierwszych elementów są. Przykład wielowartościowyc h elementów formularza Rozdział 3 – Formularze i cookie 44 .phtml. korzystając z formularza z wydruku 2. Address i Submit. Rysunek 3. ?> <br><br> </body> </html> Na rysunkach 3. Pisząc skrypt obsługujący te wartości należy pamiętać. tablica HTTP_POST_VARS zawiera trzy elementy: Colors. że element Submit jest zawsze umieszczany w tablicy HTTP_POST_VARS. przedstawiono formularz wprowadzania danych i wyniki wysłania danych do skryptu displayall.DisplayCookieVars(). jak się tego można było spodziewać.1.2. i 3. Wartością elementu Submit jest napis umieszczony na przycisku. Zauważmy.2. że na rysunku 3. tablicami.

Użycie rysunku jako przycisku wysłania danych Jeżeli projekt aplikacji WWW tak przewiduje. Nazwy zmiennych przechowujących współrzędne są tworzone poprzez dodanie _x i _y do nazwy elementu reprezentującego rysunek. Mechanizm ten jest wygodny do tworzenia map obrazów po stronie serwera. 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. Wydruk 3.phtml" method="post"> Nazwa użytkownika: <input type="text" name="Username"><br> Hasło: <input type="password" name="Password"><br> <input type="image" name="SubmitImg" src="submit.gif"> </form> </body> </html> 45 PHP – Kompendium wiedzy . Przykład użycia rysunku w formularzu <!-. Wynik przesłania formularza wielowartościoweg o do displayall.Strona HTML. czy jest to przycisk czy rysunek.html --> <html> <head> <title>Użycie rysunku zamiast przycisku</title> </head> <body> <form action="displayall. możesz użyć rysunku w miejsce przycisku HTML wysyłającego dane formularza do serwera.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. imgsubmit. Zmienne reprezentujące współrzędne będą się nazywały SubmitImg_x i SubmitImg_y.Rysunek 3.2. Na przykład na wydruku 5 nazwą elementu rysunku jest SubmitImg. 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”. Dla PHP nie ma znaczenia.5.

która będzie zawierać dopasowania wzorca odnalezione w przeszukiwanym ciągu. Funkcja eregi() jest identyczna z ereg() poza tym. if ( ereg( $aCodeFormat. kontrolę typów danych lub przeszukiwanie słowników w bazie danych. ale wyrażenia w stylu Perl dają podobne możliwości. Gdy użyjemy rysunku zamiast przycisku. pole wyboru lub przyciski opcji. które zmniejszają szansę pomyłki użytkownika. Dlatego dane muszą być kontrolowane na serwerze nawet. ereg_replace().Niektóre przeglądarki posiadają mechanizm pozwalający wykorzystać klawisz Enter zamiast klikania w przycisk na formularzu. ponieważ może być niedostępna w wielu przeglądarkach i systemach operacyjnych. string ciag [. array dopasowanie] ) int eregi( string wzorzec. są one używane we wszystkich przytoczonych tu przykładach. 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. $aCode2 = "83440-1607". PHP obsługuje dwa rodzaje wyrażeń regularnych — w stylu POSIX i Perl. Na przykład zastosowanie listy rozwijalnej z miesiącami jest mniej pracochłonne niż kontrola poprawności wpisanych nazw. to nie rób tego. Zauważ. array dopasowanie] ) Obie funkcje wymagają wzorca wyrażenia regularnego. Do kontroli poprawności używa się funkcji ereg() i eregi(). że przy przeszukiwaniu ignoruje ona wielkość liter. gdzie można zastosować listę. Kontrola poprawności kodu pocztowego i daty ISO <html> <head> <title>Kontrola poprawności amerykańskiego kodu pocztowego i daty ISO</title> </head> <body> <?php $aCode1 = "83440". 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. że w przykładach tych jest sprawdzany jedynie format a nie wartości. $aCodeFormat = "[0-9]{5}(-[0-9]{4})?". ciągu do przeszukania oraz opcjonalnej tablicy. Unikanie kontroli poprawności Chociaż kontrola poprawności jest ważna. Skupimy się tutaj na wyrażeniach w stylu POSIX. wykorzystując wyrażenia regularne. są dość skomplikowane w użyciu. eregi_replace() oraz split(). mechanizm ten nadal będzie działał. jeżeli wzorzec został odnaleziony w ciągu. Funkcje wyrażeń regularnych w stylu POSIX to: ereg(). Wydruk 3. ale nie jest ona całkowicie pewna. Ponieważ lepiej znam wyrażenia regularne w stylu POSIX. Ogólna składnia tych funkcji jest następująca: int ereg( string wzorzec. jeżeli nie musisz czegoś kontrolować. $aCode4 = "M6K 3E3". ale nie zostaną wtedy przesłane dane na temat współrzędnych. $aCode3 = "834". PHP pozwala na stosowanie kilku metod kontroli poprawności danych. Kontrola taka jest zalecana w przypadku tworzenia wysoce interaktywnych aplikacji WWW. jeżeli były one już kontrolowane na komputerze klienta. Zamiast wszędzie korzystać ze zwykłych pól tekstowych należy znaleźć miejsca. string ciag [. że funkcje wyrażeń w stylu Perl są szybsze i mają większe możliwości. Każda funkcja zwraca true. takie jak JavaScript mogą być wykorzystywane do kontroli poprawności elementów formularza przez wysłaniem ich do serwera. Nazwy funkcji wyrażeń w stylu Perl są poprzedzone przedrostkiem preg_ i są opisane w skorowidzu na końcu tej książki. ale należy pamiętać. Języki skryptowe działające na kliencie. eregi(). $aCode1 ) == True ) Rozdział 3 – Formularze i cookie 46 . Zamiast tego można zastosować takie mechanizmy wprowadzania danych. Wyrażenia te są potężnym narzędziem. 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).6. ale jeżeli wcześniej nie miałeś z nimi doświadczenia.

if ( is_numeric( $aValue1 ) == True ) print( "'$aValue1' jest liczbą<br>" ). Poniższy przykład sprawdza typy zmiennych. $aDate3 = "June 29. ). 47 PHP – Kompendium wiedzy . $aDate4 = "0000-99-99". opisane w następnych dwóch częściach. będzie wystarczająca dla wielu aplikacji. Kontrola poprawności za pomocą sprawdzania typów W niektórych przypadkach wystarczy sprawdzić typ wprowadzonej danej i nie przejmować się wprowadzoną wartością. "'$aCode4' nie jest poprawnym kodem pocztowym<br>" ). 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. $aValue2 = "123. $aDateFormat = "[0-9]{4}-[0-9]{1. $aCode4 ) == True ) "'$aCode4' jest poprawnym kodem pocztowym<br>" ). aby upewnić się. else print( if ( ereg( print( else print( if ( ereg( print( else print( if ( ereg( print( else print( "'$aCode1' nie jest poprawnym kodem pocztowym<br>" ). Jeżeli zostanie użyta w połączeniu z dodatkowym kodem kontroli poprawności. $aDate2 ) == True ) print( "'$aDate2' jest poprawnym formatem daty ISO<br>" ). $aDate1 = "2000-06-29". 2000". ale również pozwala na nieco więcej. else print( "'$aDate1' nie jest poprawnym formatem daty ISO<br>" if ( ereg( $aDateFormat. $aCodeFormat. którzy używali już wyrażeń regularnych uważają taką kontrolę poprawności za łatwą i wydajną. else print( "'$aDate2' nie jest poprawnym formatem daty ISO<br>" if ( ereg( $aDateFormat. "'$aCode2' nie jest poprawnym kodem pocztowym<br>" ). $aCode2 ) == True ) "'$aCode2' jest poprawnym kodem pocztowym<br>" ). else print( "'$aDate4' nie jest poprawnym formatem daty ISO<br>" ?> </body> </html> ). ). $aCodeFormat.print( "'$aCode1' jest poprawnym kodem pocztowym<br>" ). $aValue4 = "3 małe świnki".2}". else print( "'$aDate3' nie jest poprawnym formatem daty ISO<br>" if ( ereg( $aDateFormat. $aDate4 ) == True ) print( "'$aDate4' jest poprawnym formatem daty ISO<br>" ). $aDate1 ) == True ) print( "'$aDate1' jest poprawnym formatem daty ISO<br>" ). $aDate2 = "2000-7-4". $aCode3 ) == True ) "'$aCode3' jest poprawnym kodem pocztowym<br>" ). else print( "'$aValue1' nie jest liczbą<br>" ). $aValue3 = "1. Metoda ta jest odpowiednia do kontrolo prostych typów. takich jak liczby i ciągi.446". 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. "'$aCode3' nie jest poprawnym kodem pocztowym<br>" ). $aCodeFormat.56e18".2}-[0-9]{1. którzy nie znają wyrażeń regularnych mogą wybrać inne metody kontroli poprawności. <html> <head> <title>Kontrola liczb przy użyciu kontroli typów</title> </head> <body> <?php $aValue1 = "123". Ci zaś. if ( ereg( $aDateFormat. $aDate3 ) == True ) print( "'$aDate3' jest poprawnym formatem daty ISO<br>" ). że zostały wprowadzone tylko liczby. ).

czy istnieje w Internecie podany host Oczywiście wymaga to podłączenia z Internetem. /* Funkcja is_email kontroluje nie tylko poprawność formatu adresu email ale również sprawdza. Wydruk 3. URL i numerów telefonów. else print( "'$aEmail3' nie jest prawidłowym adresem email<br>" ). if ( $aValidator->is_phone( $aPhoneNum2 ) == True ) print( "'$aPhoneNum2' jest prawidłowym numerem telefonu<br>" ). $aPhoneNum3 = "support@intechra. else print( "'$aValue3' nie jest liczbą<br>" ). 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. Dodatkowe oprogramowanie dla PHP można pozyskać z wielu źródeł./include/class. $aPhoneNum2 = "+1 208-359-1540".8. else print( "'$aPhoneNum2' nie jest prawidłowym numerem telefonu<br>" ). Do kontroli poprawności przeznaczona jest klasa Validator zawierająca wiele funkcji upraszczających wiele zadań i oszczędzających czas.if ( is_numeric( $aValue2 ) == True ) print( "'$aValue2' jest liczbą<br>" ). Klasa Validator Jedną z najpiękniejszych cech oprogramowania typu open-source jest dostępność świetnych narzędzi uzupełniających podstawowy produkt. else print( "'$aPhoneNum1' nie jest prawidłowym numerem telefonu<br>" ). if ( $aValidator->is_email( $aEmail2 ) == True ) print( "'$aEmail2' jest prawidłowym adresem email<br>" ). Więcej informacji na temat tej klasy i innych dostarczanych przez Webmasters Net znajduje się w części „PHP Tools and Extras” — ich witryny.php3" ). else print( "'$aValue4' nie jest liczbą<br>" ).com' nie był zarejestrowany. */ $aEmail1 = "blake@intechra. if ( is_numeric( $aValue4 ) == True ) print( "'$aValue4' jest liczbą<br>" ). ?> </body> </html> Skrypt przedstawiony na wydruku 7 interpretuje pierwsze trzy wartości jako liczby natomiast ostatnią nie. else print( "'$aPhoneNum3' nie jest prawidłowym numerem telefonu<br>" ).net". Witryna Webmasters Net (http://www. is_url() i is_phone() przeznaczone do sprawdzania adresów e-mail. if ( $aValidator->is_phone( $aPhoneNum3 ) == True ) print( "'$aPhoneNum3' jest prawidłowym numerem telefonu<br>" ). W chwili pisania tego przykładu host 'invalidhost. if ( is_numeric( $aValue3 ) == True ) print( "'$aValue3' jest liczbą<br>" ). include( ". Kontrola poprawności danych przy użyciu klasy Validator <?php error_reporting( 0 ). if ( $aValidator->is_email( $aEmail3 ) == True ) print( "'$aEmail3' jest prawidłowym adresem email<br>" ).Validator. if ( $aValidator->is_email( $aEmail1 ) == True ) print( "'$aEmail1' jest prawidłowym adresem email<br>" ).. if ( $aValidator->is_phone( $aPhoneNum1 ) == True ) print( "'$aPhoneNum1' jest prawidłowym numerem telefonu<br>" ). $aPhoneNum1 = "(208) 359-1540".com". ?> Rozdział 3 – Formularze i cookie 48 . $aEmail3 = "nobody@invalidhost. else print( "'$aEmail2' nie jest prawidłowym adresem email<br>" ). else print( "'$aValue2' nie jest liczbą<br>" ).net) zawiera nieco świetnych klas i modułów z kodem źródłowym. Przykładowymi funkcjami kontroli poprawności są is_email().net". $aEmail2 = "john".thewebmasters. $aValidator = new Validator. else print( "'$aEmail1' nie jest prawidłowym adresem email<br>" ).

int bezpieczny ) Wszystkie argumenty funkcji poza nazwą są opcjonalne. że jeżeli użytkownik obejrzy witrynę przy użyciu jednej przeglądarki i zostanie ustawione cookie. większość programistów WWW i użytkowników jest zaznajomiona z koncepcją cookie. setcookie(). twoja aplikacja będzie działała z większością przeglądarek. 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. Dowolny z ciągów może zostać opuszczony podając pusty ciąg (""). ale tak jak w przypadku wszystkich narzędzi zewnętrznych należy sprawdzić.= date( "d F Y". czy spełnia twoje wymagania. string ścieżka.9.Klasa Validator jest potężnym zestawem funkcji przyspieszających tworzenie oprogramowania. Więcej ogólnych informacji na temat cookie można znaleźć w specyfikacji cookie firmy Netscape. Oznacza to. $aValMessage .". Wydruk 3. to cookie nie będzie dostępne. $aMessage . string domena.html. • Każda przeglądarka przechowuje cookie niezależnie. • Przeglądarki różnie obsługują cookie.= ". $aTwoWeeks ). $LastTime ). Użycie cookie <?php // Sprawdzenie czy istnieje zmienna cookie $LastTime if ( !empty( $LastTime ) ) { $aMessage = "Ostatnia wizyta miała miejsce ". string wartość.= " o ". jeżeli użytkownik ponownie obejrzy witrynę za pomocą innej przeglądarki.netscape. } else { $aMessage = "Nie byłeś tu przez ostatnie ". 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. Funkcja setcookie() jest zdefiniowana w sposób następujący: int setcookie( string nazwa. Jednak wielu użytkowników nie przyjmuje cookie wysłanych do przeglądarek z powodu plotek na temat ich wykorzystania.9 pokazuje jak ustawiać i wyświetlać cookie. time(). // sprawdzenie istnienia niezwykle ważnej tablicy z cookie $aValMessage = "". Jednak jeżeli korzystasz z cookie. PHP posiada tylko jedna funkcję przeznaczoną do tworzenia cookie. } // Ustawienie cookie ważnego przez dwa tygodnie $aTwoWeeks = time() + ( 60 * 60 * 24 * 14 ). if ( !empty( $CookieArray ) ) { $aValMessage = "Wartości: " . jak dzieje się to w przypadku metod GET i POST. ale nie wymagasz ich do prawidłowej pracy. cookie o podanej nazwie jest usuwane. Parametr bezpieczny wskazuje. niektórzy użytkownicy nie będą mogli jej używać. $CookieArray[0].= "dwa tygodnie. Cookie mogą przenosić wartości skalarne jak również tablice wartości. którą można uzyskać jako wynik funkcji mktime() lub time(). $CookieArray[1]. $LastTime ).10 pokazane jest jak używać buforowania wyjścia w połączeniu z funkcją setcookie(). Na wydruku 3.com/newsref/std/cookie_spec. int czas. Dowolna wartość numeryczna może zostać opuszczona podając wartość zero. Ponieważ cookie są wysyłane jako część nagłówka HTTP. że cookie może być przesyłane jedynie przez połączenie bezpieczne (HTTPS). Jeżeli twoja aplikacja opiera swoje działanie na cookie. Jeżeli funkcja jest wywołana tylko z nazwą. Argument czas jest standardowym czasem z systemu Unix w postaci liczby. Cookie są plikami tekstowymi zapisanymi na komputerze klienta i są one ze swojej natury niewinne. setcookie( "LastTime".= date( "h:i:s a". która jest dostępna pod adresem http://www. Dowolne cookie odesłane do aplikacji przez przeglądarkę jest automatycznie konwertowane na zmienną PHP tak samo. Sprawdź aplikację na możliwie dużej ilości przeglądarek. " . To samo ograniczenie obowiązuje również dla funkcji header(). $aMessage . Cookie Z powodu trwającej debaty na temat użycia cookie. Wydruk 3. 49 PHP – Kompendium wiedzy . $aMessage . $aMessage . Poniższe dwa przykłady pokazują użycie funkcji setcookie().

W aplikacjach WWW nie ma niezawodnego mechanizmu kontroli danych po wyjściu z poszczególnych pól. time() + 60 ). W PHP4 zostało to usunięte. ?> </body> </html> Wydruk 3. ?> Ostatnia uwaga na temat cookie W poprzedniej wersji PHP jeżeli chciałeś ustawić wiele cookie za pomocą jednego skryptu. $aStartValue + 1.10. ?> Działa świetnie. Mimo. */ ob_start(). $aTwoWeeks ). Jeżeli funkcja ob_start() jest zakomentowana.$aStartValue } else { = $CookieArray[1] + 1. $aValMessage ). w jakiej chciałeś obsługiwać cookie. ?> <html> <head> <title>Użycie cookie</title> </head> <body> <?php print( $aMessage . więc cała kontrola poprawności jest przeprowadzana na serwerze. że jeżeli istnieje błąd w danych. setcookie( "CookieArray[1]". Na przykład. ich tworzenie w PHP jest łatwe i proste. } // usunięcie niezwykle istotnej tablicy wartości setcookie( "CookieArray[0]" ). // dodanie niezwykle istotnej tablicy wartości setcookie( "CookieArray[0]". należało najpierw wywołać setcookie(). Należy wywoływać setcookie() w takiej kolejności jak się spodziewasz. że będą przetwarzane przez przeglądarkę. setcookie( "CookieArray[1]" ). Ważne zagadnienia programowania dla WWW Część ta zawiera niektóre tematy. "<br><br>" . czy należy używać cookie będzie nadal trwała.9. W tradycyjnych aplikacjach dane wprowadzone przez użytkownika są często kontrolowane natychmiast po ich wprowadzeniu. aby ustawić nową wartość a następnie usunąć poprzednią wartość. $aValMessage = "Wartości nie są dostępne!". Proces ten jest pokazany na wydruku 3. musiałeś wywoływać setcookie() w odwrotnej kolejności do tej. $aStartValue. $aTwoWeeks ). "anyvalue". </body> </html> <?php ob_end_flush(). że debata na temat tego. jakie muszą brać pod uwagę programiści przechodzący z pisania zwykłych aplikacji na aplikacje oparte o WWW. Oznacza to. Użycie setcookie() razem z buforowaniem wyjścia <?php /* Uruchomienie buforowania wyjścia. Pozwala to natychmiast informować o nieprawidłowych danych. Obsługa nieprawidłowych danych Pierwszym problemem jest sposób obsługi nieprawidłowych danych. Problemy te powstają zwykle w czasie przetwarzania i wykorzystywania danych przesłanych z formularza HTML. ?> <html> <head> <title>Użycie setcookie() wraz z buforowaniem wyjścia</title> </head> <body> <?php setcookie( "anyname". $aStartValue = 0. skrypt spowoduje błąd. Dalsze rozważania na temat cookie będą kontynuowane w rozdziale 7 „Sesje i stan aplikacji”. jeżeli chciałeś usunąć cookie a następnie ustawić nowe o tej samej nazwie. użytkownik nie będzie o nim wiedział aż do chwili Rozdział 3 – Formularze i cookie 50 .

html\n" )./include/class. przechodzimy do odpowiedniej strony header( "Location:thanks. Dlatego w trakcie tworzenia aplikacji musisz się zdecydować. Możesz utworzyć taki formularz przesyłając dane z formularza do tego samego skryptu. Niektóre przeglądarki nie utrzymują wartości formularza po użyciu przycisku Wstecz.?>"> Numer telefonu:</font> <input type="text" name="Phone" 51 PHP – Kompendium wiedzy . Inteligentna obsługa nieprawidłowych danych <?php error_reporting( 0 ). Jeżeli jednak tworzysz duży formularz nie należy używać tej metody. // na początku przestawiamy skrypt na zbieranie nowych danych. <?php } // end if ?> <form action="handle_errors. zmiany danych istniejących i kontroli poprawności tych danych. Na wydruku 3. Pierwszą metodą jest wypisywanie błędów i nakazanie użytkownikowi.przesłania danych formularza.php3" ). $aCurEmailVal = $Email. $aValidPhone = $aValidator->is_phone( $Phone ). $aPhoneTextCol = "black". ponieważ ten sam skrypt może być użyty do pobierania nowych danych.11. ale skutkuje powstaniem solidniejszej i bardziej użytecznej aplikacji. ale jest najprostszy do zrealizowania. if ( $aValidEmail == False ) $aEmailTextCol = "red". if ( $aValidPhone == False ) $aPhoneTextCol = "red". $aCurEmailVal = "". if ( !empty( $Submit ) ) { /* Jeżeli zmienna $Submit jest zainicjowana jesteśmy tutaj po przesłaniu danych do skryptu.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. $aCurPhoneVal = "".Validator. if ( $aValidPhone && $aValidEmail ) { // Dane są prawidłowe.. $aValidator = new Validator. } } ?> <html> <head> <title>Inteligentna obsługa nieprawidłowych danych</title> </head> <body> <?php if ( empty( $Submit ) ) { ?> Proszę wprowadzić numer telefonu i adres email. Wydruk 3. Próbujemy sprawdzić wartości zmiennych formularza. Drugą metodą obsługi nieprawidłowych danych jest ponowne pokazanie strony formularza z zainicjowanymi wszystkimi polami i zaznaczonymi nieprawidłowymi pozycjami. Jeżeli do formularza wpisywane jest bardzo mało danych (jedno lub dwa pola) metoda ta będzie do zaakceptowania. aby wrócił do poprzedniej strony i poprawił dane. wyróżniamy je $aCurPhoneVal = $Phone. */ include( ". Sprawdź dane oznaczone kolorem czerwonym. w jaki sposób reagować na błędy.phtml" method="post"> <font color="<?php print( $aPhoneTextCol ). Istnieje kilka sposobów reagowania na błędy. $aEmailTextCol = "black". przytoczymy tutaj dwa z nich. Metoda taka wymaga bardziej zaawansowanego projektowania. ponieważ może ona wymagać ponownego wprowadzenia wszystkich danych. Według mnie jest to najmniej pożądany sposób reakcji na błędy. $aValidEmail = $aValidator->is_email( $Email ). <br> <?php } else { // if ?> We wprowadzonych danych wystąpiły błędy. } else { // Dane nieprawidłowe.

. Funkcja strip_tags() usuwa wszystkie znaczniki z ciągu oprócz tych.12 pokazuje obróbkę danych do ponownego wyświetlenia. która powoduje przekierowanie przeglądarki do nowej strony zawierającej podziękowanie. Dodatkowo.12. 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. strona jest ładowana po raz drugi. Aby uniknąć tego problemu zawsze należy przetwarzać dane wprowadzone do formularza przed ich wyświetleniem. Dzieje się tak. Przedstawione metody nie są jedynymi stosowanymi do obsługi błędnych danych. Funkcja htmlentities() konwertuje specjalne znaki HTML na odpowiadające im symbole HTML. Pamiętając o tym pomyśl o formularzu. <html> <head> <title>Pobieranie danych do wyświetlenia</title> </head> <body> <form action="safedisplay. ale na pewno skutkuje różnymi efektami ubocznymi. Formularz i skrypt na wydruku 3. Jeżeli tworzysz aplikację WWW. ale tym razem pola mają wartości wprowadzone poprzednio przez użytkownika. PHP posiada kilka funkcji pomagających w tym zadaniu.?>"> <br> <input type="submit" name="Submit" value="Wyślij"> </form> </body> </html> W skrypcie na wydruku 11. więc formularz jest wyświetlany z pustymi polami. Załóżmy. więc sprawdzana jest poprawność danych. ale ilustrują one podstawy tworzenia aplikacji WWW. na pewno nie będzie lubiana. Metoda ta pozwala na szybką identyfikację przez użytkownika danych. adres e-mail oraz treść uwagi. aby wyświetlać wartości walutowe lub dodać separatory tysięcy. Zwykle nie jest to niebezpieczne. wywoływana jest funkcje header(). Na przykład znaki < i > są zastępowane przez &lt. niektórzy użytkownicy będą dodawać znaczniki HTML. aby zaznaczyć wystąpienie błędu. gdy strona jest otwierana bezpośrednio. nieprawidłowe dane są wyświetlane kolorem czerwonym. formularz wywoływany jest ponownie. i &gt.value="<?php echo $aCurPhoneVal. Wydruk 3.phtml" method="post"> Wprowadź tekst:<br> <textarea cols="40" rows="6" name="TheText"></textarea> <br><br> Wybierz metodę filtrowania: <select name="FilterType" size="1"> <option value="0">brak</option> Rozdział 3 – Formularze i cookie 52 . Jeżeli któreś pole zawiera nieprawidłową wartość. Jeżeli oba pola mają poprawne dane. ale zwykle nie ma zbyt dużo kłopotu przy wyświetlaniu danych wprowadzonych przez użytkownika. Są to funkcje strip_tags() i htmlentities(). Czasami formatowane są liczby. w którym użytkownicy będą mogli wpisywać swoje uwagi. Obsługa i formatowanie wyświetlanych danych W zwykłej aplikacji wyświetlanie danych wprowadzonych przez użytkownika nie wymaga zwykle formatowania lub przetwarzania. które zostały podane w dodatkowym opcjonalnym parametrze. ale tym razem zmienna $Submit nie jest pusta. Po wprowadzeniu tekstu wyświetlasz komunikat w celu weryfikacji a następnie przetwarzasz ten komunikat. ponieważ przeglądarka interpretuje cały tekst otrzymany z serwera 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 dostarczysz użytkownikom formularz a następnie będziesz wyświetlał wpisane dane. Wybór metody obsługi błędów może być kluczową decyzją przy projektowaniu aplikacji. aby sprawdzić co się stanie. Gdy użytkownik kliknie przycisk Wyślij. Obróbka danych do wyświetlenia.?>"> Adres e-mail:</font> <input type="text" name="Email" value="<?php echo $aCurEmailVal.?>"> <br> <font color="<?php print( $aEmailTextCol ). zmienna $Submit jest pusta. które wymagają poprawienia i nie wymaga ponownego wprowadzenia całej zawartości formularza. Jeżeli twoja aplikacja będzie niewygodna lub wymagać będzie ponownego wprowadzania danych. że stworzysz formularz w którym zapisywane będą: nazwa użytkownika. W przypadku programowania dla WWW wyświetlanie danych wprowadzonych do formularza w postaci strony WWW jest sprawą krytyczną.

Formularz wprowadzania danych 53 PHP – Kompendium wiedzy . jeżeli nie ma filtrowania.<option value="1">strip_tags()</option> <option value="2">htmlentities()</option> </select> <br><br> <input type="submit" name="Submit" value="Wyślij"> </form> </body> </html> <!-. case 2 : // htmlentities $aDisplayText = htmlentities( $TheText ). break. } ?> <html> <head> <title>Bezpieczne wyświetlenie danych użytkownika</title> </head> <body> <?php print( $aDisplayText ). pokazują wyniki filtrowania danych z formularza za pomocą funkcji odpowiednio strip_tags() i htmlentities(). zawiera formularz wprowadzania danych.3.6. pokazuje co się dzieje. Rysunek 3. break.3.phtml --> <?php error_reporting( 255 ). case 1 : // strip_tags $aDisplayText = strip_tags( $TheText ). i 3.3. do 3.5. Rysunek 3. ?> </body> </html> Rysunki 3. Rysunki 3.Skrypt safedisplay2. Rysunek 3. switch ( $FilterType ) { case 0 : // brak $aDisplayText = $TheText. pokazują formularz wejściowy i wyniki działania skryptu.6.4. break.

Rysunek 3. Wyświetlanie ze strip_tags() Rozdział 3 – Formularze i cookie 54 .5.4. Wyświetlanie bez filtrowania Rysunek 3.

Skrypt safedisplay2. która konwertuje znaki nowej linii na znaczniki <br>.6.phtml" method="post"> Wprowadź tekst:<br> <textarea cols="40" rows="6" name="TheText"></textarea> <br><br> Wybierz metodę filtrowania: <select name="FilterType" size="1"> <option value="0">none</option> <option value="1">strip_tags()</option> <option value="2">htmlentities()</option> </select> <br><br> <input type="checkbox" name="DoSS"> strip_slashes()<br> <input type="checkbox" name="DoNB"> nl2br()<br><br> <input type="submit" name="Submit" value="Wyślij"> </form> </body> </html> <!-. NUL1 i znaki backslash pochodzące z zewnętrznych źródeł. Jest to szczególnie przydatne.ini magic_quotes_gpc. Jeżeli jest ona uaktywniona. są automatycznie poprzedzane ukośnikiem.13. należy wywołać funkcję strip_slashes(). ale z dodatkowymi opcjami które powodują wywołanie funkcji strip_slashes() i nl2br(). należy pamiętać. Jeżeli chodzi o problem ze znakami nowej linii.Rysunek 3. która usuwa te dodatkowe znaki. ponieważ nie będziesz musiał ręcznie oznaczać tych znaków w ciągu SQL. Aby wyświetlić taki ciąg.phtml --> <?php 1 Znak o kodzie zero (przyp. chyba. Na przykład pojedynczy apostrof jest wyświetlany na stronie jako sekwencja

Related Interests

. że wystąpi on w bloku <pre></pre>. Pierwsze z zakłóceń jest powodowane przez dyrektywę konfiguracji --enable-magic-quotes oraz opcje pliku php. że HTML nie interpretuje znaku CR ani LF jako znaku podziału wiersza. Wyświetlanie z htmlentities() Jeżeli dokładnie przyjrzysz się tym rysunkom zauważysz.) 55 PHP – Kompendium wiedzy . Na wydruku 13 znajduje się ten sam formularz i skrypt co na wydruku 12. tłum. że widać niespodziewane wyniki po wyświetleniu danych. Ulepszona obróbka danych do wyświetlenia <html> <head> <title>Pobieranie danych do wyświetlenia</title> </head> <body> <form action="safedisplay2. wszystkie apostrofy. magic_quotes_runtime i magic_quotes_sybase. Również znaki końca linii wprowadzone w polu tekstowym nie są uwzględniane w wyświetlanym tekście. jeżeli dane te będą zapisywane w bazie danych. na przykład formularzy i bazy danych. PHP posiada funkcję nl2br(). cudzysłowy. Wydruk 3.

7. break. ?> </body> </html> Rysunek 3. break. ?> <html> <head> <title>Bezpieczne wyświetlenie danych użytkownika</title> </head> <body> <?php print( $aDisplayText ). if ( $DoNB == "on" ) $aDisplayText = nl2br( $aDisplayText ). case 2 : // htmlentities $aDisplayText = htmlentities( $TheText ). case 1 : // strip_tags $aDisplayText = strip_tags( $TheText ). Formularz wprowadzania danych Rozdział 3 – Formularze i cookie 56 .error_reporting( 0 ). } if ( $DoSS == "on" ) $aDisplayText = stripslashes( $aDisplayText ). break. switch ( $FilterType ) { case 0 : // brak $aDisplayText = $TheText.

i 3. Ponieważ PHP został zaprojektowany jako język programowania dla WWW.13. Jeżeli wcześniej miałeś doświadczenie jedynie ze zwykłymi aplikacjami. Wszystkie te tematy razem stanowią podstawę do tworzenia interaktywnych aplikacji WWW. W rozdziale tym omówiono niektóre narzędzia umożliwiające obsłużyć nieprawidłowe dane i zabezpieczyć przed szkodliwymi danymi.7. jak widać na rysunku 3. Podsumowanie Rozdział ten zawiera opis podstaw przetwarzania formularzy przy użyciu PHP. 57 PHP – Kompendium wiedzy .8.8. upraszcza on znacznie proces interakcji z formularzami HTML. strip_slashes() i nl2br() Po wprowadzeniu zmian pokazanych na wydruku 3. 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ę. W rozdziale tym omówiono również proces zapamiętywania i odczytywanie cookie na komputerze klienta.Rysunek 3. Szczegółowe omówienie tych problemów znajduje się w rozdziale 9 „Niezależność od przeglądarki”. formularz wprowadzania danych i postać danych wynikowych jest taka. Wyświetlanie przefiltrowane przez strip_tags(). 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. że każda przeglądarka działa nieco inaczej.

Na wydruku 4. Zdolność ta powoduje. // Sprawdzenie czy plik istnieje if ( is_file( $aLogFilePath ) == True ) { // Otwarcie i odczytanie pliku. W czasie pracy programu stan aplikacji jest utrzymywany w pamięci. W przypadku zwykłego programu.1. aby korzystając z plików nie naruszyć systemu bezpieczeństwa serwera WWW. że równie łatwo można zapisać dane do pliku jak również wysłać je poprzez potok do innego programu. Do obsługi plików i innych obiektów systemu plików PHP posiada funkcje podobne do tych spotykanych w języku C. UŻYCIE: Wystarczy dołączyć ten plik. . pamiętać o zagadnieniach bezpieczeństwa. Szczegółowe przedstawienie zarządzania stanem aplikacji można znaleźć w rozdziale 7 „Sesje i stan aplikacji”. Użycie plików do zliczania odwołań do stron witryny <?php /* Plik ten może być dołączany do dowolnego skryptu PHP. $aLogFilePath = "/www/auto_logs/access. zapisu i innych operacji na plikach lub innych obiektach systemu plików jest niezbędna do zrealizowania obsługi sesji i serializacji. W przypadku Apache domyślnie jest to użytkownik nobody. Ponieważ aplikacja będzie działać w kontekście serwera WWW. W chwili obecnej wystarczy wiedzieć. Bardziej szczegółowy opis wszystkich funkcji znajdują się w skorowidzu funkcji na końcu książki. Do tego celu wykorzystane zostały podstawowe operacje na plikach. takimi jak gniazda i potoki). */ error_reporting( 0 ). Oczywiście istnieje wiele sytuacji gdy narzut czasowy wprowadzany przez bazę danych lub wymagania aplikacji powodują. Format pliku to oddzielone tabulatorami // pary opisujące kolejne skrypty: // ścieżka-do-skryptu licznik $aFile = fopen( $aLogFilePath. otwarcie. którego uprawnienia ograniczają dostęp przez aplikację do obiektów systemu plików. że pliki są jedynym sensownym rozwiązaniem. Operacje na plikach Wstęp Obsługa plików jest zawarta we wszystkich nowoczesnych językach programowania. że do utrzymywania stanu aplikacji i tworzenia innych mechanizmów przechowywania danych można użyć plików. aby używając plików. Zdolność do tworzenia. pliki będą miały uprawnienia użytkownika przy pomocy którego uruchamiany jest serwer WWW. "r" ). Wydruk 4. jest sposób utrzymywania stanu aplikacji. PHP używa uchwytów plików oraz pozwala na tworzenie uchwytów (pozwalających na operacje innymi typami strumieni danych. Powoduje to automatyczne zliczanie odwołań do strony.Rozdział 4. Odczyt i zapis plików Jedną z głównych różnic przy pisaniu aplikacji opartych o sieć WWW w stosunku do zwykłych aplikacji. Należy uważać. wykonuje kilka komend i kończy działanie programu. W aplikacjach opartych o sieć WWW stan musi być utrzymywany przez serwer WWW. odczyt. zapis i zamknięcie prostego pliku śladu. ponieważ klientem jest zwykle prosta przeglądarka WWW. Ważne jest.log".1 pokazane zostało w jaki sposób można zrealizować liczniki dostępu do stron witryny. W przykładzie tym nie zostały wykorzystane wszystkie dostępne w PHP funkcje operujące na plikach. Tak jak C. W większości przypadków użycie bazy danych zamiast plików jest o wiele bardziej bezpieczne i praktyczne. Tworzy on zmienną globalną $aPageAccessCount. w funkcjach służących do odczytu i zapisu. czytania. która zawiera ilość odwołań do skryptu który dołącza ten plik. $aCountArray = array(). użytkownik uruchamia go.

Niektóre z bardziej znanych protokołów TCP/IP.1 <?php include( "auto_counter. Na koniec cała tablica jest zapisywana do pliku śladu. Na wydruku 4.1 pokazujemy użycie jednego pliku do przechowywania liczników odwołań do dowolnej liczby stron witryny. "$aKey\t$aValue\n" ). na przykład HTTP.while( !feof( $aFile ) ) { $aLine = fgets( $aFile. POP3 i SMTP posiadają swoje implementacje w PHP. ?> <html> <head> <title>Strona testowa 1</title> </head> <body> Strona ta była oglądana <b> <?php print( $aPageAccessCount ). 1024 ). Z perspektywy klienta wystarczy jedynie zestawić połączenie. } fclose( $aFile ). W skrypcie tym sprawdzamy za pomocą funkcji is_file() czy istnieje plik śladu. za pomocą których można komunikować się z innymi aplikacjami za pomocą dowolnego protokołu.php" ). jego kolejne linie są odczytywane i analizowane. Użycie skryptu z wydruku 4. który zwraca cytat dnia. </body> </html> Użycie gniazd PHP umożliwia dostęp do surowych gniazd TCP/IP.3 pokazano sposób dostępu za pomocą gniazd do serwera quotd. } } fclose( $aFile ). znak tabulacji i wartość licznika. odczytać dane a następnie zakończyć połączenie.2 pokazane jest strona demonstrująca jak łatwo można użyć tego licznika. // Zapis całej tablicy do pliku $aFile = fopen( $aLogFilePath. $aLine ). ?> Na wydruku 4. Bardziej efektywne jest odczytywanie i zapis tylko jednej wartości a nie całego pliku. ale pokazuje ideę takiego licznika. Na wydruku 4. Po zestawieniu połączenia serwer wysyła strumień danych tekstowych a następnie zamyka połączenie. Wydruk 4. } // Ustawienie globalnego licznika odwołań do strony // i uaktualnienie tablicy temp $aPageAccessCount = $aCountArray[$PATH_TRANSLATED] + 1. if ( count( $aTempArray ) == 2 ) { $aCountArray[$aTempArray[0]] = $aTempArray[1]. $aTempArray = explode( "\t". należy pamiętać. że jest to bardzo nieefektywne rozwiązanie.2. Jeżeli chcesz. Jeżeli szukasz takiego mechanizmu do twojej witryny. Każda linia zawiera pełną ścieżkę dostępu do skryptu. Protokół quotd jest bardzo prosty. możesz użyć tej tablicy do wyświetlenia liczników dla wszystkich stron witryny a nie tylko bieżącej strony. 59 PHP – Kompendium wiedzy . Nie jest to efektywny sposób. 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. "w" ). Jeżeli plik ten istnieje. foreach ( $aCountArray as $aKey => $aValue ) { fputs( $aFile. ?> </b> razy. $aCountArray[$PATH_TRANSLATED] = $aPageAccessCount. 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. więc nie musisz w tych przypadkach używać surowych gniazd.

} ?> <form action="<?php echo $PHP_SELF ?>" method="post"> Wprowadź zapytanie <b>whois</b>: <input type="text" name="WhoisQuery"> <input type="submit" name="Submit" value="Submit"> </form> </body> </html> Rozdział 4 – Operacje na plikach 60 . "r" ) ) { // odczytanie wszystkich danych z potoku while ( !feof( $aFile ) ) { $aLine = fgets( $aFile. Skrypt ten ilustruje również częstą praktykę używania tego samego skryptu do wyświetlenia formularza i przetworzenia jego danych. Użycie gniazd <html> <head> <title>Przykład wykorzystania serwera QOTD: Użycie gniazd w PHP</title> </head> <body> <?php // otwarcie gniazda serwera qotd $aFile = fsockopen( "208. // odczytanie wszystkich danych ze strumienia while ( !feof( $aFile ) ) { $aLine = fgets( $aFile.php */ // ścieżka do programu whois $whois_prog = '/usr/bin/whois'. 17 ). że potok jest jednokierunkowym strumieniem danych. Wydruk 4. 1024 ).Wydruk 4. } fclose( $aFile ). } print( "<hr>" ). exit.4. Skrypt przetwarzający zapytanie whois <?php /* whois.3. if ( !is_file( $whois_prog ) ) { // nie udało się znaleźć programu echo "Nie mogę znaleźć $whois_prog!<br>". które jest dostępne w większości systemów Unix. print( "$aLine<br>" ). Ten prosty skrypt i formularz pozwalają na wprowadzenie zapytania dla whois. Jedyną różnicą pomiędzy plikiem i potokiem jest to. } pclose( $aFile ).164". Na wydruku 4. } ?> <html> <head> <title>Whois: Uzycie potoków w PHP</title> </head> <body> <?php if ( $REQUEST_METHOD == 'POST' ) { // otwarcie potoku do polecenia whois if ( $aFile = popen( "$whois_prog $WhoisQuery". print( "$aLine<br>" ). potoki są traktowane jak kolejny uchwyt pliku.4 pokazane jest użycie potoku do odczytania wyniku zapytania do polecenia whois. 1024 ). } else { echo "Nie mogę otworzyć $whois do odczytu!<br>". Potok może być użyty do odczytu danych wyjściowych z programu lub skryptu. ?> </body> </html> Użycie potoków Tak jak w przypadku gniazd.129.36.

5 pokazany jest skrypt wyświetlający nazwy wszystkich plików w bieżącym katalogu w postaci łączy. Wydruk 4.php3" ). Użycie klasy File do wyświetlenia zawartości bieżącego katalogu <?php include( "class. $aDirContents = $aFileClass->get_files( ". Klasa ta zawiera wiele często używanych funkcji PHP operujących na plikach i hermetyzuje kontrolę błędów. print( "$aCurFile</a><br>" ).5. print( nl2br( htmlentities( $aFileCont ) ) ). szczególne wtedy. Gdy użytkownik kliknie łącze. ale również przedstawia dodatkową klasę ułatwiającą operacje na plikach. Klasa File dostępna z WebMasters Net (http://www. print( "<pre>" ). ?> <html> <head> <title>Użycie klasy File</title> </head> <body> Poniżej znajduje się lista plików w bieżącym katalogu.net) jest przydatnym narzędziem." ). print( "</pre>" ).6 wyświetla jego zawartość używając celu klasy File do odczytania jego zawartości.Klasa File W poprzednim rozdziale wspominaliśmy.phtml?fn=$aCurFile###BOT_TEXT###quot;>" ). dzięki czemu możesz więcej czasu poświęcić logice aplikacji zamiast zajmować się pisaniem podstawowych konstrukcji kontroli błędów. należy poznać sposoby korzystania z uchwytów plików i funkcji operujących na plikach.File. ?> <html> <head> <title>Użycie klsy File</title> </head> <body> <?php print( "The file <b>$fn</b>:<br><br>" ). 61 PHP – Kompendium wiedzy . for ( $nIndex = 0. Na wydruku 4.6.<br><br> <?php $aFileClass = new File(). Rozdział ten zawiera nie tylko opis podstawowych operacji na plikach i systemie plików. } ?> </body> </html> Wydruk 4. gdy twoja aplikacja intensywnie wykorzystuje pliki. że do PHP dostępne są świetne narzędzia dodatkowe pochodzące z różnych źródeł. Noe wszystkie aplikacje używają plików. skrypt zamieszczony na wydruku 4. ?> </body> </html> Podsumowanie Zdecydowanie się na użycie plików w aplikacji opartej na WWW jest jedną z krytycznych decyzji w fazie projektowania aplikacji.theWebMasters. $nIndex++ ) { $aCurFile = $aDirContents[$nIndex]. „Wysyłanie plików przez formularz”.php3" )./class. $aFileCont = $aFileClass->read_file( $fn ). Opis operacji na plikach zawarty w tym rozdziale oraz opis formularzy zamieszczony w rozdziale poprzednim stanowią odpowiednią podstawę do następnego rozdziału. print( "<a href=###BOT_TEXT###quot;disp_file.<br> Kliknij nazwę pliku aby zobaczyć ich zawartość. $nIndex < count( $aDirContents ).File. $aFileClass = new File(). Wyświetlenie zawartości pliku za pomocą klasy File <?php include( ". ale aby efektywnie korzystać z różnych typów strumieni danych. na przykład gniazd i potoków.

Możesz również pomyśleć o stworzeniu dodatkowego mechanizmu przesyłania plików. Jeżeli pozwolisz użytkownikom na wysyłanie plików za pomocą formularza. 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. Obsługa przesyłania plików w PHP jest bardzo łatwa.Rozdział 5. Znacznik <FORM> musi posiadać atrybut ENCTYPE ustawiony na multipart/form-data zamiast domyślnego application/x-www-form-urlencoded. a przykład anonimowego FTP. • $thefile_name — Zmienna ta zawiera nazwę pliku na komputerze z którego został wysłany.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. Większość nowoczesnych przeglądarek jest zgodnych z tym dokumentem. musisz rozważyć dopuszczalne typy plików oraz ich wielkości. plik zostanie stracony.2. ponieważ został on włączony do standardu HTML 3. Jeżeli przesłany plik nie ma właściwego typu lub jest większy. 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. Pisząc skrypt obsługujący przesyłanie pliku należy pamiętać.1. jak i funkcji systemu plików. jeżeli są one niezbędne do działania aplikacji. tak jak jest to pokazane na Wydruku 5. Musisz również umieścić na formularzy znacznik <INPUT> typu file. Wydruk 5.1. wyświetlany jest komunikat błędu. ale jeżeli masz zamiar przesyłać duże pliki należy się zastanowić nad zastosowaniem innego mechanizmu. Mechanizm wbudowany w PHP działa świetnie dla małych plików. PHP tworzy automatycznie cztery zmienne globalne. Formularz HTML ze znacznikiem <INPUT> <html> <head> <title>Formularz do przesyłania plików</title> </head> <body> <form action="upload_single.1. .1. PHP posiada wbudowany mechanizm pozwalający na odebranie pliku wysłanego z przeglądarki zgodnej z RFC 1867. • $thefile_type — Zmienna ta zawiera typ MIME przesyłanego pliku (o ile przeglądarka udostępnia taką informację). że PHP automatycznie usuwa plik tymczasowy po zakończeniu skryptu. jest on wyświetlany. które opisują przesłany plik: • $thefile — Zmienna zawiera nazwę pliku tymczasowego w którym znajduje się plik przesłany na serwer. zawiera prosty formularz HTML zawierający jeden znacznik <INPUT>. Wydruk 5. Nazwy tych zmiennych są tworzone w oparciu o nazwę znacznika <INPUT> w formularzu.phtml" method="post" enctype="multipart/form-data"> Wyślij plik: <input type="file" name="thefile"><br><br> <input type="submit" name="Submit" value="Wyślij"> </form> </body> </html> Po wysłaniu danych formularza z wydruku 5. więc jeżeli nie skopujesz go. • $thefile_size — Zmienna zawiera wielkość przesłanego pliku w bajtach. Skrypt na wydruku 5.

Jest to realizowane przez dodanie do formularza ukrytego pola o nazwie MAX_FILE_SIZE. } } else { $aErrors . Wydruk 5. if ( !empty( $thefile_name ) ) // nie wybrano pliku { if ( ( $thefile_type == "image/gif" ) || ( $thefile_type == "image/pjpeg" ) || ( $thefile_type == "image/jpeg" ) ) { if ( $thefile_size < ( 1024 * 100 ) ) { $aCurBasePath = dirname( $PATH_TRANSLATED ). print( "<img src=###BOT_TEXT###quot;uppics/$thefile_name###BOT_TEXT###quot; border=###BOT_TEXT###quot;0###BOT_TEXT###quot;>" ). przesłany plik jest kopiowany z katalogu tymczasowego do katalogu określonego przez przed chwilą skonstruowaną ścieżkę. zmienna $thefile_name jest pusta. $aNewName = $aCurBasePath . Dodając /uppics/ i oryginalną nazwę pliku na komputerze lokalnym. copy( $thefile. } ?> <html> <head> <title>Wyświetlenie przesłanego pliku</title> </head> <body> <?php if ( $aErrors != "" ) { print( "<b>Wystąpił błąd</b>: $aErrors<br>" ).= "Za duży plik !!!". } ?> </body> </html> W przykładzie zamieszczonym na wydruku 5. na przykład kontrolę poprawności wykonania funkcji copy. że uprawnienia do katalogu muszą pozwolić na zapis przez użytkownika nobody.3. } } else { $aErrors . Funkcja dirname() zwraca nazwę katalogu z podanej ścieżki. Na wydruku 5. Na koniec. Należy pamiętać. czy został wybrany plik do przesyłania. Opuszczono również inne zagadnienia kontroli błędów. ale dodane zostało pole MAX_FILE_SIZE ograniczające wielkość przesyłanych plików do 100 kB.Wydruk 5. że nie wszystkie przeglądarki wysyłają typu MIME pliku. czy plik ma odpowiednią wielkość i typ MIME. Korzystając z Apache w systemie Linux oznacza to.1. Ograniczenie wielkości przesyłanego pliku za pomocą MAX_FILE_SIZE <html> <head> 63 PHP – Kompendium wiedzy . } else { print( "Przesłany plik:<br><br>" ). $aNewName ). Zmienna $PATH_TRANSLATED jest zmienną PHP i zawiera pełną ścieżkę do bieżącego skryptu. Jeżeli obie wartości zostaną zaakceptowane. tworzymy nową ścieżkę.3 pokazany jest formularz identyczny z tym z wydruku 5. nie wzięto pod uwagę.2. przy pomocy wyrażenia dirname($PATH_TRANSLATED) odczytywany jest bieżący katalog na serwerze WWW. $thefile_name. że aby operacja kopiowania się udała.2. Jednak przykład ten miał za zadanie pokazanie jak łatwo można obsłużyć za pomocą PHP operacje przesyłania pliku. Jeżeli nie został wybrany plik. Następnie sprawdzane jest. Obsługa przesyłania pliku <?php $aErrors = "".= "Nie wybrano pliku". W przykładzie tym na początku sprawdzane jest.= "Plik nie jest typu gif ani jpeg". PHP posiada mechanizm pozwalający na ograniczanie w skrypcie wielkości przesyłanych plików. docelowy katalog musi posiadać odpowiednio ustawione uprawnienia. } else { $aErrors . "/uppics/" .

jakie można przesyłać używając tego mechanizmu. Innym problemem. a $thefile_name będzie zawierała odpowiednią wartość. Jeżeli nie chcesz aby pojawiał się ten komunikat. że ta graniczna wielkość pliku jest ustawiana w celu chronienia serwera WWW. Ponieważ błąd przekroczenia wielkości przesyłanego pliku występuje przed wykonaniem jakiejkolwiek linii skryptu.conf (więcej szczegółów znajduje się w rozdziale o opcjach konfiguracji. ustawienie error_log na stderr spowoduje. Przesyłanie czterech plików <html> <head> <title>Formularz do przesyłania plików</title> </head> <body> Proszę podać cztery pliki rysunków do przesłania: <form action="upload_multiple.5.4. Aplikacja twoja może sprawdzać zmienne przesyłu plików i odpowiednio obsługiwać błędy. że wszystkie błędy PHP trafią do dziennika błędów Apache. Jeżeli używasz Linuksa i Apache. Możesz następnie ustawić opcję log_errors na On a error_log na wartość odpowiednią dla twojego środowiska. nie ma możliwości przechwycenia generowanego ostrzeżenia generowanego przez mechanizm przesyłania plików. musisz ustawić w pliku php. lub ustawienie dyrektywy w pliku Apache. Wydruk 5. Jeżeli więc twoja aplikacja dopuszcza przesyłanie dużych plików. że jeżeli opcja konfiguracji display_errors ma wartość On (domyślnie) w przeglądarce będzie się pojawiał komunikat błędu. Oznacza to. że zanim rozpocznie się wykonywanie skryptu musi zostać przesłany cały plik lub maksymalna określona ilość bajtów. sieje ona zniszczenie w twoich aplikacjach. ale akceptuje jedynie niektóre typy plików.<title>Formularz do przesyłania plików</title> </head> <body> <form action="upload_single. twoi użytkownicy mogą dosyć długo czekać zanim zobaczą komunikat o odrzuceniu przesyłanego pliku. Gdy osiągnięta zostanie graniczna wielkość pliku (zarówno ustawiona w formularzu jak i globalne maksimum). przerywa przesyłanie i ustawia nazwę pliku na none. Ta wielkość jest ważniejsza od zmiennej formularza MAX_FILE_SIZE. 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. PHP generuje błąd.phtml" method="post" enctype="multipart/form-data"> Plik 1: <input type="file" name="thefiles[]"><br><br> Plik 2: <input type="file" name="thefiles[]"><br><br> Plik 3: <input type="file" name="thefiles[]"><br><br> Plik 4: <input type="file" name="thefiles[]"><br><br> <input type="submit" name="Submit" value="Wyślij"> </form> </body> </html> Wydruk 5. do 2 megabajtów.phtml" method="post" enctype="multipart/form-data"> <INPUT TYPE="hidden" name="MAX_FILE_SIZE" value="102400"> Wyślij plik: <input type="file" name="thefile"><br><br> <input type="submit" name="Submit" value="Wyślij"> </form> </body> </html> Pułapki PHP domyślnie ogranicza wielkość plików. zmienna $thefile będzie miała wartość none. Wartość ta może być zmieniona przez ustawienie wartości upload_max_filesize w pliku php. Obsługa czterech przesyłanych plików <?php $aBasePath = dirname( $PATH_TRANSLATED ).ini. // każdy przesłany plik należy skopiować Rozdział 5 – Wysyłanie plików przez formularz 64 . Poniższy przykład pokazuje użycie tablicy do przesłania czterech plików.ini opcję konfiguracji display_errors na Off. nad jakim należy się zastanowić w trakcie pisania skryptu obsługi przesyłania plików jest to. Jeżeli użytkownikowi nie uda się przesył pliku. Mimo tego. który znajduje się na końcu książki).

copy( $thefiles[$nIndex].// i zapamiętać ich nowe ścieżki do późniejszego wykorzystania for ( $nIndex = 0. print( "<pre>" ). $aNewName ). if ( ( $aType == "image/gif" ) || ( $aType == "image/pjpeg" ) || ( $aType == "image/jpeg" ) ) { $aNewName = $aBasePath . } } } ?> <html> <head> <title>Wyświetlanie przesłanego rysunku</title> </head> <body> <?php $aCount = count( $aNewNames ). należy brać pod uwagę każdą ewentualność. $aFileClass = new File(). $thefiles_name[$nIndex].6. że można je bezpiecznie uruchomić. foreach( $aNewNames as $aNewName ) { print("<img src=###BOT_TEXT###quot;uppics/$aNewName###BOT_TEXT###quot; border=###BOT_TEXT###quot;0###BOT_TEXT###quot;><br><br>"). W przykładzie tym przesłany plik jest kopiowany do nowego katalogu. W rzeczywistości 65 PHP – Kompendium wiedzy . print( nl2br( htmlentities( $aFileCont ) ) ). "/uppics/" . "/uploads/" . // skopiowanie przesłanego pliku $aCurBasePath = dirname( $PATH_TRANSLATED ). Można je jedynie odebrać i wyświetlić w postaci czystego tekstu i nie można zakładać. $nIndex < count( $thefiles ). $aNewNames[] = $thefiles_name[$nIndex]. ale wyświetlając plik odczytywany i wysyłany do przeglądarki jest plik tymczasowy. Naruszenie bezpieczeństwa podczas obsługi przesłanych plików <?php include( "class. że pliki te zostaną właściwie obsłużone na serwerze. copy( $thefile. print( "</pre>" ). $nIndex++ ) { if ( !empty( $thefiles_name[$nIndex] ) ) { $aType = $thefiles_type[$nIndex].php3" ). $aNewName ). Jeżeli pozwalasz na przesyłanie plików musisz się upewnić. Na przykład. $aFileCont = $aFileClass->read_file( $thefile ). ?> </body> </html> Jest to oczywiście wymyślony przykład. $aNewName = $aCurBasePath . Nawet pozwolenie na wyświetlenie przesłanych plików niesie ze sobą potencjalne zagrożenie. Na wydruku 5. pokazany jest prosty przykład w jaki sposób mechanizm wyświetlania plików może spowodować dziurę w systemie bezpieczeństwa.File. ?> <html> <head> <title>Naruszenie bezpieczeństwa przy przesyłaniu pliku</title> </head> <body> <?php // wyświetlenie zawartości pliku print( "Plik <b>$aNewName</b>:<br><br>" ). 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. Wydruk 5.6. $thefile_name. } ?> </body> </html> Bezpieczeństwo Jeżeli dopuszcza się dostarczanie jakichkolwiek danych do aplikacji. print( "Przesłano <b>$aCount</b> rysunki:<br><br>" ).

że niebezpieczeństwo jest rzeczywiste. Rozdział 5 – Wysyłanie plików przez formularz 66 .phtml?thefile=/etc/passwd Można przetestować to na komputerze z Uniksem. że serwer WWW pracuje jako użytkownik nobody. więc dobrym pomysłem jest zapewnienie jeszcze jednego sposobu na dostarczanie plików do aplikacji. plik /etc/passwd musi być możliwy do odczytania przez wszystkich użytkowników. W rozdziale o formularzach kładłem nacisk na to. Podsumowanie W rozdziale tym pokazane zostały sposoby odczytywania i wykorzystania plików przesłanych przez przeglądarki zgodne z dokumentem RFC 1867. Dopuszczenie do przesyłania plików do aplikacji może być w wielu przypadkach użyteczne. Niektórzy użytkownicy będą chcieli rozmyślnie wykorzystać słabości aplikacji a inni nieświadomie spowodują jej awarię. Na przykład wprowadzenie takiego adresu URL spowoduje wyświetlenie zawartości pliku /etc/passwd (zakładając. że wszyscy użytkownicy aplikacji będą używali jej zgodnie z twoimi zamiarami. Zostały przytoczone przykłady obsługi jednego pliku jak również tablicy plików. ale należy pamiętać. 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. Nawet mimo tego.com/sciezka/upload_flaw. Dla potrzeb tej prezentacji poprzedni plik pokazuje w jaki sposób źle napisany skrypt narusza system bezpieczeństwa.prawdopodobnie odczytasz i wyświetlisz plik znajdujący się na ścieżce zapamiętanej w $aNewName. że nie wolno zakładać. Tak samo jest i teraz. Aby wykorzystać niedoskonałość skryptu ktoś może wpisać do przeglądarki nazwę skryptu i podać nazwę dowolnego pliku na serwerze. że niektórzy użytkownicy mogą nie posiadać dostatecznie szybkiego łącza aby efektywnie korzystać z tego mechanizmu. że będzie on wykonywany na systemie Uniksowym): http://serwer. Należy dokładnie przemyśleć wszystkie możliwe skutki uboczne pozwolenia na przesyłanie plików na serwer WWW.

Pseudokod opisujący pobieranie danych z dowolnego systemu bazy danych przedstawiony jest na wydruku 6. że każda z baz danych ma własny zestaw funkcji. 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. jak na przykład indeksowanie. 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). W rozdziale tym skupimy się na przykładach użycia MySQL i ODBC. obsługa transakcji. język SQL jest sam w sobie niezwykle bogatym i wydajnym narzędziem. wyślij_wyrażenie_SQL(). Wydruk 6.1. ponieważ do większości baz danych dostępne są sterowniki tego standardu. Dodatkowo. Najlepiej posiłkować się dokumentacją odmiany SQL zaimplementowanej w używanej przez ciebie bazie danych. Jest to spowodowane tym. wybierz_bazę(). 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. 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.1. że czytelnicy znają podstawy SQL w stopniu wystarczającym do zrozumienia przykładów zamieszczonych na wydrukach. istnieje wspólny model dostępu do każdego z typów baz danych. 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. .Rozdział 6. Wprowadzenie Jak można wywnioskować na podstawie dokumentacji. Zakładamy w tym rozdziale. że systemy zarządzania relacyjnymi bazami danych (SZRBD) posiadają wiele bardzo wydajnych i niezwykle użytecznych mechanizmów zarządzania danymi. które również nie zostanie odpowiednio dokładnie opisane w tej książce. kaskadowe operacje wykonywane na danych i wiele innych. Przykłady ilustrują zastosowanie języka PHP i nie zawsze pokazują najlepsze zastosowania SQL oraz działania na bazach danych. relacje pomiędzy danymi. Funkcje baz danych Każda z obsługiwanych baz danych posiada własny zestaw funkcji PHP. PHP pozwala na dostęp do danych przy użyciu bogatego zestawu funkcji związanych z bazami danych. Mimo. ODBC wybrałem. Pseudokod opisujący pobieranie danych z bazy <?php połącz_z_Bazą(). autorzy PHP uważają obsługę baz danych za jedną z najważniejszych i najsilniejszych cech PHP.

więc możesz od razu zaczynać pracę. if ( !empty( $aDBLink ) ) { // wybór bazy danych MySQL if ( mysql_select_db( "mydb". na przykład mod_auth_mysql i mod_perl. PHP4 posiada wbudowaną obsługę MySQL. $aDBLink ) == True ) { $aSQL = "select * from employees". Przy użyciu tej metody instalowane są wszystkie elementy serwera.mysql.pobierz_wynik().2 pokazuje jak proste jest użycie MySQL do pobrania danych z bazy. // Wykonanie zapytania SELECT $aQResult = mysql_query( $aSQL. PRIMARY KEY (id). "user". Jednak jeżeli korzystasz z wbudowanej obsługi MySQL. while ( istnieje_wiersz ) pobierz_wiersz(). Rozpoczynamy pracę z MySQL W zależności od twoich potrzeb i typu serwera. "pass" ). Jeżeli potrzebujesz modułów używających MySQL. Pobieranie danych z bazy danych MySQL <html> <head> <title>Pobieranie danych z MySQL</title> </head> <body> <?php // Ukrywamy komunikaty błędów i sami je obsługujemy $aDBLink = @mysql_connect( "db. zamknij_połączenie(). możesz albo ściągnąć źródła MySQL. last varchar(20). dystrybucję binarną albo RPM. if ( $aQResult == True ) { // Pobranie wiersza danych i wypisanie dwóch pól while ( $aRow = mysql_fetch_array( $aQResult ) ) { $aFName = $aRow["first"]. więc nie musisz ponownie kompilować PHP aby używać funkcji mysql_. musisz przekompilować PHP podając opcję konfiguracji --with_mysql=/ścieżka/do/mysql.server. $aDBLink ). print( "$aFName. Oficjalną witryną MySQL jest http://www.com. $aPos<br>" ). Użycie MySQL Po zainstalowaniu i uruchomieniu MySQL można rozpocząć pisanie skryptów PHP.com". nie można używać innych modułów odwołujących się do MySQL. 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. ?> 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. $aPos = $aRow["position"]. Na tej witrynie znajduje się najnowsza wersja systemu oraz dokumentacja opisująca instalację i konfigurację MySQL w różnych środowiskach. które korzystają z danych umieszczonych w bazie danych. position varchar(50). first varchar(20). Jeżeli używasz systemu działającego w oparciu o Win32. Rozdział 6 – Współpraca z bazami danych 68 . najszybszą metodą pozyskania serwera jest ściągnięcie skompresowanej instalacji binarnej. adress varchar(255). Najszybszą metodą zainstalowania MySQL na systemie Linux działającym na platformie Intel jest ściągnięcie pliku RPM i zainstalowanie go.2. UNIQUE id (id) ) Wydruk 6. Skrypt zamieszczony na wydruku 6.

w naszym przypadku mydb. mysql_fetch_array(). mysql_fetch_lengths(). Używając skryptu z wydruku 6. a dostarcza o wiele więcej danych. Skrypt korzysta z funkcji mysql_insert_id() w celu zrealizowania potwierdzenia operacji wstawienia danych.com podając nazwę użytkownika i hasło. } } else { print( "Błąd wyboru bazy danych<br>" ). $aSQL .3 mamy formularz. Jeżeli nie ma więcej danych. na przykład: INSERT. // Przyłączenie do serwera i wykonanie instrukcji INSERT 69 PHP – Kompendium wiedzy . przy pomocy funkcji mysql_query() zadawane jest zapytanie do bazy danych. Może być to dowolne zapytanie. ADD TABLE lub dowolne inne zapytanie SQL. */ function InsertRecord( $aFirstName. Wydruk 6. mysql_fetch_object(). Dostarczone są specjalizowane funkcje do tworzenia i usuwania baz danych oraz funkcje umożliwiające odczytanie struktury bazy danych. W naszym przykładzie jest to zapytanie SELECT. 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. '$aLastName'. } else { print( "Błąd wykonania zapytania<br>" ). last. Na przykład za pomocą funkcji mysql_list_tables() można uzyskać listę wszystkich tabel w bazie danych. można napisać wszystkie możliwe aplikacje oparte na bazie danych.serer. jeżeli zapytanie jest typu SELECT. Wywołanie funkcji mysql_fetch_array() nie jest zauważalnie wolniejsze niż wywołanie mysql_fetch_row(). } ?> </body> </html> Po uruchomieniu skryptu z wydruku 6. ". ". Dodatkowo. który pozwala na wprowadzenie danych nowego pracownika do bazy używanej na wydruku 6. Wywołanie jednej z tych funkcji zwraca kolejny wiersz danych zwracanych przez zapytanie i przesuwa wewnętrzny wskaźnik do następnego wiersza.2. '$aPos' )". Funkcje MySQL posiadają dodatkowo kilka cech. Na wydruku 6. które są używane do odczytania wynikowych danych. Podczas testowania możesz opuścić ten symbol. Wynik funkcji jest różny od zero w przypadku powodzenia i zero w przypadku błędu. Jeżeli się to powiodło. Wstawianie rekordu do bazy danych MySQL <?php /* Funkcja InsertRecord Wstawia mowy rekord do tabeli employees. $aLastName. UPDATE. Jedną z moich ulubionych funkcji dla MySQL jest mysql_insert_id(). $aAddr. Funkcja mysql_fetch_array() zwraca wynik w postaci tablicy asocjacyjnej indeksowanej nazwami kolumn.} mysql_free_result( $aQResult ). Wywołanie funkcji mysql_fetch_row() zwraca tablicę indeksowaną liczbami. próbuje się on podłączyć do serwera bazy danych MySQL działającego na komputerze db.2 jako podstawy. $aPos ) { // Przygotowanie wyrażenia SQL INSERT $aSQL = "insert into employees ( first. W przypadku powodzenia operacji zwraca identyfikator nowego rekordu a w przypadku błędu wartość ujemną wskazującą na przyczynę błędu. Funkcje mysql_fetch_array() i mysql_fetch_row() są podobne do siebie i zwracają jeden wiersz wyniku w postaci tablicy.= "'$aAddr'. które powoduje pobranie rekordów z bazy danych. } } else { print( "Błąd przy podłączaniu do bazy danych<br>" ). ale w normalnej pracy należy go używać i stosować własne procedury obsługi błędów.3. które nie są dostępne dla wszystkich baz obsługiwanych przez PHP. Symbol @ umieszczony przed funkcją mysql_connect() powoduje zablokowanie wypisywania błędów i ostrzeżeń. wynik funkcji jest identyfikatorem wyniku przekazywanym do funkcji mysql_result().2. address. 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().= "position ) values ( '$aFirstName'. $aSQL . funkcja zwraca False. i mysql_fetch_row(). Następną czynnością wykonywaną przez skrypt jest wybranie odpowiedniej bazy danych.

$aResult = -2. $LastName. } else { // print( "Błąd wykonania zapytania<br>" ). Więcej przykładów użycia baz danych w aplikacjach WWW można znaleźć w rozdziale 15 „Witryny oparte o bazę danych”. if ( $aQResult == True ) { $aResult = mysql_insert_id( $aDBLink ). $aResult = -3. 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. $aDBLink ) == True ) { $aQResult = mysql_query( $aSQL. Znajdują się tam bardziej złożone przykłady zawierające obsługę błędów i skomplikowane zapytania. } return $aResult. Ponieważ pole id w tabeli employees jest polem typu auto_increment. $Address. ale dla naszych potrzeb kod ten nie został rozmyślnie wprowadzony. MySQL automatycznie generuje jednoznaczne wartości tego pola przy każdym wstawieniu rekordu. funkcja IndertRecord() zawiera całą logikę wstawienia nowego rekordu do bazy danych. $aResult = -1. } } else { // print( "Błąd wyboru bazy danych<br>" ). } else { print( "Błąd funkcji InsertRecord.$aDBLink = @mysql_connect( "db. Kod błędu = $aResult<br>" ). } } else { // print( "Błąd przy podłączaniu do bazy danych<br>" ). W naszym przykładzie wartość ta jest odczytywana za pomocą funkcji mysql_insert_id(). } print( "<hr>" ). $Position ). } ?> Proszę wpisać dane nowego pracownika:<br> <form action="<?php echo $PHP_SELF ?>" method="post"> Imię: <input type="text" name="FirstName" maxlength="20"><br> Nazwisko: <input type="text" name="LastName" maxlength="20"><br> Adres: <input type="text" name="Address" maxlength="255"><br> Stanowisko: <input type="text" name="Position" maxlength="50"><br><br> <input type="submit" name="Submit" value="Wyślij"> </form> </body> </html> W skrypcie z wydruku 6.server. $aDBLink ).3.com". } ?> <html> <head> <title>Przykład MySQL: Wstawianie danych do bazy </title> </head> <body> <?php if ( $REQUEST_METHOD == 'POST' ) { // Nastąpiło przesłanie danych formularza $aResult = InsertRecord( $FirstName. ID = $aResult<br>" ). na przykład sprawdzanie pustych pól. "root". Rozdział 6 – Współpraca z bazami danych 70 . Przykład ten miał na celu pokazanie prostoty korzystania z baz danych w PHP. "" ). if ( !empty( $aDBLink ) ) { if ( mysql_select_db( "mydb". if ( $aResult > 0 ) { print( "Dodano nowy wiersz. Ten typ aplikacji powinien zawierać o wiele więcej kodu odpowiedzialnego za obsługę błędów. Realistycznie patrząc.

sterownik OOB sterownik OOB OOB Client . --with-iodbc oraz --with-openlink.com/. Jeżeli jeszcze nie wybrałeś swojego systemu bazy danych. instalacja i konfiguracja ODBC jest nieco bardziej skomplikowana niż konfiguracja MySQL. W przypadku tworzenia aplikacji o wysokiej jakości koszt bazy nie jest jedynym czynnikiem jaki należy brać pod uwagę.1. Aplikacja wywołując funkcję. solidna i zawiera większość funkcji dostępnych w komercyjnych bazach danych.org/). ale musi być w tym celu odpowiednio skonfigurowany.sterownik do bazy danych aplikacji PHP DBMS . a następnie sterownik do twojego systemu bazy danych. W rozdziale tym przykłady korzystają z implementacji ODBC unixODBC (http://www. Jest on dostępny na zasadach licencji GPL lub LGPL i jest bardzo łatwy do instalacji i konfigurowania. że wszystkie odwołania do bazy danych wykonuje za pośrednictwem sterownika bazy danych. PHP Application . W PHP istnieją cztery opcje konfiguracji związane z ODBC: --with-unixODBC.2. Na rysunku 6.1. że najpierw musisz zainstalować program zarządzający sterownikami. że jest wart zainteresowania.2. 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. kontaktuje się z zarządcą sterowników. na przykład unixODBC. --with-custom-ODBC. na przykład podzapytania. ODBC tym różni się od MySQL i innych API baz danych tym.zarządca sterowników Dodajemy The OOB driver . spisz swoje wymagania i porównaj ze specyfikacją dostępnych systemów.unixodbc.serwer OOB Driver Manager .aplikacja PHP Rysunek 6. który można uzyskać z Easysoft Limited. ale posiada tak dużo zalet. Driver Manager .easysoft. Oznacza to. Również każdy z używanych sterowników baz danych musi zostać zainstalowany i skonfigurowany. Istnieje kilka implementacji ODBC API dla systemów Uniksowych. Sterownik ten pozwala na dostęp do baz danych zainstalowanych na różnych platformach za pomocą własnego modelu klient-serwer. Jest ona szybka.aplikacja PHP Rysunek 6. ODBC Open Database Connectivity (ODBC) to powszechnie stosowany interfejs API (application programming interface) służący do łączenia się z bazami danych.MySQL jest wydajną bazą danych posiadającą funkcje wystarczające do tworzenia większości typów aplikacji WWW.zarządca sterowników Komponenty Database Driver . następna część zawiera informacje na temat ODBC.sieć OOB Server . Podstawy ODBC PHP może obsługiwać praktycznie każdą implementację ODBC. pokazane są powiązania pomiędzy komponentami aplikacji PHP opartej o ODBC. PHP Application . która realizuje nasze żądanie. Jeżeli twoja firma posiada system bazy danych inny niż MySQL. Sterownik OOB powoduje wzrost komplikacji struktury.klient OOB Network . W systemie Windows ODBC jest zwykle instalowany razem z systemem. na przykład odbc_connect(). Driver Manager . które pomogą podłączyć się do twoich istniejących danych. ponieważ ODBC nie jest w chwili obecnej domyślną opcją.sterownik do bazy danych 71 PHP – Kompendium wiedzy .zarządca sterowników Database Driver . Opcje te są lepiej opisane w skorowidzu na końcu książki. http://www.SZRBD korzystającej z PHP Ponieważ ODBC wymaga zastosowania zarządcy sterowników oraz sterownika odpowiedniej bazy danych. zilustrowano sposób użycia sterownika OOB. Sterownik bazy danych wywołuje odpowiednią funkcję bazy danych. Zarządca ten jest odpowiedzialny za załadowanie odpowiedniego sterownika bazy danych i przekazanie do niego żądania. NA rysunku 6. W książce tej zostanie opisana instalacja i konfiguracja zarządcy sterowników unixODBC oraz sterownika ODBC-ODBC Bridge (OOB). Niedostępne są również niektóre elementy SQL. Jednak w czasie pisania tej książki MySQL nie zawierał mechanizmu transakcji.

kompilację PHP z obsługą unixODBC oraz instalowanie sterownika OOB. Instalowanie sterownika OOB W moim przypadku musiałem zainstalować serwer OOB na komputerze z Windows NT i skonfigurować go tak. Proces ten był niespodziewanie łatwy. aby przyjmował żądania. OOB wymaga utworzenia systemowego DSN a nie DSN użytkownika.DBMS . ponieważ nie mam na moim serwerze zainstalowanego środowiska XWindows. Rozdział 6 – Współpraca z bazami danych 72 .SZRBD Zaletą stosowania sterownika OOB jest to. Na szczęście na witrynie Easysoft bardzo łatwo jest odszukać i załadować odpowiednie programy. zainstalować nowy moduł PHP i powtórnie uruchomić Apache. Wykonałem to uruchamiając program instalacyjny i wykonując wszystkie kroki w programie instalacyjnym. musisz skompilować zarządcę sterowników./configure --disable--drivers --disable-threads --prefix=/usr/local/unixODBC --disable-gui Ponieważ miałem już potrzebny sterownik. Wyłączyłem również obsługę graficznego interfejsu użytkownika. że potrafisz kompilować programy dla tego systemu oraz. Program ten zawiera plik pomocy opisujący sposób tworzenia systemowych DSN. musisz również przekompilować Apache. Instalowanie i kompilowanie unixODBC Po ściągnięciu i rozpakowaniu plików unixODBC. Powodem wyłączenia wątków jest to. Jeżeli statycznie łączysz PHP z Apache. Jeżeli korzystasz z dynamicznego łączenia. Użyta ścieżka musi być taka sama jak ścieżka użyta w opcji --prefix podczas kompilowania unixODBC. Dodatkowym utrudnieniem jest to. gdzie na podstawie konkretnej konfiguracji otrzymamy szczegółowy opis tego jak ściągnąć i zainstalować serwer i klienta OOB. Źródła danych są mechanizmem specyficznym dla ODBC służącym do opisywania sposobu współpracy z systemem bazy danych. ż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). Wszystko zadziałało bez problemów. Konfigurowanie OOB Po zainstalowaniu całego oprogramowania należy utworzyć nazwy źródeł danych (DSN) zarówno na kliencie jak i na serwerze. Części te są przeznaczone dla użytkowników Linuksa i zakładamy. że używając OOB należy kolejno zainstalować klienta i serwer OOB na oddzielnych komputerach. Kolejne trzy części omawiają instalowanie zarządcy sterowników unixODBC. Odpowiednią opcją konfiguracji jest --with-unixODBC=/sciezka/do/unixODBC. że moja instalacja PHP jest w postaci dynamicznie ładowanego modułu (--with-apxs) a Apache nie obsługuje domyślnie wątków. że masz zainstalowane wszystkie niezbędne kompilatory i narzędzia. działającej na dowolnej platformie. W instalacji unixODBC znajduje się standardowy skrypt służący do konfigurowania środowiska kompilacji. W moim przypadku jest to /usr/local/unixODBC. Następnie w moim linuksowym serwerze WWW dodałem sterownik OOB. wystarczy wyłączyć Apache. nie potrzebowałem aby unixODBC dodał swoje sterowniki wewnętrzne. ponieważ dostępny był program instalacyjny prowadzący użytkownika przez kolejne kroki procedury instalacyjnej. Można również skorzystać z witryny Easysoft. Następnie ściągnąłem i zainstalowałem oprogramowanie klienta na serwerze z systemem Linux. 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. Skompilowanie tego modułu z obsługa wątków spowodowałoby awarię Apache w trakcie ładowania modułu. Sterownika tego można używać do podłączania się do dowolnej bazy zgodnej z ODBC. Dla przykładu w moim testowym systemie zainstalowałem Oracle 8i na serwerze Windows NT i utworzyłem prostą bazę danych. W celu skompilowania mojej konfiguracji PHP użyłem następujących opcji: . W Windows tworzy się DSN poprzez program Źródła danych ODBC dostępny w Panelu sterowania.

so Setup = /usr/local/easysoft/oob/client/libesoobsetup. Nie jest to potrzebne. który jest odpowiednikiem ODBC skryptu umieszczonego na wydruku 6. $aRowNum. Mimo.ini").2. $aRowNum = 1. } ?> </body> </html> Wydruk 6. Odczytywanie danych z bazy ODBC <html> <head> <title>Pobioeranie danych z bazy danych ODBC</title> </head> <body> <?php putenv("ODBCINI=/usr/local/unixODBC/etc/odbc. $aPos = $aRow[4].4 znajduje się skrypt. Jedyną zauważalną różnicą jest wywołanie putenv() na początku skryptu. Wydruk 6. // Ukrywamy komunikaty błędów i sami je obsługujemy $aDBLink = @odbc_connect( "localdsn". Mój plik wygląda następująco: [OOB] Driver = /usr/local/easysoft/oob/client/libesoobclient. $aPos<br>" ). print( "$aFName.4 jest właściwie taki sam jak wydruk 6. if ( !empty( $aDBLink ) ) { $aSQL = "select * from employees". koncepcja jest nieomal identyczna. $aQResult = @odbc_exec( $aDBLink.ini. while ( odbc_fetch_into( $aQResult.so FileUsage = 1 Plik odbc. &$aRow ) ) { $aFName = $aRow[1].2.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. Dodatkowo. Tabela używana w tym przykładzie jest odpowiednikiem używanej w poprzednim przykładzie. Na wydruku 6. "prodplanner". Swoje źródło skonfigurowałem następująco (serwer i hasło jest oczywiście zmyślone): [localdsn] Server=satabase. Plik odbcinst. "agdec" ).ini jest używany do opisu nazw sterowników i łączy nazwy z plikami sterowników. Wywołanie to umieszcza w środowisku programu ścieżkę do pliku inicjalizującego ODBC.4.Aby utworzyć DSN na Linuksie należy zmienić przy pomocy graficznego narzędzia unixODBC lub edytora tekstowego pliki odbcinst.server. $aRowNum++.ini i odbc. } odbc_free_result( $aQResult ).4 do pól tabeli odwołujemy się dla 73 PHP – Kompendium wiedzy . jeżeli w ten sam sposób ustawiłeś środowisko serwera WWW. $aSQL ). że nazwy funkcji są inne. } else { print( "Błąd wykonania zapytania<br>" ).ini zawiera opis źródeł danych. if ( $aQResult == True ) { $aRow = array(). } } else { print( "Błąd podłączenia do bazy danych<br>" ). na wydruku 6.

} // Tworzenie egzemplarza nowej klasy MySQLDBTest $aDB = new MySQLDBTest.uproszczenia za pomocą numer a nie nazwy. gdy zachodzi potrzeba wymiany bazy danych. W skorowidzu funkcji na końcu książki znajdują wszystkie funkcje do obsługi ODBC. PHP ciągle dostarcza tego samego połączenia do kolejnych wywołań połączenia. Największa zaleta korzystania z klas PHPLIB ujawnia się. Jedna z najczęściej używanych bibliotek. PHP posiada również zdolność tworzenia trwałych połączeń za pomocą funkcji pxxx_connect(). Użycie połączenia trwałego poprawia wydajność aplikacji. Microsoft SQL Sever i bazy ODBC.5.5.netuse. Następnie tworzony jest obiekt tej klasy. W bazach danych utworzenie połączenia trwa zwykle długo (na przykład w Oracle).5. Sybase. więc programiści mogą łatwo zmieniać typ bazy danych bez konieczności nauki nowego zestawu funkcji lub wielu zmian w kodzie. Pozwala to osiągnąć w wyniku kod. PostgreSQL. Dostępne są funkcje ODBC zapewniające obsługę transakcji. var $Database = "mydb". obsługi sesji. W skrypcie umieszczonym na wydruku 6. Oracle 8. więc użycie trwałych połączeń może mieć ogromny wpływ na ogólną wydajność aplikacji. while( $aDB->next_record() ) { $aFName = $aDB->f( "first" ). var $Password = "".ini").6. Zamiast tego powinna być tworzona klasa dziedzicząca po niej. narzędzi autoryzacji i wiele. w której ustawiane są zmienne specyficzne dla twojego środowiska pracy. Skrypt z wydruku 6.2 <?php include ( "db_mysql. $aPos = $aDB->f( "position" ). } ?> 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. w której zawarte są dane opisujące połączenie z MySQL. $aDB->query( "select * from employees" ).129. jest to idealny kandydat do takiej właśnie implementacji. Wydruk 6. // Dziedziczymy po klasie DB_Sql aby użyć jej z // bazą danych Oracle poprzez ODBC Rozdział 6 – Współpraca z bazami danych 74 . Klasy dostępu do bazy danych w PHPLIB tworzą warstwę abstrakcji dla kilku baz danych obsługiwanych przez PHP.163". aby zamiast z MySQL korzystał z Oracle poprzez sterownik ODBC. Warstwa ta zapewnia wspólny interfejs dla bazowych funkcji baz danych. var $User = "root". więc może być ono wielokrotnie używane. Poniższy wydruk pokazuje jak łatwo można zamienić skrypt z wydruku 6. 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().de. // Dziedziczymy po klasie DB_Sql aby użyć jej z // naszą bazą MySQL class MySQLDBTest extends DB_Sql { var $Host = "208. Na wydruku 6.inc" ).inc" ). W czasie pisania książki PHPLIB obsługiwał MySQL. który jest łatwiejszy do czytania. na którym wykonywane są operacje. kursorów i wiele innych. dostępne są świetne biblioteki do wykorzystania przez programistów PHP. include( "db_odbc. Po utworzeniu połączenia za pomocą odpowiedniej kombinacji host-użytkownik-hasło. Jeżeli PHP będzie obsługiwał klasy abstrakcyjne.36. wiele innych. print( "$aFName. Poniższy wydruk ilustruje siłę modułu obsługującego bazy danych z pakietu PHPLIB. Wydruk 6. pokazany został sposób uproszczenia skryptu z wydruku 6.2. ponieważ sam PHP utrzymuje połączenie z bazą danych. Zawiera ona klasy dostęu do baz danych. $aPos<br>" ). Oracle 7. PHPLIB Jak wspomniałem w poprzednich rozdziałach.5 definiowana jest klasa pochodna MySQLDBTest. utrzymania i uruchamiania.5 korzystający z Oracle i ODBC <?php putenv("ODBCINI=/usr/local/openlink/odbc. PHP Base Library (PHPLIB) jest dostępna pod adresem http://phplib. mSQL. Klasa DB_Sql nie jest przeznaczona do bezpośredniego używania. Użycie PHPLIB do powtórzenia wyników z wydruku 6.

7 pokazane zostało tworzenie listy wyboru zawierającej kraje oraz stany USA. Każda z tabel zawiera identyfikator oraz nazwę. Z powodu prostoty projektu i implementacji PHPLIB może być on użyteczny dla programistów pracujących w złożonych. przyciski opcji i inne tego typ elementy pozwalają na dużą elastyczność i ograniczają możliwość błędu przy wprowadzaniu danych. Mechanizmy kontroli poprawności danych były opisane w rozdziale 3. Na przykład. class MySQLDBTest extends DB_Sql 75 PHP – Kompendium wiedzy . Tak jak opisano w rozdziale 3. $aDB->query( "select * from employees" ). $aPos = $aDB->f( "position" ). var $Password = "agdec". Dodatkowo. Identyfikator jest przekazywany jako wartość formularza. Oczywiście można wybrać stan w USA a następnie Afrykę południową.inc" ). Pola wyboru. Skrypt z wydruku 6. cudzysłowy. PHP dostarcza wielu funkcji potrzebnych przy używaniu formularzy i baz danych. ale znaczenie tej zmiany jest olbrzymie. dane wpisane do formularza HTML muszą być sprawdzone przed ich zapisaniem do bazy danych. var $User = "prodplanner". W skrypcie tym używane są tabele us_states oraz world_countries. które będą wyświetlane muszą zostać przed wyświetleniem przetworzone za pomocą funkcji stripslashes(). wszystkie wartości. Jak wspomniano w rozdziale 3. POST i COOKIE apostrofy. których na pewno nie chciałbyś pokazywać użytkownikom. niektóre komunikaty błędów generowane przez bazę danych mogą zawierać takie informacje na temat używanej bazy danych. W przy domyślnych ustawieniach PHP automatycznie oznacza we wszystkich zmiennych GET. Umieszczenie takiego zestawu opcji w bazie danych skutkuje w dłuższym okresie stworzeniem aplikacji łatwiejszej do zarządzania.class OracleDBTest extends DB_Sql { var $Database = "localdsn". } // Tworzenie egzemplarza nowej klasy OracleDBTest $aDB = new OracleDBTest. Należy być przygotowanym na sytuacje. Skrypt z wydruku 6. } ?> Jedyną widoczną zmianą pomiędzy wydrukami 5 i 6 jest funkcja include().5 korzystał z danych z bazy MySQL działającej na tym samym komputerze co serwer WWW. Na przykład na wydruku 6. 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. Przykład ten pokazuje jedynie koncepcję. że wartość przekazana z formularza jest od razu gotowa do użycia w zapytaniu SQL. print( "$aFName.netuse.de/. jak również w prostych instalacjach składających się z jednego serwera. że niektórzy użytkownicy mogą próbować wyszukać słabe punkty w aplikacji. co powoduje bardzo łatwe ponowne użycie istniejącego kodu. Wynikiem braku kontroli danych może być niezadowolenie użytkowników z aplikacji a nawet załamanie systemu bezpieczeństwa serwera. Użycie tabel słownikowych do generacji listy opcji <?php include ( ".7. $aPos<br>" ). Wydruk 6. ponieważ formularze są najczęściej używanym mechanizmem używanym do wprowadzania danych w aplikacjach WWW. Tak jak we wszystkich aplikacjach. tam gdzie jest to możliwe należy zastępować procedury kontroli danych przez takie mechanizmy. Więcej informacji na temat klas zawartych w PHPLIB można odnaleźć na witrynie http://phplib. które ze swojej natury ograniczają pomyłki. ukośniki i znaki NUL. „Formularze i cookie”. musisz użyć funkcji addslashes() zanim skorzystasz w zapytaniu SQL z ciągu przekazanego z formularza.6 pobiera dane z bazy Oracle zainstalowanej na serwerze z Windows NT. Powoduje to. Jeżeli zablokowałeś tą opcję. Tworząc alternatywne mechanizmy wprowadzania danych należy pamiętać o możliwości korzystania z bazy danych przy tworzeniu początkowego zestawu danych. heterogenicznych środowiskach./db_mysql. while( $aDB->next_record() ) { $aFName = $aDB->f( "first" ). Przechowywanie danych z formularzy Omówienie formularzy HTML jest potrzebne w rozdziale dotyczących baz danych. Biblioteka ta zapewnia jednakowy interfejs dostępu do różnych baz danych.

pokazany jest formularz. $aSQL = "select ID. Jeżeli masz listę akceptowanych przez ciebie kart kredytowych.phtml" method="post"> <table> <tr> <td> Wybierz stan USA: </td> <td> <select name="us_state" size="1"> <?php print( GetGenOpts( "us_states". $aCurSel = "" ) { $aResult = "". "root". } ?> <html> <head> <title>Formularz wyboru stanu USA oraz kraju</title> </head> <body> <form action="some_place. Funkcja GetGenOpts() może być użyta do tworzenia listy opcji z każdej tablicy posiadającej kolumny ID oraz Name. jeżeli formularz jest użyty do edycji danych a nie do wprowadzania nowych danych.129. Użycie tabel słownikowych pozwala również na natychmiastowe zmiany w aplikacji o ile zajdzie taka potrzeba. "ID" ) ). Zamiast tego można po prostu zmienić wartości w tabeli bazy danych. "ZA" ) ). } else { $aResult . ?> </select> </td> </tr> </form> </body> </html> Na rysunku 6. należy ją przechowywać w bazie danych zamiast statycznie definiować na stronie HTML.{ var var var var $Host $Database $User $Password = = = = "208.3. Opcjonalny parametr $aCurSel może zostać użyty do określenia wybranej pozycji na formularzu. } } return $aResult.= "<option value=###BOT_TEXT###quot;$aID###BOT_TEXT###quot; selected>$aName</option>".163". } function GetGenOpts( $aTableName. Aplikacja zostanie natychmiast zmieniona się bez modyfikacji jednej linii kodu. ponieważ w razie zmiany tej listy. "". nie trzeba przeglądać wszystkich stron szukając odwołań. "mydb". $aDB = new MySQLDBTest. if ( $aID == $aCurSel ) { $aResult . $aID = $aDB->f( "ID" ). Rozdział 6 – Współpraca z bazami danych 76 . $aDB->query( $aSQL ). ?> </select> </td> </tr> <tr> <td> Wybierz kraj: </td> <td> <select name="world_country" size="1"> <?php print( GetGenOpts( "world_countries". Name from $aTableName order by Name".= "<option value=###BOT_TEXT###quot;$aID###BOT_TEXT###quot;>$aName</option>". while( $aDB->next_record() ) { $aName = $aDB->f( "Name" ).36.

Oczywiście. Spróbuj wprowadzić do pól tekstowych apostrofy oraz znaki backslash. powinieneś określić poziom wymaganego bezpieczeństwa i kontroli poprawności. które mogą spowodować naruszenie bezpieczeństwa. która pobiera identyfikator a następnie wykonuje wyrażenie SQL: select * from table where ID = wprowadzona_wartosc Spodziewasz się. Wynikowe wyrażenie SQL będzie następujące: select * from table where ID = 1. że wprowadzona_wartosc będzie jedną wartością. Zanim zacząłem pisać aplikacje dla WWW. Na przykład. Wykorzystanie możliwości bazy danych Część ta nie jest związana bezpośrednio z wykorzystaniem baz danych z PHP — jest to dodatek poświęcony pisaniu aplikacji wykorzystujących bazy danych. którzy nie pisali zbyt wielu aplikacji w środowisku wielowarstwowym. nie możesz zapomnieć o bezpieczeństwie bazy danych. Należy również przetestować aplikację za pomocą danych. zanim trafią one do serwera bazy danych. Wszyscy. Dynamicznie generowany formularz do wprowadzania danych Kolejny raz musimy powtórzyć. Można również wpisać średnik i po nim wyrażenie SQL. lub uszkodzenie bazy danych. drop database Mimo. że jest nieprawdopodobne. że przypadek ten jest dość nieprawdopodobny. Może on znajdować się również w rozdziale poświęconym inżynierii programowania. powinni dokładnie przeczytać ten fragment i stosować go podczas pisania własnych aplikacji WWW korzystających z bazy danych. Środowisko takie jest bardzo wygodne. ponieważ nie trzeba robić żadnych założeń dotyczących współbieżności a system bazy danych jest zwykle czymś więcej niż pośrednikiem służącym do odczytu i zapisu danych.Rysunek 6. drop database”. 77 PHP – Kompendium wiedzy . aby możliwy był dostęp do niej jedynie za pomocą aplikacji. ktoś może wpisać do formularza napis „1. Zawsze należy zabezpieczyć bazę danych w taki sposób. to jednak możesz odszukać podobne przykłady. Udostępniając aplikację. We wszystkich przypadkach bazy danych używał jeden użytkownik i działała na tym samym komputerze. w aplikacji nie powinny znajdować się pola umożliwiające wykonanie dowolnego zapytania SQL.3. więc można ją wkleić do wyrażenia SQL. W oparciu o typ tworzonej aplikacji. aby przykład ten spowodował jakiekolwiek szkody. zawsze musisz zweryfikować poprawność danych. spójrzmy na przykład aplikacji. Jeżeli umieścisz na formularzu pole tekstowe. Mimo. tworzyłem w większości aplikacje Windows wykorzystywane przez jednego użytkownika. że najlepszym zabezpieczeniem przed nieprawidłowymi danymi jest dobrze skonstruowany mechanizm wprowadzania danych. które mogą spowodować błąd.

TO_DAYS(birthdate))/365))))))) AS age_dif FROM persons ORDER BY age_diff DESC Każdy z wierszy wyniku zawiera imię i nazwisko osoby oraz liczbę oznaczającą żądaną wartość. uprawnieniami użytkownika. ' '. transakcjami i to odbierając wiele równoczesnych żądań w tym samym czasie. Cały fragment można zredukować do jednego wyrażenia SQL wykonywanego w całości przez bazę danych: INSERT INTO tabela SELECT sequence. Potrzebna jest zwykle nowoczesna baza danych. inne_pola FROM tabela Wyrażenie to opiera się na generatorze sekwencji do wygenerowania nowego klucza głównego. Wszystko czego potrzebujemy. Zamieszczona została również krótka dyskusja na temat inżynierii programowania i wykorzystaniu możliwości baz danych. W jednym z ostatnich projektów musiałem posortować wiersze opisujące personel w oparciu o różnicę wieku licząc od określonej daty. surneme) as fullname. Na przykład. Podsumowanie Rozdział ten zawiera opis użycia baz danych razem z PHP. ROUND(MAX(0. filtrujący bądź sortujący dane pobierane z bazy danych. Oprócz wykonywania tych krytycznych funkcji. „Zarządzanie projektem przy tworzeniu aplikacji WWW” zawiera więcej informacji na temat inżynierii programowania dla aplikacji WWW. która potrafi zarządzać współbieżnością. (10-ABS((30-ROUND(((TO_DAYS(NOW()) . musiałem określić pozycję rekordu osoby w oparciu o to. to w pętli odczytać wyniki i wyświetlić je na ekranie. ale otrzymujemy wszystkie potrzebne dane bez potrzeby pisania dodatkowego kodu manipulującego wynikami: SELECT concat (firstname. Jednym z najważniejszych problemów przypisaniu aplikacji dla WWW jest użycie właściwych narzędzi i właściwych ludzi do realizacji poszczególnych fragmentów projektu. który pisał ten fragment. które pomagają w pisaniu aplikacji. ale fragment ten prezentuje styl kodowania brute-force częsty u młodych lub niedoświadczonych programistów. Pierwsze wywołanie pobiera wszystkie wiersze i następnie dla każdego z nich jest potrzebne jedno wywołanie do wygenerowania nowego klucza głównego i jedno dla wykonania instrukcji INSERT. większość nowoczesnych baz danych posiada ogromną ilość funkcji. obliczana w oparciu o to jak blisko wiek osoby jest zbliżony do założonych wymagań wiekowych.W przypadku tworzenia aplikacji dla środowiska wielowarstwowego. czy na osobnych maszynach. ale pokazuje w jaki sposób wykorzystując odpowiednio SQL można uniknąć pisania sporej ilości kodu oraz poprawić wydajność aplikacji. baza danych pełni o wiele ważniejszą rolę. W mojej ostatniej stałej pracy trafiłem na świetny przykład. przyjrzyj się dokładniej swojemu zapytaniu SQL. Ponieważ PHP obsługuje wiele typów baz danych. Możesz skorzystać z wbudowanych funkcji bazy danych lub zastosować bardziej skomplikowany kod SQL do osiągnięcia oczekiwanych wyników. który to mechanizm musi posiadać baza danych. Na początku wyniku znajdą się osoby o wieku najbliższym 30 lat. którego wiek był oddalony od założonego o więcej niż 10 lat otrzymywał tą samą ocenę. Poniższe wyrażenie może wyglądać na dosyć skomplikowane. Znaleziony przeze mnie kod wyglądał mniej więcej tak: wybierz wszystkie wiersze do kopiowania dla każdego wiersza inicjuj nowy ciąg zawierający wyrażenie INSERT wybierz nowy klucz główny w bazie danych jeżeli te dane powinny być skopiowane bez zmian skopiuj istniejące dane do wyrażenia INSERT w przeciwnym wypadku dodaj nowe wartości do wyrażenia INSERT wykonaj wyrażenie INSERT z wyrażenia koniec dla każdego wiersza Nie mam zamiaru śmiać się z programisty. będącą liczbą od 0 do 10. czy serwer bazy danych i serwer WWW umieszczony jest na tym samym komputerze. Niezależnie od tego. Zadaniem było powielenie kilku wierszy danych z tabeli zmieniając w nowych wierszach zawartość kilku pól. powinieneś wszędzie tam gdzie jest to możliwe wykorzystywać siłę systemu zarządzania bazą danych. Fragment ten wymaga 1+ (2*ilość wierszy) odwołań do bazy danych. Dodatkowo każdej osobie przypisywana była wartość. skupiliśmy się na bazie MySQL oraz dostępowi poprzez ODBC. Każdy. Dalsze informacje na temat Rozdział 6 – Współpraca z bazami danych 78 . jak bardzo jej wiek jest zbliżony do 30 lat. Następna duża część książki.nextval AS PRIMARY KEY. Jeżeli zdarzy ci się pisać kod formatujący.

użycia baz danych znajdują się w rozdziałach 15. Najobszerniejsze przykłady znajdują się w rozdziale 15 „Witryny oparte o bazę danych”. 79 PHP – Kompendium wiedzy . 16 i 17.

niezbędne dane są serializowane oraz zapisywane i sesja pracy programu się kończy. . Serwer korzysta z danych przekazanych mu przez klientów podczas kolejnych odwołań do stron do śledzenia i utrzymywania danych sesji. że zarówno przeglądarka jak i serwer WWW nie były projektowane do uruchamiania aplikacji WWW. obsługa sesji w sieci WWW wymaga współpracy pomiędzy przeglądarką klienta i serwerem WWW. ponieważ cały model działania programu jest dosyć prosty: użytkownik uruchamia program. W standardowych aplikacjach stan jest automatycznie utrzymywany w zmiennych przechowywanych w pamięci komputera. Na rysunku 7. Zwykle identyfikator ten jest przechowywany w cookie na komputerze klienta.Rozdział 7. Jest to powodowane faktem. pokazany został schemat komunikacji pomiędzy klientem a serwerem WWW (w tym przypadku jest to serwer 1U produkowany przez Penguin Computing) w przypadku rozpoczynania sesji oraz wykorzystywania zmiennych. Stan programu jest zawsze znany. Gdy sesja zaczyna się. W aplikacjach WWW zarządzanie danymi sesji jest bardziej złożone. ale nie zawiera on ogólnego opisu problemu utrzymywania stanu. Pod pojęciem klienta kryją się tutaj poszczególni użytkownicy. plikach oraz bazach danych wykorzystywanych przez program. Jeżeli użytkownik chwilowo przełączy zadanie a następnie powróci do niego. Następnie przeglądarka wysyła ID do serwera razem z każdym żądaniem przesłania strony. ale dostępne są również moduły zewnętrzne realizujące to samo zadanie. PHP pozwala na stosowanie kilka metod utrzymywania stanu sesji. Inną metodą jest napisanie w PHP własnego mechanizmu zarządzania sesjami. w utrzymanie sesji jest zaangażowany zarówno serwer jak i klient.1. W PHP4 wbudowano funkcje do obsługi sesji. wykonuje swoje zadania a następnie zamyka program. Gdy użytkownik kończy pracę. Po zakończeniu aplikacji dane są usuwane z serwera. Ponieważ aplikacje WWW są ze swojej natury aplikacjami wielodostępnymi. stan aplikacji nie zmieni się. serwer WWW tworzy unikalny identyfikator sesji (ID) i przekazuje go do klienta. Podstawy mechanizmu sesji Jak napisałem we wprowadzeniu. Sesje i stan aplikacji Wstęp W rozdziale 4 „Operacje na plikach” zostało przedstawione wykorzystanie plików do utrzymania stanu sesji. Serwer wykorzystuje ID do odczytania i odtworzenia wszystkich potrzebnych danych aplikacji.

System zarządzania sesjami w PHP można w dużym stopniu konfigurować. Ponieważ dostępne jest wiele opcji konfiguracji. Funkcje obsługi sesji są dokładnie opisane w skorowidzu funkcji na końcu książki. print( "Konto: $aAccount<br>" ). 2. ?> <html> <head> <title>Podstawy sesji: Strona 1</title> </head> <body> <?php print( "Użytkownik: $aUser<br>" ).2.1 i 7. 3. Rozpoczęcie sesji za pomocą session_start().1. Rozpoczynanie sesji oraz użycie zmiennych sesji Wbudowany w PHP mechanizm zarządzania sesjami W wersji 4 do PHP wprowadzono mechanizm zarządzania sesjami.2 pokazują. miejsce przechowywania zmiennych sesji na serwerze oraz częstotliwość usuwania przerwanych sesji.1 zamieszczony jest skrypt inicjujący wszystkie zmienne sesji używane w aplikacji oraz łącze do skryptu z wydruku 7. 81 PHP – Kompendium wiedzy .Rysunek 7. Użycie zmiennych sesji z wydruku 7.phtml">Przejście do strony 2</a> </body> </html> Wydruk 7. część ta zostanie podzielona na części o wzrastającym stopniu skomplikowania.1.1. $aUser = "Cidnie". $aAccount = "1016".1 <?php session_start().2. Uruchamianie sesji i inicjowanie zmiennych <?php session_start(). Zarejestrowanie nazw zmiennych sesji za pomocą session_register(). "aAccount" ). Wydruk 7. Na wydruku 7. jak łatwe jest użycie sesji w PHP wykorzystujące domyślne ustawienia. ?> <br><br> <a href="listing2. Rozpoczęcie pracy z sesjami w PHP Wydruki 7. Wszystkie nazwy funkcji obsługi sesji rozpoczynają się od sesion_. Użycie zmiennych sesji. session_register( "aUser". Wykorzystując sesje w PHP należy wykonać następujące podstawowe operacje: 1. Można zmienić sposób przesyłania identyfikatora sesji. który wykorzystuje zmienne sesji ze skryptu na wydruku 7.

w domyślnej konfiguracji na Apache i Linuksa.3.1 Rysunek 7. Wynik działania skryptu z wydruku 7.. W domyślnej konfiguracji PHP używa cookie do przechowywania identyfikatora sesji. Rozdział 7 – Sesje i stan aplikacji 82 . print( "Konto: $aAccount<br>" ).2. przeglądarka samoczynnie wyśle identyfikator sesji do serwera. Na rysunkach 7. Funkcje te muszą być wywoływane przed wysłaniem do przeglądarki jakichkolwiek informacji lub musi zostać włączone buforowanie danych wyjściowych.aAccount|s:4:"1016". PHP korzysta z identyfikatora sesji do odczytania wszystkich zmiennych sesji.1 jest uruchomienie sesji poprzez wywołanie funkcji session_start(). Funkcja session_start() posiada te same ograniczenia co funkcje set_cookie() i header(). dane sesji są przechowywane w katalogu /tmp w plikach o nazwach w postaci sess_$PHPSESSID. zostają zarejestrowane dwie zmienne. $PHPSESSID. pokazane są wyniki działania skryptów umieszczonych odpowiednio na wydrukach 1 i 2.?> <html> <head> <title>Podstawy sesji: Strona 2</title> </head> <body> <?php print( "Użytkownik: $aUser<br>" ).2. i 7. W skrypcie z wydruku 7. który zawierał: aUser|s:6:"Cidnie". Po uruchomieniu poprzedniego przykładu odszukałem plik sess_e66b342b4e76889f8f25105db11820c6. ?> </body> </html> Pierwszym krokiem skryptu z wydruku 7. Chociaż można zmienić sposób przesyłania identyfikatora sesji. aUser oraz aAccount. najprostszą metodą jest wykorzystanie domyślnego mechanizmu — cookie. Po rozpoczęciu sesji.2 Możliwe jest wyświetlenie bieżącego identyfikatora sesji wypisując na ekran zawartość zmiennej Dodatkowo. Pozostałe metody zostaną opisane później.2 w trakcie wywołania funkcji session_start().3. Rysunek 7. Wynik działania skryptu z wydruku 7. Gdy użytkownik kliknie łącze prowadzące do strony 2.

"=" . $aUser = "Cidnie". poniższy kod jest semantycznie identyczny z odpowiednią linią z wydruku 7. a w przypadku niektórych dużych aplikacji WWW użycie plików na serwerze WWW może utrudniać skalowanie aplikacji. Stała ta jest zdefiniowana jako SessionName=SessionID. Na szczęście PHP posiada opcję automatycznego przekształcania łączy. Przesyłanie identyfikatora sesji bez użycia cookie Jeżeli aplikacja absolutnie wymaga zastosowania zmiennych sesji. aby identyfikator sesji był przesyłany jako zmienna GET.Domyślne ustawienia PHP dotyczące zarządzania sesjami są łatwe do użycia i wystarczają dla większości aplikacji WWW. poza łączem w trzecim wierszu od końca. ?> <br><br> <a href="listing2. każde łącze i każdy formularz w aplikacji musi zawierać identyfikator sesji. <?php session_start(). Wydruk 7. możesz uaktywnić ten mechanizm kompilując PHP z opcją --enable-transsid. session_register( "aUser". ale nie pokazuje jak mechanizm ten wpływa na tworzenie aplikacji. pokazany na wydruku 7. $aUser = "Cidnie". session_id()?>"> Przejście do strony 2</a> Należy pamiętać. więc jeżeli będziesz chciał wydrukować $SID zamiast nie otrzymasz takiego samego wyniku. Na wydruku 7. ?> <br><br> <a href="listing2. SID zostanie utracony. Wydruk 7.3 zastosowany został skrót <?=SID?>. Jeżeli nie dodasz identyfikatora do jednego łącza.3: <a href="listing2. Przetwarzanie względnych adresów URL przez PHP w celu przekazywania identyfikatora sesji SID. Zapis taki jest równoważny z <?php echo SID. Pierwszą z metod jest ręczne przesyłanie identyfikatora sesji w postaci zmiennej GET lub POST.3 może być zmieniony na nieco prostszy.1. "aAccount" ). który to mechanizm rozwiązuje ten problem za ciebie.?> zakładając. Jednak w niektórych przypadkach cookie mogą nie być pożądaną metodą przesyłania identyfikatora sesji. a aplikacja będzie źle działać.phtml">Przejście do strony 2</a> 83 PHP – Kompendium wiedzy . Należy pamiętać. że SID jest stałą a nie zmienną. że kod jest taki sam jak na wydruku 7. który pokazuje w jaki sposób należy zmienić kod z wydruku 7. session_register( "aUser". print( "Konto: $aAccount<br>" ). że niektórzy użytkownicy mają w swoich przeglądarkach włączoną obsługę cookie. Na wydruku 7. $aAccount = "1016".4.3. Po przebudowaniu PHP kod z wydruku 7. ?> <html> <head> <title>Ręczne przesyłanie identyfikatora sesji: Strona 1</title> </head> <body> <?php print( "Użytkownik: $aUser<br>" ). że w czasie kompilacji PHP użyto opcji --enable-short-tags. Następne dwie części zawierają omówienie sposobu rozwiązania tych problemów. ?> <html> <head> <title>Automatyczne przesyłanie identyfikatora sesji: Page 1</title> </head> <body> <?php print( "Użytkownik: $aUser<br>" ).1. Ręczne przesyłanie identyfikatora sesji za pomocą metody GET <?php session_start(). Jeżeli chcesz przesyłać identyfikator sesji przy użyciu metod GET i POST. Wydruk 7. "aAccount" ). Korzystając z tego mechanizmu.3 ilustruje mechanizm ręcznego przesyłania identyfikatora sesji w programie.phtml?<?php echo session_name() .phtml?<?=SID?>">Przejście do strony 2</a> </html> Należy zauważyć. do przesyłania identyfikatora sesji możesz użyć innego mechanizmu niż cookie.4. $aAccount = "1016". W tym przypadku do adresu URL została doklejona stała PHP SID. print( "Konto: $aAccount<br>" ).3 pokazany jest skrypt.

php. że na wydruku 7.phtml"> <input type="submit" name="Submit" value="Przycisk przesłania danych formularza"> </form> </html> Po uruchomieniu skryptu. że działa on jedynie dla metody POST. następny skrypt zawiera kilka względnych łączy i kilka bezwzględnych. chociaż strona ta znajduje się na tym samym serwerze. Łącze 3 nie jest oczywiście łączem względnym. session_register( "aUser". aplikacja nie będzie działała prawidłowo. $aAccount = "1016". $aUser = "Cidnie".</html> Różnica pomiędzy wydrukiem 3 i 4 jest taka. Działanie takie było przewidziane. Wydruk 7. Przykłady automatycznego uzupełniania łączy przez PHP <?php session_start(). Kod ten działa.net/">Łącze 3</a> <br><br> <a href="http://localhost/listing2.phtml">Łącze 4</a> <br><br> <form action="listing2. ?> <br><br> <a href="listing2. W tym przypadku jest to bezwzględny adres URL.1. że atrybut ACTION zostanie prawidłowo zmodyfikowany. tak samo jak w przypadku skryptu z wydruku 7. Jeżeli będziesz chciał użyć formularza korzystającego z metody GET. ?> <html> <head> <title>Uzupełnianie adresów URL</title> </head> <body> <?php print( "Użytkownik: $aUser<br>" ). Oznacza to. przeglądarka nie dodaje zmiennej PHPSESSID do ciągu zapytania (przetestowane na najnowszych wersjach Netscape i Internet Explorer). aby zawierał on wartość identyfikatora sesji. ponieważ PHP szuka na stronie względnych adresów URL i dodaje do nich potrzebną wartość identyfikatora sesji. zostały do nich dołączone dane na temat sesji.phtml"><INPUT TYPE="HIDDEN" NAME="PHPSESSID" VALUE="9771f86dc94e367cf1c62e0339d02c4b"> <input type="submit" name="Submit" value="Przycisk przesłania danych formularza"> </form> </html> Ponieważ pierwsze dwa łącza są łączami względnymi.phtml?MyVar=1234&PHPSESSID=9771f86dc94e367cf1c62e0339d02c4b"> Łącze 2</a> <br><br> <a href="http://www. Gdy użytkownik kliknie łącze.5. że wydruk 7.php. "aAccount" ).phtml?MyVar=1234">Łącze 2</a> <br><br> <a href="http://www. Jedyną wadą tego mechanizmu jest to.3.phtml?PHPSESSID=9771f86dc94e367cf1c62e0339d02c4b">Łącze 1</a> <br><br> <a href="listing2.net/">Łącze 3</a> <br><br> <a href="http://localhost/listing2. PHP uzupełnia jedynie adresy URL zapisane w postaci łączy względnych. Do przykładu został dołączony formularz. że aplikacja korzystająca z formularzy również będzie prawidłowo działała. print( "Konto: $aAccount<br>" ). Aby to pokazać. Rozdział 7 – Sesje i stan aplikacji 84 . ale wynik jego działania jest różny z powodu zmiany konfiguracji. Łącze 4 pokazuje jak ostrożnym należy być używając funkcji automatycznego uzupełniania łączy. Można również zauważyć. ponieważ PHP potrafi również uzupełniać formularz tak. URL będzie zawierał ciąg PHPSESSID=xxx.4 nie ma odwołania do stałej SID w łączu.phtml">Łącze 1</a> <br><br> <a href="listing2. Mimo. Pokazujemy również w jaki sposób PHP przetworzył łącza.phtml">Łącze 4</a> <br><br> <form action="listing2.4 jest praktycznie identyczny z wydrukiem 7. do przeglądarki został wysłany następujący kod HTML: <html> <head> <title>Uzupełnianie adresów URL</title> </head> <body> Użytkownik: Cidnie<br>Konto: 1016<br> <br><br> <a href="listing2. więc identyfikator sesji nie został dołączony.

Funkcja ta jest wywoływana w trakcie inicjalizacji sesji. string sess_name ). Funkcja jest używana do odczytania zawartości sesji. lub ostatnią wartościa przekazaną do funkcji session_name(). powinieneś przeprowadzić własne testy sprawdzające wpływ zastosowanego mechanizmu na wydajność.phtml". } $aEndTime = getmicrotime(). gdzie będą zapisywane wartości samych zmiennych sesji. powinny zostać zwrócone w postaci serializowanej. Wydruk 7. oraz bez niej.Przesyłanie identyfikatora sesji za pomocą metod GET i POST pozwala uniknąć niektórych problemów z cookie i jest łatwe do zrealizowania. $mtime = $mtime[1] + $mtime[0]. 85 PHP – Kompendium wiedzy . Skrypt uruchamiałem z aktywną opcją --enable-trans-sid. Jeżeli chcesz korzystać z tej funkcji. $nIndex++) { $aData = file( $aFileName ). Skrypt do sprawdzania wydajności <?php function getmicrotime() { $mtime = microtime(). } $aStartTime = getmicrotime(). może ona być ważna w przypadku silnie obciążonych witryn. jak przekazane przez PHP do funkcji write(). że masz zainstalowaną właściwą wersję PHP. Jeżeli dane sesji nie są dostępne. return ($mtime). że różnica taka może być w większości witryn mało znacząca. upewnij się. który odczytywał ją z serwera i zapamiętywał czas potrzebny na jej odczytanie. Jeżeli wystąpi błąd.ini. zawierał błąd w mechanizmie automatycznego uzupełniania adresów URL. Wartościami domyślnymi są odpowiednio /tmp i PHPSESSID.6 do odczytania strony kolejno 1000 razy. lub ostatnia wartość przekazana do funkcji session_save_path(). Zapisywanie zmiennych sesji w bazie danych Po wybraniu mechanizmu przesyłania identyfikatora sesji. Zanotowano średnio 9% zysk wydajności w przypadku zablokowania opcji --enable-trans-sid. aby obliczyć średnią różnicę czasów wykonania.name zdefiniowany w pliku php. Jeżeli zamierzasz skorzystać z automatycznego uzupełniania adresów.0. for ($nIndx = 0.save_path określonej w pliku php. PHP posiada mechanizm zapisywania zmiennych sesji w dowolnie wybrany sposób. Użyłem skryptu z wydruku 7. Mimo. PHP musi przecież podczas każdego uruchomienia strony odszukać wszystkie łącza na stronie i zmienić URL. powinna zostać zwrócona wartość False. Drugi argument jest nazwą sesji określoną przez parametr session. print( "Czas całkowity: $aTotTime\n"). Błąd ten poprawiono w wersji 4. które wymagały przepisania. Funkcja jest wywoływana w przypadku konieczności zapamiętania danych sesji.aStartTime. Pierwszy argument jest ścieżką podaną w jako wartość zmiennej konfiguracji session. • bool open( string save_path. $nIndex < 1000. jaki wpływ będzie to miało na wydajność aplikacji. • mixed read( string sess_id ). Do napisania dowolnego mechanizmu obsługi sesji wystarczy zdefiniować sześć funkcji i zarejestrować je w PHP. Przykładowa strona zawierała 14 łączy z których 12 było łączami względnymi. Dane te powinny być dokładnie takie same. $aFileName = "http://localhost/ch07/listing5. należy zdecydować. Można jej użyć do wstępnej inicjalizacji sesji.2. PHP wersja 4. Strona miała wielkość 9. Aby sprawdzić wpływ tego mechanizmu na wydajność stworzyłem przykładową stronę WWW oraz skrypt. $aTotTime = $aEndTime .55 kB. string value ).0. • bool write( string sess_id. powinieneś również się zastanowić. Jeżeli istnieją dane sesji.ini. powinien zostać zwrócony pusty ciąg (""). • bool close(). Zanim zastosujesz któreś z rozwiązań.1 poziom poprawek 2. $mtime). Funkcje te wraz z ich parametrami są przedstawione poniżej. Błąd w PHP Jak wspominaliśmy w tej części. ?> Test był uruchamiany wiele razy. Dane przekazane do parametru value są danymi sesji w postaci serializowanej. $mtime = explode( " ".6. Funkcja jest wywoływana w celu zakończenia sesji.

gc_probability na 100. $aUser = "Katie". Testowanie mysession. $aVal )<br>" ). $aAccount = "2026". "mysess_gc" ). ?> <html> <head> <title>Własny mechanizm obsługi sesji</title> </head> <body> <?php print( "Użytkownik: $aUser<br>" ). Wydruk 7. print( "mysess_write( $aKey. Po utworzeniu funkcji obsługi sesji należy zarejestrować je za pomocą funkcji session_set_save_handler().Funkcja jest wywoływana podczas wywołania w skrypcie funkcji session_destroy().7.7. Podczas swojego działania powinna usunąć wszystkie dane nie używane przez max_lifetime sekund. return True. } function mysess_read( $aKey ) { print( "mysess_read( $aKey )<br>" ). } function mysess_destroy( $aKey ) { print( "mysess_destroy( $aKey )<br>" ). Wydruk 7. return True. który zawiera 7 funkcji obsługi zmiennych. • bool gc( int max_lifetime ). return True. ?> • Aby pokazać w jaki sposób PHP wywołuje nowe funkcje. } session_set_save_handler( "mysess_open". <?php function mysess_open( $aSavePath.php" ). Zdefiniowany przez użytkownika mechanizm obsługi sesji: mysession. ?> </body> </html> Rozdział 7 – Sesje i stan aplikacji 86 . które jedynie wypisują swoją nazwę i parametry wywołania. print( "Konto: $aAccount<br>" ).aAccount|s:4:###BOT_TEXT###quot;1016###BOT_TEXT###quot;. "mysess_read".".php bool destroy( string sess_id ). Jest ona wywoływana z częstotliwością określoną przez parametr konfiguracji session. "mysess_write".php <?php include( ". Funkcja ta jest wywoływana w czasie rozpoczynania sesji. } function mysess_close() { print( "mysess_close()<br>" ). Funkcja read() z tego skryptu zwraca dla celów testowych wartości dwóch zmiennych sesji. } function mysess_gc( $aMaxLifetime ) { print( "mysess_gc( $aMaxLifetime )<br>" ).gc_probability. Do zilustrowania tego mechanizmu przygotowany został skrypt na wydruku 7. } function mysess_write( $aKey. return True. użyjemy skryptu z wydruku 7. return "aUser|s:6:###BOT_TEXT###quot;Cidnie###BOT_TEXT###quot;. "mysess_destroy". return True. Usuwanie niepotrzebnych danych sesji jest omówione w następnej części rozdziału. print( "Użytkownik: $aUser<br>" ). Funkcja jest przeznaczona do usuwania nieużywanych danych sesji. $aSessionName )<br>" ). $aVal ) { print( "Wywołanie mysess_write!\n\nWłaśnie tutaj!\n\n" ).8./mysession.8. Powinna usunąć wszystkie dane związane z sesją. Po tej operacji PHP będzie wywoływało wszędzie tam gdzie jest to potrzebne nowe funkcje. session_start(). "mysess_close". Dodatkowo ustawiłem wartość session. print( "Konto: $aAccount<br>" ). $aSessionName ) { print( "mysess_open( $aSavePath. więc funkcja czyszczenia pamięci jest wywoływana na początku każdej sesji.

var $User = "root". że ten efet może nie powtórzyć się w przypadku użycia innej platformy i serwera.inc" ). Problem ten jednak nie wpływa na właściwy system obsługi sesji. pole data/czas do zapamiętywania czasu ostatniej zmiany oraz dane w postaci pola tekstowego typu BLOB. ale należy pamiętać. Po dokładniejszym sprawdzeniu odkryłem. Wynik w przeglądarce jednak nadal nie był prawidłowy. Obsługa sesji przy użyciu bazy danych MySQL <?php include ( "db_mysql. stworzenie prawdziwego mechanizmu obsługi sesji będzie dosyć łatwe. Idea ta może być z początku mało zrozumiała. W celu poprawienia czytelności kodu.4. Do przechowywania danych sesji korzystamy z tabeli zdefiniowanej w następujący sposób: CREATE TABLE Sessions ( SessionId char(32) not null. INDEX (LastUpdated ) ). Awaria ta będzie wynikała z tego. Na przykład w przypadku serwera Xitami działającego na Windows widoczne były wszystkie spodziewane dane. LastUpdated datetime not null. Jeżeli aplikacja zostanie rozdzielona na kilka serwerów WWW i zastosowany zostanie mechanizm równoważenia obciążenia pomiędzy serwerami. Cały kod funkcji obsługi sesji zamieszczony jest na wydruku 7. DataValue text. Jeżeli początkowe dane zostaną zapisane na serwerze pierwszym. Jeżeli wszystkie dane sesji będą przechowywane w bazie danych. Jak można zauważyć dodałem nawet dodatkową instrukcję print() aby dokładniej sprawdzić co się stało. Oznacza to. że w którymś momencie wyjście zostało tymczasowo przekierowane z stdout na stderr. Jeżeli chcesz używać zmiennych sesji. // Specjalizacja klasy DB_Sql do wykorzystania na naszym // serwerem bazy danych MySQL class MySQLDB extends DB_Sql { var $Host = "localhost".php Gdy uruchomiłem ten skrypt. jakiego się spodziewałem. Wynik działania skryptu mysession. var $Database = "mydb". Wydruk 7. Po poznaniu zasady działania mechanizmu. że każde żądanie może być kierowane do innego serwera w klastrze.Rysunek 7. że wynik działania obu funkcji znajduje się w pliku error_log serwera Apache. 87 PHP – Kompendium wiedzy . Tabela ta zawiera pole do przechowywania identyfikatora sesji. że zapisywanie danych aplikacji na serwerze WWW może ograniczać skalowalność aplikacji. zmienne sesji będą dostępne dla wszystkich serwerów WWW w klasterze. ponieważ sposób obsługi standardowego wyjścia danych i błędów może być inny. W przeglądarce nie było informacji na temat wywołania funkcji write() i close(). W wyniku tego przekierowania nie można wysłać żadnych danych do przeglądarki zarówno w funkcji write(). wynik nie był taki.9.9. Następny wydruk zawiera prosty przykład użycia bazy danych MySQL do przechowywania danych sesji. PRIMARY KEY (SessionID). to dane sesji będą nieosiągalne. jak i close(). Trzeba powiedzieć. użycie plików do obsługi sesji może spowodować załamanie aplikacji. Pole LastUpdated posiada indeks w celu poprawienia wydajności w trakcie odzyskiwania nieużytków. powinieneś przechowywać je w bazie danych a nie w pliku. a kolejne żądanie będzie przekazane do serwera dwa. przykład korzysta z klasy DB_Sql pochodzącej z pakietu PHPLIB omówionej w rozdziale 6 „Współpraca z bazami danych”.

$aDB->query( $aSQL ). $aData = $aDB->f( "DataValue" ). mysess_write(). $aSQL = "delete from Sessions where SessionID = '$aKey'". $aSQL . $aDB->query( $aSQL ). a po zakończeniu sesji nie trzeba niczego usuwać. $aDB->query( $aSQL ).= ". Funkcje i mysess_close() nie są w tym przypadku używane. return "". $aSessionName ) { // nie trzeba nic robić return True. Funkcja mysess_destroy() usuwa rekord związany z identyfikatorem sesji. $aSQL = "select DataValue from Sessions where SessionID='$aKey'". "mysess_read". Wszystkie dane sesji są przechowywane w jednej tabeli. NOW(). $aDB->query( $aSQL ). mysess_destroy() oraz mysess_gc(). W funkcji mysess_read() do bazy jest kierowane zapytanie mające za zadanie odczytać dane związane z identyfikatorem sesji. if ( $aDB->num_rows() == 1 ) { $aDB->next_record(). ?> Kod z wydruku jest całkiem prosty jak na tak dużą zmianę mechanizmu obsługi sesji. że gdy później będą zapisywane dane sesji nie będzie konieczności sprawdzania. $aSQL = "update Sessions set DataValue='$aData'. Jeżeli dane te zostaną odnalezione — są zwracane. ". } else { // Wstaw wiersz dla bieżącej sesji aby uprościć funkcję write $aSQL = "insert into Sessions values ( '$aKey'. więc wartości przekazane do mysess_open() nie są używane. "mysess_destroy". "mysess_write". $aVal ) { $aDB = new MySQLDB. których wartość pola LastUpdated wskazuje że nie rekord nie był uaktualniany przez ostatnie $aMaxLifetime sekund. } function mysess_close() { // nie trzeba nic robić return True. Interesującymi funkcjami są mysess_read(). tworzony jest nowy rekord z pustym polem DataValue i zwracany jest pusty ciąg ("").= "LastUpdated=NOW() where SessionID='$aKey'". ponieważ nie są potrzebne. $aData = addslashes( $aVal ).UNIX_TIMESTAMP(LastUpdated) > $aMaxLifetime". return True. Funkcja mysess_write() za każdym wywołaniem uaktualnia pola DataValue oraz LastUpdated. '' )". Funkcja mysess_gc() usuwa wszystkie wiersze. } function mysess_gc( $aMaxLifetime ) { $aDB = new MySQLDB. return $aData. return True. } } function mysess_write( $aKey. } function mysess_destroy( $aKey ) { $aDB = new MySQLDB. } session_set_save_handler("mysess_open". czy istnieje już odpowiedni rekord w bazie danych. } function mysess_read( $aKey ) { $aDB = new MySQLDB. $aSQL . mysess_open() <?php Rozdział 7 – Sesje i stan aplikacji 88 . $aSQL = "delete from Sessions where UNIX_TIMESTAMP(NOW()) ". Poniższy kod pokazuje sposób wykorzystania mechanizmu sesji partego o bazę danych. return True. Powodem takiego działania jest to. "mysess_close".var $Password = "root". $aDB->query( $aSQL ). Jeżeli nie ma jeszcze rekordu w bazie. "mysess_gc"). } function mysess_open( $aSavePath.

Opcja pozwala na zdefiniowanie nazwy programu obsługi używanego do serializacji i deserializacji danych. Wartością domyślną jest php. Ustawienie na user. bieżącej nazwy sesji. Ustawienie jej wartości na files powoduje zapisywanie danych sesji w pliku na serwerze WWW.name. ale przykłady mają za zadanie pokazać ogólną ideę.gc_probability. Opcja określa prawdopodobieństwo w procentach uruchomienia funkcji gc (usuwania nieużytków) podczas obsługi żądania. session_start(). kiedy sesja się zakończyła. $aUser = "Cidnie". co oznacza. session_save_path() i session_id() mogą być użyte do odczytywania lub ustawiania odpowiednio. nazwy modułu. Wartością domyślną jest /tmp. "aAccount" ). które nie były uaktualniane przez określony czas (patrz session. Wartością domyślną jest files. czy moduł sesji automatycznie uruchamia sesję na początku strony. Jeżeli potrzebujesz w swojej aplikacji zastosować zmienne sesji. Wartość mm powoduje korzystanie z wspólnej pamięci serwera WWW. Usuwanie nieużytków polega na usuwaniu zmiennych sesji zapisanych na serwerze WWW.serialize_handler. WDDX jest dostępny jedynie po skompilowaniu PHP z obsługą WDDX. Opcja określa. Opcja określa nazwę sesji.?> <br><br> <a href="mysql_session_mgmt2. Inne funkcje i opcje dotyczące sesji PHP posiada jeszcze kilka nie omówionych jeszcze funkcji obsługi sesji. ścieżki zapisu i identyfikatora. PHP wywołuje funkcję usuwania nieużytków usuwającą zmienne sesji. W pliku php. że aplikacja posiada własny mechanizm obsługi. session_register( "aUser".auto_start. wartość opcji jest niejawnie przestawiana na user.save_path. • session. Funkcje session_name(). W przykładzie tym można zastosować kilka optymalizacji i usprawnień ulepszających działanie. PHP zawiera rozwiązania pozwalające na dowolną implementację takiego mechanizmu. Możliwe są wartości files. używaną również jako nazwa cookie. w którym byłaby zalecana zmiana tych parametrów w czasie pracy. Jeżeli używasz wbudowanego mechanizmu przechowywania danych. Opcja ta może być odczytywana lub zmieniana w czasie pracy za pomocą funkcji session_module_name(). print( "Konto: $aAccount<br>" ). • session.phtml?<?=SID?>">Przejście do następnej strony</a> </body> </html> Poprzedni przykład pokazuje jak łatwo można utworzyć i używać własny mechanizm przechowywania danych sesji w PHP. jest to nazwa katalogu gdzie są tworzone pliki. Wartością domyślną jest 0. oznacza. session_module_name(). Powinna zawierać jedynie znaki alfanumeryczne. • session. Wartością domyślną jest PHPSESSID. • session. umieszczony w dalszej części rozdziału. Domyślną wartością jest 0 (wyłączony). Wartością domyślną jest 1. Ponieważ często niemożliwe jest określenie. ze musisz korzystać z dzielenia ich przy pomocy tych funkcji powinieneś poważnie rozważyć zastosowanie sugestii zamieszczonych w części „Inżynieria programowania a sesje”. Jeżeli wywołasz funkcje session_set_save_handler().save_handler. • session.php" ). że 1% uruchomień sesji powoduje wykonanie funkcji usuwania nieużytków./mysql_session. Jeżeli do PHP – Kompendium wiedzy 89 .ini znajdują się następujące opcje konfigurujące mechanizm sesji: • sessions. • session. Dostępny jest wewnętrzny format PHP (o nazwie php) oraz WDDX (o nazwie wddx).lifetime. Miałem kłopot wymyślić projekt. Opcja określa argument przekazywany do funkcji obsługi sesji. Wartość 0 oznacza „do zamknięcia przeglądarki”. Opcja ta pozwala na zdefiniowanie nazwy programu obsługi używanego do zapisywania i odczytywania danych związanych z sesją.gc_maxlifetime). user i mm. Pozwala określić w sekundach czas ważności cookie wysyłanego do przeglądarki.include( ". ?> <html> <head> <title>Obsługa sesji z wykorzystaniem MySQL: Strona pierwsza</title> </head> <body> <?php print( "Użytkownik: $aUser<br>" ). $aAccount = "1016". Jeżeli twoja zmienna posiada tak dużo zmiennych sesji.

Domyślnie jest to 1440 sekund (24minuty). że PHPLIB można rozszerzyć w sposób. Sytuacja taka może prowadzić do problemów z bezpieczeństwem serwera. include( "db_mysql. • session. Obsługa sesji w PHPLIB <?php include( "page. Domyślnie jest to 0 (wyłączone). po których dane są uważane za „nieużytki” i usuwane. Domyślnie jest ustawiona na 0.entropy_file. które mogą być bardzo użyteczne w naszych aplikacjach. Inne metody przesyłania identyfikatora sesji wymagają więcej pracy. więc jest możliwa do rozbudowy i konfiguracji poprzez dziedziczenie i rozbudowę klasy bazowej. • session. W zależności od aplikacji możesz wydłużać lub skracać ten czas. Opcja określa ilość sekund. których można uniknąć stosując tą opcję. PHPLIB była jedną z pierwszych (i prawdopodobnie najbardziej znaną) bibliotek klas zawierających obsługę sesji w PHP. że użycie cookie wydaje się najprostszym rozwiązaniem. // Specjalizacja klasy DB_Sql do połączenia z // naszym serwerem MySQL class MySQLDB extends DB_Sql { var $Host = "localhost". Obsługa sesji w PHPLIB jest oparta w całości o kod PHP. Wydruk 7. czy identyfikatory sesji odwołujące się do zewnętrznych witryn są usuwane.gc_maxlifetime. var $Database = "mydb". Posiada ona również niektóre opcje inicjalizacji. Użycie PHPLIB do obsługi sesji W rozdziale 6 „Współpraca z bazami danych” przedstawialiśmy PHPLIB. Przykład ten jest identyczny z przedstawionym na wydruku 7. • session. może to spowodować poważne problemy. Koncepcyjnie jest ona podobna do rozwiązania zastosowanego w PHP4. który posiada dołączony identyfikator sesji. Opcja pozwala na zdecydowanie czy do przechowywania identyfikatora sesji na komputerze klienta używane będą cookie. które będzie używane jako dodatkowe źródło entropii do generowania identyfikatorów sesji. które należy odczytać z pliku określonego w poprzedniej opcji. które będą używały mechanizmu sesji.inc" ).przesyłania identyfikatora sesji używane są metody GET i POST. Opcja określa. include( "session.referer_check. Wydruk 7. ale korzystne jest wcześniejsze planowanie. aby funkcje obsługi strony sygnalizowały początek i koniec strony. Obsługa sesji w PHPLIB oparta jest o klasę kontenerową zdefiniowaną w PHPLIB. dostępne we wielu systemach Unix. Jeżeli identyfikator sesji jest przesyłany w adresie URL. który pozwala na przechowywanie zmiennych sesji w praktycznie dowolnym miejscu. var $User = "root".entropy_length. Opcja pozwala określić ilość bajtów.9. Mogą to być /dev/random lub /dev/urandom. Używana jest jedna z klas pochodnych po klasach CT_xxx.use_cookies. • session. ponieważ powoduje on. ponieważ użytkownicy mogą wyłączyć obsługę cookie. użytkownicy nie zdając sobie sprawy ze skutków mogą publikować identyfikator sesji.inc" ). Polecam metodę przesyłania identyfikatora sesji w adresie URL.10.inc" ). że korzysta on z cookie do przechowywania identyfikatora sesji na komputerze klienta. Powoduje to.inc" ). przeznaczonych do obsługi przechowywania zmiennych sesji. Prawdopodobnie nie chcesz. Mimo. PHPLIB wymaga również. include( "ct_sql. Powodem tego jest możliwość zapisania jako zakładki adresu URL. że ręczne przesyłanie identyfikatora sesji jest o wiele prostsze niż w przypadku projektu pokazanego w tym rozdziale. oraz która z „funkcji” PHPLIB jest używana na stronie. Domyślnie jest to 1 (włączone). należy zwiększyć tą wartość. ponieważ metoda ta wymaga podjęcia decyzji na temat stron. PHP zapewnia ogromną elastyczność przy obsłudze sesji. Polecam również użycie projektu witryny opartego na szablonach (szczegóły w rozdziale 12 „Oddzielanie kodu HTML od PHP”).10 zawiera skrypt ilustrujący użycie PHPLIB do zapisu zmiennych sesji w bazie MySQL. • session. Rozdział 7 – Sesje i stan aplikacji 90 . jako świetną bibliotekę zawierającą niektóre zaawansowane funkcje do tworzenia aplikacji opartych o PHP. aby użytkownicy po dłuższym czasie kontynuowali starą sesję. Projektując aplikację korzystającą ze zmiennych sesji należy rozważyć wszystkie dostępne opcje. Opcja pozwala na podanie ścieżki do zewnętrznego źródła (pliku). oprócz tego.

Kolejna klasa. $sess->register( "aAccount" ). PRIMARY KEY (name. pamięci współdzielonej oraz tabeli bazy danych. var $lifetime = 0. ale doświadczeni programiści na pewno zauważą. Pierwsza klasa pochodna. Tak jak we wbudowanym mechanizmie sesji PHP.phtml">Następna strona</a> </body> </html> <?php page_close(). val text. var $database_table = "active_sessions". Jedynym dodatkowym wymaganiem jest wywołanie w skrypcie funkcji page_close() do zaznaczenia końca skryptu. Wywołanie tej funkcji powoduje utworzenie globalnej zmiennej $sess. $lang = "pl". Poniższy kod pokazuje przykład takiego pliku inicjalizującego: <?php global $lang. Po utworzeniu klasy rejestrowane i wykorzystywane są zmienne sesji. MySQLDB jest klasą niezbędną do nawiązania połączenia z naszym serwerem bazy danych. że jest on bardzo łatwo rozszerzalny poprzez dziedziczenie bazowych klas obsługi sesji. ?> PHPLIB jest niezmiernie elastycznym narzędziem do zarządzania danymi sesji. // język aplikacji // domyślnie polski 91 PHP – Kompendium wiedzy . $sess->register( "aUser" ). Podstawowe funkcje klasy Session w PHPLIB są praktycznie identyczne z możliwościami wbudowanego mechanizmu PHP. $aUser = "Cidnie". Dodatkową funkcja PHPLIB jest możliwość dostarczania pliku inicjalizującego używanego do inicjalizacji zmiennych sesji na początku każdej sesji. która jest używana do zrealizowania dostępu do tabel. var $database_class = "MySQLDB". Tabela bazy danych wymagana przez mechanizm obsługi sesji w PHPLIB posiada następującą strukturę: CREATE TABLE active_sessions ( sid varchar(32) not null. Ostatnia klasa. która jest wykorzystywana w kolejnych wywołaniach obsługi sesji.10 jest nieco bardziej skomplikowany. która jest podstawową klasą kontenerową zapewniającą zapisywanie danych w bazach danych SQL. MySQLSession rozszerza bazową klasę Session i ustawia klasę MySQLCt jako klasę zapisującą wszystkie dane sesji. Tak jak PHP posiada on mechanizmy zapewniające zapisywanie danych sesji w liku. Kod z wydruku 7. MySQLCt jest klasą pochodną po klasie kontenerowej CT_Sql. sid). changed varchar(14) not null. Po utworzeniu klas pochodnych PHPLIB wykorzystuje funkcję page_open() do dodania „funkcji” sesji do bieżącej strony. $aAccount = "1016". name varchar(32) not null. PHPLIB pozwala na wykorzystanie cookie lub zmiennych GET i POST do przesyłania identyfikatora sesji.var $Password = "root". PHPLIB posiada również narzędzia do tworzenia klas kontenerowych używanych do zapisywania zmiennych sesji na dowolnie wymyślonym serwerze. $sess->register("lang"). ?> <html> <head> <title>Obsługa sesji w PHPLIB: Pierwsza strona </title> </head> <body> <?php print( "Użytkownik: $aUser<br>" ). // nazwa używanego kontenera } page_open( array( "sess" => "MySqlSession" ) ). } class MySQLCt extends CT_Sql { var $classname = "MySQLCt". KEY changed (changed) ). Zawiera ona odwołanie do klasy MySQLDB. // użycie cookie sesji var $that_class = "MySQLCt". ?> <br><br> <a href="phplib_session_mgmt2. } class MySqlSession extends Session { var $classname = "MySqlSession". // obsługa przechowywania var $mode = "cookie". print( "Konto: $aAccount<br>" ).

jak decyzja użycia zmiennej globalnej. może być przydatny dostęp do całego kodu źródłowego PHP. więc korzystając z tej metody zaleca się używanie odpowiedniej mechanizmu szyfrowania. autor książki „Code Complete” (Microsoft Press. ale tak jak wszystkie inne narzędzia programistyczne powinny być używane ostrożnie i według projektu. Lista ta wskazuje powody rozważane użycia zmiennych globalnych przy programowaniu zwykłych aplikacji. Bądź ostrożny przy uznawaniu zmiennej za zmienną sesji. że występują w liście parametrów każdej procedury. Może być to duże zbiory danych używane w całej aplikacji. każda strona biorąca udział w sesji musi załadować wszystkie zmienne sesji nawet. Dane globalne. Czasami niektóre dane są tak często używane w aplikacji. aby mogły być przekazane do kolejnej. Możesz również stosować PHPLIB do realizowania sesji w starszych wersjach PHP. $cart = new Shop_Cart. często są nadużywane w takim samym stopniu. Należy pamiętać. jest klucz główny lub identyfikator. to dane odzwierciedlające stan całej aplikacji. global $cart. • Uproszczenie użycia bardzo często używanych danych. Czasami wartości są przekazywane do procedury tylko po to. przesyłanie identyfikatora wymaga nieco dokładniejszego projektowania aplikacji. 1993) uważa. pełna). które nie posiadają wbudowanego mechanizmu sesji. na przykład tabele słownikowe. że powodem użycia zmiennej globalnej mogą być następujące przypadki: • Przechowywanie wartości globalnych. są one nazywany danymi wędrującymi. Inżynieria programowania a sesje Zmienne sesji mogą być niezmiernie istotne we wielu aplikacjach WWW. Z drugiej strony. Takie podejście najczęściej prowadzi do nadużywania danych globalnych i zmiennych sesji. Tak jak w przypadku wszystkich innych aspektów projektowania aplikacji należy wykona dokładną analizę potrzeb aplikacji i na jej podstawie wybrać właściwy schemat zarządzania sesjami. gdy nie korzysta z żadnej. Mając tą wartość możesz odczytać z bazy danych wszystkie potrzebne na stronie dane. jak zmienne globalne przy pisaniu tradycyjnych aplikacji. na przykład aby wykonać niektóre optymalizacje. w których należy skorzystać ze zmiennych sesji. że PHP posiada wbudowany mechanizm sesji zbliżony do rozwiązania zastosowanego w PHPLIB. ?> // waluta aplikacji // domyślnie złotówki // utworzenie obiektu wózka na zakupy // zdefiniowanego w local. ponieważ wydaje się występować w każdej procedurze i na każdej stronie witryny WWW. Ponieważ PHP posiada stałe. $sess->register("cart"). Należy również Rozdział 7 – Sesje i stan aplikacji 92 . ale decyzja użycia zmiennej sesji powinna być oparta na tych samych kryteriach. Steve McConnell. zastosowanie to nie jest dopuszczalne. Wybór niewłaściwego narzędzia na początku całego procesu może być kosztowne i prowadzić w dłuższej perspektywie do problemów z konserwacją i rozwojem aplikacji. Ponieważ zmienne sesji są bardzo łatwe do użycia. • Eliminowanie wędrujących danych. W wielu wypadkach jedyną daną. Tworzenie własnego mechanizmu sesji W niektórych przypadkach w aplikacji może nie być potrzebny kompletny mechanizm sesji. jaką musimy przesyłać pomiędzy stronami. • Zastępowanie nazwanych stałych. $cur = "PLN". Są one elastyczne i łatwe do użycia. Dodatkowo przesyłanie wartości identyfikatora otwartym tekstem może powodować naruszenie bezpieczeństwa. Projektując aplikację WWW należy szczegółowo rozważyć wszystkie zastosowania. Gdy procedury w takim łańcuchu nie korzystają z takich danych. na przykład tryb pracy (wersja próbna. $sess->register("cur"). Decyzja użycia zmiennej sesji powinna być oparta na takich samych przesłankach.global $cur. Rozwiązanie to jest proste do zrealizowania i nie wymaga żadnych dodatkowych narzutów wprowadzanych przez przedstawione w tym rozdziale narzędzia obsługi sesji. że po zdefiniowaniu w aplikacji zmiennych sesji. W takich przypadkach bardziej efektywne będzie przesyłanie identyfikatora pomiędzy stronami aplikacji za pomocą zmiennych GET i POST.inc // zarejestrowanie obiektu Mimo.

musiał na początku wybrać zbiór danych do oglądania. Dodatkowo. nie było by problemu. Po pierwsze. aby wyeliminować odwołania do baz danych (aby przyspieszyć ładowanie strony) przy pobieraniu danych o uprawnieniach. lista ta była uaktualniana (wraz z tabelą uprawnień). Spowoduje to usunięcie ogromnej ilości kodu i wyeliminuje konieczność przechowywania listy uprawnień w danych sesji. należy wykorzystywać możliwości bazy danych do poprawienia wydajności aplikacji. • Czy dana jest dana kluczową? Pytanie to jest związane z pierwszym. Tabela uprawnień zawierała identyfikator pierwotnego użytkownika i doradcy oraz identyfikator danych udostępnianych przez użytkownika. doradca miał dostęp tylko do danych zleconych w trakcie rozpoczynania sesji. są spowolnione przez proces ładowania zmiennych sesji. którym dane były udostępniane byli doradcami. Na wielu stronach kod wyglądał następująco: WYIERZ wszystkie potrzebne dane z konta pierwotnego użytkownika DLA KAŻDEGO WIERSZA JEŻELI identyfikator tego wiersza znajduje się na liście uprawnień w zmiennej sesji wyświetl lub wykorzystaj dane W PRZECIWNYM WYPADKU ignoruj ten wiersz. gdy doradca był zalogowany w aplikacji. prawdopodobnie nie potrzebujesz zmiennej sesji. Na przykład. dane o tym były zapisywane w bazie danych. jego identyfikator był poszukiwany w zawartości zmiennej sesji zamiast w bazie danych. Pierwszy cel nie został zrealizowany. zmienne sesji były używane do uproszczenia sprawdzania uprawnień w kodzie strony. aby nie korzystać z bazy danych do sprawdzania uprawnień i w zmiennej sesji przesyłana była lista zleconych identyfikatorów danych. które nie korzystają z uprawnień. Jednak jeżeli aplikacja korzysta z kilku trwałych wózków na zakupy w których użytkownik może przechowywać zamówienie w czasie kilku sesji. Na wszystkich stronach aplikacji dane o uprawnieniach są ładowane z serwera WWW i po zakończeniu strony ponownie zapisywane. ponieważ programista nie korzystał w pełni z wydajności bazy danych. Takie niefortunne działanie było spowodowane tym. postaw sobie następujące pytania: • Czy ta zmienna jest używana w całym programie? Jeżeli ta wartość jest używana na każdej stronie aplikacji. które zawierały identyfikator konta doradcy. Po drugie. unikaj przechowywania innych danych 93 PHP – Kompendium wiedzy . Jeżeli pierwotny użytkownik uaktualnił tabelę uprawnień w czasie. zapamiętaj ją w zmiennej sesji. Gdy chcesz zastosować zmienną sesji. jeżeli aplikacja korzysta z logowania użytkowników. Poprzedni przykład kodu może być zastąpiony zapytaniem. Głównym problemem powodowanym przez takie podejście były kłopoty z synchronizacją danych. że nawet strony. oraz identyfikator przeglądanych danych klienta. gdy doradca otwierał w programie zbiór danych. Użytkownicy. że pierwszy programista nie zapewnił realizacji dwóch celów. które wymagają tych informacji. w którym tabela z danymi jest połączona z tabelą z uprawnieniami. ale dobrze zaprojektowanej bazy danych. W jednym z moich ostatnich kontraktów natrafiłem na świetny przykład nieprawidłowego użycia zmiennych sesji. Za każdym razem. Gdy użytkownik udostępniał dane doradcy. jest o wiele bardziej efektywne. którym pierwsi użytkownicy ufali. Jeżeli aplikacja korzysta ze zmiennych sesji do przechowywania identyfikatora użytkownika. gdy element danych był pobierany z bazy. Gdy doradca logował się do aplikacji. • Czy zmienna ta jest unikalna dla tej sesji? Jeżeli jest to na pewno dana związana z sesją. Następnie. ponieważ doradca nie powinien go widzieć Jak wspominaliśmy w rozdziale 6 „Współpraca z bazami danych”. musisz prawdopodobnie przechowywać jego identyfikator w zmiennej sesji. rozwijanie aplikacji według tego modelu było frustrujące. ponieważ programista nie ładuje jawnie zmiennych sesji. Większość aplikacji WWW wymaga zastosowania tylko kilku zmiennych sesji. W aplikacji były ustawiane zmienne sesji. Ładowanie danych uprawnień z bazy danych jedynie na stronach. jeżeli tworzysz wózek na zakupy. że zapewniają one wygodniejszy dostęp do danych związanych z sesją. Jednak ktoś zdecydował. ale powinny być używane rozważnie. Jeżeli te identyfikatory byłyby jedynymi zmiennymi sesji. Zmienne sesji są niezmiernie potrzebne przy programowaniu aplikacji WWW. W trakcie projektowania należy rozważyć wszystkie alternatywne sposoby uzyskana tego samego efektu. są one automatycznie odczytywane z trwałego nośnika.unikać użycia zmiennych sesji jedynie dlatego. Proces ten powoduje. W aplikacji użytkownicy mogli utworzyć zbiór danych i udostępnić je do modyfikacji przez innego użytkownika. jest to świetny kandydat na zmienną sesji. zmienne sesji zostały zastosowane. ponieważ programista nie wiedział czy używać danych z bazy danych czy ze zmiennych sesji. Drugi cel nie został spełniony. Na przykład. dobrze jest przechowywać identyfikator użytkownika w zmiennej sesji.

To. Na przykład. nie przechowuj zmiennych potrzebnych do tego celu w sesji. ale nieprawidłowo używane mogą doprowadzić do stworzenia aplikacji pełnej błędów i trudnej do utrzymania. Nieprawidłowe użycie zmiennych sesji może doprowadzić do stworzenia aplikacji trudnej do rozwijania. jeżeli aplikacja personalizuje strony. Podsumowanie W PHP dostępne jest kilka świetnych narzędzi do stworzenia mechanizmu sesji. Należy wybrać mechanizm. ale również pozwala użytkownikowi na zmianę swoich ustawień w jednej sesji i natychmiastowe odzwierciedlenie tego w drugiej równoległej sesji. Zmienne sesji nie powinny zastępować innych mechanizmów przechowywania danych. że użytkownik przegląda witrynę i przeprowadza jakieś operacje niekoniecznie oznacza. Jeżeli odpowiedź na te pytania nie zgadza się z zasugerowanymi odpowiedziami. Zamiast tego. • Czy aplikacja na pewno potrzebuje zmiennych sesji? Pytanie to może wydawać się oczywiste. należy rozważyć zastosowanie innych metod przechowywania danych. Przechowuj w sesji identyfikator i wykorzystaj kilka funkcji odczytujących dane potrzebne do personalizacji. w razie potrzeby skorzystaj z identyfikatora do odczytania potrzebnych danych. ale często jest pomijane z powodu łatwości używania zmiennych sesji. Rozdział 7 – Sesje i stan aplikacji 94 . która posiada trudne do zidentyfikowania błędy.związanych z użytkownikiem w zmiennej sesji. Struktura taka nie tylko eliminuje powtórzenia danych. który najlepiej pasuje do potrzeb i którego zastosowanie będzie przynosiło owoce w dłuższym czasie a nie tylko będzie miał krótkoterminowy wpływ na kodowanie aplikacji. że potrzebna jest sesja. Sesje są świetnym narzędziem.

htaccess. że przeglądarka wyświetli standardowe okno uwierzytelniania.htaccess. Jednak jeżeli witryna jest umieszczona na dzierżawionym serwerze. Wydruk 8.2. że użytkownicy maja wystarczające uprawnienia do pracy w aplikacji. W tym rozdziale zajmiemy się uwierzytelnianiem opartym na mechanizmach serwera. ale administrator musi mieć do nich dostęp z dowolnej przeglądarki. za pomocą których można przeglądać i zmieniać wybrane elementy witryny. pokazane na rysunku 8. Wydruk 8. Osoby znające dyrektywy uwierzytelniania Apache oraz przeznaczenie plików .2 zawiera dyrektywy konfiguracji Apache które powodują wyświetlenie okna logowania. Ten rozdział poświęcony będzie sposobom upewnienia się.Rozdział 8. Większość serwerów WWW posiada narzędzia przeznaczone do autoryzacji użytkowników w oparciu o uprawnienia i pliki serwera. Na przykład może być niezbędne stworzenie zbioru stron przeznaczonych do administracji witryną. Jeżeli masz dostęp do plików konfiguracyjnych Apache powinieneś skorzystać z nich zamiast z pliku . aby dostęp do stron znajdujących się w tym katalogu wymagały autoryzacji. Podstawowe uwierzytelnianie w Apache Rozdział ten rozpoczniemy omówieniem podstawowego schematu uwierzytelniania dostępnego w serwerze WWW Apache oraz problemami związanymi z tą metodą. ponieważ jest on odczytywany za każdym żądaniem pliku z katalogu zawierającego plik .phtml">Przejdź do strony administratora</a> </body> </html> Wydruk 8. Odpowiednie dyrektywy konfiguracji mogą znajdować się w pliku httpd.htaccess jest mniej efektywne od wykorzystania standardowych plików konfiguracyjnych. Nawet w prostej witrynie może być potrzebne ograniczenie dostępu do niektórych stron. Na wydruku 8. prawdopodobnie nie będziesz mógł zmienić plików konfiguracyjnych i zrestartować serwera WWW w celu pobrania zmienionej konfiguracji.htaccess w chronionym katalogu.htaccess i innych plików konfiguracyjnych serwera Apache nie dowiedzą się tutaj zbyt wiele nowego. Istnieją różne schematy uwierzytelniania przeznaczone do różnych zadań. W dalszej części rozdziału przedstawiony zostanie również mechanizm niezależny od serwera i platformy. Uwierzytelnianie Wstęp W poprzednim rozdziale „Sesje i stan aplikacji” omówione zostały sposoby śledzenia użytkowników witryny WWW w celu zapewnienia ciągłości pracy aplikacji. ale jedynie w oparciu o serwer Apache na Linuksie (Windows i IIS również umożliwiają uwierzytelnianie. ale nie zostanie ono tutaj opisane).conf lub . Prosta strona HTML z łączem do stron administracyjnych <html> <head> <title>Proste uwierzytelnianie Apache</title> </head> <body> <a href="admin/index. Wykorzystanie mechanizmu uwierzytelniania dostarczanego przez serwer WWW jest zwykle szybkim i efektywnym sposobem zrealizowania takiego mechanizmu.1. więc kliknięcie tego łącza spowoduje.1. Dyrektywy konfiguracji Apache włączające podstawowe uwierzytelnianie AuthUserFile /www/auth_users AuthName Adminstrative . Korzystanie z pliku . Strony te nie mogą być dostępne dla wszystkich użytkowników. Aby zrealizować takie założenia możesz przenieść wszystkie strony administracyjne do osobnego podkatalogu w drzewie katalogów witryny WWW oraz zmienić konfigurację Apache tak. Strona administracyjna znajduje się w katalogu wymagającym uwierzytelniania.1 zamieszczony jest wydruk prostej strony HTML zawierającej łącze do podkatalogu ze stroną administracyjną.

których możesz użyć w aplikacji w celu odczytania danych autoryzacji. serwer WWW wysyła żądanie 401 do przeglądarki a przeglądarka odpytuje użytkownika i odsyła wprowadzone przez niego dane do serwera. print( "PHP_AUTH_PW: $PHP_AUTH_PW<br>" ).1.3 zawiera stronę wyświetlająca dane autoryzacji. Przeglądarka wysyła wprowadzone dane do serwera podczas żądania sprowadzenia wszystkich kolejnych stron aż do zakończenia pracy przeglądarki. Wydruk 8.AuthType Basic <Limit GET> require valid-user </Limit> Rysunek 8. Możesz skorzystać ze zmiennych $PHP_AUTH_USER oraz $PHP_AUTH_PW do odczytania nazwy użytkownika i hasła.3. Na rysunku 8. pokazana jest zawartość tej strony po przejściu do niej poprzez łącze znajdujące się na stronie z wydruku 8. PHP posiada zmienne globalne. ?> </body> </html> Rysunek 8. Wydruk 8. Ten rodzaj uwierzytelniania wymaga współpracy pomiędzy przeglądarką i serwerem. Okno dialogowe uwierzytelniania w przeglądarce Więcej informacji na temat użycia uwierzytelniania Apache można znaleźć w Sieci oraz we wielu świetnych książkach poświęconych serwerowi Apache.2.2. gdy chcesz chronić wszystkie strony i inne zasoby znajdujące się we fragmencie drzewa Rozdział 8 – Uwierzytelnianie 96 . Jeżeli serwer zaakceptuje uwierzytelnianie. chroniony zasób jest udostępniony użytkownikowi. Mechanizm ten wygląda następująco: gdy użytkownik musi zostać autoryzowany. Jest on szczególnie użyteczny w sytuacjach. Wyświetlanie zawartości zmiennych autoryzacji <html> <head> <title>Strona administratora</title> </head> <body> <h1>Witamy na stronie administratora</h1> <?php print( "PHP_AUTH_USER: $PHP_AUTH_USER<br>" ).1. Zmienne autoryzacji w PHP Schemat autoryzacji Apache zapewnia podstawowy stopień bezpieczeństwa witryny.

if ( !$aHTPasswd->EXISTS ) { print( "Błąd autoryzacji<br>" ). if ( !$aHTPasswd->EXISTS ) { print( "Błąd krytyczny<br>" ). } else { print( "phpbook nie jest prawidłowym użytkownikiem<br>" ). Aktualizacja pliku . Przykład korzysta z tego samego pliku.6 i 8.4 pokazany został przykład.5.Htpasswd. } else { if ( $aHTPasswd->verifyuser( "phpbook".net/) stworzyli dwie klasy służące do zarządzania użytkownikami i grupami plików dla celów podstawowego uwierzytelniana. Można udostępnić to narzędzie zaufanym osobom. usuwania użytkowników. Przy pomocy tej klasy można napisać obszerne narzędzie do administracji użytkownikami. W następnej części zostanie opisane w jaki sposób można wykorzystać PHP do aktualizacji pliku haseł. Wydruk 8./class.htaccess przy użyciu PHP Jeżeli podstawowe uwierzytelnianie serwera WWW jest wystarczające w tworzonej aplikacji./class. $aHTPasswd = new Htpasswd("/www/auth_users"). Jest ona używana do inicjalizacji skryptu i określenia czy strona jest oglądana pierwszy raz. czy została wywołana w wyniku żądania POST. Użycie klasy Htaccess do zarządzania użytkownikami <?php include( ". jak można wykorzystać tę klasę do autoryzacji użytkownika. } } ?> </body> </html> Klasę Htpasswd można również wykorzystać do dodawania nowych użytkowników. exit. } if ( { $REQUEST_METHOD == 'POST' ) switch ( $acttype ) { 97 PHP – Kompendium wiedzy . Wydruk 8.5 zawiera pierwszą część skryptu. Na wydruku 8. który został użyty w poprzednim przykładzie. sprawdzania poprawności użytkownika oraz zmiany jego nazwy.Htpasswd. którzy będą mogli operować użytkownikami bez konieczności udostępniania im bezpośredniego dostępu do serwera. "phpbook" ) ) { print( "phpbook to prawidłowy użytkownik<br>" ). Sprawdzanie poprawności autoryzacji użytkownika za pomocą klasy Htpasswd <html> <head> <title>Szybkie sprawdzenie użytkownika z uzyciem klasy Htpasswd</title> </head> <body> <?php include( ". $aHTPasswd = new Htpasswd("/www/auth_users"). zmiany hasła. Skrypty na wydruku 8. 8.4. Ograniczeniem stosowania tej metody jest konieczność dodawania i usuwania użytkowników poprzez wykonanie odpowiednich poleceń na serwerze.theWebmasters. w jaki sposób można połączyć wszystkie te operacje w jednym formularzu. które będzie pomocne przy zarządzaniu mechanizmem podstawowego uwierzytelniania serwera. które przesyłają dane do samego siebie i są używane zarówno do wyświetlania jak i do zmiany danych. co pozwoli na stworzenie narzędzia WWW do dodawania i usuwania użytkowników. Do manipulacji standardowym plikiem Apache htpasswd można wykorzystać klasę Htpasswd.php3" ).php3" ).katalogów witryny. można przy użyciu PHP stworzyć narzędzie administracyjne upraszczające zarządzanie użytkownikami. Programiści zespołu The Webmasters Net (http://www. przy użyciu bardzo małej ilości kodu.5. Wydruk 8. Skrypt ten jest podobny do wielu przytoczonych do tej pory przykładów.7 zawierają skrypty pokazujące.

rename oraz changepass. $aHTPasswd->deleteUser( $aUserName ).value = aType. $aHTPasswd->changePass( $aUserName. W skrypcie założono. Każdy przycisk na formularzu zawiera atrybut onClick. } //--> </script> </head> Ostatnia część skryptu pokazana na wydruku 8. która realizuje wysłanie danych formularza do odpowiedniej strony. Ustawianie zmiennej $acttype $acttype <html> <head> <title>Prosty program zarządający użytkownikami</title> <script language="JavaScript"> <!-function DoSubmit( aType ) { document. $aHTPasswd->renameUser( $aUserName. W następnej części skryptu ustawiana jest zmienna $acttype.7. Kod PHP jest jedynie używany do wstawiania istniejących użytkowników do listy SELECT. $nIndex++. $ChangePass ). print( "<b>Nazwa użytkownika zmieniona z $aUserName na $RenameName</b><br>" ). break. Dla wszystkich przycisków znajdujących się na formularzu zdefiniowana jest odpowiednia akcja. Strona z formularzem HTML <body> <form action="<?=$PHP_SELF?>" method="post" name="mainform" id="mainform"> <input type="hidden" name="acttype" value="none"> <h1>Prosty program zarządzający użytkownikami</h1> <h2>Dodanie użytkownika</h2> Nazwa nowego użytkownika: <input type="text" name="NewUserName"><br> Hasło: <input type="password" name="NewUserPass"><br> <input type="button" value="Dodaj" onClick="DoSubmit( 'add' ). Do ustawiania ukrytej zmiennej formularza $acttype wykorzystujemy JavaScript. Wydruk 8. Wydruk 8. print( "<b>Zmieniono hasło dla użytkownika $aUserName</b><br>" ). case 'changepass' : $aUserName = $aHTPasswd->USERS[$CurUserRow]["user"]. Zmienna posiada pięć możliwych wartości: none. } ?> Rozdział 8 – Uwierzytelnianie 98 . break. $RenameName ).mainform.mainform.case 'none' : break. break. print( "<b>Dodano użytkownika $NewUserName</b><br>" ). document.acttype. $NewUserPass ). break.6. case 'add' : $aHTPasswd->addUser( $NewUserName.submit(). na podstawie wartości zmiennej formularza podejmowana jest decyzja co do kolejnej akcji.7 jest po prostu stroną HTML zawierającą formularz. case 'rename' : $aUserName = $aHTPasswd->USERS[$CurUserRow]["user"]. W zależności od wyboru użytkownika podejmowana jest odpowiednia akcja. foreach( $aHTPasswd->USERS as $aUser ) { print( "<option value=###BOT_TEXT###quot;$nIndex###BOT_TEXT###quot;>$aUser[user]</option>" ). aby program mógł być normalnie używany niezbędne jest dodanie kodu kontroli poprawności. że wszystkie potrzebne dane są prawidłowo wypełnione. delete. Oczywiście. add. który powoduje wywołanie przedstawionej funkcji JavaScript. } } ?> Jeżeli skrypt ten zostanie wywołany w wyniku żądania POST. case 'delete' : $aUserName = $aHTPasswd->USERS[$CurUserRow]["user"]. print( "<b>Usunięto użytkownika $aUserName</b><br>" )."> <hr> <h2>Zmiana użytkownika</h2> <table> <tr> <td> <select name="CurUserRow" size="10"> <?php $nIndex = 0.

Rysunek 8. pokazana jest strona bezpośrednio o dodaniu użytkownika scott. Jak mówiliśmy wcześniej. W niektórych przypadkach może być wymagane zabezpieczenie tylko niektórych stron aplikacji lub nie jest możliwa modyfikacja odpowiednich plików na serwerze WWW.</select> </td> <td> Usunięcie zaznaczonego użytkownika: <input type="button" value="Usuń" onClick="DoSubmit( 'delete' )."> <br><br> Zmiana nazwy zaznaczonego użytkownika: <input type="text" name="RenameName"><input type="button" value="Zmiana nazwy" onClick="DoSubmit( 'rename' )."><br><br> </td> </tr> </table> </form> </body> </html> Na rysunku 8.3. Program zarządzający użytkownikami w działaniu Podstawowe uwierzytelnianie za pomocą PHP Poprzednie dwie części opisywały podstawowe uwierzytelnianie serwera Apache do ochrony fragmentów witryny WWW (zwykle katalogów). 99 PHP – Kompendium wiedzy . skrypt ten nie jest kompletnym narzędziem zarządzającym użytkownikami. W takim przypadku możesz wykorzystać PHP do wysyłania odpowiednich nagłówków do serwera i w ten sposób bezpośrednio żądać autoryzacji. a jedynie pokazuje sposób wykorzystania klasy Htpasswd. Można również skorzystać z dostarczanej przez The Webmasters Net klasy Htgroup do tworzenia i zarządzania grupami użytkowników.3."><br><br> Zmiana hasła dla zaznaczonego użytkownika: <input type="password" name="ChangePass"><input type="button" value="Zmiana hasła" onClick="DoSubmit( 'changepass' ).

\n". } ?> Skrypt ten na początku pracy sprawdza. Schemat autoryzacji PHPLIB jest uruchamiany podczas wywołania funkcji PHPLIB page_open() i zażądanie „własności” sess. Gdy zostanie zażądana ta własność. więc sposób ten jest zwykle dobrze znany. Header( "HTTP/1. Jeżeli tak. Jeżeli sprawdzenie to się powiedzie. nie ma potrzeby wysyłania do przeglądarki nagłówka autoryzacji. Jedną z zalet takiego podejścia jest możliwość odwołania uwierzytelnienia użytkownika poprzez ponowne wysłanie nagłówka HTTP 401. Poprzednia metoda jest oparta o możliwość obsługi przez przeglądarki wywołań HTTP 401 ale metoda ta posiada wiele ograniczeń. Wydruk 8. który powoduje wyświetlenie okna autoryzacji. która nie polega na wywołaniach HTTP 401 z serwera. Mechanizm uwierzytelniania realizowany przez PHPLIB jest w wielu punktach podobny do mechanizmu obsługi sesji.htaccess do zabezpieczania katalogów. Kompletny system uwierzytelniania oparty o PHP Wykorzystanie metody autoryzacji opisanej w poprzedniej części jest łatwe i proste. } } if( $aDoAuth == True ) { Header( "WWW-Authenticate: Basic realm=###BOT_TEXT###quot;My Realm###BOT_TEXT###quot;" ). Do działania wymaga on sesji PHPLIB. Poniższa implementacja wykorzystuje klasę Auth z PHPLIB. PHPLIB pozwala na stworzenie autoryzacji opartej na uprawnieniach. if ( isset( $PHP_AUTH_USER ) ) { if ( ( $PHP_AUTH_USER == "ryan" ) && ( $PHP_AUTH_PW == "dentist" ) ) { // prawidłowa nazwa użytkownika i hasło $aDoAuth = False. Prawdziwy system uwierzytelniania nie powinien mieć zaszytych nazw użytkowników i haseł w samym skrypcie. albo do przerwania uwierzytelniania przez użytkownika. czy ustawiona jest zmienna $PHP_AUTH_USER. Proces ten jest powtarzany aż do podania właściwych danych autoryzacji. auth_include. Jeżeli nie korzystamy z mechanizmów przeglądarki przy wyświetlaniu okna uwierzytelniania. należy albo wysyłać dane nagłówków przed wysłaniem jakichkolwiek danych strony. więc do każdej strony można przypisać wymagany poziom uprawnień dla każdego z użytkowników. ale przez o wymaga sporo zachodu. Jeżeli porównanie nie uda się skrypt wysyła do przeglądarki nagłówek HTTP 401. Skrypt auth_include. Dodatkowo. wymuszających na przeglądarce wyświetlenie okna uwierzytelniania. musimy sami tworzyć formularz HTML służący do pobierania danych niezbędnych dla naszej aplikacji. to wartości zmiennych $PHP_AUTH_USER i $PHP_AUTH_PW są porównywane z prawidłową nazwą użytkownika i hasłem aplikacji.8 zamieszczony jest prosty skrypt żądający autoryzacji. Głównym powodem użycia tego typu implementacji jest zwiększenie elastyczności aplikacji. Można to wykorzystać do ponownego logowania użytkownika po określonym czasie bezczynności lub do chronienia różnymi hasłami różnych części aplikacji. Następna metoda jest bardziej niezależna od platformy i posiada bardziej elastyczne podejście do uwierzytelniania. Dołączenie tego pliku na początku dowolnego skryptu powoduje konieczność autoryzacji użytkownika skryptu. echo "Nie udało się zalogowanie do systemu. Rozdział 8 – Uwierzytelnianie 100 . Większość programistów WWW wykorzystywało już pliki . exit. Zamiast tego należy wykorzystać bazę danych lub usługę katalogową (na przykład LDAP) lub nawet pliki zawierające dane uwierzytelniania. PHP posiada wystarczająco dużo narzędzi i elastyczności aby można było napisać dowolny system autoryzacji użytkowników.php <?php $aDoAuth = True. Skrypt ten jest w postaci pliku dołączanego. Jednak po jej zaprogramowaniu jest świetnym zamiennikiem metody opisanej w poprzedniej części.8. Na wydruku 8. więc będzie go można łatwo dodawać do wszystkich stron wymagających autoryzacji.0 401 Unauthorized" ). W tej części skupimy się na implementacji. Jest to ekstremalnie solidna i elastyczna implementacja.Tak jak w przypadku wysyłania innych danych nagłówka.inc. zanim można będzie ją wykorzystać. albo korzystać z buforowania wyjścia.

pokazana jest interakcja pomiędzy klientem. var $Password = "root". Tabela użyta do autoryzacji jest zdefiniowana następująco: CREATE TABLE MyAuth ( FirstName varchar(20) SurName varchar(30) password varchar(20) PRIMARY KEY (FirstName. } class MySqlSession extends Session { var $classname = "MySqlSession". ). NOT NULL. których używaliśmy w rozdziale 7). // Obsługa przechowywania var $mode = "cookie".inc" ). class MySQLDB extends DB_Sql { var $Host = "localhost".htinc" ). $SurName. W naszym przypadku dane autoryzacji znajdują się w tabeli bazy danych MySQL. var $User = "root". } class MySQLCt extends CT_Sql { var $classname = "MySQLCt". Rysunek 8. na wydruku 8. Przygotowanie klas używanych przez klasę PHPLIB Auth <?php include( "page./sample_lform. serwerem WWW (i tym razem jest to 1U z Penguin Computing) oraz aplikacją PHP. Następnie PHPLIB wywołuje dostarczoną przez użytkownika funkcję sprawdzającą uprawnienia użytkownika. // wybór kontenera var $allowcache_expire = 0. } class Sample_Auth extends Auth { var $classname = "Sample_Auth". Na rysunku 8. $aDB = new MySQLDB. include( "session.9. var $lifetime = 20. PHPLIB wyświetla stronę a w przeciwnym wypadku następuje ponowne uwierzytelnianie. jakich aplikacja wymaga do prawidłowej autoryzacji użytkownika. include( "db_mysql. // 20 minut (0 == ciągle) function auth_loginform() { include( ". } function auth_validatelogin() { global $FirstName. var $database_table = "active_sessions". var $lifetime = 0. Jeżeli funkcja ta zaakceptuje użytkownika. Jeżeli użytkownik nie podawał wcześniej danych autoryzacji.inc" ). PHPLIB wyświetla zdefiniowaną przez użytkownika stronę.4. NOT NULL. 101 PHP – Kompendium wiedzy .4.inc" ). $aSQL = "select * from MyAuth where ( FirstName = ". Po pierwsze. // użycie cookie sesji var $that_class = "MySQLCt". include( "ct_sql.PHPLIB sprawdza zalogowanie użytkownika. var $database_class = "MySQLDB". SurName) Wydruk 8.9 pokazane są klasy zdefiniowane przez użytkownika niezbędne do stworzenia klasy Auth i klas ją wspomagających (Klasy sesji i bazy danych są identyczne jak te.inc" ).= "'$FirstName' ) and ( SurName = '$SurName' )". $Password. $aSQL . var $Database = "mydb".inc" ). Interakcja w schemacie autoryzacji PHPLIB Z powodu elastyczności jaką zapewnia PHPLIB wymagane jest wykonanie kilku niezbędnych kroków zanim użyjemy naszej klasy autoryzacji. include( "auth. NOT NULL. Strona ta pobiera dowolne dane.

Wydruk 8.htinc) <?php global $FirstName. spróbuj jeszcze raz. ale zwykle dołączenie pliku jest łatwiejsze. if ( !empty( $FirstName ) ) { $aCurFirstName = $FirstName.10. Zdefiniowane są odpowiednie funkcje auth_loginform() i auth_validatelogin(). $aCurSurName = "". $aDB->query( $aSQL ). } } } ?> Klasa Sample_Auth dziedzicząca po klasie bazowej Auth zapewnia działanie specyficzne dla bieżącej aplikacji. } if ( !empty( $SurName ) ) { $aCurSurName = $SurName. } else { return False.= "and ( Password = '$Password' )". } ?> <html> <head> <title>Formularz autoryzacji dla PHPLIB</title> </head> <body> <form action="<?=$this->url()?>" method="post"> <table> <tr> <td> Imię: </td> <td> <input type="text" name="FirstName" value="<?=$aCurFirstName?>"> </td> </tr> <tr> <td> Nazwisko: </td> <td> <input type="text" name="SurName" value="<?=$aCurSurName?>"> </td> </tr> <tr> <td> Hasło: </td> <td> <input type="password" name="Password"> </td> </tr> <tr> <td colspan="2"> <input type="submit" name="Submit" value="Log In"> </td> </tr> <?php if ( !empty( $FirstName ) ) { ?> <tr> <td colspan="2"> <br><br> Podane dane są nieprawidłowe. Na wydruku 8. Funkcja auth_loginform() jest wywoływana. global $SurName. gdy klasa Auth wymaga uwierzytelnienia użytkownika. Możesz użyć instrukcji print() do stworzenia formularza HTML potrzebnego do zalogowania. if ( $aDB->num_rows() > 0 ) { return $FirstName.. Przykładowy formularz logowania (sample_lform.10 pokazany jest plik użyty w tym przykładzie.$aSQL . $aCurFirstName = "". </td> </tr> <?php } ?> </table> Rozdział 8 – Uwierzytelnianie 102 .

/auth_phplib.phtml">Strona trzecia</a></li> <li><a href="test_auth_phplib_logout. Funkcja url() zwraca stronę. Na wydruku 8.11 pokazujemy funkcję użytą w naszym przykładzie. Jeżeli odnaleziony zostanie rekord w tabeli opisujący bieżącego użytkownika. zwracana jest wartość False. nazwiska i hasła użytkownika. header ("Pragma: no-cache"). header ("Expires: Mon.phtml">Wylogowanie</a></li> 103 PHP – Kompendium wiedzy . header ("Last-Modified: " . SurName i Password. gdy wyświetlamy formularz po nieudanej autoryzacji użytkownika W tym przypadku klasa Auth ponownie wyświetla formularz logowania. $aSQL .phtml">Strona druga</a></li> <li><a href="test_auth_phplib3. if ( $aDB->num_rows() > 0 ) { return $FirstName. Następnie strona wyświetla trzy pola tekstowe do wprowadzenia imienia. } } Funkcja odwołuje się do zmiennych globalnych $FirstName.phtml">Strona główna</a></li> <li><a href="test_auth_phplib2. W kontekście tej strony zmienna $this wskazuje na bieżący obiekt klasy pochodnej po Auth. czy zmiene formularza mają jakieś wartości.php" ). Funkcja auth_validatelogin() function auth_validatelogin() { global $FirstName. Wartości zmiennych formularza są przenoszone do pól formularza FirstName i SurName jedynie z grzeczności (ale użytkownik nie musi ponownie wpisywać tych danych).= "and ( Password = '$Password' )". $SurName.net) include( ". Gdy dane formularza zostaną przesłane do oryginalnej strony. Auth sprawdza ponownie dane autoryzacji. " GMT"). 26 Jul 1997 05:00:00 GMT"). Ich wartości są wyszukiwane w tabeli MySQL zawierającej trzy kolumny: FirstName. } else { return False. Dane formularza są wysyłane do strony określonej przez $this->url(). wymagających autoryzacji. $Password. Na początku sprawdza. ?> <html> <head> <title>Przykład użycia klasy PHPLIB Auth</title> <META HTTP-EQUIV="Expires" CONTENT="-1"> <META HTTP-EQUIV="Pragma" CONTENT="no-cache"> </head> <body> <h2>Strona główna</h2> Posiadasz uprawnienia do oglądania tej strony! <ul> <li><a href="test_auth_phplib. header ("Cache-Control: no-cache").</form> </body> </html> Strona ta jest zaprojektowana jedynie do wyświetlania przez klasę Auth. Ostatnia strona z listy zapewnia wylogowanie użytkownika. Na koniec definiujemy ostrzeżenie jakie zobaczy użytkownik gdy poda niewłaściwe dane. Wydruk 8. funkcja auth_validatelogin() zwraca imię użytkownika (oczywiście użycie imienia jako identyfikatora użytkownika nie było by zbyt dobrym pomysłem). "auth" => "Sample_Auth" ) ). page_open( array( "sess" => "MySqlSession".= "'$FirstName' ) and ( SurName = '$SurName' )". $SurName i $Password.11. $aDB = new MySQLDB. $aSQL . na której był użytkownik zanim obiekt klasy interweniował i wywołał naszą stronę autoryzacji. Jeżeli nie ma pasującego rekordu. Aby to zrobić wywołuje ona zdefiniowaną przez użytkownika funkcję auth_validatelogin().12. Może to się zdarzyć. W przykładzie wyświetlane są cztery łącza do innych podobnych stron.12 pokazana została typowa strona WWW wykorzystująca o autoryzacji klasę Auth. $aDB->query( $aSQL ). Prosta strona wykorzystująca klasę Auth <?php // bez buforowania (z witryny php. Na wydruku 8. $aSQL = "select * from MyAuth where ( FirstName = ". Wydruk 8. zdefiniowanych w formularzu logowania. gmdate("D. d M Y H:i:s") .

więc podjęto szczególne środki zapewniające prawidłowe działanie przykładów. ?> Pierwsza strona dołącza prosty plik uwierzytelniania a następnie wywołuje funkcję PHPLIB page_open(). że przeglądarka nie będzie przechowywała strony w buforze. która uaktywnia sesję i mechanizm uwierzytelniania. zawiera na dole strony następujący kod wymuszający wylogowanie użytkownika: <?php $auth->logout(). w zależności od wymagań aplikacji.5. PHPLIB jest niezwykle elastycznym narzędziem. Inne mogą nie zapewniać dostatecznego poziomu bezpieczeństwa. a wymusza ona ponowne wywołanie autoryzacji użytkownika na następnej stronie. Można stworzyć skomplikowane lub proste schematy uwierzytelniania. Pierwsze kilka omówionych metod jest mocno zależne od platformy. Druga i trzecia strona jest funkcjonalnie identyczna z pierwszą. Rozdział 8 – Uwierzytelnianie 104 . ale są łatwe do implementacji. Na końcu strony wywoływana jest funkcja page_close(). szczególnie dla początkujących użytkowników. Jeżeli aplikacja wymaga jakiegoś typu uwierzytelniania użytkowników. Niektóre mechanizmy uwierzytelniania nie posiadają wystarczającej elastyczności. Przy pomocy tego rozdziału można skojarzyć twój potrzeby z oferowanymi przez poszczególne metody możliwościami. Szczególne kłopoty sprawia Microsoft Internet Explorer. Zmienne uwierzytelniania są przesyłane pomiędzy stronami przy pomocy mechanizmu sesji. pozwalającym na stworzenie własnego mechanizmu uwierzytelniania. Ostatnia metoda. Jak wcześniej wspomnieliśmy. Zaletą tego podejścia jest możliwość tworzenia własnych formularzy logowania. oraz możliwość łatwego wylogowania użytkownika. ale o wiele bardziej elastyczna i całkowicie przenośna pomiędzy serwerami WWW i systemami operacyjnymi. porównywanie wpisanych danych z danymi przechowywanymi na dowolnym nośniku informacji. Umieszczenie w aplikacji systemu zabezpieczeń wydaje się bardziej efektywne. Podczas testowania tego przykładu nie stwierdziliśmy żadnych problemów w IE 5. którzy nie będą wiedzieli.</ul> </body> </html> <?php page_close(). którzy mogą być zaskoczeni systemowymi oknami dialogowymi. WebTV i Opera. Strona Wylogowanie. Kod ten jest dosyć ważny. ?> Funkcja $auth->logout() może być wywołana w dowolnym momencie. page_close(). czy są już zalogowani. która zapisuje dane sesji. wszystkich wersjach Netscape. powinieneś w fazie projektowania określić specyficzne wymagania tej aplikacji. ponieważ buforowane strony mogą mylić użytkowników. wymagająca użycia klas PHPLIB jest bardziej złożona. Wywołania funkcji header() oraz znaczniki <META> zapewniają. Podsumowanie W tym rozdziale zostało omówionych wiele aspektów uwierzytelniania użytkowników w aplikacjach PHP. Kilka wierszy w tym przykładzie nie jest związane z mechanizmem uwierzytelniania.

Metoda ta sprawdza się w niektórych przypadkach. Wydruk 9.Rozdział 9. Jeżeli wystarczy ci proste rozpoznanie typu przeglądarki. Na przykład. Wyświetlanie podstawowych danych na temat przeglądarki <html> <head> <title>Szybkie sprawdzenie typu przeglądarki</title> </head> <body> <?php $aPos = strpos( $HTTP_USER_AGENT. Na przykład. W rozdziale tym przedstawimy przykłady wielu metod. } else { print( "Przeglądarka MS Internet Explorer!<br>" ). Kilka przeglądarek zmieniło format tego ciągu podczas jednej ze zmiany wersji.40. zawsze istnieją różnice. W czasie pisania aplikacji dla WWW. z których będziesz mógł wybrać odpowiednią dla twojej aplikacji.1. jeżeli potrzebujesz dokładnej informacji o przeglądarce. czy przeglądarka klienta to Internet Explorer. ale jest zbyt prosta. należy tak napisać aplikację. Tworzenie aplikacji niezależnej od przeglądarki wymaga możliwości wykrywania typu przeglądarka i wykorzystywania jej możliwości. } ?> </body> </html> W przykładzie tym sprawdzamy. który używa aplikacji. która jest zoptymalizowana do wyświetlania stron w określonej przeglądarce. rozpoczynając od stworzenia własnego rozwiązania do użycia narzędzi firm trzecich. można wykorzystać bezpośrednio zmienną $HTTP_USER_AGENT. PHP pozwala na odczytanie typu przeglądarki poprzez zmienną globalną $HTTP_USER_AGENT. Rozpoczynamy Na najbardziej podstawowym poziomie. if ( $aPos === False ) { print( "To <b>nie</b> jest MS Internet Explorer!<br>" ). Przykład opiera się na tym. Można wykorzystać tę informację do wyświetlenia odpowiedniego komunikatu. Nie przewiduje się niespodziewanych zmian tego interfejsu w czasie działania programu w zależności od użytkownika. "MSIE" ) . że zwracana nazwa przeglądarki w większości wersji Internet Explorera zawiera fragment MSIE.1. Jeżeli aplikacja wymaga jakiejś własności przeglądarki. aby obsługiwać ogromną ilość prawidłowych ciągów user agent. Mimo. więc rozpoznanie określonej przeglądarki może być problematyczne. lub przekierować użytkownika do innej części witryny. Niezależność od przeglądarki Wstęp Podczas pisania standardowych aplikacji interfejs użytkownika jest tworzony dla potrzeb aplikacji i zwykle jest on przeznaczony dla jednej platformy. niektóre wersje Internet Explorera zawierały następujące ciągi user agent: • Microsoft Internet Explorer/4. aby sprawdzała typ użytej przeglądarki i odpowiednio reagowała. że większość nowoczesnych przeglądarek będzie wyświetlało aplikacje w podobny sposób. Ciąg ten jest wysyłany przez przeglądarkę do serwera wraz z każdym żądaniem. sposób wykrycia przeglądarki Internet Explorer przy użyciu porównywania ciągów zamieszczony jest na wydruku 9. interfejs użytkownika nie jest już tak niezmienny.305beta (Windows 95)[en] . PHP pozwala na kilka metod wykrywania rodzaju przeglądarki. ponieważ może być on odtwarzany przez różne typy przeglądarek na różnych platformach.

0. $aNewLine ).com/browscap odszukać nadrzędnej sekcji.0 z poprawką 2. Każda z sekcji odwołuje się do sekcji wyższego dostępny bez rzędu. Bez dodatkowego znaku końca linii dostępny z wielu w trakcie uruchamiania PHP generowany jest błąd składni. Następnie.ini" ). $aNewFile = fopen( ". wersji.ini. Tym sposobem w sekcji opisującej żadnych opłat z nową przeglądarkę zdefiniowane są tylko nowe możliwości a istniejące wcześniej znajdują witryny cię w opisie starszej przeglądarki. że plik browser. Z powodu ogromnej ilości kombinacji przeglądarek i platform.ini zawierał ponad 2100 różnych przeglądarek. ponieważ nie wszystkie nazwy zapisane są małymi literami. browscap i zmień ?> na pełną Skutkiem ubocznym takiej zmiany jest to./browscap.php. Następna część omawia rozwiązanie tego problemu w oparciu o PHP. Na wydruku 9.0 (compatible. platform i języków.ini". że dokładne rozpoznanie choć jednego przeglądarki staje się problematyczne./browscap. Aby użyć funkcji get_browser() należy ściągnąć z W czasie pisania książki podejmowane były dodatkowe ulepszenia do istniejącej w sieci plik PHP funkcji get_browser(). czy przeglądarka obsługuje określone możliwości. { $aNewFile = strtolower( $aLine ). Problem wynika z tego. Zamiast tego lepiej wiedzieć. że wszystkie wywołania funkcji ją ścieżkę do pliku get_browser() muszą zawierać wywołanie funkcji strtolower(). który jest Pierwszą z nich jest dodanie pustej linii na końcu pliku.net/. więc zdefiniowana jest pewnego rodzaju struktura. Konwersja ta powoduje.0)[en] Różnice w zawartości tego ciągu powodują. o wiele bardziej skomplikowany problem jest związany z samą struktura W czasie pisania pliku. plik browscap. witryn w Sieci. MSIE 3.0 (compatible. Update a. Windows 95)[en] Mozilla/4. jak się tego spodziewamy.0.ini dostępny z firmy cyScape browscap.02.2 pokazany jest przykład użycia funkcji get_browser(). Jednak po wprowadzeniu browscap. że PHP nie potrafi pe. przy użyciu metody udokumentowanej w http://www.ini. Istnieje tak wiele kombinacji przeglądarek. Odkryłem. Po takich zmian funkcja get_browser() działa tak. Typowo. Wykorzystanie funkcji get_browser() wraz z plikiem browscap. W czasie pisania książki plik browscap. należy zmienić foreach( $aArray as $aLine ) plik php. W rzeczywistości znajomość jedynie typu przeglądarki nie jest tak ważne. MSIE 5. że sprawdzanie ich zawartości staje się nieporęczne. Na szczęście PHP zawiera kilka metod dokładniejszego rozpoznania serwera za pomocą funkcji get_browser(). Aby . Po jego rozwiązać ten problem wykonałem prosty skrypt konwertujący wszystkie linie pliku ściągnięciu i browscap.cysca konwertuje jego zawartość na małe litery. że w czasie odczytu pliku PHP http://www. trudno jest stworzyć ogólne rozwiązanie tego problemu. "w" ). Te informacje nie są zawarte w ciągu informacji o przeglądarce. Windows NT 5. konfiguracji } fclose ($aNewFile ). Tak jak opisane zostało we wskazówce „Dodatkowe informacje na temat Browscap” pierwszym krokiem powinno być przekonwertowanie zawartości $HTTP_USER_AGENT na małe litery. ponownym uruchomieniu serwera WWW będzie można korzystać z danych zawartych w pliku.ini jest zwykłym plikiem konfiguracyjnym w którym każda książki plik był sekcja reprezentuje określoną przeglądarkę.ini na małe litery: zainstalowaniu w <?php serwerze WWW. Drugim. na przykład JavaScript lub ramki.ini upraszcza proces rozpoznawania możliwości przeglądarki i rozszerza jego zakres. Odszukaj opcję fputs( $aNewFile. $aArray = file( ". ciąg identyfikacyjny przeglądarki jest zmieniany do właściwej Rozdział 9 – Niezależność od przeglądarki 106 Dodatkowe informacje na temat Browscap . (wspomnianej już wcześniej) wymaga kilku zmian aby działał z PHP 4. AOL 3.Mozilla/2.ini. • • Wewnętrzne funkcje PHP Rozpoznawanie typu serwera ma zwykle służyć do poznania możliwości przeglądarki.

używana jest funkcja eregi_replace(). } ?> </body> </html> Na rysunku 9. $aUserAgent = strtolower( $HTTP_USER_AGENT ).ini.= '*'. '*' ) === False ) { $aUserAgent .2. $aUserAgent ). if ( strpos( $aUserAgent. $array = (array) get_browser( $aUserAgent ). } ?> <html> <head> <title>Możliwości przeglądarki</title> </head> <body> <h1>Możliwości przeglądarki</h1> <?php $aUserAgent = GetMassagedUA(). echo ("<b>$key=</b> $aValue<br>"). $aUserAgent = eregi_replace( "\[[a-z]{2. Do zamiany określenia języka (na przykład [en]) na gwiazdkę. 107 PHP – Kompendium wiedzy . "*". } } else { print( "<i>brak danych przeglądarki</i><br>" ).postaci przed wywołaniem funkcji get_browser(). Wydruk 9. print( "<h2>$aUserAgent</h2>" ). która występuje w pliku browscap. Użycie funkcji get_browser() <?php function GetMassagedUA() { global $HTTP_USER_AGENT. $value ) = each ($array) ) { $aValue = stripslashes( $value ). } return $aUserAgent. w przeglądarce Netscape 4.2.7.}\]". if ( count( $array ) > 1 ) { while ( list( $key.

}\]". czy przeglądarka obsługuje ramki. Można również sprawdzić kolejno każdą z możliwości korzystając bezpośrednio z obiektu i używając zapisu $obiekt->możliwość. '*' ) === False ) { $aUserAgent . Wydruk 9. W kodzie zamieszczonym na wydruku 9. if ( $aBrowsCap->frames == 1 ) { print( "Przeglądarka obsługuje ramki<br>" ).3. wszystkie możliwości są wyświetlane poprzez rzutowanie zwracanego obiektu na tablicę i przeglądanie kolejnych par klucz-wartość. $aUserAgent = strtolower( $HTTP_USER_AGENT ). Wynik działania skryptu z wydruku 9.Rysunek 9. $aUserAgent = eregi_replace( "\[[a-z]{2. if ( strpos( $aUserAgent.= '*'. print( "<h2>$aUserAgent</h2>" ).2.7 Lista dostępnych możliwości pokazuje potęgę funkcji get_browser(). } else { print( "Przeglądarka nie obsługuje ramek<br>" ). Na wydruku 9.1 wykonywanego w przeglądarce Netscape 4. } ?> <html> <head> <title>Obsługa ramek?</title> </head> <body> <?php $aUserAgent = GetMassagedUA(). Użycie get_browser() do sprawdzenia obsługi ramek <?php function GetMassagedUA() { global $HTTP_USER_AGENT. $aBrowsCap = get_browser( $aUserAgent ). "*".2. Rozdział 9 – Niezależność od przeglądarki 108 . $aUserAgent ).3 pokazujemy przykład sprawdzenia. } return $aUserAgent.

path=/usr/share/kaffe/Klasses. Poniżej znajduje się przykład: java. Obsługa języka Java jest dostępna w PHP4.http.. użycie pliku browscap. należy skonfigurować PHP.5 i Opera 4. pokazana jest ta część informacji. Na przykład nasz plik browscap. dostępny z firmy cyScape jest świetnym narzędziem do wykrywania możliwości serwera. Dodatkowo komponent BrowserHawk wymaga kilku dodatkowych modułów. lub inny kod Java na serwerze.jar:/home/blake/java/servlet.HttpServlet. Jest on dostępny w formie obiektu COM. Po ściągnięciu i zainstalowaniu wymaganych klas Javy.0.servlet.class. . aby podążać za zmianami w najnowszych dostępnych przeglądarkach.com/SAX/.} ?> </body> </html> Funkcja get_browser() dostarcza dużo informacji i jest dobra na początek.jar:/home/blake/bhawk: Zapis taki wskazuje. dostępnego w Internecie. ale nie jest domyślnie włączona./sax2. lub jako Java bean dla innych platform.02. aby mógł skorzystać z BrowserHawk. Wywołanie funkcji phpinfo() powoduje wyświetlenie dużej ilości danych w postaci tabel HTML. Jednym z nich jest Simple API for XML (SAX) dostępny pod adresem http://www. w następnej części opisane zostanie narzędzie jednej z firm.3./bhawk4j. że klasy wymagane przez BrowserHawk są dostępne dla PHP w katalogach .jar i . Rysunek 9.jar. aby plik browscap. Jeżeli twoja aplikacja wymaga dokładnego wykrywania możliwości bieżącej przeglądarki. Jak wspomniałem wcześniej. która określa położenie plików licencyjnych i danych pakietu BrowserHawk. Pewność działania funkcji wymaga. gdy aplikacja wymaga rozpoznania typu przeglądarki w czasie pracy. również niesie ze sobą kłopoty. Ścieżka ta powinna wskazywać na katalog. które świetnie spełnia swoje zadanie.ini był często uaktualniany..class. Problem tkwi w tym. w tym w najnowszych JVM pochodzących od różnych dostawców.jar:/homeblake/php4.megginson./servlet. Niezbędne jest również zainstalowanie maszyny wirtualnej Java (JVM) na serwerze. Po ustawieniu wszystkich tych elementów konfiguracji i przekompilowaniu PHP z obsługą Javy. która wskazuje na dostępność Javy.3.path w pliku php. Wiele dystrybucji Linuksa zawiera JVM i w wielu przypadkach pakiet ten jest instalowany automatycznie. Wymagane moduły servletów można znaleźć we wielu miejscach. w którym został zainstalowany BrowserHawk..1pl2/ext/java/php_java. Na wydruku 9. Wynik działania funkcji phpinfo() pokazujący dostępność Javy 109 PHP – Kompendium wiedzy .ini nie pozwalał na prawidłowe rozpoznanie przeglądarek Internet Explorer 5. jeżeli wykorzystujesz serwer z Windows. Aby wykorzystać Java bean.jar:/home/blake/java/sax2. że uaktualnienie i rozesłanie pliku browscap. BrowserHawk Komponent BrowserHawk®.jar:/home/blake/bhawk/ lib/bhawk4j.ini. PHP musi być przekompilowane z opcją konfiguracji -with-java. Taj jak w przypadku każdej innej klasy Java należy podać położenie pliku z klasami Javy korzystając ze zmiennej java. Potrzebny będzie na przykład dostęp do klasy javax.ini wymaga sporo czasu. Jednak posiada ona kilka znaczących ograniczeń.jar.ini. Wpisana jest tutaj również ścieżka bez określenia pliku (/home/blake/bhawk). należy sprawdzić konfigurację za pomocą funkcji phpinfo().

Boolean getBeta() Sprawdza. Przykład wykorzystania BrowserHawk <html> <head> <title>Przykład wykorzystania BrowserHawk</title> </head> <body> <h1>Przykład wykorzystania BrowserHawk</h1> <?php print( "<h2>$HTTP_USER_AGENT</h2>" ). W tabeli 9. Boolean getCookies() Sprawdza. czy przeglądarka obsługuje kontrolki ActiveX. czy przeglądarka potrafi odgrywać dźwięk w tle. na przykład Netscape lub IE (Internet Explorer). double getAOLVersion() Zwraca numer wersji przeglądarki AOL. czy przeglądarka obsługuje Rozdział 9 – Niezależność od przeglądarki 110 .String getBrowser() Zwraca ogólną nazwę przeglądarki. } else { print( "Przeglądarka nie obsługuje kontrolek ActiveX<br>" ).cyscape. czy użytkownik witryny korzysta z przeglądarki firmowanej przez America Online (AOL) (na sieci AOL). java. czy przeglądarka jest w wersji beta. Boolean getDHML() Sprawdza. czy przeglądarka jest szperaczem sieciowym lub innym programem wykorzystywanym do indeksowania zawartości witryny.Po skonfigurowaniu obsługi Javy i BrowserHawk w PHP.String getFileUpload() Sprawdza. Na wydruku 9. Typ Metoda Zastosowanie Boolean getActiveXControls() Sprawdza. zamieszczone są metody odczytujące informacje na temat możliwości przeglądarki dostępne w BrowserHawk. czy przeglądarka obsługuje skrypty DHTML(). czy przegladarka obsługuje Channel Definition Format (CDF) używany do prenumerowania zawartości WWW z możliwością automatycznej aktualizacji. int getAuthenticodeUpdate() Zwraca numer wersji Authenticode obsługiwanego przez przeglądarkę.browserhawk. Boolean getCDF() Sprawdza. Wydruk 9. wykorzystanie komponentów BrowserHawk jest łatwe. czy przeglądarka przyjmuje dane w skompresowanym formacie GZip. java. $aBrowserInfo = $aBrowserHawk->getBrowserInfo( "$HTTP_USER_AGENT" ). który pokazuje w jaki sposób stworzyć obiekt BrowserHawk i wykorzystać go do odczytania kilku podstawowych danych o przeglądarce. Boolean getBackgroundSounds() Sprawdza. } ?> </body> </html> Na wydruku 9.4 pokazujemy w jaki sposób można sprawdzić obsługę ActiveX i tak samo łatwo można sprawdzić każdą z właściwości BrowserHawk.1. czy przeglądarka obsługuje cookie. Boolean getAOL() Sprawdza. // Czy przeglądarka obsługuje ActiveX? if ( $aBrowserInfo->getActiveXControls() == True ) { print( "Przeglądarka obsługuje kontrolki ActiveX<br>" ). $aBrowserHawk = new Java( "com.4. Boolean getCompressGZip() Sprawdza.lang.4 znajduje się kod. Boolean getCrawler() Sprawdza.lang.BrowserHawk" ).

lang. Dostępny jedynie w przypadku PHP – Kompendium wiedzy 111 .String Boolean Boolean java. Zwraca True. czy przeglądarka potrafi wyświetlać różne wielkości tekstu.Boolean Boolean Boolean java. Zwraca True. czy przeglądarka obsługuje protokół SSL (Secure Socket Layer). Sprawdza. Zwraca bardziej ogólne dane (w porównaniu do getOSDetails()) na temat platformy użytkownika. o ile występuje. Zwraca literę niższej części numeru przeglądarki.String getFontColor() getFontSize() getFrames() getFullversion() Boolean Boolean java. czy użytkownik jest połączony poprzez aktywne połączenie SSL. Sprawdza. Sprawdza. Zwraca niższą część numeru wersji przeglądarki. Sprawdza. Sprawdza. Zwraca kompletną wersje przeglądarki zawierającą wyższą i niższą część numeru oraz litery.lang. Zwraca numer wersji JavaScript obsługiwanego przez przeglądarkę. czy przeglądarka potrafi wyświetlać kolorowy tekst. Sprawdza. Zwraca wybrany przez użytkownika język. czy użytkownik korzysta z sieci Microsoft Network (MSN). Zwraca szczegóły na temat systemu operacyjnego (OS) systemu użytkownika.lang. Sprawdza. Zwraca wyższą część numeru wersji przeglądarki.String Boolean Boolean double java. czy przeglądarka obsługuje ramki. Zwraca zestaw szyfrowania SSL dla bieżącej sesji. jeżeli obsługuje HDML (poprzednik WAP). mouseover.lang.String int double java. czy jest to wersja Gold przeglądarki Netscape Navigator. Sprawdza.lang. czy przeglądarka obsługuje applety Java. czy przeglądarka obsługuje efekt JavaScript. jeżeli przeglądarką jest urządzeniem PDA na przykład PalmPilot. czy przeglądarka obsługuje JavaScript.String Boolean java. czy użytkownik jest połączony poprzez serwer Proxy. Sprawdza.lang.String getGold() getHDML() getIPAddr() getJavaApplets() getJavaScript() getJavaScriptVer() getLanguage() getMajorver() getMinorver() getMinorverlet() getMouseOver() getMSN() getOSDetails() getPDA() getPlatform() Boolean getPNG() Boolean Boolean Boolean java. Sprawdza. o ile występują.lang.String getProxy() getSSL() getSSLActive() getSSLCipherSuite() możliwość przesyłania plików do serwera (przeglądarki zgodne z RFC 1867). Sprawdza. Sprawdza. Zwraca adres IP klienta. czy przeglądarka obsługuje format rysunków PNG (Potrable Network Graphics).

Boolean getWAP() Zwraca True dla urządzeń obsługujących WML i WAP (Wireles Application Protocol). że jest on zaprojektowany dla użytkowników JSP. BrowserHawk zapewnia najlepsze rozpoznawanie przeglądarki.String getWAPSubscriberID() Automatycznie ustawiany na identyfikator abonenta dla użytkownika WAP. Boolean getWin16() Sprawdza. Aplikacja będzie nadal działała prawidłowo.aktywnej sesji SSL. o ile jest znany. czy przeglądarka obsługuje bezpośrednie wyświetlanie plików XML. czy przeglądarka obsługuje wyświetlanie tabel. na przykład telefony komórkowe z WAP. Boolean getTables() Sprawdza. jak na przykład Windows 3. Jeżeli aplikacja opiera się na dostarczaniu danych specyficznych dla przeglądarki lub polega na bardzo specyficznych własnościach przeglądarki.lang. Boolean getXML() Sprawdza. jaką może obsłużyć urządzenie. Boolean getVBScript() Sprawdza.Link. int getSSLKeySize() Rozdział 9 – Niezależność od przeglądarki 112 . java. aby sprawdzał o wiele więcej własności przeglądarki. który jest umieszczony w ciągu identyfikacyjnym przeglądarki. Boolean getTableBGImage() Sprawdza. niż można to zrobić korzystając z browscap. czy przeglądarka pracuje w 16 bitowym systemie operacyjnym Windows. java. Przewagą użycia komponentu BrowserHawk nad innymi metodami opisanymi w tym rozdziale jest jego dokładność i elastyczność. W dokumentacji znajduje się informacja. czy przeglądarka obsługuje ustawianie kolorów dla poszczególnych komórek tabeli HTML. że rozpoznaje on około 9 razy więcej przeglądarek.lang. Niektóre zaawansowane funkcje raportujące nie mogą być wykorzystane. niezależnie od ciągłych zmian w technologiach przeglądarek. Mimo to. Boolean getStyleSheets() Sprawdza. więc niektóre metody mogą nie być bezpośrednio dostępne poprzez PHP.String getWAPDeviceModel() Zwraca model urządzenia WAP. Sprawdza wielkość klucza SSL obsługiwaną przez przeglądarkę. Jedyną wadą przy używaniu komponentu BrowserHawk jest to. Dostępne jedynie w przypadku aktywnego połączenia SSL. int getWAPMaxDeckSize() Zawiera przybliżoną maksymalna ilość bajtów. double getVersion() Zwraca wersję przeglądarki.lang. ponieważ opierają się na obiektach specyficznych dla JSP.String getWAPGateway() Zwraca szczegóły bramy UP. o ile jest wykorzystywana.1. Boolean getTableBGColor() Sprawdza. int getVersionpos() Zwraca pozycję w numerze wersji przeglądarki. czy przeglądarka obsługuje ustawianie rysunków tła dla poszczególnych komórek tabeli HTML. BrowserHawk uaktualnia swoją bazę danych w razie potrzeby. standardowe obiekty zwracają wystarczająco dużo danych dla większości zastosowań i są stale aktualne dla najnowszych przeglądarek. niż jest to stosowane w innych metodach. czy przeglądarka obsługuje kaskadowe arkusze stylu (CSS). czy przeglądarka obsługuje VBScript. BrowserHawk jest również zaprojektowany. java.

Eleganckie zakończenie aplikacji w przypadku braku obsługi przesyłania plików <?php $aBrowserHawk = new Java( "com. Dodatkowo. takie jak animowane podpowiedzi. że operacja się nie udała.browserhawk. Warunkowe dostarczanie treści w zależności od możliwości przeglądarki <?php $aBrowserHawk = new Java( "com. Jeżeli aplikacja może działać pomimo tego. Na wydruku 9.Wykorzystanie danych o przeglądarce Pierwszym zadaniem podczas tworzenia aplikacji niezależnej od przeglądarki jest rozpoznanie możliwości przeglądarki użytkownika.<br><br> proszę przesłać pliki pocztą na adres files@my.png". gdy nie można skorzystać z którejś z wymaganych własności. Należy po prostu zapewnić możliwie największą dostępną ilość funkcji. Większość ludzi nie chce widzieć komunikatów typu „Twoja przeglądarka nie obsługuje RFC 1867”. Jeżeli przeglądarka nie obsługuje tej funkcji. $aBrowserInfo = $aBrowserHawk->getBrowserInfo( "$HTTP_USER_AGENT" ). O wiele ważniejszym krokiem jest zadecydowanie w jaki sposób zostaną wykorzystane te dane. Wydruk 9. aby użytkownicy mogli zrozumieć dlaczego wykonanie operacji się nie powiodło. Niektóre możliwości przeglądarki i własności aplikacji. } else { $aImage = "Logo. Na wydruku 9.BrowserHawk" ).5. można spróbować warunkowo dostarczać niektórych elementów w zależności od zdolności przeglądarki do ich wyświetlania. W rzeczywistości mechanizm taki jest niezbędny.cyscape. <?php } ?> </form> </body> </html> Jeżeli przeglądarka posiada obsługę wysyłania plików.com.5. zamieszczony został przykład w jaki sposób można zrealizować elegancką obsługę braku wymaganej własności przeglądarki. ?> <html> <head> <title>Wysyłanie pliku</title> </head> <body> <h1>Wysyłanie pliku</h1> <form action="someurl.6 pokazano przykład takiego działania. Wybierając taki mechanizm należy zwrócić uwagę. aby użytkownicy aplikacji uważali ją za przyjazną. wyświetlany jest napis informujący użytkownika o możliwości przesłania pliku za pomocą poczty elektronicznej. nie wyświetlaj ponownie tego komunikatu.browserhawk. } ?> <html> <head> <title>Nasze logo</title> </head> <body> <h1>Nasze logo</h1> 113 PHP – Kompendium wiedzy .gif". Projekt aplikacji powinien zawierać listę wymaganych własności przeglądarki i zapewniać elegancką obsługę sytuacji.phtml" method="post" enctype="multipart/form-data"> <?php if ( $aBrowserInfo->getFileUpload() == True ) { ?> <input type="file" name="File"><br><br> <input type="submit" name="Submit" value="Wyślij"> <?php } else { ?> Przeglądarka nie obsługuje wysyłania plików. $aBrowserInfo = $aBrowserHawk->getBrowserInfo( "$HTTP_USER_AGENT" ). skrypt ten wyświetla formularz wysyłania pliku. Wydruk 9.cyscape. na przykład zdolność przeglądarki do nawiązania połączenia szyfrowanego SSL lub obsługa wysyłania plików.domain. zależy ona od wymagań stawianych aplikacji. Brak innych własności może całkowicie zatrzymać aplikację.6. if ( $aBrowserInfo->getPNG() == True ) { $aImage = "Logo. Tak jak w przypadku innych decyzji podejmowanych w czasie projektowania.BrowserHawk" ). lub obsługa kaskadowych arkuszy stylów nie są krytyczne.

Poniższy kod jest prostym przykładem sposobu implementacji takiego przypadku.BrowserHawk" ). Należy unikać sytuacji.com/webtv/\n" ). } else { // To nie jest przeglądarka WebTV. gdy funkcja jest niedostępna. że jest to główna strona witryny. przekierowanie do standardowych stron header( "Location: http://mysite. że jeżeli użytkownik wyśle znajomemu łącze do strony przeznaczonej dla innej przeglądarki niż używa ten znajomy. ale ilustruje podstawową zasadę działania. w oparciu o wymagania projektu należy wykorzystać narzędzia do wykrywania przeglądarki i włączania niektórych funkcji. $aBrowserInfo = $aBrowserHawk->getBrowserInfo( "$HTTP_USER_AGENT" ). Zamiast wykorzystywać zmienne do wysyłania różnych danych. Wprowadzenie takiego projektu jest nieporęczne dla dużych witryn. Inni użytkownicy są kierowani do zwykłego zestawu stron przeznaczonych dla innych typów przeglądarek. użytkownicy przeglądarek WebTV są kierowani na odpowiednio zoptymalizowane strony. wygląd strony nie będzie odpowiedni dla bieżącego typu przeglądarki. Podsumowanie Wykrywanie możliwości przeglądarki może być niezmiernie ważne dla wielu aplikacji WWW. Wadą takiego rozwiązania jest to. Dodatkowo mechanizm ten wymaga.browserhawk. w przeciwnym wypadku wysyłany jest rysunek w formacie GIF. Zakładamy. zanim zatwierdzimy realizację specyficznych funkcji.com/main/\n" ). Dlatego trzeba inaczej projektować taką witrynę aby poprawić widoczność wszystkich elementów. aby każda strona posiadała kilka równoległych stron przeznaczonych dla odpowiednich typów przeglądarek. Następnie. W czasie projektowania aplikacji należy poznać ograniczenia różnych przeglądarek. Przykład ten jest prosty. Na przykład można stworzyć witrynę zoptymalizowaną dla oglądania jej przez przeglądarki WebTV. } ?> W przykładzie tym. gdy przeglądarka wyświetla niezrozumiały komunikat błędu w przypadku. <?php $aBrowserHawk = new Java( "com. Przykład ten może być rozszerzony. aplikacja może skorzystać z informacji o możliwościach przeglądarki do wyświetlenia całkowicie innej sekcji witryny. Tego typu mechanizm może być zaimplementowany przy użyciu systemu szablonów. Rozdział 9 – Niezależność od przeglądarki 114 . aby wykrywał przeglądarki działające na komputerach typu PDA lub inne specyficzne typy przeglądarek.<img src="<?=$aImage?>" width="180" height="70" alt="" border="0"> </body> </html> Skrypt ten wyświetla grafikę w formacie PNG jeżeli przeglądarka potrafi wyświetlić ten format.cyscape. przekierowanie do stron zoptymalizowanych dla WebTV header( "Location: http://mysite. które będą opisane w rozdziałach 13 i 14. Należy dążyć do zapewnienia zestawu funkcji niezależnych od używanego typu przeglądarki. if ( $aBrowserInfo->getBrowser() == "WebTV" ) { // Przeglądarka WebTV. Systemy takie mają zwykle ograniczoną wielkość ekranu i zwykle mniej możliwości wyświetlania różnych czcionek. Tam też przytoczymy przykłady implementacji takiego scenariusza. Lepszym rozwiązaniem przy tworzeniu stron specyficznych dla przeglądarki jest wyłączenie kluczowych różniących się elementów i umieszczenie ich w osobnych plikach dla każdego typu przeglądarki.

testowania modułów oraz uruchamiania. Projekt aplikacji WWW musi być tak samo dokładnie przemyślany. które mogą usprawnić uruchamianie aplikacji. jeżeli jej projekt jest odpowiednio przygotowany. ponieważ można uniknąć ogromnej pracy przy uruchamianiu aplikacji. niektóre części rozdziału są przypomnieniem zasad inżynierii programowania. W dużych projektach takie planowanie może zająć tygodnie lub miesiące. na przykład ASP i JSP. Z powodu ogromnego zainteresowania jakie wzbudziło programowanie aplikacji WWW. że może być trudno zdalnie uruchamiać program. Dodatkowo. szczególnie gdy nie masz odpowiednich uprawnień do administracji serwerem WWW. pisanie lepszego (bardziej defensywnego) kodu powoduje ogromne zmniejszenie czasu straconego w czasie uruchamiania. obsługa stanu. identyfikacja wymaganych funkcji aplikacji może wymagać wykonania sporej pracy. że kod przeszedł wszystkie wcześniejsze wymagane kroki. autoryzacja użytkownika. Jest ona dołączona do tego rozdziału. Inżynieria programowania a uruchamianie W rozdziale 3 „Formularze i cookie” doszliśmy do wniosku. Projekt aplikacji Identyfikacja wstępnych założeń aplikacji przed napisaniem jakiegokolwiek kodu jest krytyczna w przypadku każdego projektu. Pierwsza część rozdziału zawiera przypomnienie zasad inżynierii programowania. id. Tworzenie świetnej aplikacji wymaga właściwego projektu. Wstępny podział aplikacji na moduły może uprościć ten proces. że wprowadzenie zmian do aplikacji w początkowym okresie programowania (przed fazą programowania) jest 10 do 200 razy tańsze niż wprowadzanie tych samych zmian na końcu tego procesu (McConnell. Niespodziewanie. W aplikacji WWW modułami takimi mogą być współpraca z bazą danych. oraz wymyślenie możliwie wielu możliwych rozwiązań przed rozpoczęciem pisania kodu. Prawdopodobnie brak ten jest spowodowany potrzebą zaistnienia na rynku jako pierwsze narzędzie lub z faktu. powstało wiele narzędzi (między innymi PHP) do tworzenia takich aplikacji. że posiadasz pewną wiedzę inżynierii programowania. Narzędzia te zostały stworzone na podstawie istniejących już narzędzi. Kolejne części zawierają przegląd każdego z tych kroków i zakładają. Po zdefiniowaniu zadań . Dane z firm TRW i IBM wskazują. W tym rozdziale zaprezentowane zostaną porady i narzędzia. 1993). Uruchamianie Wstęp Uruchamianie aplikacji WWW jest równie krytycznym procesem jak uruchamianie innych typów aplikacji. że można uniknąć sprawdzania poprawności niektórych danych w przypadku zastosowania lepszego mechanizmu wprowadzania danych. ponieważ zakłada się. W zależności od projektu. jak projekt każdej innej aplikacji. zgodności z standardami tworzenia oprogramowania. do tego nowego środowiska programowania należy zaadaptować wszystkie istniejące zasady inżynierii programowania. ponieważ zbyt dużo czasu spędzonego przy uruchamianiu jest zwykle powodowane błędami przy tworzeniu projektu. Problemem jest to. W każdym z tych przypadków kluczowe jest przemyślenie wymagań aplikacji. W małych projektach mogą zostać zapisane na skrawku papieru w przeciągu kilku minut. Uruchamianie jest koniecznie ostatnie na tej liście. Tak samo.Rozdział 10. Niezależnie od powodu. inne natomiast zostały stworzone jedynie w celu tworzenia interaktywnych aplikacji WWW. że pierwszymi projektantami nowej technologii nie byli bardziej zaawansowani programiści. narzędzia spełniające zasady inżynierii programowania są tu w mniejszości. sprawdzania oprogramowania.

czy osobno. są mniej ważne. że PHP może działać na wielu serwerach WWW i platformach systemowych. Definiowanie standardów programowania Zdefiniowanie standardów programowania ułatwia długoterminowe utrzymanie projektów o dowolnej wielkości. Aby zmniejszyć wpływ tej decyzji na projekt można stworzyć własne funkcje pośrednie ukrywające implementację. dla których należy wybrać określony sprzęt i serwer. Nawet małe aplikacje programowane przez jednego programistę mogą korzystać z odpowiednio stosowanego zbioru standardów programowania. 1993). jak na przykład konwencje nazw plików i katalogów mogą mieć ogromne znaczenie przy konserwacji kodu2. W małych aplikacjach dobrą strategią jest podział modułów na pliki kodu bądź klasy obiektowe. Ilość funduszy dostępnych na początku projektu rzadko jest dobrym powodem wyboru platformy. należy rozważyć architekturę systemu. każda z takich kombinacji posiada indywidualne cechy. Niektóre z nich. Mimo.: nIlosc to zmienna przechowująca liczby całkowite. Jednak możesz również nie mieć wystarczająco dużo czasu na stworzenie ich od początku. a bIstnieje to zmienna logiczna. Wybór bazy danych jest równie istotny. sTytul zawiera ciąg znaków. co uprości identyfikację kodu. przegląd oprogramowania pozwala na sprawdzenie kodu z standardami kodowania. na przykład jak będą zorganizowane pliki kodu. aby dostatecznie przetestować dostępne narzędzia. np. oraz czy niektóre moduły należy zakupić. Dobrym pomysłem może być stosowanie tzw. może być to krytyczne zagadnienie. Należy tu pomyśleć o rodzaju stosowanego systemu zarządzania relacyjną bazą danych (SZRBD) i innych mniej oczywistych elementach. należy zaprojektować organizację kodu. Zdefiniuj konwencję nazywania plików i katalogów. czy serwer WWW i baza danych będą pracować na tym samym komputerze. Są również jednym z bardziej efektywnych metod zapewnienia odpowiedniej jakości oprogramowania. Tworzenie zastępników takiego kodu jest łatwe do zaimplementowania i w dłuższym okresie czasu umożliwia łatwiejsze utrzymanie aplikacji. Analizy przeglądów oprogramowania stosowanych przy tworzeniu prawdziwych aplikacji pokazały. Na koniec należy zadecydować. Następnie. Taki standard obejmuje sposoby nazywania. notacji węgierskiej. Pozwalają również mniej doświadczonym programistom na korzystanie z wiedzy bardziej doświadczonych kolegów. czy też pisać je od początku. gdzie nazwa zmiennej zaczyna się od liter określających jej typ. Oprócz zdefiniowania wymagań funkcjonalnych aplikacji. Właściwe zaprojektowanie aplikacji wymaga czasu. Rozdział 10 – Uruchamianie 116 . możesz nie i mieć wystarczająco dużo czasu. do projektowania szczegółów implementacji również potrzebny jest czas. na przykład układ kodu. Należy poświęcić nieco czasu na zdefiniowanie powodów. ponieważ nowoczesne edytory potrafią przeformatować kod. Dodatkowo należy pomyśleć. Trzeba pamiętać. jak radzić sobie ze zmianami. Ten wynik należy zestawić z jedynie 25% prawdopodobieństwem dla testowania modułów. Z powodu luźnego traktowania typów w PHP szczególnie ważne wydaje się odpowiednie nazywanie zmiennych. gdy korzystasz przy tworzeniu aplikacji z narzędzi pochodzących z innych źródeł lub oprogramowania w wersji beta. komentowania oraz konwencje układu. Na przykład. które moduły aplikacji zostaną stworzone przy pomocy gotowych narzędzi pochodzących od zewnętrznych dostawców. W 2 Przypis tłumacza. W przypadku dobrego systemu faza projektowania zajmuje 20 do 30 procent czasu tworzenia systemu (McConnell. Dodatkowo. napisz aplikację lokalizującą zmiany w kilku modułach a buforującą resztę. Przegląd oprogramowania Przegląd oprogramowania dostarcza możliwości zrealizowania kilku celów za jednym razem. Decyzja „tworzyć czy kupić” jest dosyć skomplikowana. W zależności od harmonogramu projektu. 35% dla testowania funkcji oraz 45% dla testowania integracyjnego. przeglądy takie zwiększają w dużych projektach ogólną wydajność zespołu. że pozwalają na wykrywanie błędów z prawdopodobieństwem pomiędzy 55 a 60%. Jeżeli przewidujesz występowanie zmian. że ten czas jest zużywany na projektowanie wysokiego poziomu. Wymyśl alternatywny plan na wypadek. jednak inne. jeżeli aplikacja ma być wysoce dynamiczna. Taki typ projektowania jest istotny szczególnie. W zależności od wielkości i charakteru aplikacji.poszczególnych modułów należy w razie potrzeby podzielić je na mniejsze fragmenty i zapisać przeznaczenie każdego fragmentu. gdy istnieje duże prawdopodobieństwo zmian.

Z testami związany jest określony zbiór oczekiwań i wymagań. 1993). Następna część zawiera opis kilku technik i narzędzi specyficznych dla aplikacji PHP. W zależności od natury problemu. gdy ich usuwanie jest najprostsze i najtańsze. programowania i część testowania. kto bierze udział w testowaniu powinien znać źródło problemu w momencie. że inżynieria programowania jest równie ważna w aplikacjach WWW jak w pozostałych aplikacjach oraz o tym. Wynik ich pracy jest przekazywany autorowi kodu. W tej książce prawdopodobnie nie zostanie opisane wszystko na temat prawidłowej inżynierii programowania. W małych projektach testowanie może wymagać jedynie wymyślenia kilku prostych przypadków użycia aplikacji a następnie sprawdzenie każdego przypadku. Uruchamianie Uruchamianie jest ostatnim etapem w procesie tworzenia aplikacji. mogą powstać sugestie na temat sposobu jego usunięcia. która wykona taki przegląd metodą czytania kodu. ale nie zapewni trwałego rozwiązania. Każdy twórca kodu powinien również być odpowiedzialny za testowanie swoich modułów na poziomie funkcji lub strony. aby ich praca była efektywna. Niektóre z nich są formalną inspekcją kodu inne przeglądem ogólnym lub czytaniem kodu. Niezależnie od wybranej metody. Najważniejsze jest. Gdy zidentyfikowany zostanie błąd. Przegląd projektu pozwala na identyfikację jego wad w momencie. aby pamiętać. gdy stwierdza się usunięcie problemu. Czytanie kodu poświęcone jest jedynie dla kodu programu. które naprawi błędne przypadki. kilku członków zespołu zbiera się razem w celu odszukania błędów. Uruchamianie może być przeprowadzane w trakcie każdej z fazie testowania jako część tego procesu. Testowanie każdego modułu powinno być odpowiednio zaplanowane. czasami czasowe rozwiązania mogą być wystarczające. ponieważ zmiany mogły wprowadzić nowe błędy. gdy następuje uruchamianie powinny być ukończone procesy projektowania. aby jedynym tematem była identyfikacja błędów. a nie pracy grupowej. W przypadku przeglądu ogólnego grupa programistów nieformalnie dyskutuje na temat kodu zadając pytania. którzy zajmują się jedynie testowaniem. ale każdy z programistów powinien być odpowiedzialny za dostarczenie testerom dostatecznie dużo danych. Każdy. ze właściwe stosowanie zasad inżynierii może ograniczyć nakład pracy wymagany przy uruchamianiu. Wszystkie zmiany wprowadzone do kodu w trakcie procesu uruchamiania powinny zostać ponownie przetestowane na wszystkich poziomach testowania. przeprowadzenie przeglądu kodu jest najbardziej efektywną metodą identyfikacji problemów w projekcie bądź implementacji. ale głównym celem jest nadal jego identyfikacja. Znalezienie źródła problemu powoduje stworzenie kompletnego rozwiązania zamiast obchodzenia problemu. Na przykład w przypadku. ale często jest przeprowadzane przypadkowymi metodami. Rozwiązywanie problemów powinno brać pod uwagę priorytety. Nie powinno być prostym łataniem.niektórych przypadkach powodują one 80 do 90% spadek awarii oraz 10 do 25% wzrostu wydajności (McConnell. Większe projekty mogą zawierać ludzi. Tak jak w przypadku innych projektów. W przypadku formalnej inspekcji kodu. możesz skorzystać z zatrudnienia osoby. Testowanie Zwykle testowanie nie jest pomijane. Uruchamianie powinno być gruntownym procesem przeznaczonym do identyfikacji źródła problemu. 117 PHP – Kompendium wiedzy . ponieważ w momencie. Zwykle część kodu jest przekazywana dwóm lub więcej osobom. które niezależnie pracując identyfikują błędy. ale muszą zostać odpowiednio udokumentowane. W zależności od rozmiaru i organizacji projektu użycie jednej z metod ma przewagę nad inną. testowanie modułów oraz testowanie integracyjne. Przegląd powinien być przeprowadzany zarówno podczas testowania jak i podczas implementacji. Prowadzący spotkanie prowadzi je do przodu i pilnuje. testowanie aplikacji WWW powinno zawierać testowanie na różnych poziomach: testowanie funkcji. Formalna inspekcja kodu nie powinna zawierać dyskusji na temat rozwiązań. Można wykorzystać kilka metod realizacji przeglądu. gdy pracujesz sam lub w małym zespole.

Tabela 10. że do assert() można przekazać ciąg. Użycie funkcji assert() do kontroli poprawności parametrów wejściowych <?php function ArrayAverage( $aArray ) { $aTotal = 0.quiet_eval) lub opcje przekazane jako parametr wywołania funkcji assert_options() definiują akcję jaką podejmuje funkcja assert(). więc jeżeli wykorzystywane są zmienne należy zapewnić. assert_quiet_eval 0 Wyłącza raportowanie błędów w czasie obliczenia wyrażenia asercji. Jeżeli przekazany został ciąg. assert. $aTotal += $aElement.callback i assert. assert_callback (null) Nazwa funkcji użytkownika wykonywanej w przypadku nieudanej asercji. Testowy skrypt dla funkcji z wydruku 10.2. który jest wykonywany jako kod PHP. Do sprawdzania stanu funkcji. W PHP do funkcji assert() można przekazać zarówno ciąg jak i wartość Boolean. Wydruk 10. Opcje asercji w pliku php. } return ( $aTotal / count( $aArray ) ). Funkcja assert() oblicza wartość przekazanego parametru i podejmuje określone akcje w przypadku. Na wydruku 10. Należy zwrócić uwagę. posiada funkcję assert().php" ). że PHP nie podstawi zbyt wcześnie wartości zmiennej w miejsce jej nazwy. Jako minimum. klasy lub dołączanego pliku oraz zawsze komentować niejasne fragmenty kodu.2. assert_warning 1 Wyświetla ostrzeżenie PHP przy każdej nieudanej asercji.active. czy tablica zawiera wartości numeryczne. // Apostrofy ozanczają ciąg nie interpretowany przez PHP assert( 'is_array( $aArray )' ).warning. ?> <html> <head> <title>Testowanie asercji</title> </head> <body> Rozdział 10 – Uruchamianie 118 .bail.1 spodziewa się jako parametru tablicy wartości numerycznych (liczb lub ciągów zawierających liczby) i zwraca średnią z wartości w tablicy. jak i bez nich. jest on wykonywany jako blok kodu PHP.1 jest zamieszczony na wydruku 10./arrayfunc.Programowanie defensywne Zanim zaczniesz uruchamiać program.ini (assert.1. gdy jego wartość wynosi False.1 zamieszczone są różne opcje asercji.1. Taki sposób programowania jest nazywany programowaniem defensywnym. foreach( $aArray as $aElement ) { assert( 'is_numeric( $aElement )' ). ale powinno być zgodne ze standardami. PHP. Użycie funkcji ArrayAverage() <?php include( ". tak jak wiele języków wysokiego poziomu. Wydruk 10. programiści powinni opisywać przeznaczenie funkcji. wewnętrznym sprawdzaniu stanu procedur w trakcie procesu programowania.1 pokazany został przykład użycia funkcji assert() do kontroli poprawności parametrów wejściowych. assert_bail 0 Kończy wykonanie w przypadku nieudanej asercji. Opcje asercji i ich opis Opcja Domyślnie Opis assert_active 1 Włącza wykonywanie assert(). assert. Aplikacja powinna działać identycznie z wywołaniami funkcji assert(). Wyrażenie assert() jest wykorzystywane do kontroli poprawności parametru przekazanego do funkcji a później do sprawdzania. prowadzące do napisania kodu zawierającego dużo mniej błędów. Sposób komentowania jest indywidualny dla każdego programisty. powinieneś podjąć kroki. Funkcja assert() jest zaprojektowana jedynie do wykorzystywania w czasie tworzenia programu i nie powinna być używana w czasie normalnej pracy. assert. } ?> Funkcja ArrayAverage() umieszczona na wydruku 10. Aby tego uniknąć należy używać ciągów w apostrofach. W tabeli 10. Takie programowanie polega na odpowiednim komentowaniu błędów.

"5. 2. 5 ) ). 5 ) ) = $aResult<br>" ).active jest ustawione na False. 4. 4.1. print( "ArrayAverage( array( 1. Testowanie funkcji ArrayAverage() Podejmowane przez funkcję assert() działania zależą od ustawień asercji. 4. powoduje to. $aResult = ArrayAverage( array( 1.5". ###BOT_TEXT###quot;5. 2 ) = $aResult<br>" ). "cat". print( "ArrayAverage( array( 10. $aResult = ArrayAverage( 1. "cat". 3. 2. 5 ) ) = $aResult<br>" ). Aby zmienić tą opcję należy albo wywołać funkcję assert_options( ASSERT_ACTIVE. 5 ) ). False) lub ustawić odpowiednio dyrektywę konfiguracji. że wywołanie ArrayAverage(array(1.5###BOT_TEXT###quot;. Poprzedni przykład wyorzystywał domyślne ustawienia asercji. przestają one działać. że gdy assert. Funkcja ta jako argumentu wymaga liczby całkowitej określającej poziom raportowania błędów. error_reporting(). 3. Argument ten jest traktowany jako maska bitowa. że ponieważ PHP wewnętrznie wymusza typy zmiennych. więc można podać zestaw kilku ustawień. ?> </body> </html> Testowy skrypt wywołuje funkcję ArrayAverage() cztery razy. Należy zauważyć. 3. "4". pokazany jest wynik działania skryptu. Przyjemną cechą asercji jest to. 2. 2. natomiast ostatnie dwa razy przekazane wartości są nieprawidłowe.1. 4. ###BOT_TEXT###quot;4###BOT_TEXT###quot;. print( "ArrayAverage( 1. Na rysunku 10. 4. print( "ArrayAverage( array( 1. Są one następujące: Wartość Nazwa E_ERROR 1 E_WARNING 2 E_PARSE 4 E_NOTICE 8 E_CORE_ERROR 16 E_CORE_WARNING 32 E_COMPILE_ERROR 64 E_COMPILE_WARNING 128 E_USER_ERROR 256 E_USER_WARNING 512 119 PHP – Kompendium wiedzy . gdzie asercje są aktywne. 5 ) ) = $aResult<br>" ). PHP posada zestaw stałych używanych razem z tą funkcją.<?php $aResult = ArrayAverage( array( 1. 2 ). 5 ) ). Wykorzystując opcję konfiguracji można instalować aplikację w środowisku z wyłączonymi asercjami a pracować na innym. Istnieje jeszcze jedna funkcja pomagająca w programowaniu defensywnym. ###BOT_TEXT###quot;cat###BOT_TEXT###quot;.1.1. 2. 5)) udaje się bez żadnych ostrzeżeń (poza generowanymi przez asercje). Rysunek 10. 3. Pierwsze dwa razy przekazywane są właściwe wartości. $aResult = ArrayAverage( array( 10.

error_reporting( E_ALL ). print( "aArray[state] = " . ?> </body> </html> Na rysunku 10. Jak można zauważyć. ustawienie bardziej restrykcyjnego poziomu raportowania błędów może spowodować wykrycie błędów w kodzie. "country" => "US" ). Wydruk 10.3. Na wydruku 10.2. "country" => "US" ). Wyniki jego działania są widoczne na rysunku 10. Ustawienie to jest również ważne w trakcie dołączania do aplikacji zewnętrznej biblioteki. error_reporting( E_ALL ). "county" => "Madison". Wydruk 10. print( "aArray[state] = " . problem przestanie być niewinny. Tworząc aplikację powinno się przestawić poziom raportowania błędów na E_ALL. pokazane są wyniki działania tego przykładu. Na wydruku 10. "<br>" ). "<br>" ). "county" => "Madison". co spowoduje wyświetlanie wszystkich informacji o błędach w kodzie.4 pokazujemy skrypt z taką właśnie stałą.E_USER_NOTCE 1024 Dodatkowo istnieje również stała E_ALL. ?> </body> </html> Rysunek 10. Przykład użycia funkcji error_reporting() <html> <head> <title>Poziomy raportowania błędów</title> </head> <body> <?php $aArray = array( "state" => "Idaho". ale jeżeli zdefiniujemy stałą o nazwie state reprezentującą stan działania aplikacji. "city" => "Rexburg". // standardowy poziom raportowania błędów print( "aArray[state] = " .3 zamieszczony jest przykład kodu generujący ostrzeżenia w przypadku ustawienia maksymalnego poziomu raportowania błędów. Przy standardowych ustawieniach skrypt nie powoduje wyświetlenia żadnego komunikatu. "<br>" ). // Pozostały kod używający stałej state ?> <html> <head> <title>Poziomy raportowania błędów</title> </head> <body> <?php $aArray = array( "state" => "Idaho". $aArray[state] .3. $aArray[state] . // domyślny poziom raportowania print( "aArray[state] = " . W tym przypadku problem może wydawać się niewinny. 3 ). $aArray[state] .2. która uaktywnia wszystkie informacje o błędach. "city" => "Rexburg". Wynik działania skryptu error_reporting() Rozdział 10 – Uruchamianie 120 . $aArray[state] . które mogą spowodować różne efekty uboczne w czasie tworzenia aplikacji. "<br>" ).4. Drugi przykład użycia funkcji error_reporting() oraz stałej <?php // Stan działania aplikacji define( state.

jeżeli stała taka byłaby zdefiniowana w dołączanym pliku. Jeżeli używasz Apache. Problem taki może być bardzo trudny do odszukania. że najlepiej ustawić na serwerze produkcyjnym poziom raportowania na maksimum. komunikat. Wartości parametru typ Wartość Opis 0 Parametr komunikat jest wysyłany do systemowego mechanizmu rejestrowania PHP przy użyciu mechanizmu rejestrowania zapewnianego przez system operacyjny lub pliku — w zależności od ustawienia zmiennej konfiguracji error_log. plikiem stderr dla Apache jest dziennik błędów. Do obsługi tego typu komunikatu wykorzystywana jest ta sama funkcja wewnętrzna.3 po skonfigurowaniu PGP w sposób wspomniany powyżej. możesz skorzystać z innej lokalizacji dziennika. int typ [. W dowolnych miejscach aplikacji możesz sprawdzać stan niektórych funkcji lub raportować błędy wewnętrzne i kontynuować pracę. Wszystkie wyświetlane ostrzeżenia powinny zostać zlikwidowane. log_errors i error_log na odpowiednio Off. świetnie działający nagle przestał działać.2. na ekranie nie pojawią się ostrzeżenia. a w pliku dziennika błędów Apache znajdą się następujące pozycje: [06-Dec-2001 20:53:22] PHP Warning: Undefined offset: 3 in c:\helion\php4devguide\site\ch10\error_reporting_2. Lista prawidłowych wartości parametru typ znajduje się w tabeli 10.Rysunek 10. PHP posiada funkcję error_log() przy pomocy której można dodawać własne zapisy do pliku śladu aplikacji. 1 Komunikat jest wysyłany pocztą elektroniczną na adres podany w parametrze cel. Prototyp funkcji error_log() wygląda następująco: int error_log(string komunikat.assumed 'state' in c:\helion\php4devguide\site\ch10\error_reporting.assumed 'state' in c:\helion\php4devguide\site\ch10\error_reporting. PHP – Kompendium wiedzy 121 .phtml on line 12 Następnym krokiem podczas programowania defensywnego może być napisanie własnego mechanizmu rejestrującego. Drugi z parametrów określa gdzie zostanie zapisany komunikat. aby uniknąć występowania błędów w przyszłości. zawiera zapisywane dane. ale skierować strumień błędów do pliku dziennika. Jeżeli chcesz.2. Jedynie ten typ zapisu wykorzystuje parametr naglowki. Tabela 10.phtml on line 17 [06-Dec-2001 20:54:51] PHP Warning: Undefined offset: 3 in c:\helion\php4devguide\site\ch10\error_reporting_2. string naglowki]]) Pierwszy parametr. Można to zrealizować ustawiając zmienne konfiguracji display_errors. Jednak po dodaniu w drugim przykładzie stałej.phtml on line 17 [06-Dec-2001 20:54:53] PHP Warning: Use of undefined constant state . co w funkcji mail().phtml on line 12 [06-Dec-2001 20:54:49] PHP Warning: Undefined offset: 3 in c:\helion\php4devguide\site\ch10\error_reporting_2.phtml on line 17 [06-Dec-2001 20:54:03] PHP Warning: Use of undefined constant state . że w przeglądarkach użytkowników nie pojawiają się ostrzeżenia i komunikaty błędów. Przykład ten pokazuje zalety zastosowania ustawienia poziomu raportowania błędów na maksimum. Powoduje to.assumed 'state' in c:\helion\php4devguide\site\ch10\error_reporting. W zależności od twojego środowiska.phtml on line 12 [06-Dec-2001 20:54:45] PHP Warning: Use of undefined constant state . gdy poziom raportowania błędów był ustawiony na standardowy poziom. On i stderr. Takie ustawienie powoduje. string cel [. Gdy zostanie wykonany skrypt z wydruku 10.3. możesz ustawić poziom raportowania błędów na maksymalny w trakcie rozwijania aplikacji i na minimalny na serwerze produkcyjnym. Wynik działania drugiego skryptu error_reporting() W obu przykładach. nie były generowane żadne ostrzeżenia i program wykonywał się nieomal bezbłędnie. Jednak osobiście uważam. że PHP nie wyświetla błędów w przeglądarce a zamiast tego kieruje wszystkie błędy do pliku stderr.

0 ). 3. string nazwa_skryptu. unikanie uruchamiania programu poprzez tworzenie poprawnego kodu jest o wiele cenniejsze od najlepszych narzędzi używanych przy uruchamianiu.log. Rozdział 10 – Uruchamianie 122 . gdy włączone jest uruchamianie zdalne. Na szczęście PHP pozwala w inny sposób obsługiwać takie przypadki. ale nie pozwala na obsługę błędów generowanych przez PHP.Komunikat jest wysyłany poprzez połączenie PHP używane do uruchamiania zdalnego. funkcja error_log() pozwala na skonstruowanie prostego mechanizmu rejestrowania własnych błędów występujących w aplikacji. </body> </html> 2 Pierwsze wywołanie funkcji error_log() zapisuje komunikat błędu w systemowym dzienniku błędów. int nr_lini. $aFile. Własna obsługa błędów Tak jak prawie każdy element PHP mechanizm obsługi błędów możesz dostosować do własnych potrzeb. case E_WARNING: $aErrorType = "E_WARNING".6 zamieszczony jest przykład sposobu rejestrowania i użycia funkcji obsługi błędów. "app_errors@intechra. $aContext) { switch ( $aErrorNo ) { case E_ERROR: $aErrorType = "E_ERROR". co w przypadku funkcji mail(). "From: error_logger@myhost. Prototyp takiej funkcji wygląda następująco: function ErrorCallBack( int nr_bledu. W tym przypadku parametr cel określa nazwę komputera lub adres IP oraz opcjonalnie numer portu używanego do odbierania informacji uruchamiania. // nie powinien wystąpić break. ?> Wystąpiły błędy. Na wydruku 10. Wykorzystanie tego mechanizmu nie jest w dosłownym znaczeniu uruchamianiem. Opcja ta jest dostępna jedynie w przypadku. Inne typy komunikatów działają w sposób opisany w tabeli. która będzie wywoływana za każdym razem. array kontekst) Na wydruku 10.5 pokazany jest przykład użycia funkcji error_log(). Ostatnie wywołanie powoduje dodanie komunikatu błędu do pliku. $aLine.net". // Wysłanie błędu przez e-mail error_log( "MÓJ BŁĄD: wystąpił błąd!". Kod źródłowy zawierał komentarz informujący. string ciag_bledu. Funkcja set_error_handler() wymaga podania jednego argumentu — nazwy funkcji obsługi błędów. Nie pozwala również na przechwytywanie komunikatów generowanych przez funkcje assert(). "/tmp/error. 3 Komunikat jest dołączany na koniec pliku o nazwie cel. 1. // Zapisanie błędu w pliku śladu aplikacji error_log( "MÓJ BŁĄD: wystąpił błąd!".5. Wydruk 10. aby spełniał wymagania stawiane przez aplikację. Użycie funkcji error_log() <html> <head> <title>Rejestrowanie błędów</title> </head> <body> <?php // Zapisanie błędu do dziennika systemowego error_log( "MÓJ BŁĄD: wystąpił błąd!". w tym przypadku /tmp/error. Wydruk 10.6. że zdalne uruchamianie nie jest jeszcze dostępne. Jak pokazane zostało na końcu poprzedniego przykładu.com\r\n" ). ale jego zastosowanie może zaoszczędzić czas spędzony przy właściwym uruchamianiu. $aErrorStr. Informacje zawarte w dodatkowych nagłówkach są utworzone przy użyciu tych samych zasad. Funkcja set_error_handler() pozwala zarejestrować funkcję w PHP. W czasie pisania książki typ 2 nie był dostępny. gdy wygenerowany zostanie komunikat błędu. powodując eliminację niektórych błędów i przeoczeń już w fazie programowania. Drugie wywołanie skutkuje wysłaniem poczty elektronicznej do odbiorcy określonego w parametrze cel. Wykorzystanie set_error_handler() <?php function myErrorHandler( $aErrorNo.log" ). W tym przykładzie błąd ten wysyłany do dziennika błędów Apache. Jak wcześniej wspomniałem.

Na rysunku 10. case E_CORE_ERROR: $aErrorType = "E_CORE_ERROR". case E_CORE_WARNING: $aErrorType = "E_CORE_WARNING". $aArray[state] . break. Pierwszy jest generowany przy użyciu funkcji PHP trigger_error(). break. która wyświetla komunikaty błędów w obramowanej tabeli zawierającej jedną komórkę. "city" => "Rexburg". "<b>$aErrorType</b>: <i>$aErrorStr</i><br>" ). default: $aErrorType = "UNKNOWN ERROR TYPE". case E_COMPILE_WARNING: $aErrorType = "E_COMPILE_WARNING".4. "county" => "Madison". $aArray = array( "state" => "Idaho". error_reporting( E_ALL ).3. E_USER_ERROR ). case E_NOTICE: $aErrorType = "E_NOTICE". case E_COMPILE_ERROR: $aErrorType = "E_COMPILE_ERROR". pokazany został wynik działania skryptu. skrypt powoduje dwa błędy. // nie powinien wystąpić break. print( "aArray[state] = " .6 została zdefiniowana funkcja obsługi błędów myErrorHandler(). Drugi błąd (ostrzeżenie) jest identyczny jak błąd pokazany na wydruku 10. Działanie funkcji set_error_handler() 123 PHP – Kompendium wiedzy . break. // nie powinien wystąpić break. case E_USER_WARNING: $aErrorType = "E_USER_WARNING". ?> </body> </html> W skrypcie na wydruku 10. // nie powinien wystąpić break. ?> <html> <head> <title>Własna obsługa błędów</title> </head> <body> <?php trigger_error( "Test błędów". Po zainstalowaniu funkcji obsługi. // nie powinien wystąpić break. "w pliku $aFile linia $aLine<br>" ). "<br>" ). case E_PARSE: $aErrorType = "E_PARSE". "</td></tr></table>" ). break. co pomaga w odróżnieniu komunikatu błędu od reszty kodu HTML. } set_error_handler( "myErrorHandler" ). "country" => "US" ). } print( print( print( print( "<table border=###BOT_TEXT###quot;1###BOT_TEXT###quot;><tr><td>" ).4. Rysunek 10. case E_USER_ERROR: $aErrorType = "E_USER_ERROR". break.break. // nie powinien wystąpić break. case E_USER_NOTICE: $aErrorType = "E_USER_NOTICE".

że wywołanie takie zwróci jedynie nazwę bieżącej funkcji obsługi. 0 ). funkcja użyta w tym przykładzie posiada pięć parametrów.2. Wcześniejsze wersje miały tylko dwa parametry: typ komunikatu i komunikat. Będą one opisane w następnej części rozdziału. Aby to zrealizować należy skorzystać z funkcji assert_options(). Uwaga na temat set_error_handler() Funkcja set_error_handler() jest dostępna w PHP od wersji 4. Wydruk 10. print( "w pliku $aFileName w linii $aLineNum<br>" ). pojawiły się komentarze „nie powinien wystąpić”. w funkcji assert_options() występował mały błąd. Parametry te są dostępne dopiero w wersji 4. w tym nazwę skryptu. Również funkcja assert() pozwala na zdefiniowanie wywoływanej funkcji. E_COMPILE_ERROR oraz E_COMPILE_WARNING. Dane te zawierają nazwy i wartości zmiennych istniejących w skrypcie w momencie wystąpienia błędu. ?> <html> <head> <title>Własna obsługa asercji</title> </head> <body> Nieudana asercja. "MyACallback" ). bieżące ustawienie funkcji obsługi było czyszczone. Wywołanie asercji powoduje wyświetlenie jednokomórkowej tabeli. E_CORE_ERROR. W skrypcie z wydruku 10. E_PARSE. Z tego powodu w kodzie funkcji obsługi błędów z wydruku 10. Wykorzystanie funkcji wywoływanej przez callback() <?php error_reporting( E_ALL ). $aAssertion ) { print( "<table border=###BOT_TEXT###quot;1###BOT_TEXT###quot;><tr><td>" ). $Asercja ) Uwaga na temat assert_options() W PHP do wersji 4. że w dokumentacji napisano.0. $aLineNum.Używając funkcji set_error_handler() należy pamiętać.7. $NrLinii. Na rysunku 10. Dlatego jeżeli chcesz użyć funkcji assert() z funkcją obsługi upewnij się.0.2 włącznie.0. że PHP nie przekazuje do funkcji obsługi błędów typu E_ERROR. Na wydruku 10. // wyłączenie normalnych ostrzeżeń assert_options( ASSERT_WARNING.0. że nie jest wywoływana później funkcja assert_options() w celu sprawdzenia nazwy zarejestrowanej funkcji. Jeżeli nie zostanie opcja ASSERT_WARNING. <?php assert( "1 == 2" ). Występował on w przypadku wywołania funkcji w postaci assert_options(ASSERT_CALLBACK). print( "<b>assert()</b> nieudane: <i>$aAssertion</i><br>" ). print( "</td></tr></table>" ).5.6. Funkcja obsługująca nieudane asercje jest zdefiniowana w następujący sposób: function AssertCallback ($NazwaPliku.1. Dodatkowo. pokazany został przykład zdefiniowania i użycia funkcji wywoływanej przez assert(). Rozdział 10 – Uruchamianie 124 . w celu odczytania ustawionej funkcji obsługi.7. ?> </body> </html> Kod z wydruku jest podobny do tego z wydruku 10.2. function MyACallback( $aFileName. to dodatkowo oprócz zwracania nazwy. } // zarejestrowanie funkcji obsługi assert_options( ASSERT_CALLBACK. Mimo. E_CORE_WARNING. pokazany jest wynik działania skryptu z wydruku 10.6 nie są wykorzystane dane na temat kontekstu.6. oprócz informacji zdefiniowanych przez użytkownika wyświetlony zostanie standardowy komunikat PHP. Błąd ten został zauważony i poprawiony w wersjach PHP powyżej 4. Obsługa tego typu błędów przez użytkownika nie jest bezpieczna. numer linii i dane kontekstu.7.

php i będzie on określony jako moduł MyDebug.Rysunek 10. "MyAssertHandler" ). która nie została przeniesiona do PHP 4. } if ( $aMyDebugType & MYDEBUG_DISPLAYIP ) { $aSocketHandle = fsockopen( "udp://$aMyDebugIP".8. Pozwalał on przesyłać dane za pomocą protokołu TCP/IP do innego komputera. MyDebug. Na przykład. Motywacją do napisania tego fragmentu był brak dostarczanych przez PHP narzędzi. W następnej części połączymy wszystkie przedstawione do tej pory techniki. który jest przechowywany w zmiennej środowiska serwera. Po dołączeniu pliku wykonywany jest kod pokazany na wydruku 10.com:5400.log. Jest on tak utworzony. 0 ).5. PHP 3 posiadał możliwość zdalnego uruchamiania. więc zostanie omówiony we fragmentach. Zaawansowana obsługa błędów Po omówieniu technik obsługi błędów możemy rozpocząć tworzenie ogólnego narzędzia do obsługi błędów. Oprócz tego.8. Przykład przytoczony w tej części jest niezwykle długi. "a" ). 0 ). Użycie funkcji zdefiniowanej dla assert() PHP posiada elastyczny mechanizm obsługi błędów. register_shutdown_function( "MyDebugShutdown" ). co w efekcie pozwoli lepiej uruchamiać programy w całym cyklu produkcyjnym. Pozwala on dzięki temu pisać kod łatwiejszy do uruchamiania i późniejszego utrzymania. Opcja ta prawdopodobnie niedługo się pojawi. } // Teraz rejestrujemy funkcje obsługi i funkcje porządkujące set_error_handler( "MyErrHandler" ). assert_options( ASSERT_CALLBACK. 125 PHP – Kompendium wiedzy .8. Wydruk 10.net. plik konfiguracyjny Apache może zawierać kod podobny do następującego: SetEnv MYDEBUG_CONFIG FILE=/tmp/mydebug. assert_options( ASSERT_WARNING. ale na razie muszą wystarczyć podstawowe techniki obsługi błędów opisane w tym rozdziale.IP=myserver. if ( $aMyDebugType & MYDEBUG_DISPLAYFILE ) { // jeżeli nie można zapisać do pliku sladu // poinformuj o tym uzytkownika i wyłączyć zapis do pliku if ( CheckFileSanity( $aMyDebugFile ) == False ) { error_log( "MyDebug nie udało się otworzyć pliku $aMyDebugFile". $aMyDebugType &= ~MYDEBUG_DISPLAYFILE. $aMyDebugPort ). Dołączanie modułu MyDebug ParseConfig( getenv( "MYDEBUG_CONFIG" ) ). } } if ( $aMyDebugType & MYDEBUG_DISPLAYFILE ) { $aFileHandle = fopen( $aMyDebugFile. powoduje przetworzenie ciągu konfiguracji MyDebug. MAIL=mydebug@intechra. Pierwsza linia z wydruku 10. Moduł ten znajduje się w jednym pliku. że może być łatwo dołączony do dowolnego skryptu PHP. które automatycznie łączą różne typy danych o błędach.

Wydruk 10. $aDisplayType++ ) { Rozdział 10 – Uruchamianie 126 . Funkcję kończącą może zarejestrować dowolny skrypt. funkcje te są wywoływane w tej samej kolejności. Gniazdo jest otwierane używając UDP. Po przeanalizowaniu ciągu konfiguracyjnego sprawdzane są wszystkie pliki używane do zapisu. $aFile. że można ustawiać zmienne środowiska. Przykład ten pokazuje. Następnie moduł MyDebug rejestruje funkcje obsługi błędów i asercji. $aLineNum. skrypty twoje nie powinny polegać na kolejności wykonywania funkcji kończących lub musisz sam to przetestować. } if ( $aMyDebugType & MYDEBUG_DISPLAYIP ) { fclose( $aSocketHandle ). że można do nich zapisywać dane. Funkcja MyDebug() // Funkcja MyDebug jest główną funkcją obsługi function MyDebug( $aMessage. $aContext ). $aMyDebugType.net)oraz do gniazda UDP (myserver. która może również zostać wywołana bezpośrednio ze skryptu.11. Należy również pamiętać. Po skonfigurowaniu modułu MyDebug. $aFile. $aFile. które są wykonywane w czasie kończenia pracy skryptu. $aAssertion ) { MyDebug( "asercja( $aAssertion ) nieudana".Ta opcja konfiguracji jest specyficzna dla modułu MyDebug i nie jest dostępna jako standardowa część Apache czy PHP. ale moduł MyDebug pozwala na stosowanie wielu jednoczesnych miejsc zapisu błędów. wysyłał na adres e-mail (mydebug@intechra. Wydruk 10. gdzie MyDebug będzie zapisywał błędy. gdy zapisywanie jest aktywne na serwerze produkcyjnym. } } Funkcja ta zamyka wymagane pliki oraz gniazdo sieciowe.log). $aLine. Wydruk 10. obsługuje on błędy za pomocą funkcji z wydruku 10.9. $aLineNum. } // Funkcja obsługi dla funcji assert_options() function MyAssertHandler( $aFileName. W normalnej pracy wybiera się zwykle jedną z metod zapisu błędów. $aContext) { MyDebug( $aErrorStr. $aLine. $aErrContext = array() ) { global $aMyDebugType. zapisywanie do niego jest wyłączane.com:5400). } Obie funkcje przekazują parametry do głównej funkcji obsługi błędów. ale nie zawsze jest aktywny proces nasłuchu. co pozwala na eleganckie zakończenie działania modułu. Główna funkcja obsługi błędów to przedstawiona na wydruku 10. Następnie otwierane są wszystkie potrzebne pliki i gniazda. $aLine. poprzez pliki konfiguracyjne serwera WWW i są one dostępne w kodzie PHP. Zmienna MYDEBUG_CONFIG definiuje miejsca. if ( $aMyDebugType & MYDEBUG_DISPLAYFILE ) { fclose( $aFileHandle ). $aErrorNo. $aDisplayType <= MYDEBUG_DISPLAYIP. PHP przekaże je do funkcji końcowej. funkcja MyDebug(). co nie wymaga istnienia procesu nasłuchu. Funkcje obsługi błędów // Funkcja obsługi ustawiana przez set_error_handler() function MyErrHandler( $aErrorNo. $aErrorStr.11. $aErrType = 0. $aCallType = MY_DEBUG_INTERNAL. $aFileName. Na wydruku 10. MYDEBUG_ERRCALLBACK. Można przekazać dodatkowe argumenty do funkcji register_shutdown_function(). co zostały zarejestrowanie. for ( $aDisplayType = MYDEBUG_DISPLAYFILE. Funkcja kończąca program function MyDebugShutdown( ) { global $aFileHandle. $aSocketHandle. Choć ten fakt nie jest odnotowany w dokumentacji. Ostatnią operacją jest zarejestrowanie funkcji wywoływanej po zakończeniu programu.10. Własność ta jest użyteczna szczególnie wtedy. aby mieć pewność. Ponieważ kolejność ta nie została udokumentowana. MYDEBUG_ASSERTCALLBACK ). Jeżeli moduł MyDebug nie może zapisać danych do pliku.9 pokazana jest funkcja kończąca program. PHP pozwala na rejestrowanie wielu funkcji kończących. W tym przypadku moduł będzie zapisywał błędy do pliku (/tmp/mydebug. że w funkcji końcowej nie można wysyłać żadnych danych do przeglądarki. Funkcja ParseConfg() analizuje ciąg konfiguracji i ustawia odpowiednie zmienne globalne.10.

$aContext. Funkcja FormatType() /* Funkcja formatuje typ komunikatu w oparciu o to gdzie będzie wyświetlony */ function FormatType( $aCallType. } } Funkcja MyDebugOutput() wysyła dane do właściwych miejsc.13 formatuje kod typu błędu. $aMessage. Wydruk 10. $aMessage = FormatMsg ( $aCallType. jeżeli pomyśli się o efektywności każdej z tych opcji. "From: mydebug@host. $aFile. if ( $aContext != "" ) { $aMsg . Na przykład funkcja FormatType() przedstawiona na wydruku 10. Jest ona zaskakująco prosta. } else { $aMsg . $aLine. $aDisplayType ).= "\n". $aMsg. if ( $aContext != "" ) { $aMsg .12.= "\n". case MYDEBUG_DISPLAYIP: $aMsg = "$aType|$aMessage|$aFile|$aLine|$aContext^^". Następnie wywołuje funkcje MyDebugOutput() (wydruk 10. break. e-mail lub TCP/IP). } mail($aMyDebugEmail. $aMsg ). $aDisplayType ). $aMyDebugEmail. break.13.= "Dane kontekstu:\n{$aContext}\n". $aMessage. $aFile. która wysyła dane do prawidłowego miejsca. $aLine. $aDisplayType ). ". $aMsg ). Wydruk 10. ". $aErrType.if ( $aDisplayType & $aMyDebugType ) { $aType = FormatType( $aCallType. } else { $aMsg . $aSocketHandle. $aContext.11 zostaną omówione później.com\r\n"). Każda funkcja formatująca użyta w module MyDebug posiada mechanizm zamiany wewnętrznego numeru błędu na postać czytelną dla człowieka.= "Dane kontekstu:\n{$aContext}\n". Funkcje formatujące z wydruku 10. $aDisplayType ) { global $aFileHandle.12). "Raport MyDebug". 127 PHP – Kompendium wiedzy . case MYDEBUG_DISPLAYEMAIL: $aMsg = "$aType: '$aMessage' wystąpił w $aFile w linii $aLine. $aMessage. $aDisplayType ). $aDisplayType ) { switch( $aDisplayType ) { case MYDEBUG_DISPLAYFILE: case MYDEBUG_DISPLAYEMAIL: switch ( $aCallType ) { case MYDEBUG_INTERNAL: return "INTERNAL". } fputs( $aFileHandle. Funkcja MyDebugOutput() function MyDebugOutput( $aType. } else { $aContext = "". fputs( $aSocketHandle. } } } Funkcja MyDebug() formatuje różne parametry w zależności od typu medium zapisu (plik. switch( $aDisplayType ) { case MYDEBUG_DISPLAYFILE: $aMsg = "$aType: '$aMessage' wystąpił w $aFile w lini $aLine. if ( $aCallType == MYDEBUG_ERRCALLBACK ) { $aContext = FormatContext( $aErrContext. break. } MyDebugOutput( $aType.

nie jest przeprowadzane formatowanie. Funkcja zamieszczona na wydruku 10.= " )$aDelim". } } Jeżeli dane są wysyłane poprzez TCP/IP. Dane kontekstu: a = 1 b = 2 aArray = array( 0 = spring. break. } break. &$aString. jest funkcja formatująca kontekst błędu.2 = autumn. która jest wyraźnie inna. jedynie wynikiem wystąpienia ostatniego błędu w skrypcie: ERROR CALLBACK: 'Typ błędu PHP: E_USER_ERROR . W zależności od miejsca wystąpienia błędu. Analiza danych kontekstu Funkcja formatuje typ komunikatu w oparciu o to gdzie będzie wyświetlony. ponieważ w kontekście mogą znajdować się tablice. $aString.3 = winter. Wydruk 10. $aString . ". kontekst lokalny może zawierać sporo danych. rekurencyjnie jest wywoływana funkcja FormatContextR(). case MYDEBUG_ERRCALLBACK: return "ERROR CALLBACK". Po jego uruchomieniu na końcu pliku śladu znalazł się ciąg błędu.error in sum' wystąpił w c:\helion\php4-devguide\site\ch10\test_mydebug. } function FormatContextR( $aErrContext. Poniższy tekst nie jest całym plikiem." ). $aDelim ) { foreach( $aErrContext as $aVarName => $aVarValue ) { if ( is_array( $aVarValue ) == True ) { $aString . Funkcja ta jest wywoływana jedynie wtedy. przekształcając je na postać czytelną dla człowieka.15. $aDisplayType ) { // od tej pory wszystkie wyświetlane typy // otrzymują ten sam ciąg kontekstu $aString = "".1 = summer. Analiza tych danych wymaga wykorzystania funkcji rekurencyjnej. gdy błąd zostanie obsłużony przez funkcję zarejestrowaną za pomocą set_error_handler().= "$aVarName = {$aVarValue}{$aDelim}". case MYDEBUG_DISPLAYIP: return $aCallType. Funkcja oparta o funkcję rekurencyjną FormatContextR */ function FormatContext( $aErrContext. kontekst będzie zawierał jedynie zmienne lokalne funkcji. w tym zmienne środowiska i zmienne GET i POST. case MYDEBUG_ASSERTCALLBACK: return "ASSERT CALLBACK". $aDelim = "\n". break. } } } /* Funkcja FormatContext() ustawia kilka parametrów i wywołuje funkcję rekurencyjną FormatContextR().15. break.= "$aVarName = array( ". Skrypt testowy <?php Rozdział 10 – Uruchamianie 128 . Wszystkie te zmienne znajdą się w danych kontekstu. Jeżeli napotkana zostanie tablica. Jeżeli błąd wystąpi w głównej części skryptu.14. $aString. Inne funkcje konwertujące użyte w MyDebug działają podobnie. Sam numer typu jest wysyłany do zdalnego komputera. Do skryptu testującego (wydruk 10. Dane kontekstu udostępniane przez PHP zawierają wszystkie zmienne będące w zasięgu w momencie wystąpienia błędu. $aDelim ). Jedyną funkcją formatującą. FormatContextR( $aVarValue. Funkcja rekurencyjna przegląda tablice zmiennych kontekstu i zapisuje każdą parę nazwa-wartość do wynikowego ciągu. Dane te są przesyłane w postaci tablicy asocjacyjnej z nazwami zmiennych i ich wartościami.break. w zasięgu znajdą się wszystkie zmienne globalne. return $aString. FormatContext(). W innym wypadku numer typu jest zamieniany na czytelny ciąg.) dołączyliśmy moduł MyDebug oraz ustawiliśmy zmienną konfiguracji na zapisywanie do pliku tekstowego. analizuje dane kontekstu. FormatContextR( $aErrContext. Jeżeli błąd wystąpi w funkcji. } else { $aString .14. ) Wydruk 10.phtml w lini 16.

wykorzystanie poczty elektronicznej do raportowania błędów jest niezwykle nieefektywne. że jest on niezwykle rozszerzalny. ale można wykorzystać pocztę elektroniczną do raportowania jedynie krytycznych błędów i ostrzeżeń. że wszystkie te opcje są zrealizowane całkowicie w PHP. E_USER_ERROR ). co pozwoli na wykorzystanie tej opcji w środowisku produkcyjnym. $aArray[state] . Nie wszystkie narzędzia programowania dla WWW są tak elastyczne. $b ) { $aArray = array( "spring". aby pokazać jak wywołanie funkcji wpływa na dane kontekstu przekazywane przez PHP. Po odczytaniu danych formatuje linie i wyświetla je. "city" => "Rexburg". która odczytuje pakiety UDP przychodzące do portu 5400. "summer". pokazana została ta aplikacja po odebraniu kilku komunikatów wygenerowanych przez PHP. "country" => "US" ). Aby pokazać elastyczność tego modułu.php" ). 2 ). Na rysunku 10. Jest to prosta aplikacja Delphi. W chwili obecnej PHP nie posiada programu do uruchamiania skryptów. print( "<br><br>aArray[state] = " . $aArray = array( "state" => "Idaho". E_USER_ERROR ). Linie z opisem błędu zamieszczone bezpośrednio przed wydrukiem 15 są wygenerowane przy wywołaniu funkcji sum(). podobnego do tych. Wynik funkcja sum() nie jest nigdzie używany. "county" => "Madison". które są dostępne we wielu nowoczesnych językach 129 PHP – Kompendium wiedzy . nie robi nic. ?> <html> <head> <title>Test modułu MyDebug</title> </head> <body> Nieudana asercja. Podsumowanie W tym rozdziale przedstawione zostały informacje na temat technik programowania defensywnego.include_once( ". "autumn". "<br>" ). Na przykład. Rysunek 10. "winter" )./mydebug.<br><br> <?php function sum( $a. która realizuje proces nasłuchu portu TCP/IP i wyświetla przychodzące dane. trigger_error( "error in sum". poza generowaniem błędów.6. ale jest ona umieszczone w tym skrypcie. które pozwalają na uniknięcie możliwie dużo pracy przy uruchamianiu. sum( 1. napisana została aplikacja Windows. Niezmiernie istotny jest fakt.6. Moduł MyDebug jest napisany całkowicie w PHP dodając do niego niezwykle użyteczne funkcje (kompletne źródła modułu MyDebug są dostępne wraz z wszystkimi przykładami kodu z tej książki). } assert( "1 == 2" ). Moduł ten nie jest kompletny i może być rozwijany na wiele sposobów. Aplikacja nasłuchu dla MyDebug Jednym z powodów atrakcyjności języka PHP jest to. ?> </body> </html> Skrypt testowy przedstawiony na wydruku 10.15. trigger_error( "Błąd testowy".

który zapewnia elastyczną obsługę błędów i może być modyfikowany i rozszerzany tak. Jednak przy odrobinie pomysłowości i wykorzystując rozszerzalność PHP. można stworzyć świetne narzędzia do uruchamiania aplikacji. Bibliografia Steve McConnell. 1993. Opisany został jeden z modułów. Rozdział 10 – Uruchamianie 130 . Seattle: Microsoft Press. Code Complete.programowania. aby spełniał wymagania prawie każdego programisty.

częściej należy dzielić grupy funkcji na oddzielne moduły lub klasy. Zalety ponownego użycia nie są natychmiast widoczne. ale wiele firm zauważyło około 58% wzrost wydajności rocznie w przeciągu czterech lat (McConnell. W PHP kod nadający się do powtórnego wykorzystania można tworzyć przy pomocy kilku metod. że tworzenie kodu do ponownego wykorzystania jest integralną częścią całego procesu produkcji oprogramowania i że wszyscy programiści zgadzają się z tą ideą. Wybór plików dołączanych lub podejścia obiektowego nie wpływa zbytnio na ogólne założenia. Gdy planowane jest ponowne wykorzystanie kodu. który uprości jego wykorzystanie w przyszłości. • Tworzenie kodu do ponownego wykorzystania przy użyciu możliwie najlepszych standardów programowania i dokumentacji. jeżeli nie zostanie zastosowane odpowiednie planowanie. . należy napisać go i udokumentować w sposób zgodny z najlepszymi zaleceniami stosowanymi w zespole. Ponowne wykorzystanie kodu Wstęp Podczas tworzenia dowolnej aplikacji niezmiernie ważne jest wykorzystanie istniejących modułów kodu. że przy pisaniu aplikacji w przyszłości będą potrzebne podobne fragmenty. Ponieważ PHP pozwala na dołączanie zewnętrznych plików oraz na tworzenie klas. ponieważ tworzenie takiego kodu zajmuje często dużo więcej czasu i jest bardziej kosztowne w porównaniu do tego samego kodu do jednokrotnego użycia (McConnell. precyzyjnych modułach kodu. Zalety te nie będą wykorzystane. a zamiast tego tworzyć moduł w sposób. jakie należy wziąć pod uwagę: • Zaangażowanie kierownictwa w proces ponownego wykorzystania kodu. • Skupienie się na tworzeniu małych. Tworząc kod należy mieć na uwadze. na przykład tworząc oddzielne pliki z kodem źródłowym (pliki dołączane) lub tworząc klasy obiektowe. Kluczem do sukcesu jest tworzenie kodu nadającego się do powtórnego użycia. który jest odpowiednio zorganizowany i dobrze udokumentowany. że używane moduły kodu stanowią podstawę kolejnych aplikacji i w dłuższym czasie polepszają wydajność zespołu programistów. Nowe fragmenty kodu często są tworzone w sposób ułatwiający ich ponowne wykorzystanie. Pierwszym powodem jest to. oraz przytoczone zostanie kilka przykładów kodu PHP nadającego się do powtórnego wykorzystania. ponowne wykorzystanie kodu jest dosyć proste. 1996). Taka elastyczność pozwala programistom na przenoszenie do sieci WWW istniejących aplikacji bez konieczności całkowitego przepisywania kodu. Poniżej przedstawione zostały niektóre ważne zagadnienia. W tym rozdziale ponowne wykorzystanie kodu zostanie krótko omówione z perspektywy inżynierii programowania. Jeżeli wiadomo. Należy unikać używania danych lub założeń specyficznych dla projektu. Użycie hermetyzacji i technik ukrywania danych da w efekcie maksymalne zwiększenie wydajności i efektywności ponownie wykorzystanego kodu.Rozdział 11. • Upewnienie się. Ponowne wykorzystanie kodu a inżynieria programowania Ponowne wykorzystanie kodu nie polega jedynie na integracji istniejącego kodu z nowym produktem. Mając to na uwadze. W rozdziale tym omówione zostanie wykorzystanie w projektach PHP kodu napisanego w innych językach programowania. 1996). że dany fragment kodu będzie wykorzystywany w przyszłości. ważne są efekty długoterminowe.

2. print( GetFormattedNumber( $aNumVisitors ) ). ' ' ). assert( 'count( $aDateArray2 ) == 3' ).$aTime2 ). Plik dołączany date_funcs. $aTime2 = mktime( 0. ?> <html> <head> <title>Problem z wielokrotnym dołączaniem plików</title> </head> <body> <?php $aNumVisitors = 14500." ). wykorzystuje funkcje z obu poprzednich plików dołączanych.3. 0. } ?> Wydruk 11. $aTimeDiff = abs( $aTime1 . return GetFormattedNumber( $aTimeDiff / ( 60 * 60 * 24 ) ). Zaczynając od wersji PHP 4. PHP PHP zawiera kilka narzędzi ułatwiających ponowne wykorzystanie kodu.Ponowne użycie istniejącego kodu Z powodu natury projektów internetowych. $aDateStr2 ) { $aDateArray1 = explode( "-"./date_funcs. na końcu książki. 0. w firmie może nie istnieć zbyt wiele fragmentów kodu do wykorzystania. print( "Witrynę odwiedziło " ). Ponieważ PHP jest niezwykle rozszerzalny. HTML lub ich kombinacji.3. i 11. } ?> Skrypt z wydruku 11. Z tego powodu została przygotowana podstawa do tworzenia narzędzi dla PHP tworzonych przez różne firmy.php" ). $aDateArray1[2] ). przedstawiono przykład takiego problemu i sposób jego rozwiązania. $aDateArray2[2] ). 0. $aDateArray2 = explode( "-". $aDateArray1[0]. print( "w przeciągu ostatnich " ). dostępne są funkcje include_once() i require_once(). Niektóre z nich zostały wspomniane w poprzednich rozdziałach i są wymienione na liście zasobów internetowych. Skrypt wykorzystujący oba pliki dołączane <?php include( ". assert( 'count( $aDateArray1 ) == 3' ). lub przepisuje się z innego języka na PHP. Na wydruku 11. '.1.php" ). $aDateArray2[1].1. // Zwraca ilość dni pomiędzy datami // jako sformatowany ciąg w postaci mm-dd-rrrr function GetDateDiff( $aDateStr1. funkcje te pozwalają na dołączanie czystego kodu PHP. Wydruk 11. ?> </body> </html> Rozdział 11 – Ponowne wykorzystanie kodu 132 . 0. $aDateArray2[0]. które upraszczają proces dołączania. print( " dni. Jeżeli przenosi się zwykłą aplikację biurową do sieci. istnieje wiele metod użycia obcego kodu w aplikacjach opartych o PHP.php" ). Najbardziej oczywistą metodą ponownego wykorzystania kodu PHP jest użycie funkcji include() lub require() do dołączenia istniejącego kodu. prawdopodobnie istnieje wtedy kod. include( ". $aDateArray1[1]. Używane już we wcześniejszych przykładach. który można wykorzystać.php <?php include_once( ". "8-15-1992" ) ). $aDateStr1 )./format_funcs. print( " gości " ). Jednak ponowne wykorzystanie kodu może jedynie wymagać przewidywania przyszłych projektów. Funkcje te eliminują problem występujący przy wielokrotnym dołączaniu do skryptu tego samego pliku.php <?php function GetFormattedNumber( $aNum ) { return number_format( $aNum. $aTime1 = mktime( 0. Niektóre z tych metod zostaną opisane w późniejszych częściach.'.2. o których należy pamiętać przy projektowaniu aplikacji. print( GetDateDiff( "9-21-2000". Omówione zostaną teraz niektóre techniki dostępne w PHP. $aDateStr2 ). 0. Wydruk 11./format_funcs. Plik dołączany format_funcs.

można utworzyć obiekty PHP używające implementacji w C++." ). print( "Witrynę odwiedziło " ). n = l * 12. że mamy trzy funkcje zamieszczone na wydruku 11. Ten mechanizm dołączania plików pozwala na tworzenie własnych bibliotek często używanych funkcji oraz wykorzystanie kodu od zewnętrznych dostawców. że plik dołączany date_funcs.Problem występujący w skrypcie z wydruku 11. Ponieważ PHP obsługuje dołączanie modułów oraz programowanie obiektowe.php" ). 133 PHP – Kompendium wiedzy .3 wynika z tego. który ma być przeniesiony do środowiska WW. pokazane zostało jak łatwo można rozwiązać ten problem korzystając z funkcji include_once(). C/C++ PHP jest napisany w C i C++. naturalnie pozwala na tworzenie kodu wielokrotnego użycia. j = i / (12 * 100). print( GetDateDiff( "9-21-2000". Wydruk 11. Jeżeli posiadasz istniejący kod projektu w C lub C++.php on line 2 Na wydruku 11. Wydruk 11. Skupmy się teraz na tworzeniu wbudowanych funkcji PHP opartych o istniejące funkcje w C./format_funcs. które można ponownie wykorzystywać lub rozszerzać. Funkcje te są wykorzystywane do obliczania płatności hipotecznych i tworzenia tabel amortyzacji w USA.4. Z tego powodu możliwa jest integracja istniejącego kodu C/C++ bezpośrednio w PHP. Na przykład CyberCashTM Merchant Control Kit został napisany w C a jego funkcje są dostępne w PHP jako funkcje cybercash_xxx(). Funkcje w C do konwersji na PHP /* _fin_mpmt: oblicza miesięczną spłatę kredytu w oparciu o kwotę kredytu (p). Pierwsze dwie funkcje zwracają pojedyncze wartości oznaczające odpowiednio ratę miesięczną i sumę wszystkich rat. że wymaga to sporo pracy i w efekcie może być mniej efektywne. Używając tych danych można wygenerować harmonogram amortyzacji. oprocentowanie (i) oraz czas (l) */ double _fin_mpmt (double p. Skrypt wykorzystujący include_once() <?php include_once( ". Ostatnia funkcja zwraca tabelę wartości reprezentujących wartość odsetek miesięcznych w racie. print( "w przeciągu ostatnich " ). Można zamiast tego napisać funkcje mapujące dla metod istniejących obiektów C++. Należy jednak pamiętać. niż proste przepisanie kodu na PHP. "8-15-1992" ) ). print( " dni. print( " gości " ). ?> </body> </html> Funkcje require() i require_once() działają podobnie.4. Po uruchomieniu skryptu generowany jest komunikat błędu: Fatal error: Cannot redeclare getformattednumber() in . print( GetFormattedNumber( $aNumVisitors ) ).php" ). Jeżeli istniejący kod jest napisany w C++. Dodatkowo PHP obsługuje tworzenie klas obiektowych.php.5./date_funcs. double i./format_funcs. ?> <html> <head> <title>Problem z wielokrotnym dołączaniem plików</title> </head> <body> <?php $aNumVisitors = 14500.php dołącza również plik format_funcs.5 i chcemy na ich podstawie utworzyć wewnętrzne funkcje PHP. ale nie opiszemy tutaj tego procesu. rozszerzalność PHP pozwala na wykorzystanie innego istniejącego kodu. Tak naprawdę wiele z rozszerzeń PHP jest bezpośrednio przeniesiona z C lub C++. Załóżmy. double n. W poprzednich rozdziałach zostały pokazane przykłady rozszerzania klas pochodzących z od różnych dostawców. możesz rozważyć dołączenie tego kodu do twojej instalacji PHP. include_once( ". Oprócz tego. double l) { double j.

nIndex < n. } /* _fin_total: oblicza całkowitą kwotę spłat w czasie trwania kredytu w oparciu o kwotę kredytu (p). double i. i inne ustawienia generacji kodu. } return .c.m4 jest pokazany poniżej (komentarze zostały usunięte): PHP_ARG_ENABLE(fin_funcs. Uruchom skrypt buildconf w głównym katalogu PHP. double interest. m = _fin_mpmt( p.proto --assign-params Parametr extname jest nazwą nowego rozszerzenia PHP. i czas (l) */ void _fin_table ( double p. Uruchom skrypt configure i dodaj obsługę nowego rozszerzenia. 4. Program ten znajduje się w katalogu ext dystrybucji PHP zawierającej pliki źródłowe. whether to enable fin_funcs support. $ext_shared) fi Funkcja build_skel tworzy plik źródłowy w C. Skompiluj PHP. Po uruchomieniu skryptu w sposób przedstawiony powyżej./build_skel --extname=fin_funcs --proto=/sciezka/do/fin_funcs. który zawiera pliki rozszerzeń wymagane przez PHP. for (nIndex = 0. natomiast proto jest nazwą pliku zawierającego prototypy tworzonych funkcji. n = l * 12. który służy do tworzenia zbioru szkieletowych plików konfiguracji dla nowych rozszerzeń PHP. c. Inne dostępne parametry pozwalają kontrolować wygląd dokumentacji. oprocentowanie (i). j. Skrypt testowy wykrywający. pIntPmt[nIndex] = h. q = q . } /* _fin_table: oblicza miesięczne odsetki używane w planie amortyzacji dla kredytów w oparciu o kwotę (p). Pierwsza zmiana musi zostać wprowadzona do pliku config. 1. i. Plik prototypów powinien zawierać prototypy funkcji PHP. co zostanie opisane później. double length ) array fin_table ( double principle. Dla funkcji finansowych użyjemy następującej zawartości pliku prototypów: double fin_mpmt ( double principle. double length ) Parametr assign-params powoduje. m. c = m . j = i / (12 * 100). który zawiera wymagane funkcje i dołączone pliki nagłówków. Plik ext/fin_funcs/config.4m. double l.m4 można skompilować PHP z obsługą nowych rozszerzeń. czy rozszerzenie jest aktywne w PHP. q. 3. W pliku tym zawarty jest opis omawiający wymagane zmiany. i. że pliki szkieletowe dołączają parametry o prawidłowych typach. } W dystrybucji PHP dostarczany jest program o nazwie build_skel.php) aby sprawdzić. double interest. double interest. (n * -1)))))). oprocentowanie (i) i czas (l) */ double _fin_total (double p. 2. l) * l * 12. można wykonać następujące czynności: 1. then AC_DEFINE(HAVE_FIN_FUNCS. więc natychmiast po uruchomieniu tego narzędzia i poprawieniu pliku config. q = p. l ). nIndex++ ) { h = q * j. tworzony jest nowy katalog ext/fin_funcs.return ( p* ( j/( 1 . Testowy moduł rozszerzenia jest uaktywniany za pomocą dyrektywy konfiguracji --enable-fin_funcs. double length ) double fin_total ( double principle. Aby upewnić się. Więcej szczegółów można uzyskać uruchamiając skrypt build_skel bez parametrów.(pow(( 1+j ). [ ]) PHP_EXTENSION(fin_funcs. że pliki szkieletowe i konfiguracyjne są prawidłowe. Wykonaj skrypt testowy z katalogu z rozszerzeniem (fin_funcs. int nIndex. Aby dodać funkcje finansowe do PHP należy uruchomić build_skel w następujący sposób: . double *pIntPmt) { double n. double l) { return _fin_mpmt( p. czy rozszerzenie działa jest podobny do następującego: Rozdział 11 – Ponowne wykorzystanie kodu 134 . double i.h. [ --enable-fin_funcs Enable fin_funcs support]) if test "$PHP_FIN_FUNCS" != "no". h.

&interest_arg. int n. aby korzystał z nowego rozszerzenia. } /* }}} */ /* {{{ proto double fin_total(double principle. double length) */ PHP_FUNCTION(fin_total) { zval **principle_arg. **length_arg. double interest. principle = Z_DVAL_PP(principle_arg). double length. double interest. **interest_arg. aby zawierał implementację każdej z funkcji. Wydruk 11. RETVAL_DOUBLE( aRetVal ). że skrypt build_skel wygenerował większość kodu w ciele każdej funkcji. convert_to_double_ex(interest_arg). Kod dodany ręcznie zaznaczony jest czcionką pogrubioną. **interest_arg. interest = Z_DVAL_PP(interest_arg). **interest_arg. **length_arg. 135 PHP – Kompendium wiedzy . W przykładzie z funkcjami finansowymi. interest. } ?> Po skonfigurowaniu PHP. principle = Z_DVAL_PP(principle_arg). należy jeszcze uaktualnić plik extension. &principle_arg. RETVAL_DOUBLE( aRetVal ). Funkcje finansowe dodane do PHP /* {{{ proto double fin_mpmt(double principle. double length. double principle. double length) */ PHP_FUNCTION(fin_table) { zval **principle_arg. convert_to_double_ex(length_arg). interest. We wielu przypadkach wymaga to jedynie dołączenia oryginalnych nagłówków i wywołaniu oryginalnych funkcji. &interest_arg. convert_to_double_ex(interest_arg).c. double interest.6. aRetVal = _fin_total( principle. double interest.<?php if (extension_loaded( "fin_funcs" )) { // Wykonaj jedną z funkcji } else { print( "moduł fin_funcs niedostępny<BR>" ). double aRetVal. if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3. interest = Z_DVAL_PP(interest_arg). double length) */ PHP_FUNCTION(fin_mpmt) { zval **principle_arg. &principle_arg. double interest. } convert_to_double_ex(principle_arg). } /* }}} */ /* {{{ proto array fin_table(double principle. aRetVal = _fin_mpmt( principle. double principle. &length_arg) == FAILURE){ WRONG_PARAM_COUNT. double interest. double *pIntPmts. length ). funkcje są zdefiniowane w sposób pokazany na wydruku 11. **length_arg. length = Z_DVAL_PP(length_arg).6. if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3. double principle. } convert_to_double_ex(principle_arg). convert_to_double_ex(length_arg). Należy zauważyć. length = Z_DVAL_PP(length_arg). double length. nIndex. length ). double aRetVal. &length_arg) == FAILURE){ WRONG_PARAM_COUNT.

że PHP wykona normalny proces odzyskiwania nieużytków. Ostania funkcja jest utworzona w taki sposób. Użycie funkcji finansowych dodanych do PHP <html> <head> <title>Kalkulator kredytowy</title> </head> <body> <?php if ( $REQUEST_METHOD == 'POST' ) { print( "Kwota pożyczki: <b>" . &interest_arg. number_format( $aMontlyPayment. druga wywołuje wewnętrzną funkcję obliczającą wartość a trzecia ustawia zwracaną wartość. principle = Z_DVAL_PP(principle_arg). $Term ). } convert_to_double_ex(principle_arg).7 pokazujemy przykład użycia nowego rozszerzenia. $Interest. $Term ). Pierwsza linia jest deklaracją zmiennej. aby zwracała tablicę PHP. Po pierwsze. Na koniec tymczasowa tablica jest niszczona i funkcja się kończy. "fin_table: nie udało się utworzyć tablicy"). interest. Implementacja funkcji fin_table() pokazuje kilka technik ważnych dla programowania dla PHP. $Interest. } else { for ( nIndex = 0. pIntPmts[nIndex]). W implementacji fin_table() pamięć jest przydzielana dla tablicy tymczasowej zawierającej wartości wygenerowane przez funkcję C _fin_table(). print( "Czas spłaty: <b>$Term lat</b><br><hr>" ). } efree( pIntPmts ). </td> <td> Podstawa </td> <td> Odsetki </td> </tr> <?php $nIndex = 1. nIndex++ ) add_next_index_double( return_value. length = Z_DVAL_PP(length_arg). interest = Z_DVAL_PP(interest_arg). 2 ) . } /* }}} */ W pierwszych dwóch funkcjach do implementacji rozszerzenia wymagane było napisanie jednie trzech linii kodu. print("Rata miesięczna: <b>" . Wymaga to nieco więcej pracy od dwóch pierwszych funkcji. n = (int)length * 12. $Interest. $aMontlyPayment = fin_mpmt( $Amount. $Term ). "</b><br>"). _fin_table( principle. Rozdział 11 – Ponowne wykorzystanie kodu 136 . number_format( fin_total( $Amount. ?> <table border="1"> <tr> <td> Rata nr. if (array_init(return_value)== FAILURE ) { php_error( E_ERROR. wartości z tablicy C są kopiowane do nowej tablicy PHP. natomiast efree() zapewnia. Po wywołaniu funkcji wbudowanej. Następnie przy pomocy pętli przebiegającej po kolejnych komórkach tablicy i kolejnych wywołań funkcji add_next_index_double(). mogą być one wywoływane identycznie. nindex < n. convert_to_double_ex(interest_arg). 2 ) .if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3. print( "Oprocentowanie: <b>{$Interest}%</b><br>" ). $aArray = fin_table( $Amount. Po wbudowaniu tych funkcji w PHP. Na wydruku 11. print( "Suma rat: <b>" . jak inne wewnętrzne funkcje PHP. przydział pamięci jest przeprowadzany za pomocą funkcji emalloc(). &length_arg) == FAILURE){ WRONG_PARAM_COUNT.7. length. "</b><br><br>" ). ale wyniki tej pracy są znaczące. "</b><br>" ). Wydruk 11. zwracana wartość jest deklarowana przy pomocy wywołania funkcji array_init() jako tablica PHP. pIntPmts = emalloc( sizeof( double ) * n ). pIntPmts ). &principle_arg. number_format( $Amount ) . convert_to_double_ex(length_arg).

wywoływane są funkcje finansowe i wyświetlane wyniki ich działania.1. a następnie wysyła je do samego siebie. ?> <tr> <td> <?=$nIndex?> </td> <td> <?=$aPrinciple?> </td> <td> <?=$aIntPmt?> </td> </tr> <?php $nIndex++. oprocentowanie i czas spłaty </td> </tr> <tr> <td> Kwota: </td> <td> <input type="text" name="Amount"> </td> </tr> <tr> <td> Oprocentowanie ("7. Po wywołaniu go poprzez wywołanie HTTP POST.$aIntPmt. } ?> </table> <?php } ?> <form action="<?=$PHP_SELF?>" method="post"> <table> <tr> <td colspan="2"> To jest prosty kalkulator rat kredytu.foreach( $aArray as $aIntPmt ) { $aPrinciple = number_format( $aMontlyPayment . 2 ).5" == 7. 137 PHP – Kompendium wiedzy . Wprowadź kwotę pożyczki. Na rysunku 11.5%): </td> <td> <input type="text" name="Interest"> </td> </tr> <tr> <td> Czas spłaty (w latach): </td> <td> <input type="text" name="Term"> </td> </tr> <tr> <td colspan="2"> <input type="submit" name="Submit" value="Wyślij"> </td> </tr> </table> </form> </body> </html> Skrypt ten wyświetla formularz do wprowadzenia danych kredytu. pokazany jest fragment strony będącej wynikiem typowego wykonania programu. $aIntPmt = number_format( $aIntPmt. 2 ).

Dodatkowo. Z powodu popularności Javy. Metoda ta zostanie opisana w dalszej części rozdziału. dostępne jest wiele klas i modułów klas Javy. Inną możliwością wykorzystania istniejącego kodu C/C++ jest jego skompilowanie i wykonywanie na serwerze WWW poprzez PHP. Rozdział 11 – Ponowne wykorzystanie kodu 138 . Zaletą tego rozwiązania jest możliwość ponownego wykorzystania dobrze przetestowanego kodu oraz dobra wydajność skompilowanego kodu. więc należy przekompilować PHP. Dodatkowo kroki podjęte w czasie integracji muszą być w części powtórzone dla każdej nowej wersji PHP. jeżeli PHP jest uruchamiany jako program CGI lub dynamicznie włączany moduł Apache. Przytoczony wcześniej przykład może być łatwo przepisany na PHP i zajmie to mniej czasu. musisz przekompilować PHP w celu dodania obsługi Javy. Jeżeli serwer Apache nie posiada obsługi dynamicznych modułów. Rozważając integrację istniejącego kodu C/C++ z PHP należy wziąć pod uwagę. jeżeli masz dużą bibliotekę kodu C/C++ pochodzącą z istniejących aplikacji i zamierzasz przenieść je do środowiska WWW. W podręczniku PHP znajdziemy. PHP posiada prosty mechanizm integracji istniejącego kodu z nowymi aplikacjami. Z powodów bezpieczeństwa nie zaleca się korzystania z PHP w postaci CGI. należy go wcześniej przekompilować. Jeżeli zamierzasz zawsze korzystać z najnowszej wersji PHP. które nie mogą być w chwili obecnej zrealizowane przy pomocy funkcji PHP. że nie można wykorzystać opcji konfiguracji --with-java.Rysunek 11. Opcja ta działa. Java W rozdziale 9. Obsługa Javy nie jest włączona domyślnie do PHP. „Niezależność od przeglądarki” przedstawiony został opis połączenia Javy z PHP. aby móc skorzystać z tego potężnego narzędzia. powoduje to konieczność ciągłej konserwacji istniejącej witryny. Dodawanie obsługi Javy w PHP na *niksach Jeżeli korzystasz z PHP na platformie *nix. oferowanych przez wielu niezależnych dostawców. Możliwość używania klas Javy została wprowadzona w PHP4. Na przykład implementacja bezpiecznych gniazd zapewnia możliwości.1. których nie da się napisać wyłącznie w PHP. jeżeli posiadasz PHP statycznie włączone w Apache. Wykorzystanie nowych funkcji finansowych Jak wspomniano wcześniej. funkcje napisane w C lub C++ mogą realizować funkcje. że koszt integracji może być wyższy od kosztu przepisania kodu na PHP.

make clean . w których użytkownicy mogą wysyłać takie pliki.so Po skonfigurowaniu obsługi Javy.jar" java.path=/usr/lib/kafee:/home/blake/php-4. Tak jak jest to w przypadku każdego języka umożliwiającego tworzenie komponentów. że będzie uruchomiony z głównego katalogu instalacji PHP.library. wykorzystanie RTF pozwala użytkownikowi na dostarczanie plików bez niebezpieczeństwa bezpośredniego dodawania kodu HTML do witryny.jar java.jar:/home/blake/php4. Następnie należy dodać odpowiednio sekcję z opcjami konfiguracji.. który można załadować z witryny www.home=/usr/lib/kaffe java. Dołączanie obsługi Javy w PHP dla Windows Zamiast kompilowania specjalnej wersji PHP dla Windows.jar:/home/blake/java/sax2. musisz dodać kilka opcji konfiguracji do pliku php. W Windows sekcja ta powinna wyglądać podobnie do następującej: [java] java.php. Pozostałe opcje zostaną omówione później.path=/usr/share/kaffe/Klasses.dll). Po zakończeniu kompilacji można sprawdzić konfigurację PHP za pomocą funkcji phpinfo().dll" W przypadku systemów *nix.Poniższy skrypt powoduje przekompilowanie Apache tak. java.jar:/home/blake/java/scrooge.class. Jak widać na zamieszczonych opcjach konfiguracji. sekcja ta jest następująca: [java] java.path="D:\php4\php_java. Można to zrobić przy pomocy java -showversion.D:\PHP4 book\other\RTF2HTML\lib\Scrooge_09b7.so).3" java.path zawiera pełną ścieżkę do plików implementacji..0.dll do katalogu systemowego.) którego możemy użyć do sprawdzenia siły i elastyczności modułu.ini.jar:/home/blake/bhawk/lib/bhawk4j. Następnie należy uaktualnić plik php. Są one kluczowe do prawidłowego działania Javy na każdej platformie. że będzie on uruchomiony z głównego katalogu instalacji Apache.p12/ext/java/php_java.ini musisz podać lokalizację klas Javy lub plików JAR. w pliku php. rozszerzenie Javy jest dostępne do pobrania z www.ini.jar:/home/blake/bhawk:/home/blake/java/num berspeller.3\bin\hotspot\jvm. Jednym z dostępnych komercyjnie modułów Javy jest konwerter RTH na HTML Scrooge. Ponieważ RTF obsługuje różne czcionki i układy.0. Opcje konfiguracji Javy Niezależnie od platformy. Należy również ustawić kilka opcji konfiguracji Javy w pliku php.de.jar.2. jeżeli obsługa Javy jest aktywna w PHP.library=/www/libexec/libkaffevm. Zakładamy w nim. Funkcja ta może być wykorzystywana we wielu aplikacjach.betabeans. dla Javy dostępne jest wiele narzędzi.home="D:\Program Files\JavaSoft\JRE.library="D:\Program Files\JavaSoft\JRE.class. Moduł Scrooge zawiera przykładowy plik RTF (pokazany na rysunku 11. której chcesz używać. który będzie potrzebny do skompilowania PHP. Należy to wykonać dla każdej używanej klasy Javy. aby korzystał z dynamicznie ładowanych modułów oraz tworzy właściwie skonfigurowany skrypt apxs. Należy pobrać odpowiedni plik rozszerzenia i skopiować php_java. make make install Opcja --with-java może zawierać ścieżkę oznaczającą katalog instalacji używanej maszyny wirtualnej Javy.1p12/modules java. Powinieneś sprawdzić która wersja JDK (Java Development Kit) jest zainstalowana na serwerze. z których można skorzystać za pomocą języka obsługującego API.class. 139 PHP – Kompendium wiedzy .1. Należy doda linię ładującą rozszerzenie (extension=php_java. Moduł ten posiada prosty interfejs używany do konwertowania plików RTF na standardowy HTML.net. W skrypcie tym zakładamy. Pierwsza jest linia z dołączeniem rozszerzenia (extension=libphp_java. make clean .jar:/home/blake/java/servlet.ini./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. W Windows 95 jest to zwykle \windows\system a Windows NT \winnt\system32./configure --with-apxs=/www/bin/apxs --with-java .

Po przesłaniu danych formularza sprawdzany jest typ pliku i jeżeli jest prawidłowy tworzony jest obiekt Scrooge. Wydruk 11.Rysunek 11. } } ?> <FORM METHOD="POST" ACTION="<?=$PHP_SELF?>" enctype="multipart/form-data"> Przesyłanie pliku: <INPUT TYPE="file" NAME="rtffile"><br><br> <INPUT TYPE="submit" NAME="submit" value="Wyślij"> </FORM> </BODY> </HTML> Skrypt ten zawiera formularz przesyłania pliku. print( $aOutput ). oraz listę dostępnych metod i właściwości. Rozdział 11 – Ponowne wykorzystanie kodu 140 . Przykładowy plik RTF modułu Scrooge Użycie modułu Scrooge jest łatwe i proste.scrooge. W skrypcie z wydruku 11. Użycie modułu Javy Scrooge <HTML> <HEAD> <TITLE>Konwersja RTF na HTML</TITLE> </HEAD> <BODY> <?php if ($REQUEST_METHOD == 'POST' ) { if ( ( $rtffile_type == "text/richtext" ) || ( $rtffile_type == "application/rtf" ) ) { // utworzenie obiektu Scrooge $aR2H = new Java ("de.2. Dołączona dokumentacja zawiera nazwę klasy Javy.Scrooge").8. $aArray) ).8 pokazane jest wykorzystanie tego modułu. } else { print ("Wybrany plk nie jest plikiem <b>RTF</b>.<BR>"). $sR2H->setOptWrapHTML( False ). $aOutput = $aR2H->convert( implode( "". $aArray = file ( $rtffile ).betabeans. za pomocą którego użytkownik może przesłać plik RTF.

$aArray = split( "[ ]+". W części tej omówimy serwer konwersji walut Cloanto Currency Server. pokazują formularz z cenami w dwóch różnych walutach. } pclose( $aProgFile ). że użycie COM w PHP jest bardzo naturalne. Użycie serwera konwersji walut Cloanto <html> <head> <title>Użycie potoków</title> </head> <body> <?php $aFreeProg = '/usr/bin/free'. while ( !feof( $aProgFile ) ) { $aLine = fgets( $aProgFile. Wynik przetworzenia przykładowego pliku RTF na kod HTML Java jest tylko jednym z języków umożliwiających tworzenie komponentów. Na rysunku 11. a następnie używając funkcji implode(). $aLines[$nIndex++] = $aLine. ?> Całkowita ilość dostępnej pamięci <?=$aTotalK?> KB. Obiekt ten posiada bogaty zestaw metod. przedstawiony jest wynik uzyskany z przykładowego pliku RTF. które można wykorzystać w środowisku PHP. $aLines = array(). Na wydruku 11. Implementacja COM w PHP ewoluowała z opartego o funkcje API w wersji 3.<br> <?php } else 141 PHP – Kompendium wiedzy . if ( !is_file( $aFreeProg ) ) { print( "Nie można znaleźć programu na serwerze<br>" ).2]. Standardowa instalacja PHP dla Windows posiada obsługę COM. zamieszczony jest przykład wykorzystania tego obiektu. $aTotal = $aLines[$aCount . $aTotalK = number_format( $aArray[1] ). $aFreeK = number_format( $aArray[3] ). Obiekt ten pozwala na przeliczanie walut pomiędzy sobą i posiada wewnętrzną bazę danych kursów.Przesłany plik jest odczytywany do tablicy za pomocą funkcji file(). więc nie jest potrzebna dodatkowa konfiguracja. $aTotal ). ale bardzo łatwo można użyć podstawowych funkcji w środowisku testowym. Wydruk 11. Rysunki 11. i 11. nie potrafię uruchomić tego przykładu Rysunek 11. Zwracaną wartością jest ciąg zawierający kod HTML utworzony na podstawie przesłanego pliku. 1024 ). tablica jest konwertowana na ciąg. więc dyskusja ta odnosić się będzie do PHP działającego na serwerze pracującym pod kontrolą systemu Windows.<br> Użyte <?=$aUsedK?> KB. if ( $aProgFile = popen( $aFreeProg . COM COM jest z natury oparty o Windows. Powoduje to. 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.9. } else { $aLines = array(). dostępny z witryny http://cloanto.9. " -t". $aCount = count( $aLines ).3.com. do implementacji obiektowej w PHP 4.<br> Wolna pamięć <?=$aFreeK?> KB. Wynikowy kod HTML jest wysyłany do przeglądarki. "r" ) ) { $nIndex = 0.4. Baza ta jest automatycznie uaktualniana.5. Następna część opisuje użycie obiektów COM w PHP. który jest przekazywany do obiektu Scrooge.3. $aUsedK = number_format( $aArray[2] ).

Po przesłaniu danych formularza skrypt wykorzystuje serwer Cloanto do przeliczenia cen na wybraną walutę. wyświetlana waluta: dolary amerykańskie Rysunek 11. 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ę. Rozdział 11 – Ponowne wykorzystanie kodu 142 . Obiekt ten jest używany do uzyskania listy krajów. współczynników wymiany oraz wykonuje przeliczanie na bieżąco.4. Jeżeli tworzona jest aplikacja handlu elektronicznego. utworzona jest prosta tabela cen dla trzech różnych towarów. która eliminuje frustrujące pomyłki w liczeniu cen.{ print ( "Nie można użyć programu na serwerze<br>" ). } } ?> </body> </html> Rysunek 11.9. wyświetlana waluta: forinty węgierskie W skrypcie umieszczonym na wydruku 11. Przykład użycia serwera Cloanto.5. Przykład użycia serwera Cloanto. przy pomocy tego obiektu można dodać niezwykle przydatną dla użytkowników funkcję. Dodatkowo dostępny jest formularz do wyboru lokalnej waluty.

" -t". ale podstawowa idea jest ta sama. W przypadku systemów Unix oznacza to. $aTotal ). } else { $aLines = array(). dostępnego na większości systemów *nix. $aArray = split( "[ ]+". Ponieważ tematem tego rozdziału jest integracja. $aUsedK = number_format( $aArray[2] ). Technika ta była przedstawiona w rozdziale 4 „Operacje na plikach”. W zależności od zwracanych danych może być niezbędna bardziej zaawansowana analiza. if ( !is_file( $aFreeProg ) ) { print( "Nie można znaleźć programu na serwerze<br>" ). którego nie da się wykorzystać przy użyciu żadnej z przedstawionych metod. Skrypt otwiera potok. 1024 ).Z powodu dużej ilości programistów Windows oraz dojrzałości modelu COM. Użycie potoków do integracji PHP z istniejącymi skryptami lub programami wykonywalnymi <html> <head> <title>Użycie potoków</title> </head> <body> <?php $aFreeProg = '/usr/bin/free'. da się go zastosować w skrypcie. Wydruk 11. ?> Całkowita ilość dostępnej pamięci <?=$aTotalK?> KB. dostępne jest wiele komponentów dla wszystkich typów projektów. nadal można go wykorzystać w PHP. który powoduje uruchomienie programu. "r" ) ) { $nIndex = 0. że można w ten sposób użyć nieomal każdej komendy bezpośrednio z PHP – Kompendium wiedzy 143 . $aLines[$nIndex++] = $aLine. $aCount = count( $aLines ). Na wydruku 11.10. Skrypt odczytuje z potoku kolejne wiersze wyniku i wyświetla je w przeglądarce. Technika ta może być użyta dla każdego programu. $aTotalK = number_format( $aArray[1] ). if ( $aProgFile = popen( $aFreeProg . $aTotal = $aLines[$aCount . Program zwraca dane na temat ilości dostępnej pamięci w komputerze. PHP posiada kilka funkcji służących do uruchamiania programów i skryptów na serwerze. Inne metody Prawdopodobnie posiadasz istniejący kod.2]. Jeżeli tak się stanie.<br> <?php } else { print ( "Nie można użyć programu na serwerze<br>" ). } } ?> </body> </html> Skrypt ten otwiera potok do standardowego programu free. } pclose( $aProgFile ). Używając obsługi COM w PHP można z łatwością wykorzystać istniejący kod we własnych projektach.<br> Wolna pamięć <?=$aFreeK?> KB. $aLines = array().10. Jeżeli kod ten jest skryptem (na przykład skryptem Perla) lub można go skompilować do postaci wykonywalnej. $aFreeK = number_format( $aArray[3] ). 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. while ( !feof( $aProgFile ) ) { $aLine = fgets( $aProgFile. który zwraca wyniki na standardowe wyjście. na przykładzie programu whois.<br> Użyte <?=$aUsedK?> KB. pokazany został przykład odczytywania bieżącej ilości użytej pamięci w systemach *nix.

Seattle: Microsoft Press. Rozdział 11 – Ponowne wykorzystanie kodu 144 . można otrzymać aplikację łatwiejsza w konserwacji i skalowaniu. Rapid Development. Pozwala to na szybsze rozpoczęcie testowania funkcji aplikacji minimalizując ilość koniecznych prac programistycznych. Pozwala to łatwo zrealizować odczytanie statusu systemu. Używając ich mądrze. Bibliografia Steve McConnell. że uruchamianie programów wymaga znacznej ilości zasobów serwera. 1996. że aplikacja będzie powolna i trudna do skalowania. Używając tych komponentów można znacznie zmniejszyć czas potrzebny na napisanie programu.PHP. zwracanie danych lub inne operacje. Należy jednak zaznaczyć. Planując tworzenie biblioteki kodu w PHP przeznaczonej do wielokrotnego użytku lub przenosząc istniejący kod do aplikacji WWW. Jeżeli trzeba przenieść istniejący kod do PHP. 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ć. Podsumowanie W PHP nie brakuje możliwości ponownego użycia kodu. że większość projektowanej aplikacji jest już napisana. pozwala to na szybkie prototypowanie. co może powodować. przed zastosowaniem wcześniej opisanych metod.

W przypadku projektowania dla WWW. . Gdy tworzenie interfejsu i kodu jest rozdzielone pomiędzy zespołami lub osobami. ale wiele małych zmian ogranicza się do pojedynczej warstwy. a w rozległych testach programiści osiągali o 15% lepsze wyniki pracując nad programem modularnym niż nad niemodularnym (McConnell. W praktyce nadal jest to trudne. że konserwacja aplikacji jest prostsza i bardziej efektywna. moduły mogą zawierać dane będące częścią interfejsu. Według badań 89% użytkowników kodu zgłaszało poprawienie możliwości utrzymania aplikacji modularnej. które pozwala na łatwiejsze użycie istniejących modułów. 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. możliwe jest. rysunki przycisków i podobne elementy wpływające na graficzny wygląd produktu. dostępne dla większości programistów. Najważniejszym zadaniem przy projektowaniu wielowarstwowym jest logiczne oddzielenie warstw a nie ich fizyczna implementacja. Tak jak w przypadku wszystkich aplikacji.Rozdział 12. że nie będzie konieczne ponowne kodowanie. 1993). prawa autorskie lub mogą być modułami kodu. Na przykład: graficy i projektanci przygotowują stronę graficzną aplikacji. • Możliwość zmian w warstwie bez potrzeby modyfikacji innych. Wprowadzenie Programowanie dla WWW jest często nazywane tworzeniem aplikacji wielowarstwowej. 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. Dodatkowo oddzielenie interfejsu użytkownika od logiki aplikacji jest jedną z technik programowania modularnego. warstwa aplikacji (biznesowa) oraz warstwa bazy danych. że standardowe aplikacje wykorzystują standardowe narzędzia tworzenia interfejsu użytkownika. Nawet w małych jednoosobowych projektach oddzielenie HTML od logiki aplikacji powoduje. Głównymi zaletami podejścia wielowarstwowego przy tworzeniu aplikacji WWW są: • Możliwość przydzielenia zadań osobom najlepiej przygotowanym do ich realizacji. np. • Możliwość przeniesienia bądź replikacji określonych warstw na inny sprzęt w celu zapewnienia skalowania bądź nadmiarowości. Jeżeli zmiany te są ograniczone do jednej warstwy. Jedynymi fragmentami tworzonymi przez inne osoby są emblematy. 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. W programowaniu tradycyjnym projekt modularny jest zwykle postrzegany jako tworzenie modułów kodu. oddzielenie kodu i HTML staje się naturalne a integracja wyników pracy ważna. ponieważ stosowane są tutaj oddzielne logiczne warstwy. Często używanymi nazwami warstw są: warstwa prezentacji. Celem tego rozdziału jest pokazanie sposobów tworzenia aplikacji odpornych na zmiany w późnych stadiach rozwoju. podczas trwania projektu aplikacji dla WWW mogą pojawić się żądania wprowadzenia zmian. Każda z tych warstw może być fizycznie oddzielona od drugiej. które mogą być używane w dowolnych aplikacjach. Jest to spowodowane tym. Programowanie dla WWW. programiści tworzą logikę aplikacji a projektanci baz danych projektują i uruchamiają infrastrukturę bazy danych.

Jak wspomniano w poprzednim rozdziale. W wszystkich przykładach umieszczonych do tej pory w książce. wyzwalacze i zdalne procedury (Fournier.1. 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. PHP i HTML w jednym skrypcie <?php if ( $aShowForm == True ) { ?> <p> <font face="Arial" size="3"> <b> <?php print( $aQuestion ). W kolejnych częściach zostanie opisane kilka metod implementacji tych metod. że wspólne fragmenty lub moduły aplikacji zawsze powinny być najpierw projektowane. Wydruk 12. Rozdział 12 – Oddzielanie kodu HTML od PHP 146 . ale również procedury przechowywane w bazie danych. Dodatkowo w tym rozdziale jak również w rozdziale 14 „Witryny oparte o szablony”. } else { $aSQL = "SELECT * FROM Answers WHERE (QuestionID=$aQuestionID)". } $aDB->SetSQL( $aSQL ). W książce A Methodology for Client/Server and Web Application Development Roger Fournier sugeruje. Dla przykładu. 1998). tworzone i testowane a następnie udostępniane dla całej korporacji. Komponenty te powinny zawierać nie tylko moduły kodu. ?>"> <?php } ?> <ul> <font face="Arial" size="2"> <!--wyświetl możliwe odpowiedzi--> <?php if ( $aQuestionID != -1 ) { if ($aSortOrd != 0 ) //Sortowanie alfabetyczne { $aSQL = "SELECT * FROM Answers WHERE (QuestionID=$aQuestionID) ORDER BY Text". Motywacja Pierwszą motywacją dla oddzielenia elementów HTML od kodu jest umożliwienie ponownego wykorzystania kodu oraz jego łatwiejszej konserwacji. W przypadku tworzenia kodu prawdziwego kodu technika ta jest niewygodna i powoduje powstanie trudnych do analizy skryptów. skrypt z wydruku 12. ?> </b> <form action="response. ?>"> <?php } ?> <?php if ($aQuestionID != -1 ) { ?> <input type="Hidden" name="QuestionID" value="<?php print($aQuestionID ). Część ta opisuje kilka sposobów zrealizowania tego zadania. tworzenie aplikacji modularnej wymaga dodatkowych prac projektowych i podjęcia odpowiednich decyzji.php3" method="POST"> <?php if (!empty( $UserID )) { ?> <input type="Hidden" name="UserID" value="<?php print($aUserID ). dołączone są kompletne przykłady zastosowania tych technik. HTML i PHP były wymieszane w celu otrzymania krótkich i prostych przykładów. Niektóre przykłady w kolejnych częściach pokazują techniki jakich należy unikać.1 zawiera fragment strony WWW ze zintegrowanym kodem PHP i HTML. ale w efekcie można otrzymać aplikację łatwiejszą do zrozumienia i konserwacji.

jpg" width="250" height="68" alt="" border="0"> <h1>Nowości wydawnictwa Helion</h1> Mimo. a programiści mogą być zmuszeni uaktualniać fragmenty kodu jedynie w celu zmiany wyglądu. Na wydruku 12.2. jeżeli zainwestowano w projekt interfejsu. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4. Fragment z nagłówkiem HTML require().3 umieszczone są fragmenty projektu strony rozdzielonej na nagłówek i stopkę. Jeżeli twoja firma zamierza dostarczać wysokiej jakości i łatwe do konserwacji aplikacje WWW. 2001 Helion. że projektanci uaktualnią wygląd przycisków nawigacji i muszą być one umieszczone w witrynie. ponieważ projektanci mogą nie mieć wystarczająco dużo doświadczenia.0 Transitional//EN"> <html> <head> <title>Nowe książki wydawnictwa Helion</title> </head> <body> <img src="logo. </p> </body> </html> Wydruk 12. tworzenie stron za pomocą przedstawionej metody nie powinno być stosowane. aby nie popsuć kodu podczas wprowadzania zmian. które są używane przez moduły kodu PHP w czasie ich wykonywania. należy zmienić jedynie pliki HTML. że przykład jest niekompletny.1 pokazany jest wygląd wynikowej strony w przeglądarce. zlokalizowanie bloków kodu może być trudne.0 Transitional//EN"> <html> <head> <title>Nowe książki wydawnictwa Helion</title> </head> <body> <img src="logo. Odpowiedź na pytanie kto powinien wprowadzić zmiany jest trudna. Nawet pomocą edytorów wyróżniających składnię. co ułatwia tworzenie efektywnych i łatwych do modyfikacji aplikacji. Dodatkowo. 147 PHP – Kompendium wiedzy .3. jest to bardzo prosty przykład. Na przykład.2 i 12. Wydruk 12. Jeżeli projekt nagłówka lub stopki ulegnie modyfikacji.Oprócz tego.4.4 pokazano sposób integracji tych segmentów z dynamicznie tworzonym fragmentem strony. Przykład ten pokazuje wartość oddzielenia kodu od HTML. załóżmy.jpg" width="622" height="106" alt="" border="0"> <h1>Nowości wydawnictwa Helion</h1> Wydruk 12. Problemy z utrzymaniem tego typu skryptów wykraczają jednak poza podstawowe problemy z czytelnością kodu. Skrypt łączący kod z projektem <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4. Równie trudno jest wprowadzać zmiany zarówno do kodu. jak i wyglądu strony bez wpływania na inne elementy. nie należy tego marnować tworząc aplikację utrudniającą wprowadzanie prostych zmian. Implementacja Najprostsza metodą integracji osobnych modułów jest wykorzystanie funkcji PHP include() lub Metoda ta wymaga umieszczenia elementów projektu HTML w osobnych plikach. Na przykład na wydruku 12. W obu przypadkach wynikiem są opóźnienia w projekcie. Wydruk 12.1 pokazuje jak skomplikowana może stać się strona HTML z wbudowanym PHP. Fragment ze stopką HTML <br><br><br> <hr> <p> &copy. pokazuje on w jaki sposób można użyć funkcji include() w celu integracji HTML i kodu. Teraz zostaną zademonstrowane dostępne w PHP metody integrowania oddzielnych modułów kodu i projektu. Wszystkie prawa zastrzeżone. Na wydruku 12. Można tego uniknąć stosując lepsze praktyki projektowe.

Nagłówek HTML <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4. i 12. </p> </body> </html> Wydruk 12.0 Transitional//EN"> <html> <head> <title>Nowe książki wydawnictwa Helion</title> <link rel="STYLESHEET" type="text/css" href="css1.5. Na wydruku 12. Wszystkie prawa zastrzeżone. Skrypt aplikacji PHP <?php function MyIncludeFile( $aFileName ) { if ( !is_file( $aFileName ) ) { // przekierunkowanie na stronę błędu exit. Wydruk 12. 2001 Helion.7 znajduje się warstwa logiczna strony. ponownie jest umieszczony nagłówek i stopka.5. Łączenie HTML i kodu PHP przy użyciu include() Zamiast funkcji include() lub reqiure(). Użycie własnych funkcji dołączania plików pozwala na to. foreach( $aFileArray as $aLine ) { print( "$aLine" ).6. Kolejne wydruki zawierają bardziej szczegółowy przykład wykorzystania poprzedniej techniki wykorzystując funkcje obsługi plików zamiast funkcji include().Rysunek 12.7. 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. Rozdział 12 – Oddzielanie kodu HTML od PHP 148 . Dla celów tej demonstracji utworzone zostały dwa osobne pliki CSS. Stopka HTML <p class="copyright"> &copy. aby w plikach HTML nie było żadnego kodu PHP.jpg" width="622" height="106" alt="" border="0"> <h1>Nowości wydawnictwa Helion</h1> Wydruk 12.css"> </head> <body> <img src="logo.1. w tym odszukiwanie plików i obsługę błędów. Dodatkowo użyte zostały kaskadowe arkusze stylów (CSS) w celu zapewnienia większych możliwości zmiany wyglądu strony. natomiast na wydruku 12. Metoda ta pozwala na większą kontrolę nad obsługą plików. } $aFileArray = file( $aFileName ).6.

Dodatkowo ważna jest elastyczność rozwiązania wykorzystującego pliki CSS.phtml?news_id=$aNewsID###BOT_TEXT###quot;>pełny tekst.} } MyIncludeFile( ".</a>" ). Zawartość i struktura bazy danych nie jest istotna.. Tak jak w poprzednich przykładach. var $User = "root". print( print( print( print( print( } MyIncludeFile( ". 149 PHP – Kompendium wiedzy . // tworzenie klasy news_db class służące do odczytu wiadomości class news_db extends DB_Sql { var $Host = "localhost". "<h4>autor: $aAuthor</h4>" ). że w tekście strony PHP znajduje się kilka podstawowych znaczników HTML. var $Password = "root". var $Database = "mydb".3. ?> "<h2>$aTitle</h2>" ). } // Tworzenie obiektu klasy news_db i odczytanie wiadomości $aDB = new news_db. "<br><br><hr>" ). i 12. $aTitle = $aDB->f( "title" ).inc" ). ich użycie jest ograniczone a sposób ich interpretacji jest kontrolowany przez CSS. include( ". $aAuthor = $aDB->f( "author" ). while( $aDB->next_record() ) { $aNewsID = $aDB->f( "news_id" ). $aSynopsis = $aDB->f( "synopsis" ).2. Mimo. Aplikacja ta wykorzystuje małą bazę danych do przechowywania tekstów wiadomości. "<p>$aSynopsis</p>" ).html" ).html" )./footer_2./header_2. "<a href=###BOT_TEXT###quot;full_story. $aDB->query( "select * from news order by date desc limit 5" ). ponieważ jest to przykład rozdzielania kodu oraz technik jego integracji. w przykładzie tym wykorzystane są klasy obsługi baz danych PHPLIB./db_mysql. Wygląd kompletnej strony jest pokazany na rysunkach 12..

Przykłado wa aplikacja z pierwszym arkuszem stylów Rozdział 12 – Oddzielanie kodu HTML od PHP 150 .Rysunek 12.2.

Rysunek 12. Ułatwia to rozdzielenie odpowiedzialności programistów PHP i projektantów interfejsu. 151 PHP – Kompendium wiedzy . Przykłado wa aplikacja z pierwszym arkuszem stylów Czego należy unikać Korzystając z tej metody należy unikać mieszania kodu programu i HTML. powoduje to. Czasami programiści przesadzają w swoim zapale pisania kodu i tworzą mechanizmy. Używając przedstawionych technik i wykorzystując przy projektowaniu pliki CSS. Utrudnia to również wprowadzanie hurtowych zmian w wyglądzie całej witryny WWW. podział odpowiedzialności pomiędzy projektantami i programistami oraz ułatwiają konserwację aplikacji. cel ten jest nieomal osiągnięty. trzeba dynamicznie generować wszystkie łącza.3. na przykład może być to generowany dynamicznie znacznik łącza. Choć pozwala to na pisanie kodu PHP nie zawierającego znaczników HTML. Podsumowanie: Oddzielanie i integracja przy wykorzystaniu funkcji PHP Tworząc mechanizm oddzielania kodu PHP od HTML należy pamiętać o najważniejszych celach takiego działania. Jednak czasami trzeba dynamicznie wygenerować niektóre znaczniki HTML. niezbędne będzie dołączenie części znaczników HTML do kodu PHP. który generuje kod HTML. Należy unikać kodu PHP. W tych przypadkach jeżeli wykorzystywana będzie opisana technika integracji. że za zmiany projektu witryny odpowiada programista PHP. Celem oddzielenia HTML od PHP jest uproszczenie aplikacji. które nie spełniają prawdziwych potrzeb. Również jeżeli przesyłany jest identyfikator sesji lub inny identyfikator specyficzny dla aplikacji. a dołączane pliki PHP — jedynie kod PHP. Dołączane pliki HTML powinny zawierać jedynie kod HTML. Celem oddzielenia HTML od PHP może być całkowite oddzielenie projektu od logiki aplikacji.

$nIndex <= 10. } ". Użycie metody assign() do skojarzenia wartości do zmiennych szablonu. Wydruk 12. Tak jak przy wszystkich dotychczasowych technikach projektowania. $aTemplate = new FastTemplate( ". W prostych aplikacjach plik szablonu może być wykorzystywany dla wszystkich stron witryny. Podstawowym założeniem jest podział strony na jeden lub więcej szablonów projektowych.= "$nIndex ". Utworzenie obiektu klasy FastTemplate. ponieważ cały HTML może być pod opieką projektantów. Skrypt aplikacji <?php include( "class. Następnie w kodzie należy wykonać następujące kroki: 1. $aBodyText = "Bardzo krótka zawartość strony. BODY i COPYRIGHT. for ( $nIndex = 1." ). aby osiągnąć zamierzony wynik wykorzystując szablony.net.8. FastTemplate jest łatwy do użycia i istnieje specjalna dokumentacja dla początkujących.9. Gdy wszystkie znaczniki HTML zostaną usunięte z kodu. Przykładowy plik szablonu znajduje się na wydruku 12.9. Aby rozpocząć pracę z FastTemplate należy utworzyć plik szablonu. W bardziej skomplikowanych.8. może być użyte bardzo wiele szablonów. W szablonach FastTemplate zmienne są umieszczane w nawiasach klamrowych ({}). Oczywistą zaletą wykorzystania szablonów jest umożliwienie doświadczonym projektantom HTML na całkowite panowanie nad wszystkimi aspektami projektu. W najprostszym przypadku. Wydruk 12.tpl' ) ). BODY_COLOR. Jest to zalecana metoda. Użycie metody define() do przydzielenia plikom szablonów unikalnych nazw. Użycie metod FastPrint() lub fetch() do wypisania lub odczytania przetworzonego pliku szablonu.8 zawiera cztery zmienne FastTemplate: TITLE. Wykorzystanie systemu szablonów System szablonów jest mechanizmem przeznaczonym do całkowitego oddzielenia elementów projektu HTML od kodu PHP. zmienne te mogą być ustawione bezpośrednio z kodu.php" ). 3. dostępne jest świetne narzędzie o nazwie FastNet.thewebmasters. wymagane są dodatkowe prace projektowe oraz skuteczne wprowadzenia ich w życie. 2. które można załadować z witryny www.0 Transitional//EN"> <html> <head> <title>{TITLE}</title> </head> <body bgcolor="{BODY_COLOR}"> {BODY} <hr> <font size="1"> {COPYRIGHT} </font> </body> </html> Przykładowy szablon pokazany na wydruku 12. Rozdział 12 – Oddzielanie kodu HTML od PHP 152 .FastTemplate. 5. że każdy może zbudować własny system szablonów. które są łączone z dynamiczną zawartością generowaną przez kod PHP. Uruchomienie metody parse() do przetworzenia pliki szablonu i przypisania wartości do zmiennych. 4. FastTemplate Mimo. w sposób pokazany na wydruku 12. $aTemplate->define( array( 'basic' => 'sample_1.W następnej części zatytułowanej „Wykorzystanie systemu szablonów” opisuję szczegóły metody umożliwiającej całkowite oddzielenie kodu PHP od HTML. cała warstwa projektu interfejsu aplikacji może być modyfikowana niezależnie od logiki aplikacji. $nIndex++ ) { $aBodyText . Przykładowy szablon FastTemplate <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4. zwykle z rozszerzeniem tpl.

</td> </tr> <tr> <td align="center" valign="top"> <!-. Nowymi plikami są: plik z danymi o prawach autorskich. która może zostać wydrukowana lub zachowana dla innych celów.phtml">tutaj</a>.Panel nawigacji --> <a href="index. Wydruk 12. $aTemplate->FastPrint( 'PAGE' ).$aTemplate->assign( array( 'TITLE' => 'Prosty przykład'. zmiennym FastTemplate przypisywane są wartości. Wydruk 12. 'BODY_COLOR' => 'white'.4.”. oraz główny plik szablonu zamieszczone odpowiednio na wydrukach 10 i 11. W kilku kolejnych liniach generowany i zapamiętywany jest również test strony oraz wykorzystując metodę assign(). W naszym przykładzie został wykorzystany bieżący katalog „. Ostatnia opcja pozwala na zagnieżdżanie plików szablonów. Konstruktor wymaga jednego argumentu — ścieżki do pliku szablonu. które zostały do tej pory pokazane. Główny plik szablonu (body. Dodatkowe informacje na temat praw autorskich mozna znaleźć <a href="legal.8 zostaje nadana nazwa basic. Wynik przetwarzania prostego szablonu Po przetworzeniu szablonu przez obiekt FastTemplate. $aTemplate->parse( 'PAGE'. 'BODY' => $aBodyText.11. 'basic' ).phtml">o nas</a><br><br> <a href="links. Na koniec Szablon jest przetwarzany i zapamiętywany w zmiennej PAGE. wynik jest zapisany w zmiennej.phtml">łącza</a><br><br> </td> <td width="90%" valign="top"> <!-. muszą im zostać przypisane wartości.phtml">początek</a><br><br> <a href="about. lub zmienna ta może być użyta w kolejnym szablonie. 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} 153 PHP – Kompendium wiedzy .tpl) &copy. Wszystkie prawa zastrzeżone. a następnie jej zawartość wysyłana jest do przeglądarki. Wynik pokazany jest na rysunku 12.tpl) <table width="100%"> <tr> <th colspan="3"> {PAGE_HEADER} </th> </tr> <tr> <td colspan="3"> &nbsp. Następnie plikowi umieszczonemu na wydruku 12.10. wszystkie prawa zastrzeżone' ) ). Rysunek 12. ?> Pierwszym krokiem jest utworzenie obiektu klasy FastTemplate.4. 'COPYRIGHT' => 'Helion 2001. zawierają swoje zmienne FastTemplate i aby szablony działały prawidłowo.Tutaj reklamy i inne --> </td> </tr> </table> Każdy z dodatkowych plików szablonów. Szablon z prawami autorskimi (copyright.Główna sekcja tekstu --> {PAGE_CONTENT} </td> <td width="125" valign="top"> <!-. {YEARS} Helion. Jeżeli nie zostanie przypisana zmienna FastTemplate.

} $aStartYear = 1997. $aYears. => => => => => 'Lepszy przykład'. $aTemplate->FastPrint( 'PAGE' ). ". Na wydruku 12. Zagnieżdżone pliki szablonów <?php include( "class.FastTemplate. Zmienna $aBodyText posiada identyczną wartość jak w poprzednim przykładzie. $nIndex++ ) { $aBodyText .12. } $aTemplate = new FastTemplate( ". Zamiast tego zmienne te otrzymują wartości przy wywołaniu metody parse() na końcu tego skryptu. for ( $nIndex = 1. 'white'. więc dane o prawach autorskich są zawsze aktualne. $aYears = "$aStartYear". ?> W przykładzie tym zdefiniowano dwa dodatkowe pliki szablonów nadając im nazwy copyright i body. => 'body. => 'copyright." ). } $aTemplate->assign( array( 'TITLE' 'BODY_COLOR' 'YEARS' 'PAGE_HEADER' 'PAGE_CONTENT' ) ). $aCurrentYear = GetCurrentYear(). function GetCurrentYear( ) { $aNow = getdate(). zmiennym tym należy przypisać wartości. return $aNowYear.tpl'.php" ). $nIndex".Dodając nowe pliki szablonów należy również zmienić główny plik PHP. 'basic' ).= ". $aTemplate->define( array( 'basic' 'copyright' 'body' => 'sample_1.12 pokazany jest nowy skrypt PHP używający zagnieżdżonych szablonów. $aNowYear = $aNow["year"]. $aTemplate->parse( 'PAGE'. $aTemplate->parse( 'COPYRIGHT'. Wartość zmiennej YEARS jest generowana automatycznie. $aBodyText $aTemplate->parse( 'BODY'.5. Rozdział 12 – Oddzielanie kodu HTML od PHP 154 . 'body' ). for ( $nIndex = $aStartYear + 1. $nIndex <= $aCurrentYear. $nIndex++ ) { $aYears . $nIndex <= 10.tpl' ) ).tpl'. że w tym rozdziale zmienne BODY i COPYRIGHT nie są ustawiane w metodzie assign(). Wydruk 12. 'Lepszy przykład'. Należy zauważyć. Wynik działania tego skryptu jest pokazany na rysunku 12. 'copyright' ). Ponieważ te pliki szablonów zawierają własne zmienne FastTemplate.= "$nIndex ". $aBodyText = "Bardzo krótka zawartość strony.

12. 155 PHP – Kompendium wiedzy .15.Rysunek 12.css"> </head> {NEWS_BODY} </html> Wydruk 12. Wydruk 12..tpl) <body> <table width="640" border="0" align="center"> <tr> <td> <img src="logo. Zamiast wykorzystywać do tego celu pliki dołączane.tpl) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4. W przykładzie tym użyty jest szablon zawierający prawa autorskie.16.13.</a> <br><br><hr> Na wydruku 12. Aby lepiej zilustrować tą technikę w kolejnym przykładzie wrócimy do przykładu aplikacji dostarczającej najnowszych wiadomości. Szablon elementu wiadomości (ft_news_item. ale większość kodu pochodzi z poprzednich przykładów. Szablon treści w aplikacji wiadomości (ft_news_body. za pomocą którego można tworzyć bogate i złożone projekty interfejsu. Skrypt ten jest bardziej skomplikowany niż w poprzednim przykładzie.5. w kodzie tym wykorzystana zostanie siła klasy FastTemplate. zamieszczony jest skrypt generujący stronę z nowościami.0 Transitional//EN"> <html> <head> <title>{TITLE}</title> <link rel="STYLESHEET" type="text/css" href="css2.jpg" width="250" height="68" alt="" border="0"> <h1>Nowości wydawnictwa Helion</h1> </td> </tr> <tr> <td> <br><br> {NEWS_ITEMS} </td> </tr> <tr> <td> <br> <p class="copyright"> {COPYRIGHT} </p> </td> </tr> </table> </body> Wydruk 12.. Podstawowy szablon dla aplikacji dostarczającej wiadomości (ft_news_base.13. wykorzystany w poprzednim przykładzie. Wynik działania zagnieżdżonych szablonów FastTemplate Klasa FastTemplate jest potężnym narzędziem.14 i 12. treść i element wiadomości. Na wydrukach 12.tpl) <h2>{NEWS_TITLE}</h2> <h4>autor: {NEWS_AUTHOR}</h4> <p>{NEWS_SYNOPSIS}</p> <a href="{FULL_STORY_URL}">więcej.15 umieszczony jest kod HTML szablonów tworzących podstawowy układ strony.14.

"copyright. $aYears = "$aStartYear". $aAuthor = $aDB->f( "author" ). "ft_news_item. "copyright" ). // generowanie roku dla treści praw autorskich $aStartYear = 1997. } $aTemplate->assign( array( "YEARS" "TITLE" => $aYears. } $aTemplate = new FastTemplate( ". => "Nowości wydawnictwa Helion" ) ). $aURL ) ).inc" ). return $aNowYear. $aTemplate->assign( array( "NEWS_TITLE" "NEWS_AUTHOR" "NEWS_SYNOPSIS" "FULL_STORY_URL" $aTemplate->parse( "NEWS_ITEMS".= ". while( $aDB->next_record() ) { $aNewsID = $aDB->f( "news_id" ). "body" ).tpl"./db_mysql. $aSynopsis = $aDB->f( "synopsis" ).Wydruk 12. // Tworzenie obiektu klasy news_db i generowanie elementów wiadomości $aDB = new news_db. Kolejną główną funkcją skryptu jest dynamiczne dodawanie kolejnych wiadomości." ).tpl" ) ). "base" ). $nIndex". Rozdział 12 – Oddzielanie kodu HTML od PHP 156 .php" ). $aTitle = $aDB->f( "title" ). Zostało to zrealizowane przez pobranie pięciu najnowszych wiadomości z bazy danych i wypisanie ich przy pomocy pętli. $aTemplate->parse( "BASE". error_reporting( E_ALL & ~E_NOTICE ).16. $nIndex <= $aCurrentYear. $aCurrentYear = GetCurrentYear(). Zauważmy. ". YEARS i TITLE reprezentujące odpowiednio rok praw autorskich i tytuł strony. ?> => => => => $aTitle. function GetCurrentYear( ) { $aNow = getdate(). że na początku skryptu wyłączone zostały ostrzeżenia PHP. var $User = "root".item" ). $aTemplate->parse( "NEWS_BODY". for ( $nIndex = $aStartYear + 1. $aTemplate->define( array( "base" "body" "item" "copyright" => => => => "ft_news_base. Na początku skryptu inicjowane są dwie główne zmienne FastTemplate.tpl". include( ". $aTemplate->FastPrint( "BASE" ). ponieważ ostrzeżenie generowane przez FastTemplate zostaną omówione później. } // Tworzenie klasy news_db do pobrania wiadomości class news_db extends DB_Sql { var $Host = "localhost". $aDB->query( "select * from news order by date desc limit 5" ). $aNowYear = $aNow["year"]. $aSynopsis.FastTemplate. var $Database = "mydb". a obsługa bazy danych z poprzedniej realizacji aplikacji wiadomości. $aURL = "full_story. $nIndex++ ) { $aYears .phtml?news_id=$aNewsID". W każdym przebiegu pętli przetwarzany jest szablon item i dodawany do zmiennej FastTemplate NEWS_ITEMS. } $aTemplate->parse( "COPYRIGHT". var $Password = "root". W skrypcie tym zdefiniowane zostały cztery pliki szablonów. W przykładzie tym funkcja generująca rok dla tekstu o prawach autorskich pochodzi z poprzednich przykładów.tpl". $aAuthor. "ft_news_body. Główny skrypt aplikacji <?php include( "class.

'navi' ). Szablon nawigacji <?php include( "class. powinno być w tym momencie dosyć oczywiste. session_id().tpl) <a href="{HREF_INDEX}">początek</a> <a href="{HREF_NEWS}">nowości</a> <a href="{HREF_LINKS}">łącza</a> Właściwe adresy URL dla łączy mogą być tak generowane. Drugie znalazło się w rozdziale 9. Poprzedni przykład pokazuje w jaki sposób można wykorzystać klasę FastTemplate do generowania powtarzających się elementów. jest ono warte zainteresowania. } $aTemplate = new FastTemplate( ". $aTemplate->assign( array( 'HREF_INDEX' => MyGenURL( 'HREF_INDEX' ). lub inny specyficzny dla aplikacji. session_name() . Dlatego właśnie w pierwszym przebiegu pętli FastTemplate generuje ostrzeżenie wskazujące." ). Inną zaletą wykorzystania takich adresów jest łatwa modyfikacja położenia stron w czasie pracy aplikacji. Pierwsze zagadnienie. 'HREF_NEWS' => MyGenURL( 'HREF_NEWS' ).phtml'. Pierwsze zostało wspomniane w rozdziale 7. break.) przed nazwą szablonu. W tej części skupimy się na tych dwóch zagadnieniach. $aTemplate->parse( 'NAVI'. case 'HREF_LINKS' : $aBaseURL = 'links. default : $aBaseURL = 'badlink. gdzie znalazła się sugestia. function MyGenURL( $aLinkName ) { switch( $aLinkName ) { case 'HREF_INDEX' : $aBaseURL = 'index. break.php" ).FastTemplate.tpl' ) ). Oczywistą zaletą klasy FastTemplate jak również innych systemów szablonów jest to. Zaawansowane techniki użycia FastTemplate W poprzednich rozdziałach dwa zagadnienia były z rozmysłem odsuwane aż do tego rozdziału.17. Po ustawieniu w pętli wartości zmiennej NEWS_ITEMS przetwarzana jest reszta szablonów a następnie drukowana strona. aby zawierały identyfikator sesji. przesyłanie identyfikatora sesji. Szablon nawigacji (navi. Po poznaniu podstawowych założeń używanie FastTemplate staje się niezwykle naturalne. Wydruk 12.phtml'. Wydruk 12. $aTemplate->FastPrint( 'NAVI' ). 'HREF_LINKS' => MyGenURL( 'HREF_LINKS' ) ) ). że wykorzystanie systemu szablonów wymaga nieco innego myślenia w trakcie projektowania. "=" .phtml'. w którym mówiono o lepszych sposobach przenoszenia identyfikatora sesji w aplikacji. Podobna konstrukcja może być wykorzystana do tworzenia wierszy tablicy lub listy łączy.18. że zmienna NEWS_ITEMS nie jest zainicjowana. że elementy projektu strony mogą być tworzone i zmieniane niezależnie od kodu aplikacji. Wykorzystując szablony projekt może zawierać dynamiczne łącza URL generowane w kodzie PHP. break. session_start().Dodawanie to jest zrealizowane poprzez dodanie kropki (. że system szablonów może być alternatywną metodą dostarczania zawartości zależnej od typu przeglądarki. Mimo. takich jak treść kolejnych wiadomości. $aTemplate->define( array( 'navi' => 'navi.17. „Sesje i stan aplikacji”.phtml'. break.18 zamieszczony jest skrypt generujący dynamiczne adresy URL dla poprzedniego szablonu. „Niezależność od przeglądarki”. case 'HREF_NEWS' : $aBaseURL = 'news. Na wydruku 12. ?> 157 PHP – Kompendium wiedzy . Podstawowy przykład szablonu nawigacyjnego zamieszczony jest na wydruku 12. } return $aBaseURL .

to strony zależne od możliwości przeglądarki. podobna do tej zamieszczonej na witrynie firmy Macromedia. że zmienna $aHasFlash jest ustawiana przez // prawdziwą funkcję wykrywania Flash-a $aHasFlash = False. ?> Przykład ten pokazuje. "navi" ).swf" quality=high bgcolor=#FFFFFF WIDTH=320 HEIGHT=240 TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.21. "base" ). Używając szablonów preferowana jest pierwsza metoda.tpl) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.19.tpl". Funkcja taka ma dodatkową możliwość obsługi nieznanych nazw łączy.19." ). if ( $aHasFlash == True ) { $aNaviFile = "flash_menu. Rozdział 12 – Oddzielanie kodu HTML od PHP 158 . i 22. Oczywiście powinna zostać wykorzystana prawdziwa funkcja wykrywająca. Menu oparte o Flash (flash_menu. Pobiera ona symboliczną nazwę łącza i zwraca prawdziwą lokalizację strony wraz z dołączonymi danymi sesji. "base" => "base_basic. } else { $aNaviFile = "html_menu. natomiast wydruk 12.swf"> <PARAM NAME=quality VALUE=high> <PARAM NAME=bgcolor VALUE=#FFFFFF> <EMBED src="Track As Menu.Funkcja MyGenURL() jest głównym elementem skryptu. Menu HTML (html_menu. pokazuje w jaki sposób można zintegrować treści zależne od typu przeglądarki z szablonami. 21. $aTemplate->FastPrint( "BASE" ).0" WIDTH=320 HEIGHT=240> <PARAM NAME=movie VALUE="flash_menu. // zakładamy.22 zawiera skrypt PHP.tpl) <a href="index.22.com/shockwave/download/index. 20. Na wydruku 12. Wykorzystanie szablonów do dostarczania treści zależnych od przeglądarki również jest korzystne.20. $aTemplate->parse( "NAVI".FastTemplate.phtml">wiadomości</a> <a href="links..cgi?P1_Prod_Version=ShockwaveFlash"></EMBED> Wydruk 12. Skrypt <?php include( "class. } $aTemplate = new FastTemplate( ". Wydruk 12. W rozdziale 9.macromedia.tpl" ) ). Pozwala to unikać brzydkich komunikatów „HTTP 404: Page Not Found” spotykanych we wielu aplikacjach WWW. Problemem z przekierowaniem jest to. W oparciu o specyficzne potrzeby witryny można pomysłowo rozdzielać wiele aspektów projektu w zależności od możliwości używanej przeglądarki i wykorzystać system szablonów do dostarczenia najlepszej zawartości dla każdej z przeglądarek.0. Podstawowy szablon strony (base_basic. $aTemplate->parse( "BASE".21.0 Transitional//EN"> <html> <head> <title>{TITLE}</title> </head> <body> {NAVI} </body> </html> Wydruk 12. zasugerowane były metody warunkowego dołączania plików lub przekierowania użytkownika do katalogu odpowiadającego używanej przeglądarce. i 12.phtml">łącza</a> Wydruk 12. Przykład umieszczony na wydrukach 19.phtml">początek</a> <a href="news.cab#version=5. w jaki sposób można umieszczać na stronie menu zrealizowane w programie Macromedia FlashTM.tpl) <OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.. gdy używana przeglądarka potrafi je wyświetlić i zwykłe menu HTML w przypadku korzystania z innych przeglądarek. pokazany jest główny szablon strony. $aTemplate->define( array( "navi" => $aNaviFile. Wydruk 12.php" ). że użytkownik może wysłać łącze do strony do osoby używającej innej przeglądarki.20.macromedia.tpl". $aTemplate->assign(array("TITLE" => "Przykład działania zależnego od przeglądarki")).com/pub/shockwave/cabs/flash/swflash.0.

Jakiś czas temu zdałem sobie sprawę. który pozwala na pełne oddzielenie wszystkich elementów projektu od kodu.Podsumowanie Oddzielanie elementów projektu aplikacji WWW od jej logiki powoduje promowanie projektowania modularnego i dzięki temu zwiększenie możliwości ponownego wykorzystania kodu oraz jego łatwiejszej konserwacji. Steve McConnell. Wykorzystuję klasę FastTemplate w nieomal wszystkich moich obecnych projektach. Pozwala to osiągnąć ogólną poprawę witryny. ponieważ warstwa prezentacji jest odpowiedniej jakości a ja nie muszę jej tworzyć ani zmieniać samemu. że nigdy nie będę projektantem graficznym ani artystą. Tak zupełnie na marginesie. Bibliografia Roger Fournier. rozdział ten ma podłoże czysto osobiste. Code Complete. więc w mojej firmie poświęciłem sporo czasu na znalezienie sposobu na dołączenie projektów profesjonalnych projektantów z moimi aplikacjami. New Jersey: Prentice Hall PTR. A Mehodology for Client/Server and Web Application Development. Z powodu elastyczności PHP cel modularnego tworzenia witryn WWW może być osiągnięty wieloma sposobami. Zalecaną w tym rozdziale metodą jest wykorzystanie systemu szablonów. 159 PHP – Kompendium wiedzy . Seattle: Microsoft Press. Pozwala ona moim projektantom łatwo stworzyć pliki szablonów stron wykorzystując nawiasy klamrowe do zaznaczenia elementów i pozwala mi na projektowanie w pełni funkcjonalne oraz szybkie zmiany w logice aplikacji. 1993. 1998.

Rozdział 13. Fajny PHP
Wstęp
W przypadku języka tak potężnego i rozszerzalnego jak PHP, trudno jest poszufladkować wszystkie fajne rzeczy, jakie można zrobić przy jego pomocy. Rozdział ten zawiera opis niektórych z nich. Tematy tu omawiane są albo zagadnieniami, które musiałem kiedyś zaprogramować, albo odpowiedziami na pytania często pojawiające się na listach dyskusyjnych poświęconym PHP. Rozdział ten nie opisuje oczywiście wszystkich rozszerzeń i własności PHP, ale opisuje niektóre z nich, które nie zostały opisane w innych częściach książki.

Wysyłanie do przeglądarki plików innych niż HTML
Ogólnie mówiąc, PHP jest wykorzystywany do wysyłania plików HTML do przeglądarki, ale może być on również użyty do automatyzacji ściągania plików, lub dostarczania innych typów plików do przeglądarki. Na przykład można umożliwić użytkownikom na zapisanie fragmentu zawartości bazy danych w formacie tekstowym, na przykład takim jak CSV. Przykład ten ilustruje sposób, w jaki można umożliwić użytkownikom zapisanie fragmentu tabeli bazy danych. Na wydruku 13.1. umieszczono skrypt pobierający dane z bazy danych, formatujący je oraz wysyłający je do przeglądarki. Wydruk 13.1. Wysyłanie CSV do przeglądarki
<?php include_once( "db_mysql.php" ); // Tworzenie klasy pochodnej po DB_Sql służącej do pobrania danych pracownika class employee_db extends DB_Sql { var $Host = "localhost"; var $Database = "mydb"; var $User = "root"; var $Password = "root"; } $aSQL = "select * from employees ";

$aDB = new employee_db; $aDB->query( $aSQL ); /* metoda metadata() bardzo zależy od wersji MySQL przykład ten może nie działać dobrze na wszystkich wersjach MySQL */ $aMetaData = $aDB->metadata(); $aData = ""; $aNumFields = count( $aMetaData ); for ( $nIndex = 0; $nIndex < $aNumFields; $nIndex++ ) { $aData .= "###BOT_TEXT###quot;" . $aMetaData[$nIndex]["name"] . "###BOT_TEXT###quot;,"; } // usunięcie ostatniego znaku w ciągu (,) i znaku końca linii (\n) $aData = substr( $aData, 0, strlen( $aData ) - 1 ) . "\n"; while ( $aDB->next_record() ) { $aLine = ""; for ( $nIndex = 0; $nIndex < $aNumFields; $nIndex++ ) { $aLine .= "###BOT_TEXT###quot;" . $aDB->f( $nIndex ) . "###BOT_TEXT###quot;,"; } // usunięcie ostatniego znaku w ciągu (,) i znaku końca linii (\n) $aLine = substr( $aLine, 0, strlen( $aLine ) - 1 ); $aLine .= "\n";

$aData .= $aLine; } header( "Content-length: " . strlen( $aData ) ); header( "Content-type: application/octetstream" ); header( "Content-disposition: inline; filename=###BOT_TEXT###quot;employees.csv###BOT_TEXT###quot;" ); print( $aData ); ?>

Pierwszą czynnością realizowaną przez skrypt jest zdefiniowanie klasy pochodnej po klasie DB_Sql pochodzącej z PHPLIB, która jest używana do uruchomienia zapytania na bazie danych. Więcej informacji na ten temat znajduje się w rozdziale 6. „Współpraca z bazami danych”. Następnie wykonywane jest zapytanie i pobierane z niego są metadane. Metadane zawierają ilość pól oraz nazwę każdego ze zwracanych pól. Dane te są potrzebne do skonstruowania pierwszej linii pliku CSV. Zwykle CSV zawiera wiersz nagłówka zawierający nazwy pól, a następnie umieszczone są wiersze danych. Każde pole w CSV jest umieszczone w cudzysłowach i oddzielona są od siebie przecinkami. Każdy wiersz kończy się znakiem nowej linii. Po dodaniu wiesza nagłówka, skrypt przebiega po kolejnych rekordach wyniku i konstruuje z nich sformatowane wiersze CSV. Następnie do przeglądarki wysyłane są trzy wiersze nagłówka HTML. Pierwszy zawiera wielkość wysyłanego pliku, Następna zawiera typ zawartości pliku. Jest ona ważna, ponieważ przeglądarka wykorzystuje te dane do rozpoznania, w jaki sposób powinna traktować przesyłane dane. Jeżeli linia ta zawierała by text/html, przeglądarka próbowała by wyświetlić przychodzące dane w postaci HTML. Ponieważ typem tym jest w tym przypadku application/octetstream, przeglądarka nie próbuje wyświetlić tych danych, a zamiast tego pozwala zapisać je na dysku. Ostatni wiersz wskazuje przeglądarce, że dane są wysyłane razem z nagłówkami oraz sugeruje nazwę dla zapisywanego pliku. Na rysunku 13.1. pokazane jest okno dialogowe wyświetlane przez Internet Explorer po uruchomieniu tego skryptu. Pierwsze dwie linie tego pliku umieszczone są na wydruku 13.2., natomiast na rysunku 13.2. widać wygląd tego pliku w programie Microsoft Excel. Rysunek 13.1. Okno dialogowe Zapisz jako

161

PHP – Kompendium wiedzy

Rysunek 13.2. Plik CSV w Excelu

Wydruk 13.2. Surowy plik CSV
"id","first","last","address","position" "1","Bob","Smith","Poziomkowa 16, Miastko","Szef marketingu"

Innym częstym zastosowaniem przesyłania zawartości innej niż HTML do przeglądarki, jest wysyłanie plików graficznych. Na przykład możesz mieć aplikację, która zapisuje małe rysunki w bazie danych. Następnie można przy pomocy PHP zapisywać je oraz pobierać i wyświetlać. Poniższy wydruk pokazuje w jaki sposób można pobierać rysunki poprzez formularz HTML, zapisywać je w bazie danych, a następnie wyświetlać je na innej stronie. Na wydruku 13.3. znajduje się formularz HTML używany do przesyłania rysunków, natomiast wydruk 13.4. zawiera skrypt zapisujący rysunki do bazy danych. Tabela MySQL używana do przechowywania rysunków zdefiniowana jest następująco:
CREATE TABLE pictures ( picture_id int(11) DEFAULT '0' NOT NULL, name varchar(30) NOT NULL, date datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, pic_data mediumblob NOT NULL, pic_size int(11) DEFAULT '0' NOT NULL, pic_type varchar(30) NOT NULL, PRIMARY KEY (picture_id) );

Wydruk 13.3. Formularz przesyłania plików
<html> <head> <title>Przesyłanie rysunków</title> </head> <body> <form action="upload_pic.phtml" method="post" enctype="multipart/form-data"> <table> <tr> <td colspan="2"> Proszę wybrać plik z rysunkiem (jpeg lub gif) do przesłania, oraz podać jego nazwę. </td> </tr> <tr> <td> Plik rysunku: </td> <td> <input type="file" name="PicFile"> </td> </tr> <tr> <td> Nazwa rysunku: </td> <td> <input type="text" name="PicName" maxlength="30">

Rozdział 13 – Fajny PHP

162

</td> </tr> <tr> <td colspan="2"> <input type="submit" name="Submit" value="Wyślij"> </td> </tr> </table> </form> </body> </html>

Wydruk 13.4. Zapisywanie przesłanego pliku w bazie danych
<?php include_once( "db_mysql.php" ); // Utworzenie podklasy DB_Sql do zapisywania i odczytu rysunków class pictures_db extends DB_Sql { var $Host = "localhost"; var $Database = "mydb"; var $User = "root"; var $Password = "root"; } $aErrors = False; if ( !empty( $PicFile_name ) ) // nie wybrano pliku { if ( ( $PicFile_type == "image/gif" ) || ( $PicFile_type == "image/pjpeg" ) || ( $PicFile_type == "image/jpeg" ) ) { $aFile = fopen( $PicFile, "rb" ); $aFileContents = addslashes( fread( $aFile, filesize( $PicFile ) ) ); fclose( $aFile ); $aDB = new pictures_db(); $aSQL = "select ( max( picture_id ) + 1 ) as new_id from pictures"; $aDB->query( $aSQL ); if ( $aDB->next_record() ) { $aNewID = $aDB->f( "new_id" ); } if ( empty( $aNewID ) == True ) { $aNewID = 1; } $aSQL = "insert into pictures ( picture_id, name, date, pic_data, "; $aSQL .= "pic_size, pic_type ) values ( $aNewID, '$PicName', "; $aSQL .= "NOW(), '$aFileContents', '$PicFile_size', '$PicFile_type' )"; print( $aSQL ); $aDB->query( $aSQL ); if ( $aDB->Errno != 0 ) { $aErrors = True; } } else { $aErrors = True; } } else { $aErrors = True; } if ( $aErrors == False ) { header( "Location: upload_ok.html\n" ); } else { header( "Location: upload_failed.html\n" ); } ?>

Skrypt ten ponownie wykorzystuje klasę PHPLIB do obsługi odwołań do bazy danych. Na początku sprawdzane jest, czy plik jest właściwego typu. Następnie plik jest umieszczony w zmiennej i przygotowany do 163 PHP – Kompendium wiedzy

umieszczenia w bazie danych poprzez użycie funkcji addslashes(). Następnie z tabeli pobierany jest nowy identyfikator i dane są umieszczane w bazie danych. Na końcu skryptu przeglądarka jest kierowana do odpowiedniego pliku w zależności od tego, czy operacja się powiodła czy nie. Aby wyświetlić rysunek, wykorzystujemy kod z wydruków 5. i 6. Na wydruku 13.5. umieszczona jest prosta strona HTML powodująca wyświetlenie jednego, określonego rysunku. Wydruk 13.6. zawiera skrypt wyświetlający rysunki. Wydruk 13.5. Strona HTML powodująca wyświetlenie rysunku z bazy danych
<html> <head> <title>Wyświetlenie rysunku</title> </head> <body> <img src="show_pic.phtml?ID=1" border="0" alt=""> </body> </html>

Wydruk 13.6. Skrypt wyświetlający rysunki
<?php include_once( "db_mysql.php" ); // Utworzenie podklasy DB_Sql do zapisywania i odczytu rysunków class pictures_db extends DB_Sql { var $Host = "localhost"; var $Database = "mydb"; var $User = "root"; var $Password = "root"; } $aDB = new pictures_db(); $aSQL = "select * from pictures where ( picture_id = $ID )"; $aDB->query( $aSQL ); if ( $aDB->next_record() ) { header( "Content-length: " . $aDB->f( "pic_size" ) ); header( "Content-type: " . $aDB->f( "pic_type" ) ); print( $aDB->f( "pic_data" ) ); } else { // Nie znaleziony rysunek, obsługa błędu! Header( "HTTP/1.0 404 Not Found" ); } ?>

Mimo, że dziwny wydaje się znacznik <IMG> wskazujący na skrypt PHP, nie ma jednak żadnej różnicy. Ważny kod znajduje się w skrypcie PHP, gdzie ustawiany jest właściwy typ zawartości dla rysunku z bazy danych. Skrypt powoduje pobranie odpowiedniego rysunku z bazy danych i przesłanie danych. Jeżeli identyfikator rysunku ($ID) nie zostanie odnaleziony w bazie danych, skrypt zwraca standardowy kod błędu HTTP 404. Ponieważ PHP pozwala na wysłanie dowolnych nagłówków HTTP, można w ten sposób przesyłać dowolną zawartość. Elastyczność ta pozwala na łatwe tworzenie aplikacji o dużych możliwościach.

Skrypty automatyzujące
PHP nie jest jedynie językiem programowania dla WWW, który do działania wymaga serwera WWW, ale jest on językiem skryptowym, który może zostać do dowolnych zadań programowych. Ponieważ jest on tak bogaty w funkcje, może być wykorzystany do automatyzacji zadań, które mogą być trudne do zrealizowania w standardowych językach programowania powłoki lub plikach wsadowych. Dodatkowo, ponieważ PHP jest dostępny na wielu platformach, te same skrypty mogą być użyte na wielu platformach. Wykorzystanie PHP jako osobnego narzędzia skryptowego wymaga skompilowania wersji CGI PHP. Jest to opsane w rozdziale 1., „Kompilacja i instalowanie PHP 4”. Mając dostępną wersję CGI można uruchomić dowolny skrypt PHP z linii poleceń. Poniższy przykład pokazuje wykorzystanie PHP do generowania plików stref DNS co jest przydatne w przypadku obsługi wielu stref. Rozdział 13 – Fajny PHP 164

Wydruk 13.7. Baza do obsługi DNS
CREATE TABLE Domains ( domain_id int(11) NOT NULL, name varchar(250) NOT NULL, soa_server_id int(11) DEFAULT '1' NOT NULL, cname_list varchar(250) NOT NULL, mail_server_id int(11) DEFAULT '1' NOT NULL, ip_address_id int(11) DEFAULT '1' NOT NULL, incl_zone_file tinyint(4) DEFAULT '1' NOT NULL, created_date datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, PRIMARY KEY (domain_id), KEY name (name), UNIQUE name_2 (name), KEY created_date (created_date) ); CREATE TABLE IPAddressess ( ip_address_id int(11) NOT NULL, value carchar(15) NOT NULL, PRIMARY KEY (ip_address_id), KEY value (value) ); CREATE TABLE MailServers ( mail_server_id int(11) NOT NULL, name varchar(250) NOT NULL, PRIMARY KEY (mail_server_id), KEY name(name) ); CREATE TABLE NameServers ( name_server_id int(11) NOT NULL, name varchar(250) NOT NULL, PRIMARY KEY (name_server_id), KEY name(name) ); CREATE TABLE SOAServers ( soa_server_id int(11) NOT NULL, name varchar(250) NOT NULL, PRIMARY KEY (soa_server_id), KEY name(name) );

Baza danych jest wykorzystywana do przechowywania danych niezbędnych do utworzenia plików strefy oraz innych plików konfiguracyjnych niezbędnych do działania serwera DNS. Poniżej pokazany jest jeden rekord z tabeli Domains:
INSERT INTO Domains VALUES( '4', 'intechra.net', '1', 'www, secure, mail', '1', '1', '1', '2000-08-25 13:29:37');

Wiersz ten zawiera dane DNS na temat domeny intechra.net. Chociaż rekord ten nie jest sam szczególnie użyteczny, to jednak połączony z innymi powiązanymi tabelami pozwala uzyskać informacje na temat adresów IP, serwerów pocztowych oraz serwerów SOA. Używając wszystkich tych danych oraz skryptu PHP można niezmiernie uprościć proces uaktualniania serwera DNS. Poniższe siedem wydruków zawiera elementy głównego skryptu. Wydruki 8. do 13. są plikami szablonów używanych do generowania plików wynikowych. Przykład ten korzysta z klasy FastTemplate opisanej w rozdziale 12. „Oddzielanie kodu HTML od PHP”. Wydruk 13.8. Główny szablon dla pliku strefy DNS (dns_primary.tpl)
$TTL 86400 {DOMAIN}. IN SOA {SOA_SERVER}. {ADMINISTRATOR}. ( {SERIAL} ; nr seryjny 10800 ; odswieżanie 3600 ; ponowna próba 604800 ; wygaśnięcie 86400 ; domyślny TTL ) {NAMESERVERS} {DOMAIN}. IN A {IPADDRESS} {CNAME_RECORDS} {DOMAIN}. IN MX 10 {MAIL_SERVER}. {DOMAIN}. LOC 43 49 57.551 N 111 46 38.071 W 1480.7m

Wydruk 13.9. Szablon nazw hostów DNS (zastępuje CNAME_RECORDS z wydruku 13.8.) (dns_secondary.tpl)
{CNAME} IN CNAME {DOMAIN}.{CRLF}

Wydruk 13.10. Szablon serwerów nazw DNS (zastępuje NAMESERVERS z wydruku 13.8.) (dns_nservers.tpl)
{DOMAIN}. IN NS {NAMESERVER}.{CRLF}

Wydruk 13.11. Główny szablon dla pliku named.conf (named_primary.tpl) 165 PHP – Kompendium wiedzy

acl trustedslaves { ns1.nameserver.com;ns2.nameserver.com; }; options { directory "/var/named"; recursion yes; fetch-glue no; allow-query { any; }; }; zone "." { type hint; file "cache.db"; }; {ZONES}

Wydruk 13.12. Pomocniczy szablon dla pliku named.conf (zastępuje ZONES z wydruku 13.11.) (named_secondary.tpl)
zone "{DOMAIN}" { type master; file "{DOMAIN_FILE}"; notify yes; allow-transfer { trustedslaves; }; };

Wydruk 13.13. Szablon dla pliku podrzędnych DNS (named_slaves.tpl)
zone "{DOMAIN}" { type slave; file "{DOMAIN_FILE}"; masters { master.com; }; };

Szablony te tworzą szkielet niezbędny do utworzenia wszystkich plików konfiguracyjnych dla serwera nazw BIND. Pierwsze trzy generują osobne pliki stref, które mogą posiadać różną liczbę serwerów nazw i definicji nazw komputerów. Pozostałe są używane do utworzenia pliku named.conf oraz pliku podrzędnego, wykorzystywanego w podrzędnym serwerze nazw. Skrypt pokazany na wydruku 13.14 odczytuje z bazy danych dane DNS i generuje wszystkie pliki konfiguracyjne. Wydruk 13.14, Skrypt DNS
<?php include( "./class.FastTemplate.php" ); include( "./db_mysql.php" ); // db_mysql.inc o zmienionej nazwie // tworzenie klasy obsługi bazy danych dla aplikacji class genapps_db extends DB_Sql { var $Host = "localhost"; var $Database = "mydb"; var $User = "root"; var $Password = "root"; } // katalog dla plików wynikowych $aPath = "./dns_output"; $tpl = new FastTemplate( "." ); $tpl->define( array( named_main => "named_primary.tpl", named_zones => "named_secondary.tpl", named_slaves => "named_slaves.tpl", dns_main => "dns_primary.tpl", dns_cnames => "dns_secondary.tpl", dns_nservers => "dns_nservers.tpl" )); // pobierz listę serwerów nazw i zapamiętaj do późniejszego wykorzystania $aNSDB = new genapps_db(); $aSQL = "select * from NameServers"; $aNSDB->query( $aSQL ); // pobierz wszystkie dane strefy $aDB = new genapps_db(); $aSQL = "select A.name, A.cname_list, A.incl_zone_file, B.name as soa_server, C.name as "; $aSQL .= "mail_server, D.value as ip_address from Domains A, SOAServers B, "; $aSQL .= "MailServers C, IPAddressess D where ( A.soa_server_id = B.soa_server_id)"; $aSQL .= "and ( A.mail_server_id = C.mail_server_id ) and "; $aSQL .= "( A.ip_address_id = D.ip_address_id )"; $aDB->query( $aSQL ); while ( $aDB->next_record() ) { $aDomainName = strtolower( $aDB->f( "name" ) ); $aCNames = $aDB->f( "cname_list" ); $aSoaServer = $aDB->f( "soa_server" ) ; $aMailServer = $aDB->f( "mail_server" ); $aIPAddress = $aDB->f( "ip_address" ); $aInclZoneFile = $aDB->f( "incl_zone_file" ); $tpl->assign( array( DOMAIN => $aDomainName, ADMINISTRATOR => "admin." . $aSoaServer, SERIAL => date( "Ymd" ) . "00", MAIL_SERVER => $aMailServer, SOA_SERVER => $aSoaServer, IPADDRESS => $aIPAddress, CRLF => "\n" ) ); /* nazwy hostów (rekordy CNAME) są przechowywane w liście rozdzielanej przecinkami w bazie danyche. Dzielenie listy i tworzenie linii dla każdego elementu */ $tpl->clear( CNAME_RECORDS );

Rozdział 13 – Fajny PHP

166

$aFile = fopen( "$aPath/$aDomainFile".dns_nservers" ). 'named_main' ). print( "Główny plik 'named.db". $tpl->fetch( DNS_MAIN ) ). "w" ). foreach( $aCNameList as $aCName ) { $aCName = trim( $aCName ). 167 PHP – Kompendium wiedzy . $aNSDB->seek( 0 ) .$aCNameList = explode( ". 9.conf' utworzony\n" ). $tpl->parse( NAMESERVERS. $aFile = fopen( "$aPath/named. fwrite( $aFile. fwrite( $aFile. } // dodanie linii serwerów nazw do pliku strefy $tpl->clear( NAMESERVERS ). /* plik strefy jest tworzony tylko wtedy. fwrite( $aFile. i 10.named_zones' ).dns_cnames"). Jest on utworzony za pomocą szablonów z wydruków 8.". } $aDomainFile = $aDomainName . $tpl->parse( SLAVES. "w" ). Przykładowy plik strefy pokazany jest na rysunku 13. $tpl->assign( array( CNAME => $aCName ) ). "dns_main"). gdy pole 'incl_zone_file' w bazie danych ma wartość '!' */ if ( $aInclZoneFile == "1" ) { $tpl->parse( DNS_MAIN. '. } $tpl->parse( NAMED_CONF.slave". } /* dodanie biżącej nazwy domeny do głównego i pomocniczego pliku konfiguracyjnego */ $tpl->assign( array( DOMAIN_FILE => $aDomainFile ) ).conf".4. print ("Plik domeny '$aDomainFile' został utworzony\n" ). $aCNames ).slave' utworzony\n" ). fclose( $aFile ). $tpl->parse( ZONES. fclose( $aFile ). print( "Plik domeny 'named.named_slaves' ). $tpl->parse( CNAME_RECORDS. while ( $aNSDB->next_record() ) { $tpl->assign( array( NAMESERVER => $aNSDB->f( "name" )) ). '. $aFile = fopen( "$aPath/named. $tpl->fetch( SLAVES ) ). ". ". fclose( $aFile ). ". $tpl->fetch( NAMED_CONF ) ).. "w" ). ?> Skrypt ten odczytuje kolejne pozycje w tabeli Domains i tworzy plik strefy.

Ponieważ PHP jest kompletnym językiem skryptowym. Aby uruchomić ten skrypt pod Windows lub na systemach Unix należy użyć polecenia php create_dns. Patrząc na najbardziej podstawowym poziomie. a pliki wynikowe są tworzone w katalogu określonym na początku skryptu. Pakiet ten zawiera dokumentację i przykłady użycia WDDX. Postęp wykonywania skryptu jest pokazywany na standardowym wyjściu. kompilując PHP z obsługą WDDX umożliwia się serializację danych w postaci pakietów WDDX oraz deserializację pakietów danych WDDX do struktur danych Rozdział 13 – Fajny PHP 168 . monitorowanie sieci lub aplikacji i wiele innych.conf. składowanie i uaktualnianie bazy danych.wddx. Ponieważ PHP jest niezwykle elastyczny. Użyty z mechanizmami automatycznego uruchamiania programów. Przykładowy plik strefy DNS Dodatkowo tworzony jest odpowiednio sformatowany plik named. Celem WDDX jest zapewnienie spójnego interfejsu danych dla informacji przekazywanych pomiędzy aplikacjami sieciowymi. Tworzenie plików konfiguracyjnych dla dowolnych programów może być bardzo łatwo wykonane przy użyciu systemu szablonów. na przykład pakietu FastTemplate. SDK dla WDDX można ściągnąć z witryny www. oparta na XML technologia pozwalająca aplikacjom WWW działających na dowolnych platformach.php.Rysunek 13. może być on użyty do napisania skryptów do takich zadań jak: wysyłanie masowej poczty.org. można wykorzystać WDDX do współdzielenia przez partnerów danych z bazy danych. W celu stworzenia tych plików do odczytania zapamiętanego tekstu wykorzystana została metoda FastTemplate fetch(). na przykład cron. WDDX WDDX (Web Distributed Data Exchange) to bezpłatna. Obsługa WDDX może być uaktywniona w PHP poprzez podanie opcji konfiguracji --enable-wddx i ponowne skompilowanie PHP. PHP może być wykorzystany do wykonania wielu złożonych zadań.4. Dla przykładu. łatwo wymieniać pomiędzy sobą dane. przy jego pomocy można napisać dowolne narzędzia automatyzujące złożone zadania.

aProducts = MyDeser. Wydruk 13.ARECORDS[nIndex]. "green". zawiera skrypt PHP wykorzystujący ten szablon. wddx_add_vars( $aPacketID.18. Gdy użytkownik wybierze z listy nazwę produktu.length. $aWDDXPacket = wddx_packet_end( $aPacketID ). Wynik serializacji pokazany jest na wydruku 13.15. Pakiet WDDX <wddxPacket version='1.17 Użycie WDDX do manipulacji danymi na kliencie <html> <head> <title>{TITLE}</title> <link rel="STYLESHEET" type="text/css" href="css2. Na wydruku 13.16. pokazany jest szablon HTML. "aAge" ). nIndex < aNumProds.Dołączenie obsługi WDDX / Javascript ---> <SCRIPT SRC="wddx.Dołączenie obsługi obiektu WddxDeserializer ---> <SCRIPT SRC="wddxDes. Aby to zilustrować.15. for (var i in obj) { result += obj_name + ". Pakiet danych WDDX zawiera wszystkie dane niezbędne do odtworzenia zmiennych za pomocą funkcji wddx_deserialize().DESCRIPTION. cenę i wagę. "aFirstName" ). print( $aWDDXPacket ).PHP.ARECORDS. Wydruk 13. gdzie jest używany przez JavaScript. Dane WDDX reprezentują informacje o towarach: nazwę. wddx_add_vars( $aPacketID. nIndex++ ) { aValue = aProducts. w polach tekstowych tylko do odczytu uaktualniana jest cena i waga wybranego produktu. $aAge = 25. aName = aProducts. "aArray" ). // Czyszczenie listy produktów // dodanie produktu do listy for ( var nIndex = 0. $aPacketID = wddx_packet_start( "products" ). Wykorzystanie WDDX <html> <head> <title>Przykład użycia WDDX</title> </head> <body> <?php $aFirstName = "Arian". aNumProds = aProducts. tworzy kilka zmiennych i serializuje je w pakiet danych WDDX. Następnie do tego pakietu dodawane są trzy zmienne PHP i pakiet jest zamykany. skrypt z wydruku 13. } function SetupProductsList() { MyDeser = new WddxDeserializer. } return result. wddx_add_vars( $aPacketID. natomiast wydruk 13. obj_name) { var result = "". $aArray = array( "red".0'><header><comment>products</comment></header><data><struct><var name='aFirstName'><string>Arian</string></var><var name='aAge'><number>25</number></var><var name='aArray'><array length='3'><string>red</string><string>green</string><string>blue</string></array></var></struct></data></wd dxPacket> W przedstawionym przykładzie funkcja wddx_packet_start() tworzy nowy pakiet WDDX.js" LANGUAGE="JavaScript"></SCRIPT> <!--. ?> </body> </html> Wydruk 13. } function Initialize() { SetupProductsList().css"> <!--.16. oraz wypisuje zawartość pakietu. "blue" ).js" LANGUAGE="JavaScript"></SCRIPT> <script language="JavaScript"> <!-function show_props(obj. w kolejnym przykładzie pakiet WDDX jest wysyłany do strony WWW. Przykład ten pokazuje w jaki sposób można manipulować danymi na kliencie przy pomocy JavaScript. Aby pokazać jak można wykorzystać WDDX w systemie używającym kilku języków programowania.PRODUCT_ID.17. 169 PHP – Kompendium wiedzy .deserialize( '{PRODUCTS_WDDX}' )." + i + " = " + obj[i] + "\n".ARECORDS[nIndex].

options[nIndex] = NewOpt.// tworzenie nowej opcji NewOpt = new Option( aName. </td> </tr> <tr> <td colspan="3"> &nbsp.MainForm."> <option></option> <option></option> </select> </td> <td> <input type="text" name="Price" readonly> </td> <td> <input type="text" name="Weight" readonly> </td> </tr> </table> </form> </body> </html> Szablon ten intensywnie wykorzystuje JavaScript. } } //--> </script> </head> <body onload="Initialize()"> <form action="" name="MainForm" id="MainForm"> <table> <tr> <td colspan="3"> Wybierz towar z listy. </td> </tr> <tr> <th> Towar </th> <th> Cena </th> <th> Waga </th> </tr> <tr> <td> <select name="Product_List" size="1" onChange="SetInfo().ARECORDS[RowNum]. Wydruk 13.Product_List. Funkcja SetInfo() jest wywoływana po zmianie przez użytkownika wybranego elementu w liście rozwijalnej. } function SetInfo() { // ustawienie ceny i wagi zaznaczonego produktu var RowNum = document. false.ARECORDS[RowNum].WEIGHT.Price. które zostały odczytane z bazy danych przez PHP.MainForm.Weight. Funkcja SetupProductsList() deserializuje dane towarów.MainForm. Pierwsza funkcja.PRICE.value = aProducts.value = aProducts. Funkcja korzysta z obiektu WddxDeserializer dostępnego w SDK dla WDDX. Uaktualnia ona wartości wyświetlane w polach tekstowych cena i waga. Funkcja Initialize() inicjuje stronę i jest wywoływana automatycznie przez zdarzenie strony onLoad.Product_List. Przygotowanie pakietu danych WDDX <?php Rozdział 13 – Fajny PHP 170 . Ta funkcja z kolei wywołuje funkcję SetupProductsList() a następnie dodaje nazwy i identyfikatory produktów do listy rozwijalnej. true ). Po deserializacji pakietu danych WDDX obiekt JavaScript aProducts zawiera wszystkie dane produktów. // Dodanie nowego obiektu do listy SELECT document.selectedIndex. if ( RowNum > -1 ) { document. aValue. document. aby zobaczyć jego cenę i wagę. } SetInfo().18. show_props() jest jedynie funkcją testującą używaną przy wyświetlaniu właściwości obiektu.MainForm.

tpl" ) ). var $Database = "mydb". var $User = "root". while( $aDB->next_record() ) { $aRecord = $aDB->Record. include( "db_mysql. $aTemplate->assign( array( "PRODUCTS_WDDX" => addslashes( $aWDDXPacket ) ) ). Drugi wymiar to tablica asocjacyjna z nazwami kolumn i ich wartościami. Dane pochodzące z wyniku są przechowywane pod indeksami numerycznymi. $aDB = new products_db. $aTemplate->FastPrint( "BASE" ). $aTemplate->define( array( "base" => "products_wddx. Jeszcze jeden fragment tego kodu wymaga skomentowania. "aRecords" ).inc" ). "base" ). error_reporting( E_ALL & ~E_NOTICE ). 171 PHP – Kompendium wiedzy .FastTemplate. $aRecords = array(). $aTemplate->assign( array( "TITLE" => "Products Page" ) ). class products_db extends DB_Sql { var $Host = "localhost". Linia z funkcją is_numeric() jest używana do usuwania nadmiarowych informacji zwracanej przez niejawnie wykonywaną funkcję mysql_fetch_array().php" ). foreach( $aRecord as $aName => $aValue ) { if ( !is_numeric( $aName ) ) { $aRecords[$nIndex][$aName] = $aValue. $aDB->query( "select * from Products" ). $nIndex = 0. pokazana jest wynikowa strona w przeglądarce. Funkcja mysql_fetch_array() zwraca wiersz z wyniku w postaci tablicy. Jest to realizowane w pętli przebiegającej przez rekordy wyniku.5. jak również pod indeksami asocjacyjnymi gdzie jako klucze są wykorzystywane nazwy pól." ).include( "class. Zawsze po wybraniu nowego towaru automatycznie jest uaktualniana cena i waga. ?> Główny skrypt PHP wykorzystuje klasę FastTemplate w celu utworzenia kompletnej strony HTML. $aPacketID = wddx_packet_start( "products" ). } wddx_add_vars( $aPacketID. $aTemplate->parse( "BASE". var $Password = "root". Na rysunku 13. Jest to tablica dwuwymiarowa. } } $nIndex++. $aWDDXPacket = wddx_packet_end( $aPacketID ). gdzie pierwszy wymiar jest numeryczną reprezentacją numeru wiersza. dodając dane do nowej tablicy. Sprawdzenie to usuwa dane indeksowane liczbami. pozostawiając jedynie dane asocjacyjne. $aRecords. Głównym działaniem skryptu jest odczytanie zawartości tabeli Products i utworzenie pakietu WDDX zawierającego odpowiednie dane. } $aTemplate = new FastTemplate( ".

if ( $aPos > 0 ) { // wykorzystanie zmienności typów zmiennych PHP // do konwersji czasu na liczbę $aTime = substr( $aLine.0. phpPing().19. oraz łatwego współdzielenia danych pomiędzy różnymi platformami i językami. $aTraceCmd = '/usr/sbin/traceroute -n'.19. 1024 ). serwera pocztowego itd.5. $aTotalTime += $aTime. "r" ) ) { // odczytanie danych z potoku while ( !feof( $aFile ) ) { $aLine = fgets ( $aFile. zamieszczone są trzy funkcje. } Rozdział 13 – Fajny PHP 172 . $aPingCount++. WDDX zawiera narzędzia do szybkiego dostarczania treści w postaci neutralnej dla platformy i języka. Ostatnia wykorzystuje gniazda do wysłania żądania HTTP HEAD do strony w celu sprawdzenia dostępności serwera i samej strony. tworzenie narzędzi monitorujących sieć jest łatwe. Przykład ten może być szkieletem. Może być używany do przesyłania firmowych danych pomiędzy serwerami. } } pclose( $aFile ). $aPos + 5 ) * 1. może być używany na wiele sposobów. if ( $aFile = popen( "$aPingCmd $aAddress". Wydruk 13. // *nix // *nix // zwraca średni czas wykonania komendy ping function phpPing( $aAddress ) { global $aPingCmd. Jeżeli planujesz współdzielenie danych. Funkcje sieciowe <?php $aPingCmd = '/bin/ping -c 4'.Rysunek 13.0. Na wydruku 13. Monitorowanie sieci Ponieważ PHP wewnętrznie obsługuje gniazda i protokoły sieciowe. Pierwsze dwie wykorzystują komendy systemowe do wykonania operacji ping i traceroute. phpTrace() i phpPageCheck(). Poniższy przykład wykorzystuje potoki i gniazda do zrealizowania prostych funkcji monitorujących sieć. $aPingCount = 0. } return $aTotalTime / $aPingCount. // odszukanie danych o czasie $aPos = strpos( $aLine. Przykład wykorzystania danych WDDX na kliencie Choć przykład ten pokazuje w wykorzystanie WDDX do dostarczenia danych dla klienta. który można rozszerzać o nowe funkcje. Można rozszerzyć ten przykład o sprawdzanie stanu serwera nazw. $aTotalTime = 0. "time=" ).

$aTraceResults = "". 1024 ). albo mogą być użyte bezpośrednio ze strony WWW. Wykorzystanie funkcji sieciowych <?php include( ". "r" ) ) { // odczytanie wszystkich danych z potoku while ( !feof( $aFile ) ) { $aLine = fgets ( $aFile.0\r\n\r\n".php. co pozwala rozszerzać przytoczony przykład o sprawdzenie dostępności wszystkich rodzajów serwerów i komponentów sieciowych. if ( $aURL["scheme"] == "http" ) { $aRequest = "HEAD {$aURL['path']} HTTP/1. "phpTrace: <ul>" . while( !feof( $aSocket ) ) { $aLine = fgets( $aSocket.function phpTrace( $aAddress ) { global $aTraceCmd. ?> <html> <head> <title>Test funkcji sieciowych</title> </head> <body> <?php print( print( print( print( print( ?> </body> </html> "phpPing: " . SNMP. "<br><br>" ). "</ul><br>" ). } return $aTraceResults.net' ) . if ( substr( $aLine. pokazuje w jaki sposób używa się tych funkcji. 0.20. if ( $aSocket ) { fputs( $aSocket. } } } } } return $aResult. $aLine )./net_funcs. 173 PHP – Kompendium wiedzy . 4 ) == "HTTP" ) { $aArray = explode( " ". 80 ). 1024 ). phpPing ( 'www. if ( ( $aArray[1] >= 200 ) && ( $aArray[1] < 300 ) ) { $aResult = True.net' ) .net/' ) ? "OK" : "NOT OK" ). } function phpPageCheck( $aWebPage ) { $aURL = parse_url( $aWebPage ).20. NNTP i POP3. } ?> Funkcje te mogą być wykorzystane w skrypcie automatyzującym do okresowego zapisywania wyników do bazy danych lub do pliku. "<br>" ).php" ).= $aLine . PHP obsługuje również inne protokoły sieciowe. Wydruk 13. $aSocket = fsockopen( $aURL["host"]. Skrypt z wydruku 13.php. $aResult = False. $aTraceResults . "<br>". $aRequest ). if ( $aFile = popen( "$aTraceCmd $aAddress".php. takie jak IMAP. } pclose( $aFile ). phpPageCheck( 'http://www. Przykład ten pokazuje jak łatwo można wykorzystać PHP do wykonania podstawowego monitorowania sieci. phptrace( 'www. "phpPageCheck: " ).

Rozdział 13 – Fajny PHP 174 . analizy XML. tworzenia plików PDF i wielu innych zadań. Istnieją również rozszerzenia do tworzenia rysunków. należy spodziewać się dalszego zwiększania elastyczności i funkcjonalności. Ponieważ PHP jest tak rozszerzalny i rozwijany przez ogromną grupę programistów.Podsumowanie Rozdział ten opisywał różne zagadnienia pokazujące siłę i elastyczność PHP.

W tym rozdziale zostanie szczegółowo opisane wykorzystanie szablonów do tworzenia witryn. Użycie szablonów do projektowania aplikacji umożliwia o wiele więcej.net/. Aby stworzyć system szablonów dla takiej witryny zdefiniowano następujące szablony: 1. Podstawy wykorzystania szablonów Tworzenie witryn WWW korzystających z systemu szablonów wymaga nieco dokładniejszego projektowania interfejsu użytkownika.tpl: Stopka każdej strony. łącza.Informacje. Na rysunku 14. Każda strona produktu powinna zawierać dane o towarze. Jednak korzyści wykorzystania dobrze zaprojektowanego zaczną się ujawniać bardzo szybko.Podstawowa strona HTML szablonów Main body . Przeglądając wybraną kategorię produktów. Page header . Przykłady przytoczone w tym rozdziale wykorzystują klasę FastTemplate dostępną z witryny http://www. Rysunek 14. należy ocenić potrzeby witryny i zinwentaryzować elementy znajdujące się na stronach. Przykładem będzie witryna pełniąca funkcję sieciowego katalogu towarów. 4.. links. 2.thewebmasters. ponieważ są one właściwie takie same. Katalog ten jest podzielony na kategorie produktów. 3. 5. 6. merch_header. merch_body. do 6 zawierają kolejne pliki wymienione powyżej. Wydruki od 1. waga. niezależności od przeglądarki oraz obsługi wielu języków.panel nawigacji składająca się z footer .1. news . personalizacji.tpl: Nagłówek wspólny dla wszystkich stron witryny. prezenty.tpl. merch_navi. przedstawiona zostaną teraz zawartość każdego z nich. Aby zaprojektować witrynę korzystającą z szablonów. Aby pokazać jak zostały stworzone te pliki.tpl: Podstawowy plik zawierający ogólny układ HTML. „Oddzielanie HTML od PHP” zostało opisane użycie systemu szablonów. powinien być wyświetlany element graficzny oznaczający tą kategorię. Witryny oparte o szablony W rozdziale 12. która może być podzielona na kilka osobnych plików szablonów. Każda strona musi zawierać wspólne elementy nawigacyjne oraz logo całej witryny. niż tworzenie tej samej aplikacji bez szablonów.Rozdział 14.nagłówek strony Strona WWW navigation .1. Pliki dla pozostałych kategorii nie zostały pokazane.3 pokazany został plik merch_catubrania_header. Istnieją również inne systemy szablonów. nowości Na rysunku 14. pokazana jest strona składająca się z jednego lub więcej szablonów. takie jak cena.tpl <html> <head> .1.tpl: Nagłówek określonej kategorii (XXX zastąpione przez nazwę kategorii). zabawki itd. merch_catXXX_header.tpl: Panel nawigacyjny katalogu. elastyczna i łatwa do nauki.1. merch_base. właściwy dla kategorii produktów ubrania. dostępne kolory itd. niż jedynie oddzielanie logiki aplikacji od projektu graficznego. merch_base. takie jak: ubrania. Wydruk 14. ale ta implementacja jest wydajna. merch_footer. Na wydruku 14. Na niektórych witrynach WWW może być wykorzystany tylko jeden szablon dla wszystkich stron witryny. contacts.stopka kilku plików HTML base page .tpl: Treść każdej strony. które składają się na stronę HTML z różnymi logicznymi sekcjami strony. W innych. kontakty.Główny obszar strony information. Szablony umożliwiają zastosowanie zapożyczania fragmentów witryn. pokazana jest typowa strona WWW. każda strona może być tworzona na podstawie kilku szablonów.

merch_catubrania_header. merch_header.166" href="{HREF_CONTACT}" > <area shape="rect" coords="12. na przykład nagłówek zawiera jedynie rysunek. Wydruk 14.gif" width="630" height="37" border="0"><br> <div align="center"><p>{CATEGORY_SPECIALS}</p></div> Wydruk 14.tpl <hr> <p> &copy {COPYRIGHT_YEARS} Intechra LLC.6.73. jak na przykład szablon panelu nawigacyjnego zawiera zarówno rysunek.2. </p> <h3> {PRODUCT_NAME} </h3> <p> {PRODUCT_DESCRIPTION} </p> <p> {PRODUCT_PRICE} </p> Wydruk 14. $aTPL = new FastTemplate( ".132" href="{HREF_CART}" > <area shape="rect" coords="18. Inne. // zakładamy.<title>{TITLE}</title> </head> <body bgcolor="White"> <table width="630" border="0" cellspacing="0" cellpadding="0" align="center"> <tr> <td colspan="2">{PAGE_HEADER}</td> </tr> <tr> <td colspan="2" align="center">{CAT_HEADER}</td> </tr> <tr> <td valign="top">{LEFT_NAVI}</td> <td valign="top"> {BODY} </td> </tr> <tr> <td colspan="2"> {PAGE_FOOTER} </td> </tr> </table> </body> </html> Wydruk 14. Łączenie szablonów <?php include( "class.90. Wszystkie prawa zastrzeżone. 'merch_navi." ).tpl <img src="merch_layout_r3_c1.7.tpl'. merch_footer. $aTPL->define( array( 'base' 'header' 'navi' 'footer' 'cat_header' 'body' => => => => => => 'merch_base2.86.tpl <img name="merch_layout_r2_c1" src="merch_layout_r2_c1.4. jak i mapę obrazu. Skrypt PHP pokazany na wydruku 14. merch_navi. 'merch_footer.tpl <img src="merch_layout_r1_c1.php" ).3.tpl'.tpl'.143. że szablon nawigacyjny nie zawiera aktualnych adresów URL.180. merch_body.gif" width="630" height="61" border="0"> Wydruk 14.FastTemplate.5.tpl' Rozdział 14 – Witryny oparte o szablony 176 .56.221" href="{HREF_COMPANY_INFO}" > <area shape="rect" coords="7. pokazuje w jaki sposób można połączyć pliki szablonów w jedną całość. </p> Pliki te pokazują jak niewiele potrzeba do stworzenia dosyć skomplikowanej witryny korzystającej z szablonów. na przykład zawierających identyfikator sesji.tpl <p> &nbsp.7. $aCategoryHeader.gif" width="104" height="382" border="0" usemap="#merch_layout_r3_c1"> <map name="merch_layout_r3_c1"> <area shape="rect" coords="5.80" href="{HREF_HOME}" > </map> Wydruk 14.84.tpl'. Niektóre z tych plików. 'merch_body.97. 'merch_header. że wybraną kategorią są ubrania $aCategoryHeader = 'merch_catubrania_header. Należy zwrócić uwagę.tpl'. a jedynie zmienne szablonu Pozwala to na stworzenie właściwych adresów łączy.

na ten z wydruku 14.phtml'. 'Koszulka Intechra'. większość wymaganych zmiennych (takich jak PAGE_HEADER i BODY) nie było by dostępnych.phtml' 'header' ). jeżeli w powyższym przykładzie strona base była by analizowana na początku. Skrypt ten wykorzystuje klasę FastTemplate do analizy i połączenia wszystkich plików szablonów tworzących katalog produktów. 'Świetna koszulka z logo Intechra LLC!'. Dla przykładu zmienna PAGE_HEADER jest ustawiana poprzez analizę strony o nazwie header. 'navi' ). Dla przykładu. $aTPL->FastPrint( 'BASE' ).6.phtml'. 177 PHP – Kompendium wiedzy . Dodatkowo niektóre zmienne FastTemplate są ustawiane za pomocą metody parse(). $aTPL->parse( 'PAGE_HEADER'. Efekt zmiany szablonu base pokazany jest na rysunku 14. 'cart. Na przykład zmienna COPYRIGHT_YEARS wykorzystywana w szablonie merch_footer. $aTPL->assign( array( 'TITLE' 'CATEGORY_SPECIALS' 'PRODUCT_NAME' 'PRODUCT_DESCRIPTION' 'PRODUCT_PRICE' 'COPYRIGHT_YEARS' 'HREF_HOME' 'HREF_CART' 'HREF_CONTACT' 'HREF_COMPANY_INFO' ) ). 'footer' ). 'index. pokazany został wygląd strony wygenerowanej przez skrypt z wydruku 14. Na rysunku 14. 'cat_header' ). który w naszym przykładzie został nazwany base. wygląd strony ulega całkowitej zmianie. że niektóre zmienne FastTemplate są ustawiane przy użyciu metody assign().8.tpl. W przykładzie tym wszystkie wartości zostały na stałe zaszyte w skrypcie w celu uproszczenia opisu.95 zł'. Siłą zastosowania szablonów jest możliwość łatwego wprowadzania zmian w projekcie graficznym witryny. Zmieniając szablon o nazwie base. $aTPL->parse( 'PAGE_FOOTER'. Aby zrozumieć w jaki sposób FastTemplate analizuje stronę należy wiedzieć. '2001'.2.phtml'. Dodatkowo należy analizować szablony we właściwej kolejności.) ). 'Sprzedajemy koszulki Intechra!'.1. ?> => => => => => => => => => => 'Katalog towarów: Ubrania'. że w przypadku zagłębiania szablonów należy zainicjować wszystkie wymagane zmienne szablonu przed jego analizą. W prawdziwej aplikacji dane na temat kategorii produktu oraz wyświetlanego produktu powinny być dostarczone poprzez formularz lub inną metodę dynamicznego dostarczania danych. Skrypt ten po prostu przypisuje wartości do wszystkich zmiennych potrzebnych we wszystkich plikach szablonów. $aTPL->parse( 'BODY'.tpl jest inicjowana wartością 2000 przy użyciu metody assign(). '14.3. $aTPL->parse( 'CAT_HEADER'. $aTPL->parse( 'LEFT_NAVI'. z zamieszczonego na wydruku 14. 'body' ). 'company. Należy pamiętać. że wartość PAGE_HEADER jest już dostępna w czasie analizy pliku merch_base. 'base' ). Powoduje to. $aTPL->parse( 'BASE'. 'contact.

Nowy plik szablonu „base” <html> <head> <title>{TITLE}</title> <link rel="STYLESHEET" type="text/css" href="new_base.8. Wydruk 14.7.2.Rysunek 14. Strona wygenerowana przez skrypt z wydruku 14.css"> </head> <body bgcolor="White"> <table width="630" border="0" cellspacing="0" cellpadding="0" align="center"> <tr> <td colspan="2">{PAGE_HEADER}</td> </tr> <tr> <td colspan="2" align="center">{CAT_HEADER}</td> </tr> <tr> <td width="526" valign="top"> {BODY} </td> <td valign="top">{LEFT_NAVI}</td> </tr> <tr> <td colspan="2"> {PAGE_FOOTER} </td> </tr> </table> </body> </html> Rozdział 14 – Witryny oparte o szablony 178 .

W poprzednim przykładzie jedyną znacząca zmianą wprowadzoną w szablonie base było dołączenie pliku CSS. Edytor ten upraszcza proces tworzenia plików CSS oraz pozwala na podgląd zmienionych stylów.Rysunek 14.com/). CSS jest wartościowym dodatkiem do większości zastosowań WWW. natomiast programiści aplikacji równolegle tworzą i konserwują część logiczną. natomiast nie zostały wprowadzone żadne zmiany po stronie PHP. znacznie zmieniony został wygląd strony. Strona wygenerowana przy użyciu nowego szablonu „base” Siła systemu szablonów nie może być przeceniana. Tak jak to zostało pokazane. Na wydrukach 14. Wykorzystując CSS. pokazany jest wygląd komercyjnego edytora CSS o nazwie TopStyle z firmy Bradbury Software LLC (http://www. Oczywiści zachodzi niezbędna interakcja pomiędzy programistami i projektantami interfejsu. aby w kontekście tej witryny wyglądał w określony sposób. ale po zdefiniowaniu zestawu plików szablonów i zmiennych szablonów praca obu grup może pracować równolegle.4.5. Dodatkowo. Elastyczność ta pozwala projektantom na tworzenie i konserwację bogatego interfejsu użytkownika. do czasu aż projektanci dostarczą im ostateczne wersje. ponieważ stanowi on system szablonów dla HTML.3. Na przykład można tak zdefiniować znacznik <h3>. zmieniając zawartość szablonu base.bradsoft. 179 PHP – Kompendium wiedzy . można zmienić atrybuty wszystkich elementów HTML. wykorzystanie szablonów pozwala programistom na wykorzystywanie zestawu prototypowych plików interfejsu. i 14.

<td> i <h3> Rysunek 14.4. Pliki CSS mogą być nawet dołączane dynamicznie. <td> i <h3> Użycie CSS wraz z systemem szablonów zwiększa możliwość wprowadzania zmian do wyglądu witryny minimalizując konieczność wprowadzania zmian do kodu aplikacji. w postaci zmiennej szablonu.Rysunek 14. Arkusz stylu pokazujący możliwość modyfikacji znaczników <body>.5. że nie jest to optymalne rozwiązanie dla wszystkich typów witryn. pozwala zrealizować kolejny poziom konfiguracji wyglądu tworzonej aplikacji. Inny arkusz stylu pokazujący możliwość modyfikacji znaczników <body>. Mimo. Rozdział 14 – Witryny oparte o szablony 180 .

Wynik działania skryptu przedstawiony jest na rysunku 14. korzystając z klasy FastTemplate. Na wydruku 14. Często zachodzi potrzeba stworzenia tabeli zawierającej wszystkie towary. szablon pojedynczego elementu. $aTPL->parse( 'ITEMS'. Wydruk 14. '.php" ).tpl' ) ). $aTPL->parse( 'BASE'. $aCategories = array( "ubrania". $aTPL->FastPrint( 'BASE' ). lub listę kategorii zapisanych w bazie danych. Wydruk 14. foreach( $aCategories as $aID => $aName ) { $aTPL->assign( array( 'CAT_ID' => $aID. "prezenty". Efekt końcowy pokazany jest na rysunku 14.7. w jaki sposób można dołączyć powtarzające się elementy. } $aTPL->assign( array( 'TITLE' => 'Lista kategorii' ) ).9. // analiza elementu i jego dołączenie do zmiennej szablonu // ITEM_LIST $aTPL->parse( 'ITEM_LIST'.10. 'base' )." ).11. 'CAT_NAME' => $aName ) ).12. Wydruk 14.11.10.tpl'. że dział projektowy zdecydował się na zmianę formatu listy kategorii z listy wypunktowanej na tabelę. to zawartość szablonu items. Kolejny przykład pokazuje. Jednak nie zostały tu pokazane przykłady tworzenia powtarzających się elementów. Skrypt generujący stronę z listą kategorii <?php include( "class.Poprzedni przykład stanowi podstawowy szkielet dla tworzenia aplikacji WWW opartej o szablony. Główny szablon kategorii <html> <head> <title>{TITLE}</title> </head> <body> {ITEMS} </body> </html> Wydruk 14. i 14. Szablon kategorii ‘items’ Do wyboru są następujące kategorie produktów: <ul> {ITEM_LIST} </ul> Wydruk 14.item' ). $aTPL->define( array( 'base' => 'cat_base. $aTPL = new FastTemplate( ". Szablon dla pojedynczej kategorii <li><a href="show_category. Po raz kolejny załóżmy. "książki" ). PHP – Kompendium wiedzy 181 . ?> Rysunek 14.phtml?cat_id={CAT_ID}">{CAT_NAME}</a></li> Wydruk 14. "zabawki".FastTemplate. Wykorzystując poprzedni przykład zmienione szablony przedstawione są na wydrukach 13. Lista kategorii Przedstawiony przykład zawiera wbudowaną listę kategorii w celu wygenerowania strony z listą kategorii.6. 'item' => 'cat_item.6. zawiera główny plik szablonu.tpl'. 'items' => 'cat_items. 'items' ).12 znajduje się skrypt łączący te szablony w całość.9. Zmiany są ograniczone jedynie do plików items i item. natomiast wydruk 14.

Rozdział 14 – Witryny oparte o szablony 182 . Nowy skrypt PHP <?php include( "class.FastTemplate.BEGIN DYNAMIC BLOCK: item --> <tr> <td> Kategoria nr. co stworzenie osobnego pliku zawierającego szablon item. Lista kategorii w postaci tabeli Przedstawiony przykład pokazuje podstawowe kroki potrzebne do generowania listy powtarzających się elementów przy użyciu FastTemplate. Na wydrukach 15. Zostały one zamieszczone na wydruku 14.php" ). zamieszczone są zmienione pliki. i 16. $aTPL = new FastTemplate( ".Wydruk 14.END DYNAMIC BLOCK: item --> </table> W szablonie tym został zdefiniowany podszablon — blok dynamiczny o nazwie item." ). {CAT_ID} </td> <td> <a href="show_category. Wydruk 14.13. Użycie szablonów wymaga również kilku zmian w skrypcie używającym klasy FastTemplate. Wydruk 14.16. Wynik działania tego skryptu jest taki. Nowy szablon „items” Do wyboru są następujące kategorie produktów: <br><br> <table border="1"> {ITEM_LIST} </table> Wydruk 14. Istnieje również w FastTemplate inny mechanizm pozwalający na wyeliminowanie dodatkowych plików zawierających szablon pojedynczego elementu. $aTPL->define( array( 'base' => 'cat_base. jak pokazany na rysunku 14.7. 'items' => 'cat_items_dyn. Nowy szablon „item” <tr> <td> Kategoria nr. {CAT_ID} </td> <td> <a href="show_category. Zaletą takiego rozwiązania jest utrzymanie oryginalnej struktury pliku HTML oraz ograniczenie ilości niezbędnych plików szablonów.15. Nowy szablon „items” korzystający z dynamicznych bloków Do wyboru są następujące kategorie produktów: <br><br> <table border="1"> <!-.16.tpl'.phtml?cat_id={CAT_ID}">{CAT_NAME}</a> </td> </tr> Rysunek 14. Aby użyć tego mechanizmu zmienimy szablon items. oraz główny skrypt PHP.phtml?cat_id={CAT_ID}">{CAT_NAME}</a> </td> </tr> <!-.tpl') ).7. Jest to dokładnie to samo.14.

należy zdecydować na ile konfigurowalna powinna być taka witryna. Tworząc aplikację. można jedynie umieszczać tam dowolną ilość znaków odstępu. ?> W skrypcie tym widoczne są dwie wyraźne zmiany w stosunku do wydruku 14.item' ). Linie BEGIN i END nie mogą rozciągać się na większa ilość linii. jak poniższa linia kodu. i 18. aby upewnić się. W linii zawierającej wyrażenia BEGIN i END nie powinno być żadnego innego tekstu. Po drugie. 'CAT_NAME' => $aName ) ). żądać zmian w terminologii itd. że w szablonie items istnieje blok dynamiczny o nazwie item. Istnieje kilka sposobów zrealizowania takiego scenariusza w PHP. Zapożyczanie Zapożyczanie jest bardzo łatwo realizowalne za pomocą witryny opartej o szablony. poniższe pliki szablonów są wykorzystywane w aplikacji przedstawionej w poprzedniej części. jak przedstawiona. 'items' ). } $aTPL->assign( array( 'TITLE' => 'Lista kategorii' ) ). $aTPL->parse( 'ITEMS'. która wskazuje systemowi FastTemplate. <!-. 'base' ).$aTPL->define_dynamic( 'item'. Tworzenie zapożyczonej witryn jest w zasadzie identyczne. "zabawki". // analiza elementu i jego dołączenie do zmiennej szablonu // ITEM_LIST $aTPL->parse( 'ITEM_LIST'. Aby zilustrować to zagadnienie.css"> 183 PHP – Kompendium wiedzy . która może być zapożyczana. z dokładnością do odstępów pomiędzy znakami.18. jak tworzenie innych witryn opartych o szablony. '. Zapożyczanie witryny to wykorzystanie projektu witryny partnerskiej jako podstawy własnej aplikacji. jak to zostało zaplanowane. "książki" ). Dla przedstawianego wcześniej przykładu katalogu produktów. w nowym skrypcie brakuje jednego wywołania metody define(). </p> Wydruk 14. Składnia linii BEGIN i END musi być poprawna i wymagane jest zachowanie odpowiedniej wielkości liter. Korzystając z tego mechanizmu. &copy 2000 &copy {COPYRIGHT_YEARS} Intechra LLC. integracja i testowanie musi być przeprowadzone przez obie strony. 'items' ). jak byłby to osobny plik. Następna część tego rozdziału zawiera kilka przykładów scenariuszy stosowanych w prawdziwych aplikacjach. W tym scenariuszu zmienione zostały jedynie dane o prawach autorskich oraz szablon bazowy. Wydruk 14. aby blok dynamiczny był poprawny składniowo. jest możliwe aby kilk