You are on page 1of 390

Spis Tresci

SPIS TRESCI............................................................................................................................................................ 1 WSTEP ...................................................................................................................................................................... 7 Dla kogo jest przeznaczona ta ksiazka ............................................................................................................... 7 Konwencje .......................................................................................................................................................... 7 Omwienie ksiazki.............................................................................................................................................. 7 Od autora ........................................................................................................................................................... 8 Przyklady kodu ................................................................................................................................................... 8 CZYM JEST PHP....................................................................................................................................................... 8 DLACZEGO POWINIENES UZYC PHP......................................................................................................................... 9 GDZIE SZUKAC POMOCY .......................................................................................................................................... 9 PODZIEKOWANIA ................................................................................................................................................... 10 O AUTORZE............................................................................................................................................................ 10 ROZDZIAL 1. KOMPILACJA I INSTALOWANIE PHP................................................................................ 11 WSTEP ................................................................................................................................................................... 11 POBIERANIE PHP................................................................................................................................................... 11 INSTALOWANIE WERSJI BINARNEJ .......................................................................................................................... 11 Binarna instalacja dla Windows ...................................................................................................................... 11 Instalowanie PHP w postaci modulu ISAPI................................................................................................. 12 Uzycie PHP jako CGI................................................................................................................................... 14 Inne instalacje binarne..................................................................................................................................... 14 KOMPILOWANIE PHP ............................................................................................................................................ 15 Kompilowanie PHP w Uniksach ...................................................................................................................... 15 Kompilacja modulu CGI .............................................................................................................................. 15 Kompilacja PHP jako statycznie dolaczanego modulu Apache................................................................... 17 Kompilacja PHP do postaci dynamicznie ladowanego modulu Apache ..................................................... 17 Podsumowanie kompilacji PHP w systemach Unix..................................................................................... 18 Kompilowanie PHP w srodowisku Windows ................................................................................................... 18 Podsumowanie kompilacji PHP....................................................................................................................... 20 KONFIGUROWANIE PHP ........................................................................................................................................ 20 Korzystanie z pliku php.ini ............................................................................................................................... 20 Inne metody zmiany konfiguracji PHP............................................................................................................. 21 PODSUMOWANIE ................................................................................................................................................... 22 ROZDZIAL 2. JEZYK .......................................................................................................................................... 23 WSTEP ................................................................................................................................................................... 23 OGLNE INFORMACJE NA TEMAT SKLADNI ............................................................................................................ 23 TYPY ..................................................................................................................................................................... 24 Liczby calkowite i zmiennoprzecinkowe ...................................................................................................... 24 Ciagi ................................................................................................................................................................. 24 Tablice .............................................................................................................................................................. 25 ZMIENNE I STALE ................................................................................................................................................... 26 Zmienne predefiniowane .................................................................................................................................. 26 Zasieg zmiennych ............................................................................................................................................. 30

Stale.................................................................................................................................................................. 31 OPERATORY I KOLEJNOSC OPERATORW ............................................................................................................... 31 PROGRAMOWANIE PRZEPLYWU 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 PORWNYWANIE WZORCW ................................................................................................................................. 39 Podsumowanie ................................................................................................................................................. 39 ROZDZIAL 3. FORMULARZE I COOKIE....................................................................................................... 40 WSTEP ................................................................................................................................................................... 40 OBSLUGA FORMULARZY W PHP ............................................................................................................................ 41 Skalarne i wielowartosciowe elementy formularza.......................................................................................... 41 Alternatywne metody odczytywania wartosci z formularza ............................................................................. 42 Uzycie formularzy do przesylania plikw ........................................................................................................ 45 Uzycie rysunku jako przycisku wyslania danych.............................................................................................. 45 KONTROLA POPRAWNOSCI DANYCH FORMULARZA................................................................................................ 46 Kontrola danych za pomoca wyrazen regularnych.......................................................................................... 46 Kontrola poprawnosci za pomoca sprawdzania typw.................................................................................... 47 Klasa Validator ................................................................................................................................................ 48 COOKIE ................................................................................................................................................................. 49 WAZNE ZAGADNIENIA PROGRAMOWANIA DLA WWW.......................................................................................... 50 Obsluga nieprawidlowych danych ................................................................................................................... 50 Obsluga i formatowanie wyswietlanych danych .............................................................................................. 52 PODSUMOWANIE ................................................................................................................................................... 57 ROZDZIAL 4. OPERACJE NA PLIKACH........................................................................................................ 58 WSTEP ................................................................................................................................................................... 58 ODCZYT I ZAPIS PLIKW ........................................................................................................................................ 58 UZYCIE GNIAZD ..................................................................................................................................................... 59 UZYCIE POTOKW ................................................................................................................................................. 60 KLASA FILE ........................................................................................................................................................... 61 PODSUMOWANIE ................................................................................................................................................... 61 ROZDZIAL 5. WYSYLANIE PLIKW PRZEZ FORMULARZ ................................................................... 62 WSTEP ................................................................................................................................................................... 62 WYSYLANIE POJEDYNCZEGO PLIKU ....................................................................................................................... 62 PULAPKI ................................................................................................................................................................ 64 PRZESYLANIE WIELU PLIKW ................................................................................................................................ 64 BEZPIECZENSTWO ................................................................................................................................................. 65 PODSUMOWANIE ................................................................................................................................................... 66 ROZDZIAL 6. WSPLPRACA Z BAZAMI DANYCH ................................................................................... 67 WSTEP ................................................................................................................................................................... 67 WPROWADZENIE ................................................................................................................................................... 67 FUNKCJE BAZ DANYCH .......................................................................................................................................... 67 MYSQL................................................................................................................................................................. 68 2 Spis Tresci

Rozpoczynamy prace z MySQL ........................................................................................................................ 68 Uzycie MySQL.................................................................................................................................................. 68 ODBC ................................................................................................................................................................... 71 Podstawy ODBC .............................................................................................................................................. 71 Instalowanie i kompilowanie unixODBC .................................................................................................... 72 Kompilowanie PHP z obsluga unixODBC .................................................................................................. 72 Instalowanie sterownika OOB...................................................................................................................... 72 Konfigurowanie OOB .................................................................................................................................. 72 Korzystanie z ODBC ........................................................................................................................................ 73 PHPLIB ................................................................................................................................................................ 74 PRZECHOWYWANIE DANYCH Z FORMULARZY........................................................................................................ 75 WYKORZYSTANIE MOZLIWOSCI BAZY DANYCH ..................................................................................................... 77 PODSUMOWANIE ................................................................................................................................................... 78 ROZDZIAL 7. SESJE I STAN APLIKACJI....................................................................................................... 80 WSTEP ................................................................................................................................................................... 80 PODSTAWY MECHANIZMU SESJI ............................................................................................................................. 80 WBUDOWANY W PHP MECHANIZM ZARZADZANIA SESJAMI .................................................................................. 81 Rozpoczecie pracy z sesjami w PHP ................................................................................................................ 81 Przesylanie identyfikatora sesji bez uzycia cookie........................................................................................... 83 Zapisywanie zmiennych sesji w bazie danych .................................................................................................. 85 Inne funkcje i opcje dotyczace sesji.................................................................................................................. 89 UZYCIE PHPLIB DO OBSLUGI SESJI ....................................................................................................................... 90 TWORZENIE WLASNEGO MECHANIZMU SESJI ......................................................................................................... 92 INZYNIERIA PROGRAMOWANIA A SESJE ................................................................................................................. 92 PODSUMOWANIE ................................................................................................................................................... 94 ROZDZIAL 8. UWIERZYTELNIANIE.............................................................................................................. 95 WSTEP ................................................................................................................................................................... 95 PODSTAWOWE UWIERZYTELNIANIE W APACHE ..................................................................................................... 95 AKTUALIZACJA PLIKU .HTACCESS PRZY UZYCIU PHP............................................................................................ 97 PODSTAWOWE UWIERZYTELNIANIE ZA POMOCA PHP ........................................................................................... 99 KOMPLETNY SYSTEM UWIERZYTELNIANIA OPARTY O PHP ................................................................................. 100 PODSUMOWANIE ................................................................................................................................................. 104 ROZDZIAL 9. NIEZALEZNOSC OD PRZEGLADARKI ............................................................................. 105 WSTEP ................................................................................................................................................................. 105 ROZPOCZYNAMY ................................................................................................................................................. 105 WEWNETRZNE FUNKCJE PHP .............................................................................................................................. 106 Dodatkowe informacje na temat Browscap ................................................................................................... 106 BROWSERHAWK .................................................................................................................................................. 109 WYKORZYSTANIE DANYCH O PRZEGLADARCE..................................................................................................... 113 PODSUMOWANIE ................................................................................................................................................. 114 ROZDZIAL 10. URUCHAMIANIE................................................................................................................... 115 WSTEP ................................................................................................................................................................. 115 INZYNIERIA PROGRAMOWANIA A URUCHAMIANIE ............................................................................................... 115 Projekt aplikacji ............................................................................................................................................. 115 Definiowanie standardw programowania.................................................................................................... 116 Przeglad oprogramowania............................................................................................................................. 116 Testowanie...................................................................................................................................................... 117 Uruchamianie................................................................................................................................................. 117 PROGRAMOWANIE DEFENSYWNE ......................................................................................................................... 118 WLASNA OBSLUGA BLEDW................................................................................................................................ 122 PHP Kompendium wiedzy 3

ZAAWANSOWANA OBSLUGA BLEDW ................................................................................................................. 125 PODSUMOWANIE ................................................................................................................................................. 129 BIBLIOGRAFIA ..................................................................................................................................................... 130 ROZDZIAL 11. PONOWNE WYKORZYSTANIE KODU ............................................................................ 131 WSTEP ................................................................................................................................................................. 131 PONOWNE WYKORZYSTANIE KODU A INZYNIERIA PROGRAMOWANIA .................................................................. 131 PONOWNE UZYCIE ISTNIEJACEGO KODU .............................................................................................................. 132 PHP ................................................................................................................................................................ 132 C/C++ ............................................................................................................................................................ 133 Java ................................................................................................................................................................ 138 Dodawanie obslugi Javy w PHP na *niksach ............................................................................................ 138 Dolaczanie obslugi Javy w PHP dla Windows .......................................................................................... 139 Opcje konfiguracji Javy.............................................................................................................................. 139 COM ............................................................................................................................................................... 141 Inne metody .................................................................................................................................................... 143 PODSUMOWANIE ................................................................................................................................................. 144 BIBLIOGRAFIA ..................................................................................................................................................... 144 ROZDZIAL 12. ODDZIELANIE KODU HTML OD PHP ............................................................................. 145 WSTEP ................................................................................................................................................................. 145 WPROWADZENIE ................................................................................................................................................. 145 ODDZIELENIE I INTEGRACJA PRZY UZYCIU WBUDOWANYCH FUNKCJI PHP.......................................................... 146 Motywacja ...................................................................................................................................................... 146 Implementacja ................................................................................................................................................ 147 Czego nalezy unikac ....................................................................................................................................... 151 Podsumowanie: Oddzielanie i integracja przy wykorzystaniu funkcji PHP.................................................. 151 WYKORZYSTANIE SYSTEMU SZABLONW............................................................................................................ 152 FastTemplate.................................................................................................................................................. 152 Zaawansowane techniki uzycia FastTemplate ............................................................................................... 157 PODSUMOWANIE ................................................................................................................................................. 159 BIBLIOGRAFIA ..................................................................................................................................................... 159 ROZDZIAL 13. FAJNY PHP.............................................................................................................................. 160 WSTEP ................................................................................................................................................................. 160 WYSYLANIE DO PRZEGLADARKI PLIKW INNYCH NIZ HTML.............................................................................. 160 SKRYPTY AUTOMATYZUJACE .............................................................................................................................. 164 WDDX................................................................................................................................................................ 168 MONITOROWANIE SIECI ....................................................................................................................................... 172 PODSUMOWANIE ................................................................................................................................................. 174 ROZDZIAL 14. WITRYNY OPARTE O SZABLONY ................................................................................... 175 PODSTAWY WYKORZYSTANIA SZABLONW ......................................................................................................... 175 ZAPOZYCZANIE ................................................................................................................................................... 183 PERSONALIZACJA WITRYNY................................................................................................................................. 185 OBSLUGA WIELU JEZYKW .................................................................................................................................. 187 PODSUMOWANIE ................................................................................................................................................. 189 ROZDZIAL 15. WITRYNY OPARTE O BAZE DANYCH............................................................................ 190 WSTEP ................................................................................................................................................................. 190 PROJEKT BAZY DANYCH ...................................................................................................................................... 190 ZARZADZANIE DANYMI APLIKACJI....................................................................................................................... 192 WYSWIETLANIE DANYCH .................................................................................................................................... 199 PODSUMOWANIE ................................................................................................................................................. 204 Spis Tresci 4

ROZDZIAL 16. GENEROWANIE STATYCZNYCH STRON HTML W OPARCIU O DYNAMICZNE DANE..................................................................................................................................................................... 205 WSTEP ................................................................................................................................................................. 205 KONCEPCJA ......................................................................................................................................................... 205 GENEROWANIE STRON STATYCZNYCH ................................................................................................................. 205 Uzycie buforowania........................................................................................................................................ 205 Uzycie FastTemplate ...................................................................................................................................... 207 TECHNIKI BUFOROWANIA .................................................................................................................................... 208 PODSUMOWANIE ................................................................................................................................................. 210 ROZDZIAL 17. WITRYNY HANDLU ELEKTRONICZNEGO ................................................................... 211 WSTEP ................................................................................................................................................................. 211 BEZPIECZENSTWO ............................................................................................................................................... 211 Zastosowanie SSL........................................................................................................................................... 211 Certyfikaty ...................................................................................................................................................... 211 Bezpieczenstwo bazy danych .......................................................................................................................... 212 PRZETWARZANIE PLATNOSCI ............................................................................................................................... 212 DOSTARCZANIE PRODUKTW .............................................................................................................................. 219 PODSUMOWANIE ................................................................................................................................................. 220 DODATEK A. FUNKCJE ................................................................................................................................... 221 DODATEK B. PREDEFINIOWANE ZMIENNE I STALE PHP................................................................... 367 ZMIENNE ............................................................................................................................................................. 367 Zmienne Apache ............................................................................................................................................. 367 Zmienne srodowiska....................................................................................................................................... 369 Zmienne PHP ................................................................................................................................................. 369 STALE .................................................................................................................................................................. 370 DODATEK C. OPCJE KOMPILACJI PHP..................................................................................................... 372 BAZY DANYCH .................................................................................................................................................... 372 HANDEL ELEKTRONICZNY ................................................................................................................................... 374 GRAFIKA ............................................................................................................................................................. 374 RZNE ................................................................................................................................................................. 375 --enable-inline-optimization........................................................................................................................... 376 SIEC ..................................................................................................................................................................... 379 DZIALANIE PHP .................................................................................................................................................. 379 SERWER ............................................................................................................................................................... 380 TEKST I JEZYK ..................................................................................................................................................... 380 XML ................................................................................................................................................................... 381 DODATEK D. OPCJE KONFIGURACJI PHP ............................................................................................... 382 OGLNE DYREKTYWY KONFIGURACJI ................................................................................................................. 382 DYREKTYWY KONFIGURACJI POCZTY .................................................................................................................. 385 DYREKTYWY KONFIGURACJI TRYBU BEZPIECZNEGO ........................................................................................... 385 DYREKTYWY KONFIGURACJI DEBUGGERA ........................................................................................................... 385 DYREKTYWY LADOWANIA ROZSZERZEN ............................................................................................................. 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 MOZLIWOSCI PRZEGLADAREK ................................................................................ 389 DYREKTYWY KONFIGURACJI ZUNIFIKOWANEGO ODBC ..................................................................................... 389 DODATEK E. ZASOBY SIECI.......................................................................................................................... 390

Spis Tresci

Wstep
Ksiazka ta jest przeznaczona dla programistw tworzacych aplikacje WWW za pomoca PHP. Nalezy zwrcic uwage, ze zostalo uzyte okreslenie aplikacje WWW a nie strony WWW lub witryny WWW. W przeszlosci w Sieci znajdowaly sie w wiekszosci proste strony HTML o ograniczonej mozliwosci interakcji. Dzisiejszy obraz Sieci jest o wiele bardziej skomplikowany. Uzytkownicy i firmy oczekuja od Sieci coraz wiecej. Powoduje to powstanie coraz wiekszej ilosci dynamicznych aplikacji WWW. PHP jest idealny do tworzenia takich aplikacji, poniewaz zostal zaprojektowany wlasnie do realizacji tego zadania.

Dla kogo jest przeznaczona ta ksiazka


Ksiazka ta powinna byc uzyteczna dla szerokiego grona programistw WWW, ale pisana byla z mysla o srednio zaawansowanych lub zaawansowanych programistach. PHP jest jezykiem programowania a nie jezykiem opisu strony, wiec przydatne bedzie doswiadczenie w programowaniu. Programisci znajacy C lub Perla powinni uznac PHP za jezyk bardzo przyjazny, natomiast programisci pracujacy w ASP Microsoftu (Active Server Pages) uznaja PHP za jezyk o podobnej strukturze. Poniewaz ksiazka ta nie jest kierowana do poczatkujacych programistw, podstawowe pojecia dotyczace programowania zostana przedstawione bardzo skrtowo. Zaklada sie, ze Czytelnik zna takie pojecia programowania, jak funkcje, zmienne i stale.

Konwencje
W ksiazce przyjeto nastepujace konwencje: Kod programu i jego wyniki zaznaczone sa czcionka o stalej Nazwy plikw i katalogw zaznaczone sa czcionka pochyla. Komendy i elementy jezyka zaznaczone sa czcionka o stalej
szerokosci. szerokosci.

Omwienie ksiazki
Ksiazka zawiera zwiezle wprowadzenie do PHP, oraz opis jezyka. Zostal w niej rwniez przedstawiony sposb instalacji i konfiguracji PHP. Druga czesc, Specjalne wymagania przy programowaniu WWW, przeznaczona jest dla programistw tradycyjnych aplikacji rozpoczynajacych prace przy aplikacjach WWW. W czesci tej przedstawione zostaly takie zagadnienia jak: przetwarzanie formularzy, interakcje z uzytkownikiem, utrzymywanie stanu oraz niezaleznosc od przegladarki. Nastepna czesc, Zarzadzanie projektem aplikacji WWW opisuje zalety modularnosci i powtrnego uzycia kodu. Czesc Przyklady zastosowan pokazuje uzycie PHP na podstawie fragmentw dzialajacych juz aplikacji. Czesc ta laczy zagadnienia przedstawione w poprzednich czesciach i pokazuje przyklady pelnej wymiany informacji pomiedzy przegladarka uzytkownika i aplikacja zainstalowana na serwerze WWW. Na koncu ksiazki znajduje sie skorowidz zawierajacy wszystkie funkcje PHP4.

Od autora
Od okolo trzech lat tworze aplikacje WWW przy uzyciu PHP i ASP, jako niezalezny przedsiebiorca. Fundamentem mojego sukcesu bylo uzycie PHP, poniewaz pozwala on na szybkie budowanie prototypw, oraz jest wystarczajaco wydajny i pewny nawet do tworzenia duzych aplikacji WWW. Celem tej ksiazki jest przekazanie innym programistw uzytecznych informacji. Nie bede opisywal rznic pomiedzy PHP i innymi tego typu narzedziami i nie bede zajmowal sie historia PHP. Wszystkie te informacje mozna znalezc na oficjalnej witrynie PHP, www.php.net. Zamiast tego pokaze zastosowanie PHP do stworzenia aplikacji WWW. Omwie rwniez inzynierie programowania w projektach WWW, sposoby przeniesienia istniejacego kodu do nowych projektw WWW. Przedstawie rwniez kilka przydatnych narzedzi napisanych dla PHP.

Przyklady kodu
Zamieszczone przyklady kodu byly tworzone i testowane pzy uzyciu PHP 4.0.1 (poprawka 2) na Apache 1.3.11 dzialajacym w systemie RedHat 6.1. Do edycji plikw HTML i PHP wykorzystuje edytor Allaire Homeite 4.5.1 zainstalowany na Windows NT. Do testowania malych fragmentw kodu stosowalem nastepujacy szablon HTML do ktrego wklejalem odpowiedni kod PHP:
<html> <head> <title>Nazwa przykladu</title> </head> <body> <!-- Kod PHP wkleic ponizej --> </body> </html>

Wieksze fragmenty kodu byly tworzone od razu razem z kodem HTML.

Czym jest PHP


PHP to jezyk programowania przeznaczony dla programistw WWW pozwalajacy na szybkie tworzenie dynamicznych aplikacji WWW. Oficjalnym rozwinieciem skrtu PHP jest PHP: Hypertext Preprocessor (preprocesor hipertekstu). Jest to jezyk programowania osadzany w HTML skladniowo podobny do C, Perla i Javy. Na wydruku 1. przedstawiony jest przyklad kodu PHP. Wydruk 1. Prosty przyklad kodu PHP
<html> <head> <title>Prosty przyklad kodu PHP</title> </head> <body> <?php echo "Witajcie w PHP!" ; ?> </body> </html>

Po uruchomieniu tego przykladu (poprzez odpowiednio skonfigurowany serwer WWW) generowany jest kod HTML zamieszczony na wydruku 2. Wydruk 2. Wynik dzialania wydruku 1
<html> <head> <title>Prosty przyklad kodu PHP</title> </head> <body> Witajcie w PHP! </body> </html>

Preprocesor PHP wykonuje caly kod zawarty pomiedzy znacznikami <?php i ?> umieszczonymi w kodzie HTML i zwraca wynik w postaci tekstu. Nie jest to szczeglnie interesujacy, ale pokazuje jak latwo mozna umieszczac kod PHP w kodzie HTML. Nalezy pamietac, ze kod ten jest wykonywany na serwerze WWW a nie na kliencie. Oznacza to, ze przegladarka nie wie, ze do stworzenia strony byl uzywany PHP. Otrzymuje ona po prostu strumien kodu HTML, identycznie jak w przypadku zwyklych stron. Wiecej na ten temat znajduje sie w Wstep 8

czesci Specjalne wymagania przy programowaniu WWW.

Dlaczego powinienes uzyc PHP


PHP jest pelnowartosciowym jezykiem programowania pozwalajacy na tworzenie aplikacji WWW z wszystkimi potrzebnymi funkcjami. PHP wsplpracuje z wieloma systemami baz danych. Pozwala to na bardzo latwe tworzenie aplikacji WW korzystajacych z informacji zapisanych w bazie danych. Mozliwy jest rwniez dostep do uslug sieciowych takich jak IMAP, POP3, NNTP i TTP. Pozwala on rwniez na otwieranie gniazd sieciowych i podlaczanie sie do innych protokolw TCP/IP. PHP moze byc uzyty we wielu konfiguracjach serwerw. Poniewaz PHP jest rozprowadzany glwnie w postaci kodu zrdlowego, moze byc skompilowany na wielu rznych platformach, na przyklad na Linuksie, FreeBSD i nawet na Windows. Dostepne sa rwniez binarne dystrybucje dla Win32. PHP moze dzialac jako program CGI lub moze byc zainstalowany jako modul Apache lub rozszerzenie ISAPI. Dzieki temu moze on dzialac z praktycznie kazdym serwerem WWW, od Apache na Linuksie do IIS na Windows NT. W celu utworzenia najbardziej elastycznego srodowiska pracy nalezy samodzielnie skompilowac i zainstalowac PHP. Jezeli wolisz szybko zaczac prace, mozesz zastosowac binarna dystrybucje PHP.

Gdzie szukac pomocy


Pomoc mozna uzyskac na witrynie PHP oraz poprzez kilka grup dyskusyjnych i wysylkowych. W lutym 2000 roku okolo 1400000 domen korzystalo z PHP. Poniewaz jest on tak popularny, istnieje ogromna grupa programistw i konsultantw, ktrzy moga odpowiedziec na pytania. Wiecej informacji na temat dostepnych zasobw Sieci znajduje sie w czesci Zasoby na koncu ksiazki.

PHP Kompendium wiedzy

Podziekowania
Na poczatku chcialbym podziekowac wszystkim z wydawnictwa McGraw-Hill za umozliwienie mi zrealizowania tego zadania. Szczeglne podziekowania naleza sie Rebece Young za wsparcie i pomoc w technicznych aspektach pisania ksiazki. Dziekuje Johnowi Steele, mojemu redaktorowi technicznemu, ktry niezmiernie pomgl mi swoimi trafnymi uwagami i informacjami. Oczywiscie, nalezy podziekowac calemu zespolowi tworzacemu PHP. Wiele osb z tego zespolu pomagalo mi w pracy nad ksiazka. Cala czesc zawierajaca skorowidz funkcji jest ich zasluga. To oni spedzili setki lub tysiace godzin tworzac ten wspanialy jezyk programowania i bogata dokumentacje. Dziekuje Mattowi Wilson za umozliwienie mi wykorzystania w przykladzie do ksiazki kodu MWeather. Dziekuje Nickowi Bradbury za pozwolenie wykorzystania informacji i rysunkw z edytora TopStyle. Podziekowania dla Nate Weiss za pomoc przy uzyciu deserializera WDDX dla JavaScript, dla Johna Kos za pomoc przy unixODBC i EasySoft ODBC-ODBC Bridge. Dla Martina Evans, glwnego programisty ODBCODBC Bridge, za stworzenie tego swietnego produktu. Dziekuje Michaelowi Justin za pomoc przy konwerterze RTF do HTML firmy Scrooge. Dziekuje rwniez Michaelowi C. Battilana za pomoc przy Cloanto Currency Server. Dla Sama Ockman za umozliwienie wykorzystania w ksiazce rysunku serwera Penguin 1U. Dziekuje Richardowi Litofski za pomoc przy BrowserHawk. Podziekowania dla Ali Ersheid za umozliwienie wykorzystania w ksiazce dokumentacji CyberCash. Dziekuje Josephowi Harris (znany jako CDI) za klase FastTemplate oraz inne fantastyczne narzedzia dostepne na witrynie The Webmasters.net. Dziekuje rodzicom i braciom za nieustanne wsparcie nawet, gdy w latach osiemdziesiatych spedzalem cale noce na pisaniu programw w Apple Basicu. Dziekuje pani Barton, pani Smith i panu Wakefield, moim nauczycielom angielskiego z liceum, ktrzy mieli ogromny wplyw na moje pisanie. Dziekuje Garemu Rogers i Jasonowi Wallin za wskazanie mi PHP i Linuksa w czasie gdy coraz bardziej pograzalem sie wykorzystujac ASP i Windows. Dziekuje Tracy Ard za pozyteczne komentarze do tej pracy oraz za jego niezmienna przyjazn. Na koniec najwazniejsze podziekowania naleza sie mojej zonie i crce za umozliwienie mi zakonczenia tej pracy. Teraz znw mozemy wieczorami chodzic skakac na trampolinie.

O autorze
Blake Schwendiman rozpoczal programowanie w 1980 roku rozpoczynajac od Apple IIe i jezyka Basic. Zdobyl licencjat na uniwersytecie Arizona State University w roku 1994. W chwili obecnej Blake zarzadza firma Intechra LLC, http://www.intechra.net/, firma konsultingowa specjalizujaca sie w oprogramowaniu, ktra ma siedzibe w Rexburg, Idaho. Intechra LLC specjalizuje sie w tworzeniu oprogramowania dla WWW. Blake ma zone Holy i trzyletnia crke. Mozna sie z nim skontaktowac pod adresem blake@intechra.net.

Wstep

10

Rozdzial 1. Kompilacja i instalowanie PHP


Wstep
Zanim rozpoczniemy nauke jezyka PHP, nalezy go poprawnie zainstalowac i skonfigurowac w uzywanym srodowisku interpreter PHP. Poniewaz pakiet PHP moze dzialac na wielu serwerach WWW i systemach operacyjnych, w rozdziale tym znajda sie szczeglowe opisy instalacji na jedynie kilku platformach, ale podane informacje sa wystarczajaco uniwersalne i moga byc wykorzystane przy konfigurowaniu srodowiska pracy na innych platformach. W rozdziale tym opisane zostana szczeglowo Apache dla Linuksa oraz IIS dla Windows NT. Sa to czesto spotykane konfiguracje serwerw WWW i sa one na tyle rzne, ze ilustruja oglne zasady instalacji pakietu PHP na wiekszosci platform. Szczeglowe dane na temat okreslonej platformy mozna rwniez znalezc na witrynie www.php.net.

Pobieranie PHP
Pierwszym krokiem do rozpoczecia pracy z PHP jest zaopatrzenie sie w kopie interpretera PHP. Na witrynie www.php.net umieszczone jest kilka wariantw tego pakietu. Najnowsza wersja zawsze znajduje sie na grze listy. W przypadku serwerw uniksowych zaleca sie pobranie pakietu zawierajacego kompletny kod zrdlowy i przeprowadzenie samodzielnej kompilacji. Platformy uniksowe to miedzy innymi Linux, BSD, Solaris itp. W przypadku Windows zaleca sie pobranie binarnej instalacji PHP. Ze strony zawierajacej pakiety instalacyjne mozna rwniez pobrac poprzednie wersje programw, dokumentacje i narzedzia pomocnicze. Poprzednie wersje moga byc potrzebne, jezeli masz juz gdzies zainstalowane PHP i nie chcesz ryzykowac niekompatybilnosci.

Instalowanie wersji binarnej


Po pobraniu binarnej dystrybucji PHP, instalacja jest banalna. Najczesciej binarna instalacja PHP jest przeznaczona dla Windows. Poniewaz jednak niektre dystrybucje Uniksa zawieraja binarna dystrybucje PHP, opisany zostanie rwniez taki przypadek.

Binarna instalacja dla Windows


W PHP prawie wszystkie operacje mozna wykonac na kilka sposobw. Instalacja binarna dla Windows zawiera zarwno wersje CGI (Common Gateway Interface) PHP, jak rwniez wersje ISAPI. Jezeli korzystasz z serwera IIS (Internet Information Server) lub PWS (Personal Web Server) zalecane jest uzycie modulu ISAPI. Wersja CGI powoduje, ze PHP jest uruchamiany za kazdym odwolaniem do strony, wiec jest mniej efektywny od dynamicznego modulu jakim jest rozszerzenie ISAPI. Modul ISAPI jest rwniez ze swojej natury bezpieczniejszy od programu CGI.

Instalowanie PHP w postaci modulu ISAPI Jezeli korzystasz z serwera IIS, PWS lub innego serwera WWW obslugujacego moduly ISAPI, najlepszym rozwiazaniem bedzie uzycie PHP w postaci modulu ISAPI. Aby zainstalowac taka wersje, nalezy skopiowac pliki php4ts.dll i msvcrt.dll do katalogu systemowego Windows (zwykle \windows\system w Windows 95 lub \winnt\system32 w Windows NT). Sa to wspldzielone biblioteki niezbedne do prawidlowej pracy kazdej wersji PHP dla Windows. Dodatkowo mozna skopiowac do katalogu systemowego inne pliki .dll, ale nie jest to konieczne do ich uzycia. Nastepnie nalezy tak skonfigurowac IIS lub PWS, aby korzystal z modulu ISAPI do obslugi plikw php. Serwer IIS mozna konfigurowac za pomoca konsoli konfiguracji zainstalowanej w menu Option Pack. Na rysunku 1.1. znajduje jest rozwiniete menu pokazujace polozenie tego programu w Windows NT. Rysunek 1.1. Uruchamianie aplikacji konfigurujacej IIS

Po uruchomieniu konsoli Menedzer uslug internetowych nalezy kliknac prawym przyciskiem myszy na wezle serwera WWW (prawdopodobnie zatytulowany Domyslna witryna sieci Web) i wybrac Wlasciwosci, tak jak jest to pokazane na rysunku 1.2. Nastepnie w oknie Wlasciwosci nalezy przejsc na zakladke Katalog macierzysty i kliknac przycisk Konfiguracja. Opcja ta pozwala na dodawanie i edycje skojarzen. Rysunek 1.2. Konfigurowanie IIS

Teraz nalezy kliknac przycisk Dodaj i wprowadzic potrzebne informacje. Na rysunku 1.3. pokazany jest proces dodawania mapowania rozszerzenia phtml do modulu ISAPI PHP.

Rozdzial 1 Kompilacja i instalowanie PHP

12

Rysunek 1.3. Dodawanie mapowania dla rozszerzenia w IIS

Po dodaniu mapowania zmiany sa od razu widoczne w oknie dialogowym Konfiguracja aplikacji. Czasami moze byc pozyteczne skojarzenie niektrych rozszerzen z modulem ISAPI a niektrych z programem CGI. Na rysunku 1.4. pokazana jest konfiguracja mojego serwera WWW. Na rysunku widac mapowania dla PHP3, dla PHP4 jako CGI oraz PHP4 jako ISAPI. Jest to przydatne przy testowaniu rznic pomiedzy wersjami 3 i 4 PHP. Rysunek 1.4. Mapowanie rozszerzen PHP

Po zakonczeniu konfiguracji nalezy ponownie uruchomic serwer WWW. Mozna to zrobic przy uzyciu modulu Uslugi w Panelu sterowania, lub uruchamiajac z linii polecen nastepujace polecenia:
net stop iisadmin net start w3svc

Po uruchomieniu serwera nalezy go przetestowac tworzac prosty plik testowy, na przyklad taki, jak pokazany na wydruku 1.1. i otwierajac go poprzez twj serwer. Jezeli wszystko jest skonfigurowane poprawnie, powinienes zobaczyc ekran z informacjami na temat instalacji PHP. Wydruk 1.1. Testowy skrypt PHP
<html> <head> <title> phpinfo() </title> </head> <body> <?php phpinho(); ?> </body> </html>

13

PHP Kompendium wiedzy

Trzeba pamietac, ze w pakiecie instalacyjnym PHP znajduje sie uwaga na temat stanu modulu ISAPI ktra ostrzega, ze nie powinien byc stosowany w srodowisku produkcyjnym. Sugeruje sie, ze w celu zapewnienia odpowiedniej stabilnosci powinna byc uzyta wersja CGI. Nastepna czesc rozdzialu opisuje uzycie PHP jako CGI. Uzycie PHP jako CGI Jezeli nie masz zainstalowanego serwera WWW obslugujacego moduly ISAPI lub istnieja inne powody wyboru wersji CGI, nalezy przeprowadzic instalacje PHP jako CGI. Instalacja jest bardzo podobna do tej przedstawionej powyzej, rznice wystepuja jedynie przy mapowaniu rozszerzen. Zamiast wybierac biblioteke .dll ISAPI, nalezy wybrac plik php.exe. Serwer IIS lub PWS wysyla parametry do pliku wykonywalnego CGI, wiec oprcz nazwy pliku wykonywalnego nalezy podac opcje linii polecen %s %s. Jest to pokazane na rysunku 1.4. dla rozszerzenia .php4. Rzne serwery WWW maja rzne metody okreslenia mapowania rozszerzen. Do Apache dla Windows istnieje swietny podrecznik dostepny pod adresem www.php.net/manual/config-apache-nt.html. Zasoby sieci na temat instalacji PHP na rznych serwerach WWW dla Windows mozna odszukac za pomoca wyszukiwarki umieszczonej na witrynie www.php.net.

Inne instalacje binarne


Niektre instalacje Uniksa posiadaja instalacje binarna PHP zintegrowana z instalacja serwera WWW. Niektrzy dostawcy, na przyklad Red Hat, udostepniaja rwniez binarna instalacje na swoich witrynach. Instalacja taka jest wykonana w formie plikw RPM (Red Hat Package Manager). Zaleta uzycia plikw RPM jest latwosc instalacji. Nie trzeba martwic sie szczeglami procesu kompilacji, poniewaz plik RPM zawiera gotowa do uzycia odpowiednio skompilowana wersje programu. Wada jest to, ze z powodu wielu mozliwych wariantw platform dla Uniksa, problemem dla poczatkujacych moze byc nawet wybr wlasciwego pliku. Poza tym w pliku RPM nie zawsze sa ustawione wszystkie potrzebne opcje konfiguracji, niezbedne do prawidlowego dzialania programu. Jezeli masz plik RPM z PHP, mozesz go zainstalowac wydajac polecenie rpm -i <plikrpm.rpm>. Powoduje to zainstalowanie plikw binarnych do katalogw okreslonych przez twrce pliku RPM. Dla wiekszosci uzytkownikw katalogi te sa prawidlowe. Po instalacji nalezy recznie skonfigurowac serwer WWW tak, aby korzystal z zainstalowanych wlasnie plikw binarnych PHP. Ponizej przedstawimy sposb konfiguracji Apache. Inne serwery WWW wymagaja przeprowadzenia podobnych czynnosci. Niezaleznie od tego, czy PHP bedzie dzialalo jako program CGI czy w postaci modulu, pierwszy krok konfiguracji jest zawsze taki sam. Trzeba utworzyc skojarzenie pomiedzy rozszerzeniem pliku a wewnetrznym typem stosowanym przez serwer. Robi sie to dodajac do pliku konfiguracyjnego nastepujace linie:
AddType application/x-httpd-php .php AddType application/x-httpd-php .phtml AddType application/x-httpd-php .inc

Dyrektywy te powoduja, ze Apache uwaza wszystkie pliki z rozszerzeniami .php, .phtml i .inc jako pliki typu application/x-httpd-php. Do przetwarzania tego typu plikw wykorzystywane jest PHP. Zakladajac, ze masz zainstalowane PHP w postaci modulu Apache, kolejnym krokiem bedzie modyfikacja pliku konfiguracyjnego httpd.conf tak, aby Apache zaladowal modul PHP:
LoadModule php4_module libexec/libphp4.so

Jezeli zainstalowana zostala wersja CGI, nalezy wprowadzic nieco inne zmiany do pliku konfiguracji httpd.conf. Dyrektywa konfiguracji jest podobna do poprzedniej, ale odwoluje sie do programu w postaci pliku wykonywalnego.:
Action application/x-httpd-php /cgi-bin/php

Dyrektywa Action definiuje typ pliku powodujacy uruchomienie PHP po otrzymaniu zadania sciagniecia strony z serwera WWW. Oczywiscie nalezy podac wlasciwa sciezke do pliku wykonywalnego. Po wprowadzeniu zmian nalezy ponownie uruchomic serwer WWW, aby zaczely dzialac nowe ustawienia. Serwer Apache mozna zrestartowac za pomoca polecenia:
/sciezka/do/apachectl restart

Aby przetestowac konfiguracje mozna wczytac za pomoca przegladarki skrypt testowy, przedstawiony na wydruku 1.1. Binarna dystrybucja PHP ulatwia szybkie rozpoczecie pracy z PHP w Uniksach, ale moze ona sprawiac problemy. Z powodu istnienia wielu wariantw Uniksw, znalezienie gotowej wersji dzialajacej na okreslonym Rozdzial 1 Kompilacja i instalowanie PHP 14

systemie moze byc czasami trudne. W wielu przypadkach bedzie to bardziej czasochlonne niz sciagniecie kodu zrdlowego, skompilowanie i zainstalowanie PHP. Proces ten zostanie opisany w kolejnej czesci rozdzialu.

Kompilowanie PHP
Jezeli chcesz skorzystac z elastycznosci wlasnej instalacji PHP lub jezeli przewidujesz dodawanie wlasnych rozszerzen do jezyka PHP (opisane w rozdziale 11. Ponowne wykorzystanie kodu), musisz dokladnie poznac proces kompilowania PHP. Jezeli pracujesz na platformie, dla ktrej nie ma instalacji binarnej, mozesz nie miec innego wyboru jak tylko samodzielnie kompilowac PHP.

Kompilowanie PHP w Uniksach


W tej czesci rozdzialu przedstawione zostana informacje na temat kompilowania PHP na platformie Unix. Nalezy pamietac, ze Unix okresla cala rodzine systemw, np.: Linux, BSD, Solaris i inne. Oczywiscie systemy te rznia sie miedzy soba, ale wiele z krokw niezbednych do kompilacji PHP jest identycznych. Wiecej informacji na temat okreslonej platformy mozna odszukac za pomoca wyszukiwarki dostepnej na witrynie www.php.net. Dla kazdej platformy istnieje kilka sposobw kompilacji PHP. Jezeli serwerem WWW jest Apache, mozna skompilowac PHP jako plik wykonywalny, jako modul ladowany dynamicznie lub jako statyczna biblioteke. Jezeli nie korzystasz z Apache, nalezy odszukac w dokumentacji PHP i serwera WWW szczegly postepowania. Przy okazji mozemy zarekomendowac korzystanie z PHP w postaci dynamicznie ladowanego modulu, jako najlepsze rozwiazanie dla wiekszosci aplikacji. Jezeli PHP zostanie statycznie dolaczony do Apache, kazda zmiana konfiguracji wymaga wiekszego nakladu pracy. W przypadku modulu CGI, wystepuja problemy z bezpieczenstwem. W kolejnych czesciach zakladamy, ze sciagnales juz zrdla PHP i rozpakowales je. Proces kompilacji jest wlasciwie taki sam dla kazdego typu pliku wynikowego. Na poczatku trzeba uruchomic skrypt configure, ktry ustawia opcje kompilacji. Nastepnie przy pomocy narzedzia make przeprowadza sie kompilacje. Na koniec trzeba zainstalowac gotowe PHP i zrestartowac serwer WWW. Informacje na temat skryptu konfiguracyjnego sa przedstawione w czesci poswieconej kompilowaniu modulu CGI, wiec zaleca sie przeczytanie tego fragmentu jako wprowadzenia. Kompilacja modulu CGI Kompilacja PHP do postaci wykonywalnego modulu CGI jest najprostsza metoda kompilacji i dobrym rozwiazaniem, jezeli nigdy wczesniej nie kompilowales programw dla Uniksa. Ponizej przedstawiona jest kompletna lista operacji jakie nalezy wykonac. Niektre z nich nie sa obowiazkowe. Operacje opcjonalne sa zaznaczone czcionka pochyla. Odwolanie do <php_dir> powinno byc zamienione na nazwe twojego katalogu bazowego PHP.
cd <php_dir> rm config.cache make clean ./configure make make install

Wykonanie tych operacji spowoduje usuniecie podrecznych danych konfiguracji, usuniecie plikw wynikowych a nastepnie skompilowanie PHP do postaci CGI. Jest to najprostsza metoda kompilacji, przytoczona jedynie jako przyklad. W prawdziwej kompilacji do skryptu konfiguracyjnego dolacza sie opcje okreslajace atrybuty PHP. Druga i trzecia linia jest nieobowiazkowa, poniewaz polecenia w nich umieszczone sa uzywane jedynie do wyczyszczenia poprzedniej konfiguracji i pozostalosci po poprzedniej kompilacji. Jezeli wczesniej nie konfigurowales ani nie kompilowales PHP, nie sa one potrzebne. Mozna rwniez nie korzystac z tych opcji przy kompilacji PHP, choc czasami ich wykonanie jest niezbedne. Jezeli wprowadzane sa powazne zmiany w konfiguracji lub zmieniasz typ kompilacji z CGI na inny, moze okazac sie, ze wykonanie czyszczenia jest niezbedne, aby kompilacja przebiegla prawidlowo. W zaleznosci od szybkosci komputera, na ktrym wykonywana jest kompilacja, przeprowadzenie calej konfiguracji i kompilacji moze zajac dosyc duzo czasu. 15 PHP Kompendium wiedzy

Pozostawienie zapisanych opcji konfiguracji oraz obiektw binarnych spowoduje znaczne skrcenie czasu tworzenia PHP. Wszyscy, ktrzy nigdy nie przeprowadzali takiego procesu powinni wiedziec, ze skrypt konfiguracyjny poszukuje w systemie narzedzi, plikw i innych danych systemowych. Nastepnie na podstawie tych danych tworzy specyficzny dla systemu skrypt za pomoca mozna skompilowac kod. Jezeli w czasie dzialania skryptu konfiguracyjnego nastapi awaria, czesto zdarza sie, ze wymagany plik lub narzedzie nie jest odnajdywane lub niewlasciwie skonfigurowane. Po zakonczeniu dzialania skryptu konfiguracyjnego tworzony jest plik tymczasowy config.cache zawierajacy szczegly na temat systemu, wiec badanie systemu nie musi byc powtarzane przy ponownym uruchomieniu konfiguracji. Jezeli wprowadzisz duze zmiany do konfiguracji systemu, musisz usunac plik tymczasowy przed kolejnym uruchomieniem skryptu konfiguracyjnego. W ten sposb upewniamy sie, ze zmiany te zostana wykryte. Po wykonaniu wszystkich podanych polecen zostanie utworzony nowy plik wykonywalny php. Mozna przetestowac poprawnosc kompilacji za pomoca nastepujacego polecenia:
php < /dev/null

Jezeli zobaczysz wynik podobny do ponizej przedstawionego, udalo ci sie poprawnie skompilowac i zainstalowac PHP w postaci CGI.
X-Powered-By: PHP/4.0.2 Content-type: text/html

Trzeba zauwazyc, ze skompilowana wlasnie wersja PHP nie posiada funkcji, ktre byc moze bedziemy chcieli wykorzystywac w aplikacjach, poniewaz zostala skompilowana z uzyciem tylko ustawien domyslnych. Trzeba ponownie uruchomic skrypt konfiguracyjny, ustawic opcje potrzebne w aplikacji a nastepnie ponownie skompilowac i zainstalowac PHP. Pozyteczna cecha zestawu domyslnych ustawien jest to, ze dolaczone jest do niego wiele czesto uzywanych opcji konfiguracji, w tym obsluga bazy danych MySQL, sesji i wiele, wiele innych. Oznacza to, ze przytoczone polecenia umozliwiaja skompilowanie PHP, ktry pozwala na rozpoczecie nauki jezyka. Jezeli potrzebujesz obslugi innej bazy danych lub innego rozszerzenia, trzeba dodac odpowiednia opcje konfiguracji. Lista dostepnych opcji jest wyswietlana po wpisaniu:
./configure --help

with-PAKIET.

Wiekszosc opcji konfiguracji wplywajacych na dostepne funkcje PHP ma postac Aby dodac funkcje do PHP nalezy uzyc jednej z ponizszych form: Aby usunac funkcje z PHP, nalezy uzyc:

--enable-FUNKCJA

lub --

--enable-FUNKCJA --enable-FUNKCJA=yes --disable-FUNKCJA --enable-FUNKCJA=no

Pelna lista opcji konfiguracji znajduje sie w skorowidzu na koncu ksiazki. Funkcje korzystajace ze skladni --enable sa to zwykle wbudowane opcje PHP, takie jak mozliwosc wykorzystywania krtkich znacznikw lub obsluga protokolu FTP. Pakiety sa to zwykle moduly zewnetrzne, ktre moga byc dolaczone do PHP, na przyklad obsluga bazy danych Oracle lub Javy. Te wlasnosci wymagaja zwykle wskazania zewnetrznego pliku i do jego wlaczania korzysta sie z nastepujacego zapisu:
--with-PAKIET=/sciezka/do/pakietu

Aby wylaczyc pakiet nalezy uzyc polecen:


--with-PAKIET=no --without-PAKIET

Jako przyklad przedstawimy nastepujaca konfiguracje:


./configure --with-apxs=/www/bin/apxs --with-java --with-cybercash=/home/blake/mck-3.2.0.6-i586-pc-linuxgnulibc2.1 --withunixODBC=/usr/local/unixODBC --disable-debug --enabletrack-vars -- enable-fin-funcs --withsnmp=/home/blake/ucd-snmp-4.1.2 --enable-ucd-snmp-hack

Powyzsze wywolanie konfiguracji powoduje dodanie do PHP obslugi Javy, CyberCash, SNMP (Simple Network Management Protocol) oraz unixODBC. Nie zostalo podane polozenie katalogu Javy, wiec skrypt konfiguracyjny uzyje domyslnej sciezki do katalogu z tym pakietem. Dodatkowo zostala dodana opcja -withapxs, ktra powoduje, ze PHP jest kompilowane do postaci dynamicznie ladowanego modulu Apache a nie jako program typu CGI. Pzniej omwimy to zagadnienie dokladniej. W przedstawianej konfiguracji wylaczono informacje dla debuggera oraz wlaczono opcje track-vars, fin-funcs oraz ucd-snmp-hack. Opcja fin-funcs powoduje dodanie wlasnego modulu rozszerzen opisanego w dalszej czesci ksiazki (rozdzial 11.), natomiast pozostale sa standardowymi elementami konfiguracji opisanymi w skorowidzu na koncu ksiazki.

Rozdzial 1 Kompilacja i instalowanie PHP

16

Wiele z pakietw oprogramowania jakie chcemy dodac do PHP musi byc osobno zainstalowane. Wiecej informacji na temat tego, gdzie mozna zaopatrzyc sie w potrzebne pakiety, mozna znalezc w dokumentacji na witrynie www.php.net. Po utworzeniu PHP w postaci CGI, nalezy skonfigurowac serwer WWW do wsplpracy z nowym programem. Aby skonfigurowac serwer Apache nalezy dodac nastepujace dyrektywy do pliku httpd.conf:
AddType application/x-httpd-php .php AddType application/x-httpd-php .phtml AddType application/x-httpd-php .inc Action application/x-httpd-php /cgi-bin/php

Pierwsze trzy dyrektywy definiuja zawartosc plikw z rozszerzeniami php, phtml i inc jako typ application/x-httpd-php. Ostatnia dyrektywa powoduje wyslanie wszystkich plikw tego typu do pliku wykonywalnego php. Zakladamy, ze plik ten jest umieszczony w katalogu cgi-bin serwera WWW. Dyrektywy te sa minimum wymaganym do konfiguracji PHP w Apache, ale ta sama czynnosc moze byc zrealizowana jeszcze na kilka sposobw. Wiecej szczeglw mozna znalezc w dokumentacji do Apache. Kompilacja PHP jako statycznie dolaczanego modulu Apache Apache pozwala na statyczne dolaczanie modulw bezposrednio do pliku binarnego Apache. W porwnaniu z wersja CGI uzycie modulu pozwala poprawic wydajnosc aplikacji oraz zwiekszyc bezpieczenstwo systemu,. Wada tej metody jest koniecznosc powtrnej kompilacji Apache po kazdej kompilacji PHP. Moze byc to czasochlonne i frustrujace, poniewaz w przypadku wystapienia klopotw z konfiguracja PHP, Apache moze rwniez przestac dzialac. Jednak niektre aplikacje wymagaja zastosowania statycznie dolaczanego modulu Apache, opiszemy teraz sposb jego tworzenia. Przed skonfigurowaniem i skompilowaniem PHP niezbedne jest skonfigurowanie Apache. Zakladamy, ze na dysku jest juz katalog z kodem zrdlowym Apache. Aby skonfigurowac Apache, nalezy uzyc nastepujacych polecen:
cd <apache_dir> ./configure

Po zakonczeniu dzialania tego skryptu mozna zajac sie konfigurowaniem i kompilowaniem PHP.
cd <php_dir> ./configure --with-apache=<apache_dir> make make install

Opcja --with-apache powoduje kompilacje do postaci statycznej biblioteki oraz pozwala podac katalog z plikami zrdlowymi Apache. Nastepnie nalezy skompilowac serwer Apache za pomoca polecen:
cd <apache_dir> ./configure --prefix=/www --activate-module=src/modules/php4/libphp4.a make make install

Dyrektywa prefix moze byc inna w twoim systemie, poniewaz wskazuje ona katalog gdzie zostana zainstalowane pliki zalezne od architektury. Teraz nalezy uruchomic serwer Apache i przy wykorzystaniu skryptu testowego z wydruku 1.1. sprawdzic poprawnosc konfiguracji. Aby Apache prawidlowo przetwarzal pliki PHP nalezy odpowiednio zmodyfikowac plik httpd.conf. W zaleznosci od rozszerzen jakie zostaly wybrane do reprezentowania plikw PHP, nalezy wprowadzic odpowiednie zmiany. I tym razem standardowa konfiguracja wyglada nastepujaco:
AddType application/x-httpd-php .php AddType application/x-httpd-php .phtml AddType application/x-httpd-php .inc

Przedstawiony opis przedstawia jedynie bardzo prosta wersje PHP, ktra zawiera jedynie opcje domyslne. Wiecej informacji o zmianie konfiguracji kompilacji PHP znajduje sie w czesci na temat kompilacji wersji CGI. Kompilacja PHP do postaci dynamicznie ladowanego modulu Apache Sposb kompilacji PHP do postaci dynamicznie ladowanego modulu Apache nie rzni sie zbytnio od innych przedstawionych do tej pory metod. Zaleta tej metody jest mozliwosc kompilacji PHP bez koniecznosci rwnoczesnej kompilacji Apache. Rwniez niektre moduly rozszerzen (na przyklad Java) wymagaja do poprawnej pracy, aby PHP byl skompilowany do postaci dynamicznie ladowanego modulu. Aby Apache obslugiwal dynamicznie ladowane moduly nalezy go przekompilowac z nastepujacymi opcjami konfiguracji:
cd <apache_dir> make clean ./configure --enable-module=so --enable-rule=SHARED_CORE --prefix=/www make

17

PHP Kompendium wiedzy

make install

Oprcz kompilacji Apache przedstawione polecenia przygotowuja skrypt apxs, ktry jest niezbedny do kompilacji dynamicznego modulu PHP. Jezeli wystapia klopoty ze skryptem apxs mozna powtrnie wykonac przedstawione polecenia, co spowoduje ponowne wygenerowanie prawidlowo skonfigurowanego skryptu. Po skompilowaniu Apache z obsluga dynamicznie ladowanych modulw, nalezy skompilowac PHP w nastepujacy sposb:
cd <php_dir> make clean rm config.cache ./configure --with-apxs=/www/bin/apxs (pozostale opcje) make make install

Polecenia porzadkujace sa zalecane, jezeli PHP byl juz kompilowany w innej konfiguracji. Sciezka podana w dyrektywie konfiguracji --with-apxs powinna byc pelna sciezka do skryptu apxs na serwerze. Tak jak w przypadku poprzednich sposobw kompilacji nalezy prawidlowo skonfigurowac Apache, aby przetwarzal pliki PHP. Po zmodyfikowaniu konfiguracji nalezy uruchomic Apache i wywolac skrypt testowy. Podsumowanie kompilacji PHP w systemach Unix Celem tego fragmentu ksiazki nie bylo podawanie szczeglowego i wyczerpujacego opisu wszystkich mozliwych opcji konfiguracji, ale pokazanie podstawowych metod kompilowania PHP do rznych postaci. Jezeli nie kompilowales wczesniej PHP, powinienes na poczatku sprbowac skompilowac podstawowa konfiguracje, a pzniej uzupelniac potrzebne opcje. Po zapoznaniu sie z procesem kompilacji jest juz bardzo latwo testowac rzne konfiguracje i dodawac niestandardowe rozszerzenia. Po skompilowaniu PHP i sprawdzeniu, czy dziala z Apache, mozna zapoznac sie z opcjami konfiguracji, ktre mozna ustawiac bez potrzeby ponownej kompilacji. Zostaly one opisane w dalszej czesci rozdzialu.

Kompilowanie PHP w srodowisku Windows


Kompilowanie PHP dla Windows jest na poczatku bardziej skomplikowanym procesem niz kompilacja PHP dla Uniksa. Dokumentacja zaleca uzycie Visual C++ wersja 6, choc wersja 5 rwniez powinna dzialac. Prbowalem sprawdzic, czy mozna uzyc pakietu Borland C++ Builder, ale nie udalo mi sie tego zrobic. Problem stanowily prekompilowane pliki lib, poniewaz Microsoft i Borland korzystaja z rznych formatw tych plikw. Prawdopodobnie mozna zastosowac kompilator Borlanda, ale trzeba wczesniej przekompilowac wszystkie biblioteki. W ponizszym opisie zakladamy uzycie Visual C++. Przed rozpoczeciem pracy nalezy sie zaopatrzyc w kilka programw i plikw pomocniczych. Tabela 1.1. zawiera wszystkie dodatkowe programy oraz adresy w Internecie, gdzie byly dostepne w czasie pisania ksiazki. Tabela 1.1. Dodatkowe pliki pomocnicze i ich adresy w Sieci Program Polozenie Kod zrdlowy PHP www.php.net/download.php Pakiet Cygwin http://sources.redhat.con/cygwin/ Narzedzia do kompilacji PHP dla www.php.net/extra/win32build.zip Win32 Obsluga BCMath www.php.net/version4/downloads/num ber.tar.gz Zastepnik pliku resolv.lib www.php.net/version4/downloads/bind lib_w32.zip Pakiet Cygwin zawiera popularne narzedzia GNU, takie jak gcc, make i bison. Niektre z tych programw sa wykorzystywane w procesie kompilacji, wiec trzeba wczesniej zainstalowac ten pakiet. Inne potrzebne pliki sa integralna czescia dystrybucji PHP. Kod zrdlowy PHP jest identyczny jak ten, ktry jest uzywany do utworzenia wersji dla Uniksa. Potrzebny jest rwniez program do rozpakowywania plikw. Ja uzywam programu Winzip, poniewaz bez problemu radzi sobie z plikami .tar.gz. Rwniez inne programy posiadaja takie mozliwosci. Na poczatku nalezy zainstalowac narzedzia Cygwin. Trzeba recznie dodac zmienna srodowiska wskazujac na polozenie plikw Cygwin. Jezeli pracujesz w Windows 95, trzeba dodac ta zmienna recznie do pliku autoexec.bat. W Windows NT nalezy kliknac prawym przyciskiem myszy ikone Mj komputer i wybrac z menu Wlasciwosci. Teraz trzeba Rozdzial 1 Kompilacja i instalowanie PHP 18

kliknac zakladke Srodowisko i dodac nowa zmienna, tak jak jest to pokazane na rysunku 1.5. Zmienna nazywa sie a jej wartoscia jest sciezka do katalogu, gdzie zainstalowane sa narzedzia Cygwin. Rysunek 1.5. Ustawienie zmiennej srodowiskowej CYGWIN
CYGWIN

Nastepnie utwrz katalog i rozpakuj do niego zawartosc pliku win32build.zip. Uruchom Visual C++ i wybierz Options z menu Tools. Teraz wybierz zakladke Directories (rysunek 1.6.) i przy uzyciu listy rozwijalnej opisanej Show directories for, wybierz opcje Executable files i dodaj katalog z plikami Cygwin. Teraz z listy rozwijalnej wybierz Include files i dodaj katalog z win32build\include (rysunek 1.6.). Na koniec wybierz Library files i dodaj katalog win32build\lib. Od tej pory kompilator Visual C++ bedzie mgl korzystac z zainstalowanych narzedzi i plikw. Rysunek 1.6. Ustawienie katalogw w Visual C++

Kolejnym krokiem bedzie skompilowanie nowej wersji pliku resolv.lib. Najpierw utwrz nowy katalog i rozpakuj do niego pliki z archiwum bindlib_w32.zip. W Visual C++ otwrz projekt bindlib.dsp. Z menu Build wybierz Set Active Project Configuration i wybierz wersje handlowa biblioteki lub wersje do uruchamiania. Nacisnij klawisz F7, aby skompilowac projekt. Po zakonczeniu kompilacji nalezy skopiowac plik resolv.lib do katalogu win32build\lib. Nastepnie rozpakuj zrdla PHP i plik number.tar.gz za pomoca zewnetrznego programu lub narzedzia tar z pakietu Cygwin. Skopiuj rozpakowane pliki number.c i number.h do katalogu ext/bcmath w katalogu z kodem zrdlowym PHP. 19 PHP Kompendium wiedzy

Jezeli wykonales wszystkie opisane wczesniej czynnosci, jestes gotowy do kompilacji PHP. Uruchom Visual C++ i otwrz plik projektu php4ts.dsp, znajdujacy sie w podkatalogu win32 katalogu z kodem zrdlowym PHP. Projekt ten zawiera kilka konfiguracji. Najlatwiej jest rozpoczac od skompilowania wersji CGI wybierajac wersje handlowa lub wersje z danymi dla debuggera, tak jak jest to pokazane na rysunku 1.7. Rysunek 1.7. Wybr konfiguracji dla wersji CGI

Skompiluj projekt i jezeli wszystko pjdzie dobrze posiadasz juz wlasna wersje PHP. Jezeli potrzebujesz wersji PHP jako ISAPI lub NSAPI, wystarczy wybrac odpowiednia konfiguracje dla kompilacji i ponownie skompilowac projekt. Jak wspomnialem wczesniej, najtrudniejsza czescia bylo wstepne przygotowanie srodowiska. Gdy wszystko jest juz gotowe, cala reszta jest tak samo prosta jak w Uniksie.

Podsumowanie kompilacji PHP


Kompilowanie wersji PHP dla Windows jest za pierwszym razem duzo trudniejsze od wersji dla Uniksa, ale gdy wszystkie potrzebne dodatki zostana odpowiednio skonfigurowane, jest juz proste. Gdy poznales juz proces kompilowania PHP dla obu platform mozesz tworzyc wysoce specjalizowane wersje PHP, spelniajacych precyzyjnie potrzeby konkretnej witryny. Dokladna wiedza na temat procesu kompilacji PHP jest rwniez niezbedna, aby mc tworzyc rozszerzenia PHP. Zagadnienie to zostalo opisane w rozdziale 11.

Konfigurowanie PHP
Niezaleznie od platformy na ktrej dziala PHP, sposb jego konfigurowania jest taki sam. Wykorzystuje sie w tym celu plik php.ini. Plik ten jest dostarczany w dystrybucji PHP jako php.ini-dist i php.ini-optimized. Jezeli nie znasz dobrze opcji konfiguracji, powinienes rozpoczac do podstawowych ustawien z pliku php.ini-dist. Pierwszym krokiem bedzie skopiowanie i zmiana nazwy pliku. Plik powinien byc nazwany php.ini i skopiowany do katalogu zaleznego od uzywanej platformy. W tabeli 1.2. zamieszczone sa podstawowe warianty. Tabela 1.2. Platformy PHP i polozenie pliku php.ini Platforma Polozenie pliku php.ini Windows Katalog <windows> zwykle \windows w Windows 95 i \winnt w Windows NT Unix Mozna to sprawdzic za pomoca funkcji phpinfo(), ale zwykle jest to /usr/local/lib. Po umieszczeniu pliku konfiguracyjnego w odpowiednim katalogu, nalezy do niego wprowadzic odpowiednie zmiany. Plik php.ini jest podzielony na sekcje, rozpoczynajace sie od linii [nazwa_sekcji] podobnie, jak w standardowych plikach ini systemu Windows. Plik ten zawiera obszerne komentarze opisujace przeznaczenie sekcji i opcji konfiguracji. W pozostalej czesci ksiazki czasami beda przytaczane opcje niezbedne do uruchomienia przykladw. Zwykle przyklad taki zawiera nazwe sekcji, nazwe opcji oraz wartosc. Aby wprowadzic zmiany najczesciej zmienia sie plik php.ini i ponownie uruchamia Apache, ale istnieja rwniez inne mechanizmy zmiany opcji. Mechanizmy te opisane zostana w pzniejszej czesci rozdzialu.

Korzystanie z pliku php.ini


Zalecana metoda zmiany konfiguracji jest modyfikacja pliku php.ini i ponowne uruchomienie serwera WWW. Jezeli korzystasz z PHP w postaci programu CGI nie musisz restartowac serwera, poniewaz plik php.ini jest odczytywany za kazdym uruchomieniem programu CGI. Dla przykladu mozna zmienic sposb raportowania bledw przez PHP, korzystajac z odpowiednich opcji konfiguracji. Opcje te maja nastepujace wartosci domyslne: Rozdzial 1 Kompilacja i instalowanie PHP 20

error_reporting display_errors log_errors error_log

= = = =

E_ALL & ~E_NOTICE ; Pokaz wszystkie bledy oprcz informacji On ; Wypisuj bledy (jako czesc wynikowego HTML) Off ; Zapisuj bledy do pliku bledw syslog ; Zapisuj bledy do dziennika systemowego

Pierwsza opcja powoduje generowanie komunikatw dla wszystkich typw bledw poza typem E_NOTICE. Nastepna linia powoduje wstawianie komunikatw bledw do wynikowego kodu HTML. Nastepne dwa wiersze powoduja zapisywanie komunikatw bledw w pliku. Zalzmy, ze w instalacji produkcyjnej nie chcemy wyswietlac bledw, a zamiast tego bledy beda zapisywane do okreslonego pliku. Mozna to zrealizowac zmieniajac konfiguracje w nastepujacy sposb:
error_reporting display_errors log_errors error_log = = = = E_ALL ; Pokaz wszystkie bledy Off ; On ; Zapisuj bledy /tmp/php_log ; Zapisuj bledy do pliku /tmp/php_log

Taka konfiguracja powoduje, ze wszystkie komunikaty bledw, w tym informacje, beda zapisywane w pliku /tmp/php_log. Oczywiscie plik ten powinien miec odpowiednio ustawione prawa dostepu, aby serwer WWW mgl zapisac w nim dane. Z powodu duzej ilosci opcji konfiguracji, nie zostana tu przedstawione wszystkie mozliwe opcje. Pelna lista znajduje sie w skorowidzu na koncu ksiazki. Tutaj przedstawione zostana jedynie oglne sposoby wykorzystywania tych opcji. Aby zmienic opcje konfiguracji, nalezy otworzyc w edytorze plik php.ini i odszukac opcje. Zwykle znajduje sie tam sporo komentarzy opisujacych mozliwe wartosci danej opcji.

Inne metody zmiany konfiguracji PHP


Istnieja dwie metody zmiany konfiguracji PHP bez koniecznosci modyfikacji pliku php.ini. Pierwszym sposobem jest wstawienie tych opcji do pliku konfiguracyjnego Apache httpd.conf lub do pliku .htaccess. Pierwsza metoda jest uzyteczna, jezeli chcemy miec rzne ustawienia PHP dla rznych serwerw wirtualnych lub rznych katalogw. Druga metoda jest wykorzystywana, gdy nie jest mozliwy dostep do plikw php.ini i httpd.conf. Jest to czesta sytuacja, witryna jest umieszczona na dzierzawionym serwerze zewnetrznej firmy. Jest to jednak najmniej zalecana metoda, poniewaz plik .htaccess jest wczytywany i analizowany za kazdym odwolaniem do stron znajdujacych sie w tym katalogu. Powoduje to znaczne spowolnienie serwera WWW. W obu tych przypadkach sposb zmiany konfiguracji PHP jest tak sam. Nalezy uzyc dyrektyw konfiguracji php_value i php_flag do ustawienia potrzebnych opcji. Na przyklad, aby ustawic poprzednio opisane opcje konfigurujace sposb raportowania bledw, nalezy uzyc nastepujacych dyrektyw Apache:
<VirtualHost 192.1.1.1> ServerAdmin admin@server.net DocumentRoot /www/hosts/wwwprojects/ ServerName www.testserver.com php_value error_reporting 2047 php_flag display_errors off php_flag log_errors on php_value error_log /tmp/php_log </VirtualHost>

Umieszczenie tych ustawien w pliku httpd.conf spowoduje, ze zostanie ustawiony sposb raportowania bledw dla serwera wirtualnego o nazwie www.testserver.com. Jezeli na tej samej maszynie istnieja inne serwery wirtualne, uzywaja one konfiguracji okreslonej przez plik php.ini. Pozwala to na posiadanie rznych konfiguracji PHP dla rznych serwerw wirtualnych lub katalogw. Jezeli musisz zmienic konfiguracje PHP a nie masz dostepu do pliku php.ini ani do httpd.conf, mozesz wykorzystac pliki Apache .htaccess. Jest to rwniez uzyteczne, jezeli okreslony katalog musi miec inne ustawienia konfiguracji niz reszta witryny. Na przyklad, mozna zmienic sposb raportowania bledw dla jednego katalogu na czas uruchamiania skryptw w nim sie znajdujacych. W tym celu nalezy stworzyc plik .htaccess z nastepujaca zawartoscia:
php_value error_reporting 2039 php_flag log_errors off php_flag display_errors on

Nalezy zauwazyc, ze w obu przykladowych plikach konfiguracyjnych Apache wartosc zmiennej konfiguracji error_reporting jest ustawiana za pomoca wartosci numerycznej a nie stalej. Jest o jedyny sposb poprawnego ustawienia wartosci. Nalezy pamietac, ze konfigurujac PHP poprzez dyrektywy Apache nie mozna uzywac jako wartosci zadnych stalych PHP. W przeciwnym wypadku efekty moga byc niespodziewane. Aby zilustrowac potege dostepnego mechanizmu konfiguracji na rysunku 1.8. przedstawiony zostal schemat mozliwosci konfiguracji srodowiska PHP. 21 PHP Kompendium wiedzy

Rysunek 1.8. Elastycznosc konfiguracji z zastosowaniem php.ini oraz plikw konfiguracyjnych Apache

Podsumowanie
W tym rozdziale przedstawiono kilka informacji niezbednych do rozpoczecia pracy z PHP. Z powodu elastycznosci i duzej ilosci obslugiwanych platform niemozliwe jest szczeglowe opisanie wszystkich dostepnych konfiguracji. Korzystajac jednak z informacji umieszczonych w tej ksiazce, oraz na witrynie www.php.net powinienes byc w stanie zainstalowac i skonfigurowac PHP na twojej platformie. Trzeba zauwazyc, ze PHP posiada wiele wlasnych funkcji zmieniajacych ustawienia konfiguracji. Przykladami takich funkcji sa error_reporting() oraz set_time_limit(). Wiecej informacji na temat tych funkcji mozna znalezc w skorowidzu na koncu ksiazki.

Rozdzial 1 Kompilacja i instalowanie PHP

22

Rozdzial 2. Jezyk
Wstep
W rozdziale tym znajduje sie zwiezly opis jezyka programowania PHP. Jak wspomnialem we wstepie do ksiazki nie jest moja intencja poswiecac zbyt wiele czasu na omawianiu oglnych koncepcji programowania. W tym rozdziale znajduje sie opis skladni podstawowych konstrukcji programowania, na przyklad zmiennych, stalych i funkcji. Przyklady przytoczone w tym rozdziale nie pokazuja najlepszych technik programowania a jedynie ilustruja skladnie i uzycie omawianych elementw. Pelny opis jezyka znajduje sie w dokumentacji jezyka dostepnej na witrynie http://www.php.net.

Oglne informacje na temat skladni


Poniewaz PHP jest zwykle wbudowywany w kod HTML istnieja specjalne znaczniki ograniczajace bloki PHP. Uzycie tych znacznikw jest nazywane czasem wyjsciem z trybu HTML. Wydruk 2.1. Sposoby oznaczania bloku kodu PHP w HTML
<? echo "uzycie krtkich znacznikw PHP do wyjscia z trybu HTML<br>"; ?> <?php echo "wyjscie przy uzyciu pelnych znacznikw PHP<br>"; ?> <script language="php"> echo "niektre edytory HTML nie obsluguja instrukcji przetwarzania<br>"; </script> <% echo "mozna stosowac rwniez znaczniki w stylu ASP<br>"; %>

Pierwsza metoda oznaczania blokw PHP jest dostepna jedynie wtedy, gdy uaktywnione sa krtkie znaczniki. Aby to zrobic nalezy uzyc funkcji short_tags(), wlaczyc w pliku konfiguracyjnym opcje short_tag_open lub skompilowac PHP z opcja -enable-short-tags. Znaczniki w stylu ASP sa dostepne jedynie wtedy, gdy uaktywniona jest opcja konfiguracji asp_tags. Wiecej informacji na temat kompilowania i konfiguracji PHP znajduje sie w rozdzialach Kompilacja i instalowanie PHP oraz dodatku D - Opcje konfiguracji. PHP jest syntaktycznie bardzo podobny do C. Na przyklad, instrukcje sa oddzielone srednikiem. Znacznik ?> jest niejawnym koncem instrukcji, wiec ponizsze przyklady sa poprawne skladniowo: Wydruk 2.2. Koniec instrukcji
<?php echo "Test, test...<br>"; ?> <?php echo "Test, test...<br>" ?>

Komentarze w PHP mozna oznaczac symbolami komentarzy pochodzacymi z C, C++ lub stosowanych w skryptach Uniksa. Komentarze jednoliniowe komentuja tekst do konca linii lub do konca biezacego bloku PHP w zaleznosci od tego, co bedzie pierwsze. Nie mozna zaglebiac wielowierszowych komentarzy w stylu C. Wydruk 2.3. Komentarze
<?php echo "Witaj swiecie!<br>"; // To jest jednowierszowy komentarz w stylu C++ /* To jest wielowierszowy blok komentarza */ echo "Witamy ponownie.<br>"; # To jest komentarz w stylu skryptw Uniksa ?> <?php /* Ponizsza linia spowoduje wypisanie "To wyswietli nic." */ ?> To wyswietli <?php # echo "cos"; ?> nic.<br> <?php

/* echo "A tutaj mamy problem."; /* Komentarz ten jest nieprawidlowy */ */ ?>

Typy
PHP posiada nastepujace typy: liczby zmiennoprzecinkowe, liczby calkowite, ciagi, tablice i obiekty. Typ zmiennej jest ustalany w oparciu o kontekst w jakim jest uzyta zmienna i nie jest on jawnie ustalany przez programiste. Jest to wazna cecha o ktrej nalezy pamietac podczas programowania aplikacji PHP, poniewaz niejawna konwersja typw moze spowodowac trudne do odnalezienia bledy. Na przyklad ponizsza instrukcja jest prawidlowa i spowoduje wyswietlenie liczby 9:
print( 3* "3 male swinki");

Aby mozna bylo zapanowac nad typami, PHP posiada funkcje gettype() i settype() oraz kilka funkcji przeznaczonych dla okreslonych typw, na przyklad is_integer() lub is_array(). W skorowidzu funkcji na koncu ksiazki znajduje sie pelne omwienie tych funkcji. Teraz zostanie opisany kazdy z typw zmiennych (oprcz obiektw). Obiekty PHP zostana opisane w dalszej czesci rozdzialu.

Liczby calkowite i zmiennoprzecinkowe


Liczby calkowite mozna podawac uzywajac notacji dziesietnej, semkowej i szesnastkowej. Liczby zmiennoprzecinkowe mozna podawac uzywajac notacji zwyklej lub zapisu naukowego. Na ponizszym wydruku pokazana jest skladnia PHP dla wszystkich tych notacji. Wydruk 2.4. Reprezentacja liczb
<?php $int1 = 523; // liczba dziesietna $int2 = -523; // dziesietna ujemna $int3 = 01013; // semkowa reprezentacja liczby 523 $int4 = 0x20B; // szesnastkowa reprezentacja liczby 523 $float1 = 523.197; // zwykly zapis liczby zmiennoprzecinkowej $float2 = 5.23197e2; // notacja naukowa liczby zmiennoprzecinkowej /* Wypisanie wszystkich liczb. Wyswietla "523, -523, 523, 523, 523.197, 523.197". */ print( "$int1, $int2, $int3, $int4, $float1, $float2<br>" ); ?>

Ciagi
Ciagi w PHP sa ograniczane apostrofami (') lub cudzyslowami ("). Zapisy te rznia sie sposobem interpretacji ciagu. Jezeli ciag jest otoczony cudzyslowami, zmienne zapisane w ciagu zostaja zamienione na ich wartosci. Aby zapisac znaki specjalne w ciagach otoczonych cudzyslowami, nalezy uzyc znaku lewego ukosnika (\), tak jak zostalo to pokazane w tabeli 2.1. Tabela 2.1. Znaki specjalne w ciagach otoczonych cudzyslowami Sekwencja znakw Znaczenie \n nowa linia \r powrt karetki (CR) \t tabulacja \\ lewy ukosnik \" cudzyslw \$ znak dolara W ciagach otoczonych apostrofami zmienne nie sa zastepowane. Jedynymi dopuszczalnymi sekwencjami sterujacymi sa te oznaczajace lewy ukosnik (\\) i apostrof (\'). Sekwencje te pozwalaja na wpisanie do ciagu znaku apostrofu i lewego ukosnika. Ciagi moga byc laczone przy uzyciu operatora kropki (.). Dokladniej jest to opisane w czesci rozdzialu na temat operatorw. Podobnie jak w jezyku C, mamy dostep do poszczeglnych znakw ciagu, traktujac go jak tablice znakw. Wydruk 2.5. Przyklad operacji na ciagach
<?php

Rozdzial 2 Jezyk

24

$aStr1 = "To jest zwykly ciag."; print( "$aStr1<br>" ); $aStr2 = "Thatcher"; print( "$aStr2<br>" ); $aStr3 = "Nazywam sie $aStr2"; // $aStr3 = "Nazywam sie Thatcher" print( "$aStr3<br>" ); $aStr4 = "Nazywam sie \$aStr2"; // $aStr4 = "Nazywam sie $aStr2" print( "$aStr4<br>" ); $aStr5 = 'Nie rozwijaj \'$aStr2\''; // $aStr5 = "Nie rozwijaj '$aStr2'" print( "$aStr5<br>" ); // wypisuje "Nazywam sie Thatcher i Nazywam sie $aStr2" print( "$aStr3" . " i " . "$aStr4" ); ?>

Z powodu ulotnej natury typw w PHP, zmienne moga zmieniac swj typ w zaleznosci od kontekstu w jakim wystepuja. Liczby moga byc konwertowane niejawnie na ciagi, jezeli zostana uzyte jako argument operatora operujacego na ciagach. Ciagi moga rwniez zostac skonwertowane na liczby, jezeli beda uzyte w wyrazeniach matematycznych. Jezeli PHP prbuje skonwertowac ciag na liczbe, korzysta z nastepujacych zasad: Jezeli ciag zaczyna sie od danych numerycznych, zostana one skonwertowane na liczbe. Jezeli ciag nie zaczyna sie prawidlowymi danymi liczbowymi, wartoscia ciagu bedzie zero (0). Jezeli dane numeryczne zawieraja jeden ze znakw .,e lub E, wartosc bedzie liczba zmiennoprzecinkowa a w przeciwnym przypadku liczba calkowita. Prawidlowymi danymi numerycznymi sa: opcjonalny znak po ktrym nastepuje jedna lub wiecej cyfr, opcjonalna kropka dziesietna oraz opcjonalny znak wykladnika. Znakiem wykladnika jest e lub E, po ktrym nastepuje jedna lub wiecej liczb. Wydruk 2.6. Niejawna konwersja pomiedzy ciagiem i liczba
<?php $aVar = 123; print( "\$aVar = $aVar, typ = " . gettype( $aVar ) . "<br>" ); $aVar2 = $aVar . " niejawnie skonwertowane do ciagu"; print( "\$aVar2 = $aVar2, typ = " . gettype( $aVar2 ) . "<br>" ); $aVar3 = $aVar2 + 1; // niejawna konwersja na liczbe calkowita print( "\$aVar3 = $aVar3, typ = " . gettype( $aVar3 ) . "<br>" ); $aVar3 = $aVar2 * 1.1; // niejawna konwersja na liczbe zmiennoprzecinkowa print( "\$aVar3 = $aVar3, typ = " . gettype( $aVar3 ) . "<br>" ); $aNotNumber = "abc"; $aVar4 = $aNotNumber * 1; // prba konwersji na liczbe, zwracane jest 0 print( "\$aVar4 = $aVar4, typ = " . gettype( $aVar4 ) . "<br>" ); $aIsNumber = "3 male swinki"; $aVar5 = $aIsNumber + 1; // konwersja $aIsNumber na liczbe 3 print( "\$aVar5 = $aVar5, typ = " . gettype( $aVar5 ) . "<br>" ); ?>

Tablice
Tablice w PHP zachowuja sie zarwno tak jak tablice indeksowane (wektory) oraz jak tablice mieszajace (asocjacyjne). PHP pozwala rwniez na tworzenie tablic wielowymiarowych. Z powodu unikalnej konstrukcji tablic w PHP, mozna indeksowac jeden wymiar tablicy wielowymiarowej liczbami a inny w sposb asocjacyjny. Tablice moga byc tworzone przy uzyciu funkcji list() lub array() albo poprzez jawne podanie kazdej z wartosci. W skorowidzu funkcji na koncu ksiazki zostaly opisane wszystkie funkcje do manipulacji tablicami. Jednowymiarowe tablice moga zamieniane w ciagach przez mechanizm zastepowania zmiennych na wartosci w sposb identyczny jak wszystkie inne zmienne. W przypadku tablic wielowymiarowych nalezy uzyc nawiasw klamrowych do zaznaczenia indeksw. Ponizszy wydruk pokazuje przyklady uzycia rznych typw tablic. Wydruk 2.7. Inicjowanie i uzycie 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( "Wartosc szesnastkowa koloru czerwonego wynosi {$color['czerwony']}<br>" ); // Tworzenie tej samej co poprzedniej tablicy asocjacyjnej // tylko nieco prosciej $color = array( "niebieski" => "#0000FF", "zielony" => "#00FF00", "czerwony" => "#FF0000" ); print( "Wartosc szesnastkowa koloru zielonego wynosi {$color['zielony']}<br>" ); // Reczne tworzenie tablicy wielowymiarowej $m[0][0] = "Zero Zero"; $m[0][1] = "Zero Jeden"; print( "Wartoscia \$m[0][1] jest {$m[0][1]}<br>" ); // Reczne 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 stale
Zmienne PHP sa oznaczane znakiem dolara ($), po ktrym nastepuje nazwa zmiennej. Wielkosc liter w nazwach zmiennych jest rozrzniana. Prawidlowe nazwy zmiennych musza zaczynac sie litera lub znakiem podkreslenia, po ktrych moze nastapic litera, liczba lub znak podkreslenia. Prawidlowymi literami w zmiennych sa 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; // nieprawidlowa nazwa zmiennej $_test = "test"; // prawidlowo, rozpoczyna sie podkresleniem $_aec = "test2"; // prawidlowo ?>

Wartosci moga byc przypisywane do zmiennych przez wartosc lub przez referencje. Gdy przypisanie jest realizowane przez wartosc, obliczona wartosc wyrazenia jest przepisywana do docelowej zmiennej. Po przypisaniu zmienne sa niezalezne i zmiana wartosci w jednej nie wplywa na wartosc drugiej zmiennej. Gdy wartosci sa przypisywane przez referencje, nowa zmienna staje sie odwolaniem do oryginalnej zmiennej. Zmiana wprowadzona do dowolnej zmiennej powoduje zmiane drugiej. Aby wykonac przypisanie przez referencje, nalezy poprzedzic nazwe znakiem &. Wydruk 2.9. Przypisywanie zmiennych
<?php $variable1 = "Ryan"; $variable2 = $variable1; // przypisanie wartosci print( "$variable1, $variable2<br>" ); // wypisuje "Ryan, Ryan" $variable2 = "Scott"; print( "$variable1, $variable2<br>" ); // wypisuje "Ryan, Scott" $variable3 = &$variable1; // przypisanie przez referencje print( "$variable1, $variable3<br>" ); // wypisuje "Ryan, Ryan" $variable3 = "Katie"; print( "$variable1, $variable3<br>" ); // wypisuje "Katie, Katie" ?>

Zmienne predefiniowane
Oprcz zmiennych definiowanych przez uzytkownika, w PHP istnieja zmienne tworzone przez system. Lista tych zmiennych zalezy od kontekstu wykonania skryptu (na przyklad, czy jest uruchamiany samodzielnie, Rozdzial 2 Jezyk 26

czy poprzez serwer WWW), wersji PHP i typu serwera WWW. Poniewaz lista zmiennych jest zalezna od wielu czynnikw, niektre z nich moga nie byc nigdy dostepne. PHP generuje rwniez zmienne dla cookie i danych formularzy przesylanych za pomoca metod GET i POST. Szczeglowe omwienie tych zmiennych zawarte jest w rozdziale 3 Formularze i cookie. Czesc ta zawiera podzbir dostepnych zmiennych dostepnych w czasie pracy PHP4 wraz z serwerem Apache 1.3.11. Aby zobaczyc wszystkie zmienne dostepne w srodowisku mozna uzyc funkcji phpinfo(). Kompletniejsza lista predefiniowanych zmiennych znajduje sie w skorowidzu na koncu ksiazki. Tabela 2.2. zawiera podzbir zmiennych srodowiska Apache, tabela 2.3., podzbir zmiennych srodowiska systemu a tabela 2.4. zawiera zmienne generowane przez PHP. W tabeli 2.5. zebrane sa operatory arytmetyczne, natomiast operatory bitowe w tabeli 2.6. Tabela 2.7. zawiera operatory porwnania, tabela 2.8 operatory zwiekszania i zmniejszania a tabela 2.9. zawiera operatory logiczne. Ostatnia tabela, 2.10. zawiera operatory przypisania. Tabela 2.2. Zmienne srodowiska serwera Apache Zmienna Definicja HTTP_HOST Zawartosc naglwka Host: o ile zostal wyslany przez przegladarke. HTTP_USER_AGENT Zawartosc naglwka User Agent: wyslanego przez przegladarke. Naglwek ten opisuje przegladarke zadajaca strony, na przyklad: Mozilla/4/0 (compatible; MSIE 5.01; Windows NT). Wiecej na temat wykorzystania tej zmiennej znajduje sie w rozdziale 9 Niezaleznosc od przegladarki. REMOTE_ADDR Adres IP uzytkownika ogladajacego strone. SERVER_PROTOCOL Nazwa i wersja protokolu za pomoca ktrego zostalo wyslane zadanie strony, na przyklad HTTP/1.1. GATEWAY_INTERFACE Wersja specyfikacji CGI uzywanej przez serwer, na przyklad CGI/1.1. Tabela 2.3. Zmienne srodowiska systemu Zmienna
HOSTNAME HOSTTYPE PATH OSTYPE

Definicja Nazwa komputera serwera. Typ komputera, na przyklad i386. Systemowa sciezka serwera. System operacyjny dzialajacy serwerze, na przyklad 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 pomoca metody GET. Tablica asocjacyjna zmiennych przekazanych do skryptu za pomoca metody POST. PHP Kompendium wiedzy

27

Tabela 2.5. Operatory arytmetyczne Operator Nazwa + Dodawanie Odejmowanie


* / %

Przyklad
$a + $b $a - $b $b $a * $b $a / $b

Wynik Suma $a i $b Rznica $a i Iloczyn $a i $b Iloraz $a i $b Reszta z dzielenie $a przez $b

Mnozenie Dzielenie Reszta dzielenia

$a % $b

Tabela 2.6. Operatory bitowe Operator Nazwa & Iloczyn bitowy


|

Przyklad
$a & $b $a | $b

Suma bitowa

Rznica symetryczna

$a ^ $b

Negacja

~$a

<<

Przesuniecie w lewo

$a << $b

>>

Przesuniecie w prawo

$a >> $b

Wynik Bity ustawione w $a i $b sa ustawione Bity ustawione w $a lub $b sa ustawione Bity ustawione w $a lub $b, ale nie w obu na raz sa ustawione Bity ustawione nie sa teraz ustawione i odwrotnie Przesuniecie bitw w $a w lewo o $b krokw Przesuniecie bitw w $a w prawo o $b krokw

Tabela 2.7. Operatory porwnania Operator Nazwa == Rwny


===

Przyklad
$a == $b $a === $b

Identyczny

!= < > <=

Rzny Mniejszy Wiekszy Mniejszy rwny lub

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

>=

Wiekszy rwny

lub

$a >= $b

Wynik jezeli $a jest rwne $b True, jezeli $a jest rwne $b i sa one tych samych typw True, jezeli $a jest rzne od $b True, jezeli $a jest mniejsze od $b True, jezeli $a jest wieksze od $b True, jezeli $a jest mniejsze lub rwne $b True, jezeli $a jest wieksze lub rwne $b
True,

Tabela 2.8. Operatory zwiekszania i zmniejszania Rozdzial 2 Jezyk 28

Operator, przyklad
$a++ ++$a $a---$a

Nazwa Postinkrementacja Preinkrementacja Postdekrementacja Predekrementacja

Wynik Zwraca $a, a nastepnie zwieksza $a o jeden Zwieksza $a o jeden i zwraca $a Zwraca $a, a nastepnie zmniejsza $a o jeden Zmniejsza $a o jeden i zwraca $a

Tabela 2.9. Operatory logiczne Operator Nazwa and Iloczyn logiczny


or

Przyklad
$a and $b

i
$a or $b

$b True

Wynik True, jezeli $a maja wartosc


True,

Suma logiczna Rznica symetryczna Negacja Iloczyn logiczny Suma logiczna

lub
True xor $a xor $b

$b

jezeli $a maja wartosc

! &&

!$a $a && $b

jezeli $a maja wartosc True, ale nie razem True, jezeli $a nie jest True True, jezeli $a i $b maja wartosc lub
$b True True,

True,

||

$a || $b

lub
True

$b

jezeli $a maja wartosc

Tabela 2.10. Operatory przypisania Operator Przyklad


= += $a = $b

Wynik Przypisuje wartosc do $a.

$b

$a += $b

-=

$a -= $b

*=

$a *= $b

/=

$a /= $b

.=

$a .= $b

%=

$a %= $b

|=

$a |= $b

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

29

&=

$a &= $b

^=

$a ^= $b

<<=

$a <<= $b

>>=

$a >>= $b

do $a. Jest to identyczne z $a=$a|$b. Przypisuje wartosc ($a&$b) do $a. Jest to identyczne z $a=$a&$b. Przypisuje wartosc ($a^$b) do $a. Jest to identyczne z $a=$a^$b. Przypisuje wartosc ($a<<$b) do $a. Jest to identyczne z $a=$a<<$b. Przypisuje wartosc ($a>>$b) do $a. Jest to identyczne z $a=$a>>$b.
($a|$b)

Zasieg zmiennych
Oglnie rzecz ujmujac, zmienne globalne PHP maja taki sam zasieg. Rozciaga sie on rwniez na pliki dolaczane. Wewnatrz funkcji definiowanych przez uzytkownika zmienne maja zasieg lokalny. Zmienne globalne musza byc deklarowane jako globalne, aby mogly byc wykorzystywane wewnatrz funkcji. PHP posiada rwniez zmienne statyczne, ktre deklarowane wewnatrz funkcji zapewniaja utrzymywanie swojej wartosci pomiedzy kolejnymi wywolaniami funkcji. Wydruk 2.10. Zasieg zmiennych
<?php $aGlobal1 = "To jest test"; /* Dolaczamy inny plik z kodem PHP. POwyzsza zmienna $aGlobal1, bedzie dostepna w dolaczanym pliku. */ include( "example10_inc.php" ); function DoPrint( ) { /* Ponizsza instrukcja wydrukuje tylko <br> poniewaz zmienna $aGlobal1 wewnatrz funkcji jest poza zasiegiem. */ print( "$aGlobal1<br>" ); } DoPrint(); function DoPrint2( ) { global $aGlobal1; /* Ponizsza instrukcja wypisze wartosc zmiennej poniewaz zostala zadeklarowana jako globalna. */ print( "$aGlobal1<br>" ); } DoPrint2(); function StaticFunc( ) { static $aVal = 0; print( "$aVal<br>" ); $aVal++; } // Ponizsze wywolania spowoduja wypisanie 0, a nastepnie 1 StaticFunc(); StaticFunc(); ?> --- Zawartosc pliku example10_inc.php3 --<?php print( "$aGlobal1<br>" ); ?>

Rozdzial 2 Jezyk

30

Stale
PHP posiada kilka predefiniowanych stalych oraz pozwala na definiowanie wlasnych. Pelna lista stalych znajduje sie w skorowidzu na koncu ksiazki. Aby zdefiniowac nowa stala uzywa sie funkcji define(). Zauwaz, ze stale PHP nie sa makrami w stylu C i dlatego musza byc wartosciami skalarnymi. Wydruk 2.11. Stale
<?php define( "aString", "To jest staly ciag znakw" ); define( "aNumber", 1 ); print( "Mamy tutaj zdefiniowane " . aNumber . " stalych.<br>" ); print( "Jej wartoscia jest '" . aString . "'<br>" ); ?>

Operatory i kolejnosc operatorw


PHP posiada zestaw operatorw znanych programistom C i C++. W tabelach od 2.5. do 2.10. zamieszczone zostalo zestawienie dostepnych operatorw. Oprcz operatorw umieszczonych w tabelach istnieje jeszcze kilka operatorw, ale sa one trudniejsze do klasyfikacji. Operator trjskladnikowy, zapisywany jako ?: jest dostepny zarwno w PHP jak i w C. Wyrazenie $wart = (wyrazenie1) ? (wyrazenie2) : (wyrazenie3); przypisuje do zmiennej $wart wartosc wyrazenie2, jezeli wyrazenie1 bedzie mialo wartosc True, natomiast w przeciwnym przypadku $wart bedzie mialo wartosc wyrazenie3. Operator wykonania oznaczany przez znak ` (na jednym klawiszu ze znakiem ~) jest podobny do operatora dostepnego we wielu jezykach programowania powloki. Wyrazenie otoczone znakami ` jest wykonywane na serwerze a zwracana wartosc przekazywana do zmiennej. PHP posiada rwniez operator kontroli bledw @. Gdy operator ten jest umieszczony przed wyrazeniem, nie sa generowane komunikaty bledw powodowanych przez to wyrazenie. Uzycie tego operatora pozwala na stworzenie lepszej obslugi bledw, o ile uaktywniona jest opcja track_errors. Gdy opcja ta jest aktywna, komunikaty bledw zatrzymane przez operator @ sa zapamietywane w zmiennej globalnej $php_errormsg. Zmienna ta jest nadpisywana przez kolejne bledy, wiec aby kontrola bledw dzialala poprawnie, zmienna ta powinna byc sprawdzana mozliwie szybko. Wydruk 2.12. Niektre dzialania z operatorami
<?php $aNum1 = 1; $aNum2 = 2; = ( $aNum1 == $aNum2 ) ? "Wartosci sa rwne" : "Wartosci sa rzne"; print( "$aVal<br>" ); // drukuje "Wartosci sa rzne" $aVal = ( 1 == "1" ) ? "Wartosci sa rwne" : "Wartosci sa rzne"; print( "$aVal<br>" ); // drukuje "Wartosci sa rwne" $aVal

$aVal

= ( 1 === "1" ) ? "Wartosci sa identyczne" : "Wartosci nie sa identyczne"; print( "$aVal<br>" ); // prints "Wartosci nie sa identyczne" /* Ponizszy fragment powoduje przypisanie do $aListing zawartosci biezacego katalogu serwera, a nastepnie konwersje znakw nowej linii na znaczniki <br> I wypisanie wynikw */ $aListing = `ls -l`; $aFmtList = nl2br( $aListing ); print( "<br>Zawartosc katalogu:<br><b>$aFmtList</b><br>" ); ?>

31

PHP Kompendium wiedzy

Programowanie przeplywu sterowania


PHP posiada standardowe instrukcje programowania przeplywu sterowania takie jak if oraz petle while i for. Programisci C nie beda mieli klopotu ze skladnia tych instrukcji. Dodatkowo PHP posiada dwie funkcje dolaczania plikw z kodem zrdlowym: include() i require().

if, else, elseif


Jest to oczywiscie najwazniejszy element jezyka. Instrukcja tworzenie rozgalezien na podstawie wyrazen logicznych. Wydruk 2.13. Przyklad uzycia if, else i elseif
<?php if ( 1 < 2 ) print( "To zostanie wydrukowane.<br>" ); else print( "To nie zostanie wydrukowane.<br>" ); $aValue = 2; if ( $aValue == 1 ) { // Uzywamy nawiasw klamrowych do otaczania blokw instrukcji print( "\$aValue == 1<br>" ); } elseif ( $aValue == 2 ) { print( "\$aValue == 2<br>" ); } elseif ( $aValue == 3 ) { print( "\$aValue == 3<br>" ); } else { print( "\$aValue nie jest 1, 2 ani 3<br>" ); } ?>

if

organizuje przeplyw sterowania poprzez

while
Jest to najprostszy typ petli w PHP, ktra zachowuje sie identycznie jak w C i innych jezykach wysokiego poziomu.

do .. while
Mimo, ze jest to petla podobna do while, to w petli do..while warunek petli jest sprawdzany po pierwszym przebiegu petli. Gwarantuje to, ze cialo petli zostanie wykonane co najmniej raz. Wydruk 2.14. Przyklad uzycia while i do..while
<?php print( "Liczenie w gre przy uzyciu <b>while</b>.<br>" ); $nIndex = 0; // wypisuje liczby od 0 do 9 while ( $nIndex < 10 ) { print( "$nIndex<br>" ); $nIndex++; } print( "Liczenie w dl przy uzyciu <b>do..while</b>.<br>" ); // wypisuje liczby od 10 do 1 do { print( "$nIndex<br>" ); $nIndex--; } while ( $nIndex > 0 ); ?>

Rozdzial 2 Jezyk

32

for
Petla for jest najbardziej zlozona instrukcja petli w PHP, ale jest ona skladniowo identyczna z instrukcja for w jezyku C. Jej skladnia jest nastepujaca:
for (wyr1; wyr2; wyr3) instrukcja

Wartosc pierwszego wyrazenia (wyr1) jest obliczana raz, na poczatku petli. Wartosc drugiego (wyr2) jest obliczana na poczatku kazdego przebiegu petli. Jezeli bedzie ono mialo wartosc True, petla bedzie sie nadal wykonywala i zostana wykonane instrukcje ciala petli. Jezeli drugie wyrazenie jest puste, przyjmowane jest, ze ma ono wartosc True. Na koncu kazdego przebiegu petli wykonywane jest trzecie wyrazenie (wyr3). Kazde z tych trzech wyrazen moze byc puste. Wydruk 2.15. Przyklad uzycia for
<?php // Wypisuje liczby od 0 do 9 for ( $nIndex = 0; $nIndex < 10; $nIndex++ ) { print( "$nIndex<br>" ); } /* $nIndex ma wartosc 10. Pokazemy teraz, ze kazde z trzech wyrazen moze zostac opuszczone. Nie jest to zalecane ze wzgledu na czytelnosc kodu. Petla powoduje wypisanie liczb od 10 do 1 */ for ( ; $nIndex > 0; $nIndex-- ) { print( "$nIndex<br>" ); } ?>

foreach
Wyrazenie foreach jest wygodnym sposobem na przegladanie tablic. Podobne konstrukcje znajduja sie w VBScript, Perl i innych jezykach. PHP posiada dwa warianty skladni:
foreach ( tablica as zmienna_wartosc) instrukcja foreach ( tablica as zmienna_klucz => zmienna_wartosc) instrukcja

Pierwsza postac petli przebiega po podanej tablicy i w kazdym przebiegu wartosc biezacego elementu tablicy jest przypisywana do zmiennej (zmienna_wartosc) a wskaznik biezacego elementu tablicy jest przesuwany. Druga postac realizuje to samo, ale dodatkowo do zmiennej (zmienna_klucz) jest przypisywany klucz biezacej pozycji. Wydruk 2.16. Przyklad uzycia foreach
<?php $aArray = array( "Czerwony", "Zielony", "Niebieski" ); foreach( $aArray as $aValue ) { print( "Biezaca wartosc to $aValue<br>" ); } "Czerwony" => "#FF0000", "Zielony" => "#00FF00", "Niebieski" => "#0000FF" ); foreach( $aColorArray as $aKey => $aValue ) { print( "Wartosc szesnastkowa $aKey to $aValue<br>" ); } ?> $aColorArray = array(

switch
Instrukcja switch upraszcza tworzenie wielokrotnych warunkw. Jest ona czesto uzywana zamiast skomplikowanych konstrukcji if...elseif...else zawierajacych wiele wystapien elseif. Skladnia i implementacja tej instrukcji jest identyczna jak w C. Korzystnym ulepszeniem w PHP jest mozliwosc uzywania ciagw jako wyrazen instrukcji switch.

33

PHP Kompendium wiedzy

Programisci Delphi i Pascala maja zwykle klopoty z zapamietaniem, ze w konstrukcji switch w C wystepuja instrukcje break. Czasami opuszczenie tej instrukcji jest wygodne. Ponizszy przyklad ilustruje czeste zastosowania instrukcji switch. Wydruk 2.17. Przyklady uzycia switch
<?php $nIndex = 2; // Najprostsza instrukcja switch switch ( $nIndex ) { case 0: print( "zero<br>" ); break; case 1: print( "jeden<br>" ); break; case 2: print( "dwa<br>" ); break; } // Uzycie frazy 'default' $nIndex = 17; switch ( $nIndex ) { case 0: print( "zero<br>" ); break; case 1: print( "jeden<br>" ); break; case 2: print( "dwa<br>" ); break; default: print( "Nie jest to zero, jeden ani dwa<br>" ); break; } // Switch z uzyciem ciagu $aColor = "niebieski"; switch( $aColor ) { case "czerwony": print( "#FF0000<br>" ); break; case "zielony": print( "#00FF00<br>" ); break; case "niebieski": print( "#0000FF<br>" ); break; default: print( "inny<br>" ); break; } /* Opuszczenie instrukcji break spowoduje wykonanie wszystkich wyrazen po pasujacej pozycji. Jezeli $nIndex jest 0, zostana wykonane wszystkie trzy instrukcje print. Jezeli $nIndex jest 1, wykonane zostana ostatnie dwie instrukcje print. */ $nIndex = 0; switch ( $nIndex ) { case 0: print( "zero<br>" ); case 1: print( "jeden<br>" ); case 2: print( "dwa<br>" ); } /* opuszczenie instrukcji break moze byc czasami przydatne */ $aColor = "Czerwony"; switch( $aColor )

Rozdzial 2 Jezyk

34

{ case "czerwony": case "Czerwony": // Ponizsza instrukcja zostanie wykonana, jezeli $aColor // bedzie mial wartosc "Czerwony" lub "czerwony" print( "#FF0000<br>" ); break; case "zielony": case "Zielony": print( "#00FF00<br>" ); break; case "niebieski": case "Niebieski": print( "#0000FF<br>" ); break; default: print( "inny<br>" ); break; } ?>

break i continue
PHP posiada rwniez znane z C instrukcje break i continue, ktre pozwalaja na dodatkowe sterowanie petlami. Obie te instrukcje pozwalaja na podanie im parametru numerycznego, ktry okresla ilosc zaglebionych petli, ktre nalezy przerwac lub rozpoczac od poczatku. Wyrazenie break konczy wykonanie biezacej konstrukcji sterujacej (petli lub wyrazenia switch). Wyrazenie continue jest uzywane jedynie w petlach. Powoduje ono opuszczenie pozostalych instrukcji ciala petli i rozpoczecie nowej iteracji. Najczesciej instrukcje break i continue sa stosowane w zagniezdzonych petlach. W przypadku petli prostych, wyrazenia warunkowe sa wystarczajace do realizacji tych zadan. Wydruk 2.18. Przyklady uzycia break i continue
<?php $aArray = array( 4, 5, 15, 12, 7, 3, 20, 11, 31 ); $aCurMax = 17; /* Sprawdzamy, czy istnieje w tablicy wartosc wieksza od biezacej wartosci maksymalnej. */ foreach( $aArray as $aValue ) { /* Wyrazenie bedzie prawdziwe, gdy osiagnieta zostanie wartosc 20. Poniewaz wykonujemy instrukcje break, nie sprawdzamy wartosci ktre sa w tablicy po wartosci 20 */ if ( $aValue > $aCurMax ) { $aCurMax = $aValue; break; // mozemy napisac 'break 1;' } } // wypisuje "Biezacym maksimum jest 20" print( " Biezacym maksimum jest $aCurMax<br>" ); // wypisuje liczby nieparzyste od 0 do 20 $nIndex = 0; for ( $nIndex = 0; $nIndex < 20; $nIndex++ ) { if ( ( $nIndex % 2 ) == 0 ) continue; // opcjonalnie 'continue 1;' print( "$nIndex<br>" ); } ?>

PHP osiada alternatywna skladnie dla konstrukcji sterujacych if, while, for i switch. W kazdej z tych konstrukcji otwierajaca klamra jest zamieniona na dwukropek (:) a zamykajaca klamra na odpowiednio endif, endwhile, endfor i endswitch. Gdy tworzysz duze skrypty wbudowane w HTML, skladnia alternatywna moze byc uzyteczna, poniewaz zapewnia wyrazna identyfikacje konca struktur sterujacych. Wydruk 2.19. Przyklad uzycia alternatywnej skladni PHP na stronie HTML
<html> <head> <title>Przyklad 19</title>

35

PHP Kompendium wiedzy

</head> <body> <!-- Uzywamy PHP do utworzenia listy opcji --> <form action="someotherpage.phtml" method="post"> <table> <tr> <td> Wybierz swj rok urudzenia: </td> <td> <select name="BirthYear" size="1"> <?php /* Generujemy znaczniki dla lat 1920-2000 w odwrotnej kolejnosci */ $aCurYear = 2000; while( $aCurYear >= 1920 ): ?> <option value="<?php print( $aCurYear ); ?>"> <?php print( $aCurYear ); ?> </option> <?php $aCurYear--; endwhile; /* zakladajac, ze pomiedzy while i endwhile jest duzo wiecej tekstu, moze byc trudno znalezc koncowy srednik, jezeli uzyjemy zwyklej skladni. */ ?> </select> </td> </tr> </table> </form> </body> </html>

include i require
PHP posiada dwa mechanizmy dolaczania plikw zewnetrznych: include() i require(). Wyrazenie jest zwykla funkcja PHP, natomiast require() jest konstrukcja jezykowa, ktra posiada kilka ograniczen. W obu przypadkach po dolaczeniu pliku PHP przechodzi do trybu HTML na poczatku dolaczanego pliku. Na koncu pliku analizator wraca do trybu PHP. Oznacza to, ze dowolny kod zawarty w pliku dolaczanym musi byc otoczony prawidlowymi znacznikami PHP. Funkcja include() jest wykonywana za kazdym jej wywolaniem i moze znajdowac sie wewnatrz petli lub instrukcji warunkowych. Pozwala to warunkowo wlaczac pliki, lub wlaczac grupy plikw przy pomocy odpowiednio skonstruowanej petli. Funkcja include() pozwala rwniez, aby dolaczany plik zwracal wartosc, ktra mozna nastepnie przypisac do zmiennej. Przetwarzanie pliku w instrukcji include() konczy sie, gdy zostanie napotkana instrukcja return. Wyrazenie require() rzni sie tym od include(), ze nie wchodzi w sklad konstrukcji sterujacych. Oznacza to, ze pliki nie moga byc warunkowo dolaczane za pomoca require(). Wyrazenie to jest wykonywane raz, jezeli znajduje sie w petli lub nawet, jezeli znajduje sie w instrukcji warunkowej, ktrej warunek ma wartosc False. Inna rznica jest to, ze pliki dolaczane za pomoca require() nie moga zwracac wartosci. Prba zwrcenia wartosci w wyrazeniu require() powoduje blad skladni.
include()

Funkcje
PHP pozwala na tworzenie funkcji definiowanych przez uzytkownika. Funkcje nie musza byc deklarowane przed ich uzyciem w kodzie PHP4. Funkcje w PHP moga posiadac nastepujace cechy: zmienne nazwy funkcji, zmienna liczba argumentw, argumenty domyslne i argumenty przekazywane przez referencje. PHP pozwala na wykonywanie dowolnego kodu w ciele funkcji, wlaczajac w to wywolania innych funkcji. Zdolnosc ta pozwala rwniez na tworzenie funkcji rekurencyjnych. PHP nie pozwala na przeciazanie funkcji, nie ma rwniez mechanizmu usuwania lub przedefiniowania wczesniej zdefiniowanych funkcji. Rozdzial 2 Jezyk 36

Domyslnie argumenty sa przekazywane przez wartosc. Aby przekazac argument przez referencje, nalezy poprzedzic nazwe zmiennej znakiem &. Uzywajac argumentw domyslnych, musza byc one umieszczone po wszystkich argumentach obowiazkowych. W przypadku zmiennej listy argumentw, dostepne sa funkcje func_num_args(), func_get_arg() i func_get_args(), za pomoca ktrych mozna pobrac dane przekazane jako argumenty. Ponizsze przyklady pokazuja uzycie funkcji w PHP. Wydruk 2.20. Przyklady funkcji definiowanych przez uzytkownika
<?php // prosta funkcja function ReturnSum( $a, $b ) { return $a + $b; } // przekazanie argumentu przez referencje function StringAppend( &$BaseString, $AddString ) { // poniewaz jest to przekazane przez referencje, wartosc // $BaseString moze byc zmieniona poza ta funkcja $BaseString .= $AddString; } // wartosci domyslne /* Funkcja ta moze byc wywolana przy uzyciu jednej z postaci: PrintAnchorTag( "href", "text" ); PrintAnchorTag( "href", "text", "target" ); */ function PrintAnchorTag( $aHREF, $aText, $aTarg = "" ) { if ( $aTarg == "" ) { print( "<a href=\"$aHREF\">$aText</a>" ); } else { print( "<a href=\"$aHREF\" target=\"$aTarg\">$aText</a>" ); } } // zmienna lista argumentw function PrintEverything( ) { $aNumArgs = func_num_args(); for ( $nIndex = 0; $nIndex < $aNumArgs; $nIndex++ ) { $aArgVal = func_get_arg( $nIndex ); print( "Argument $nIndex: $aArgVal<br>" ); } } print( "ReturnSum( 3, 5 ): " . ReturnSum( 3, 5 ) . "<br>" ); $aString = "Marysia miala "; StringAppend( $aString, "mala owieczke" ); print( "$aString<br>" ); // wypisuje "Marysia miala mala owieczke" PrintAnchorTag( "example10.phtml", "Zobaczmy jeszcze raz przyklad 10" ); print( "<br>" ); PrintAnchorTag( "example10.phtml", "Zobaczmy jeszcze raz przyklad 10 w nowym oknie", "_blank" ); print( "<br>" ); print( "Wywolanie PrintEverything( 1, 2, 3, 4, 5 ):<br>" ); PrintEverything( 1, 2, 3, 4, 5 ); ?>

Klasy i programowanie obiektowe


PHP posiada zdolnosc tworzenia klas za pomoca skladni podobnej jak w C++. PHP posiada rwniez bardzo prosta implementacje programowania obiektowego, ktra jest jednak wystarczajaca dla wiekszosci aplikacji WWW. Dostepne jest dziedziczenie jednobazowe, nie ma dziedziczenia wielobazowego. Istnieja konstruktory klas, ale nie ma destruktorw. PHP posiada (i wymaga uzywania) wskaznik $this, ktry jest 37 PHP Kompendium wiedzy

stosowany do odwolywania sie do metod i zmiennych obiektu. Ponizszy przyklad pokazuje tworzenie prostej klasy. Wiecej przykladw na ten temat znajdzie sie w pzniejszych rozdzialach ksiazki. Wydruk 2.21. Przyklady uzycia klas w PHP
<?php // tworzenie prostej klasy class ShoppingBasket { var $fItems; var $fCurValue; /* jest to konstruktor klasy, poniewaz ma taka sama nazwe jak klasa. Tak samo jak w C++ konstruktor moze posiadac argumenty W tym przypadku jest to poczatkowa wartosc koszyka. Moze byc to stala prowizja lub rabat.. */ function ShoppingBasket( $aInitialValue = 0.0 ) { $this->fCurValue = $aInitialValue; } // Dodanie okreslonej ilosci przedmiotw function AddItem( $aName, $aValue, $aQuantity = 1 ) { $this->fItems[$aName]["Quantity"] += $aQuantity; $this->fItems[$aName]["Value"] = $aValue; $this->fCurValue += $aValue * $aQuantity; return True; } function RemoveItem( $aName, $aQuantity = 1 ) { // Usuwamy okreslona ilosc przedmiotw // jedynie, gdy byla dostepna wystarczajaca ich ilosc if ( $this->fItems[$aName]["Quantity"] > $aQuantity ) { $this->fItems[$aName]["Quantity"] -= $aQuantity; $this->fCurValue -= $this->fItems[$aName]["Value"] * $aQuantity; } else { return False; } } function PrintBasket( ) { if ( count( $this->fItems ) > 0 ) { print( "Zawartosc koszyka:<blockquote>" ); foreach( $this->fItems as $aKey => $aValue ) { print( "{$aValue['Quantity']} $aKey<br>" ); } print( "Wartosc calkowita: $" . number_format( $this->fCurValue, 2 ) ); print( "</blockquote>" ); print( "<br>" ); } else { print( "<i>Koszyk jest pusty</i><br><br>" ); } } } /* Tworzenie nowego obiektu ShoppingBasket. Dodanie kilku przedmiotw usuniecie kilku przedmiotw i wypisanie zawartosci koszyka */ $aBasket = new ShoppingBasket( 3.50 ); $aBasket->PrintBasket(); $aBasket->AddItem( "gizmo", 1.50 ); // dodanie 1 gizmo $aBasket->PrintBasket(); $aBasket->AddItem( "foobar", 2.10, 6 ); // dodanie 6 foobarw $aBasket->PrintBasket(); $aBasket->RemoveItem( "foobar", 15 );

Rozdzial 2 Jezyk

38

$aBasket->PrintBasket(); $aBasket->RemoveItem( "foobar", 3 ); $aBasket->PrintBasket(); ?>

Porwnywanie wzorcw
PHP posiada dwa typy funkcji do porwnywania wzorcw (lub wyrazen regularnych). Pierwszy typ jest zgodny ze specyfikacja POSIX i sa to funkcje ereg(), eregi(), ereg_replace(), eregi_replace() oraz split(). Kazda z tych funkcji jako pierwszego argumentu wymaga wyrazenia regularnego. PHP korzysta z rozszerzonych wyrazen regularnych zdefiniowanych przez POSIX 1003.2. PHP zawiera w katalogu regex strony podrecznika, ktre w pelni opisuja wyrazenia regularne POSIX. Drugi typ funkcji porwnywania wzorcw jest zgodny z wyrazeniami regularnymi Perl. Nazwy tych funkcji sa poprzedzone ciagiem preg_. Pelna lista tych funkcji znajduje sie w skorowidzu na koncu ksiazki. Skladnia tych wyrazen jest taka sama jak w Perl 5 z kilkoma rznicami. Biezaca implementacja tych funkcji odpowiada Perl 5.005. Rznica pomiedzy implementacja w Perl 5.005 i w PHP jest dokladnie opisana w dokumentacji PHP dostepnej z witryny http://www.php.net.

Podsumowanie
Rozdzial ten jest zwiezlym opisem jezyka PHP i nie zawiera szczeglowo opisanych podstaw programowania. Dlatego nie zawiera on dyskusji na temat tego kiedy lub dlaczego nalezy uzywac okreslonych konstrukcji. Zamieszczone zostaly za to przyklady ilustrujace skladnie i dostepne funkcje. PHP zawiera wszystkie wlasnosci potrzebne do tworzenia zlozonych i latwych do zarzadzania aplikacji WWW. Jezyk jest wystarczajaco sprawny do realizacji wiekszosci zadan, ale jest przygotowany do tworzenia aplikacji dla WWW, co zostanie pokazane w kolejnych rozdzialach.

39

PHP Kompendium wiedzy

Rozdzial 3. Formularze i cookie


Wstep
W czasie tworzenia dowolnego typu aplikacji utworzenie dobrego mechanizmu interakcji z uzytkownikiem jest jednym z najwazniejszych zadan programisty. HTML posiada elementy formularzy, ktre sa uzywane do zbierania danych od uzytkownika, natomiast PHP zapewnia prosty mechanizm przetwarzania tych formularzy. Poniewaz PHP zostal zaprojektowany jako jezyk programowania dla WWW, obsluguje on automatycznie wiele szczeglw przetwarzania formularzy. Rozdzial ten zawiera informacje nie tylko na temat sposobu uzycia formularzy HTML w PHP, ale rwniez na temat kontroli poprawnosci i przetwarzania danych formularza. Dla programistw, ktrzy przechodza od pisania zwyklych aplikacji do tworzenia aplikacji WWW przeznaczona jest czesc zatytulowana Wazne zagadnienia programowania dla WWW, ktra sygnalizuje niektre problemy jakie powstaja gdy jako urzadzenie wyjsciowe uzywana jest przegladarka WWW. W rozdziale tym znajduje sie rwniez omwienie mechanizmu cookie, poniewaz jest ono skladniowo podobne do obslugi elementw formularzy. Cookie moga rwniez pomc w zrealizowaniu mechanizmu utrzymywania stanu, ktry jest zwykle potrzebny w czasie dialogu z uzytkownikiem.
Konwencje nazw plikw We wszystkich przykladach oraz w mojej aktualnej pracy do oznaczania skryptw PHP ktre generuja strony HTML uzywam rozszerzenia .phtml oraz rozszerzen .php lub .php3 do plikw dolaczanych. Nie uzywam najczesciej uzywanych rozszerzen .php i .php3 do stron wyswietlajacych dane jedynie dlatego, ze uwazam ze rozszerzenie .phtml lepiej wyglada. Jest to jedyny powd. Do plikw dolaczanych uzywam innego rozszerzenia i chcemy zaznaczyc, ze jest to kod PHP. Nie uzywam typowego rozszerzenia inc. Mozesz uzywac dowolnego rozszerzenia dla skryptw PHP. Wszystkie rozszerzenia jakich uzywasz do skryptw PHP i plikw dolaczanych powinny zostac dolaczone do konfiguracji serwera WWW. Rozszerzenia te konfiguruje sie uzywajac opcji konfiguracji, ktre zostaly opisane w rozdziale 1, Kompilacja i instalowanie PHP. Na przyklad, jezeli uzywasz rozszerzen php i inc do oznaczania skryptw PHP i plikw dolaczanych, powinienes sie upewnic, ze serwer WWW zostal tak skonfigurowany, ze bedzie traktowal oba te rozszerzenia jako pliki PHP i przetwarzal je przed wyslaniem do przegladarki uzytkownika. Jezeli nie zrobisz tego, uzytkownik moze zapisac twoje skrypty. Rozwazmy nastepujacy przyklad:
<!-- Plik: securityhole.phtml --> <html> <head> <title>Przyklad: bledny plik dolaczany otwiera dziure w systemie zabezpieczen</title> </head> <body> <?php /* Plik dolaczany bogus.inc, zawiera blad ale rwniez znajduje sie w nim nazwa uzytkownika bazy danych i haslo. */ include( "bogus.inc" ); print( "Poznajmy dziure w systemie bezpieczenstwa.<br>" ); ?> </body> </html> <!-- Plik: bogus.inc --> <?php // Jest to dolaczany plik PHP demonstrujacy // potencjalna dziure w systemie zabezpieczen, // powatajaca, gdy zle skonfigurowany zostanie serwer WWW. $aDatabaseIP = "12.34.56.123"; $aDatabaseUser = "secretuser"; $aDatabasePass = "secretpassword"; /*

Zagniezdzony komentarz powoduje blad. /* wlasnie tutaj */ */ ?>

W przykladzie tym do glwnego pliku, securityhole.phtml, dolaczany jest plik bogus.inc. Dolaczany plik zawiera dane na temat polaczenia z baza danych, w tym nazwe uzytkownika i haslo. Zawiera on rwniez blad syntaktyczny. Gdy otwarty zostanie plik securityhole.phtml, wyswietlony zostanie blad: Parse error: parse error in bogus.inc on line 12. Dociekliwy uzytkownik moze sprbowac obejrzec plik bogus.inc wpisujac odpowiedni URL w pasku adresu. Jezeli serwer WWW jest skonfigurowany taj aby traktowac pliki .inc jako tekst (tak jak mj), caly tekst pliku pojawi sie w przegladarce. Jezeli serwer WWW jest tak skonfigurowany, aby traktowac pliki .inc jak kazdy inny skrypt PHP, uzytkownik zobaczy jedynie wczesniej wspomniany komunikat bledu. Podsumowujac. W trakcie tworzenia aplikacji PHP mozesz uzyc dowolnego rozszerzenia, ale aby uniknac potencjalnego zagrozenia bezpieczenstwa nalezy tak skonfigurowac serwer WWW, aby analizowal wszystkie pliki posiadajace uzywane przez ciebie rozszerzenia.

Obsluga formularzy w PHP


Do pobierania danych od uzytkownika w HTML stosuje sie formularze. W domyslnej konfiguracji PHP po przeslaniu danych formularza do skryptu PHP, konwertuje wszystkie elementy formularza na zmienne PHP. Ponizsza strona HTML zawiera prosty formularz, do ktrego nalezy wpisac nazwe uzytkownika i jego haslo. Po przeslaniu formularza do skryptu post1.phtml, zmienne $UserName i $Password beda zawieraly wartosci wpisane jako nazwe uzytkownika i haslo. Wydruk 3.1. Strona HTML i skrypt PHP ilustrujace procedure logowania sie uzytkownika.
<!-- To jest strona HTML, listing1.html --> <html> <head> <title>Wydruk 3.1 - listing1.html</title> </head> <body> <form action="post1.phtml" method="post"> Nazwa uzytkownika: <input type="text" name="Username"><br> Haslo: <input type="password" name="Password"><br> <input type="submit" name="Submit" value="Wyslij"> </form> </body> </html> <!-- To jest skrypt PHP, post1.html --> <html> <head> <title>Wydruk 3.1: post1.phtml</title> </head> <body> <?php print( "Nazwa uzytkownika: $Username<br>" ); print( "Haslo: $Password<br>" ); ?> </body> </html>

Skalarne i wielowartosciowe elementy formularza


Elementy formularzy HTML zawieraja zwykle wartosci skalarne. Zamieszczony na wydruku 1 przyklad zawiera formularz z dwoma wartosciami skalarnymi nazwa uzytkownika i haslem. Mozna rwniez tworzyc elementy formularza zawierajace wiele wartosci, na przyklad liste wielokrotnego wyboru. Aby uzyc nieskalarnych elementw formularza w PHP, nalezy dodac do nazwy nawiasy kwadratowe oznaczajace zmienna tablicowa. Formularz na wydruku 2 pokazuje takie wielowartosciowe elementy formularza. Wydruk 3.2. Formularz HTML z elementami wielowartosciowymi
<form action="displayall.phtml" method="post"> <table> <tr>

41

PHP Kompendium wiedzy

<td valign="top"> Wybierz kolory ktre lubisz: </td> <td valign="top"> <!-- Nazwy sa 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">Zlty</option> </select> </td> </tr> <tr> <td valign="top"> Wprowadz twj adres: </td> <td valign="top"> <!-- Trzy linie na dane adresowe. Uzywamy notacji tablicowej aby zaznaczyc uzycie 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="Wyslij"> </td> </tr> </table> </form>

Po przeslaniu danych formularza z wydruku 2 do skryptu PHP, kazda z tablic bedzie zawierac zero lub wiecej wartosci.

$Colors[]

$adress[]

Alternatywne metody odczytywania wartosci z formularza


PHP posiada alternatywna metode dostepu do danych przeslanych do skryptu. Predefiniowane zmienne tablicowe HTTP_GET_VARS i HTTP_POST_VARS zawieraja tablice asocjacyjne elementw przeslanych do skryptu przy pomocy metod odpowiednio GET i POST. Skrypt wyswietlajacy dane z wydruku 1 moze zostac przepisany w nastepujacy sposb:
<!-- To jest skrypt PHP, post2.html --> <html> <head> <title>Wydruk: post2.phtml</title> </head> <body> <?php error_reporting( 255 ); print( "Nazwa uzytkownika: {$HTTP_POST_VARS['Username']}<br>" ); print( "Haslo: {$HTTP_POST_VARS['Password']}<br>" ); ?> </body> </html>

W niektrych przypadkach preferowane jest uzycie zmiennych HTTP_GET_VARS lub HTTP_POST_VARS zamiast korzystania ze zmiennych globalnych. Na przyklad mozesz chciec wyswietlic w czasie uruchamiania skryptu wartosci wszystkich danych wyslanych z formularza. Jezeli bardzo przejmujesz sie wydajnoscia serwera WWW, mozna tu nieco zyskac, poniewaz PHP nie bedzie musial tworzyc zmiennych globalnych dla kazdego z elementw formularza. Mozna wiec tak skonfigurowac PHP, aby nie udostepnial tych zmiennych globalnych i tak pisac skrypty, aby korzystaly z wartosci zawartych w tablicach HTTP_GET_VARS i HTTP_POST_VARS. Wiecej na temat tej dyrektywy konfiguracji napisane zostalo na koncu ksiazki przy opisie opcji konfiguracji register_globals. Ponizsza funkcja demonstruje uzycie tablic HTTP_GET_VARS i HTTP_POST_VARS do wyswietlenia wszystkich danych przekazanych z formularza do skryptu:
function DisplayGetVars() { global $HTTP_GET_VARS; DisplayArray( $HTTP_GET_VARS ); } function DisplayPostVars() {

Rozdzial 3 Formularze i cookie

42

global $HTTP_POST_VARS; DisplayArray( $HTTP_POST_VARS ); }

Obie z tych funkcji opieraja sie o funkcje DisplayArray przedstawiona na wydruku 3.3. Jest to prosta funkcja wyswietlajaca wszystkie elementy tablicy w tablicy HTML. Obsluguje ona rekurencyjnie elementy tablicy, ktre same sa tablicami. Wydruk 3.3. Funkcja DisplayArray
function DisplayArray( $aArray ) { // Upewniamy sie, czy $aArray jest na pewno tablica if ( is_array ($aArray ) && (count( $aArray ) > 0 )) { // Rozpoczecie tabeli print ("<table border = \"1\">"); // Wyswietlenie naglwka tabeli print ( " <tr><th>Klucz</th><th>Wartosc</th></tr>"); // Wyswietlenie wszystkich par klucz/wartosc z tabeli foreach( $aArray as $aKey => $aValue ) { print( "<tr>" ); // Jezeli biezaca wartosc jest tablica // wywolujemy rekurencyjnie funkcje // w przeciwnym wypadku wyswietlamy wartosc if (!is_array( $aValue )) { // jezeli wartosc jest pusta, poinformujmy o tym if (empty( $aValue )) { print( "<td>$aKey</td><td><i>pusty</i></td>"); } else { print( "<td>$aKey</td><td><i>$aValue</i></td>"); } } else { print( "<td>$aKey(array)</td><td>"); DisplayArray( $aValue ); print ("</td>" ); } print ("</tr>"); } print ("</table>"); } else { print("<i>pusty lub nieprawidlowy</i>"); } }

Uzywajac tej funkcji mozna pisac wlasne skrypty PHP wyswietlajace wartosci wszystkich przeslanych elementw formularza. Ponizszy skrypt, displayall.phtml powoduje wyswietlenie wszystkich danych przeslanych przez HTTP GET, HTTP POST i cookie odeslane przez przegladarke (cookie zostana omwione w dalszej czesci tego rozdzialu). Wydruk 3.4. Skrypt displayall.phtml.
<html> <head> <title>Wyswietlenie wszystkich elementw formularza</title> </head> <body> <?php error_reporting( 255 ); include( "../include/gen_form_funcs.php" ); ?> <h2>Cala zawartosc HTTP_GET_VARS</h2> <?php DisplayGetVars(); ?> <br><br> <h2>Cala zawartosc HTTP_POST_VARS</h2> <?php DisplayPostVars(); ?> <br><br> <h2>Cala zawartosc HTTP_COOKIE_VARS</h2> <?php

43

PHP Kompendium wiedzy

DisplayCookieVars(); ?> <br><br> </body> </html>

Na rysunkach 3.1. i 3.2. korzystajac z formularza z wydruku 2. przedstawiono formularz wprowadzania danych i wyniki wyslania danych do skryptu displayall.phtml. Zauwazmy, ze na rysunku 3.2, tablica HTTP_POST_VARS zawiera trzy elementy: Colors, Address i Submit. Wartosci dwch pierwszych elementw sa, jak sie tego mozna bylo spodziewac, tablicami. Wartoscia elementu Submit jest napis umieszczony na przycisku. Piszac skrypt obslugujacy te wartosci nalezy pamietac, ze element Submit jest zawsze umieszczany w tablicy HTTP_POST_VARS. Rysunek 3.1. Przyklad wielowartosciowyc h elementw formularza

Rozdzial 3 Formularze i cookie

44

Rysunek 3.2. Wynik przeslania formularza wielowartoscioweg o do displayall.phtml

Uzycie formularzy do przesylania plikw


Wiekszosc nowoczesnych przegladarek posiada zdolnosc przesylania plikw z dysku komputera uzytkownika na serwer WWW. PHP posiada obsluge przesylania plikw wbudowana bezposrednio w jezyk. Jest ona dokladniej opisana w rozdziale 5 Wysylanie plikw przez formularz.

Uzycie rysunku jako przycisku wyslania danych


Jezeli projekt aplikacji WWW tak przewiduje, mozesz uzyc rysunku w miejsce przycisku HTML wysylajacego dane formularza do serwera. Dla PHP nie ma znaczenia, czy jest to przycisk czy rysunek, ale jezeli uzywasz rysunku oprcz danych do serwera zostana wyslane dodatkowo wsplrzedne x i y (wzgledem lewego grnego rogu rysunku) punktu gdzie zostal klikniety rysunek. Nazwy zmiennych przechowujacych wsplrzedne sa tworzone poprzez dodanie _x i _y do nazwy elementu reprezentujacego rysunek. Na przyklad na wydruku 5 nazwa elementu rysunku jest SubmitImg. Zmienne reprezentujace wsplrzedne beda sie nazywaly SubmitImg_x i SubmitImg_y. Mechanizm ten jest wygodny do tworzenia map obrazw po stronie serwera. Wydruk 3.5. Przyklad uzycia rysunku w formularzu
<!-- Strona HTML, imgsubmit.html --> <html> <head> <title>Uzycie rysunku zamiast przycisku</title> </head> <body> <form action="displayall.phtml" method="post"> Nazwa uzytkownika: <input type="text" name="Username"><br> Haslo: <input type="password" name="Password"><br> <input type="image" name="SubmitImg" src="submit.gif"> </form> </body> </html>

45

PHP Kompendium wiedzy

Niektre przegladarki posiadaja mechanizm pozwalajacy wykorzystac klawisz Enter zamiast klikania w przycisk na formularzu. Gdy uzyjemy rysunku zamiast przycisku, mechanizm ten nadal bedzie dzialal, ale nie zostana wtedy przeslane dane na temat wsplrzednych.

Kontrola poprawnosci danych formularza


Czesc ta jest poswiecona kontroli poprawnosci danych formularza przez mechanizmy umieszczone na serwerze a nie na komputerze klienta. Jezyki skryptowe dzialajace na kliencie, takie jak JavaScript moga byc wykorzystywane do kontroli poprawnosci elementw formularza przez wyslaniem ich do serwera. Kontrola taka jest zalecana w przypadku tworzenia wysoce interaktywnych aplikacji WWW, ale nie jest ona calkowicie pewna, poniewaz moze byc niedostepna w wielu przegladarkach i systemach operacyjnych. Dlatego dane musza byc kontrolowane na serwerze nawet, jezeli byly one juz kontrolowane na komputerze klienta. PHP pozwala na stosowanie kilku metod kontroli poprawnosci danych, wykorzystujac wyrazenia regularne, kontrole typw danych lub przeszukiwanie slownikw w bazie danych.

Kontrola danych za pomoca wyrazen regularnych


Prawdopodobnie najskuteczniejszym mechanizmem kontroli danych jest uzycie wyrazen regularnych i funkcji wyrazen regularnych w PHP. Wyrazenia te sa poteznym narzedziem, ale jezeli wczesniej nie miales z nimi doswiadczenia, sa dosc skomplikowane w uzyciu. PHP obsluguje dwa rodzaje wyrazen regularnych w stylu POSIX i Perl. Skupimy sie tutaj na wyrazeniach w stylu POSIX, ale wyrazenia w stylu Perl daja podobne mozliwosci. Nazwy funkcji wyrazen w stylu Perl sa poprzedzone przedrostkiem preg_ i sa opisane w skorowidzu na koncu tej ksiazki. Poniewaz lepiej znam wyrazenia regularne w stylu POSIX, sa one uzywane we wszystkich przytoczonych tu przykladach, ale nalezy pamietac, ze funkcje wyrazen w stylu Perl sa szybsze i maja wieksze mozliwosci. Funkcje wyrazen regularnych w stylu POSIX to: ereg(), ereg_replace(), eregi(), eregi_replace() oraz split(). Do kontroli poprawnosci uzywa sie funkcji ereg() i eregi(). Oglna skladnia tych funkcji jest nastepujaca:
int ereg( string wzorzec, string ciag [, array dopasowanie] ) int eregi( string wzorzec, string ciag [, array dopasowanie] )

Obie funkcje wymagaja wzorca wyrazenia regularnego, ciagu do przeszukania oraz opcjonalnej tablicy, ktra bedzie zawierac dopasowania wzorca odnalezione w przeszukiwanym ciagu. Kazda funkcja zwraca true, jezeli wzorzec zostal odnaleziony w ciagu. Funkcja eregi() jest identyczna z ereg() poza tym, ze przy przeszukiwaniu ignoruje ona wielkosc liter.
Unikanie kontroli poprawnosci Chociaz kontrola poprawnosci jest wazna, jezeli nie musisz czegos kontrolowac, to nie rb tego. Zamiast tego mozna zastosowac takie mechanizmy wprowadzania danych, ktre zmniejszaja szanse pomylki uzytkownika. Na przyklad zastosowanie listy rozwijalnej z miesiacami jest mniej pracochlonne niz kontrola poprawnosci wpisanych nazw. Zamiast wszedzie korzystac ze zwyklych pl tekstowych nalezy znalezc miejsca, gdzie mozna zastosowac liste, pole wyboru lub przyciski opcji.

Ponizszy przyklad pokazuje zastosowanie wyrazen regularnych do kontroli poprawnosci amerykanskiego kodu pocztowego oraz dat w formacie ISO (YYYY-MM-DD). Zauwaz, ze w przykladach tych jest sprawdzany jedynie format a nie wartosci. Wydruk 3.6. Kontrola poprawnosci kodu pocztowego i daty ISO
<html> <head> <title>Kontrola poprawnosci amerykanskiego kodu pocztowego i daty ISO</title> </head> <body> <?php $aCode1 = "83440"; $aCode2 = "83440-1607"; $aCode3 = "834"; $aCode4 = "M6K 3E3"; $aCodeFormat = "[0-9]{5}(-[0-9]{4})?"; if ( ereg( $aCodeFormat, $aCode1 ) == True )

Rozdzial 3 Formularze i cookie

46

print( else print( if ( ereg( print( else print( if ( ereg( print( else print( if ( ereg( print( else print(

"'$aCode1' jest poprawnym kodem pocztowym<br>" ); "'$aCode1' nie jest poprawnym kodem pocztowym<br>" ); $aCodeFormat, $aCode2 ) == True ) "'$aCode2' jest poprawnym kodem pocztowym<br>" ); "'$aCode2' nie jest poprawnym kodem pocztowym<br>" ); $aCodeFormat, $aCode3 ) == True ) "'$aCode3' jest poprawnym kodem pocztowym<br>" ); "'$aCode3' nie jest poprawnym kodem pocztowym<br>" ); $aCodeFormat, $aCode4 ) == True ) "'$aCode4' jest poprawnym kodem pocztowym<br>" ); "'$aCode4' nie jest poprawnym kodem pocztowym<br>" );

$aDate1 = "2000-06-29"; $aDate2 = "2000-7-4"; $aDate3 = "June 29, 2000"; $aDate4 = "0000-99-99"; $aDateFormat = "[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}"; if ( ereg( $aDateFormat, $aDate1 ) == True ) print( "'$aDate1' jest poprawnym formatem daty ISO<br>" ); else print( "'$aDate1' nie jest poprawnym formatem daty ISO<br>" if ( ereg( $aDateFormat, $aDate2 ) == True ) print( "'$aDate2' jest poprawnym formatem daty ISO<br>" ); else print( "'$aDate2' nie jest poprawnym formatem daty ISO<br>" if ( ereg( $aDateFormat, $aDate3 ) == True ) print( "'$aDate3' jest poprawnym formatem daty ISO<br>" ); else print( "'$aDate3' nie jest poprawnym formatem daty ISO<br>" if ( ereg( $aDateFormat, $aDate4 ) == True ) print( "'$aDate4' jest poprawnym formatem daty ISO<br>" ); else print( "'$aDate4' nie jest poprawnym formatem daty ISO<br>" ?> </body> </html>

);

);

);

);

Wyniki dzialania skryptu z wydruku 6 sa nastepujace:


'83440' jest poprawnym kodem pocztowym '83440-1607' jest poprawnym kodem pocztowym '834' nie jest poprawnym kodem pocztowym 'M6K 3E3' nie jest poprawnym kodem pocztowym '2000-06-29' jest poprawnym formatem daty ISO '2000-7-4' jest poprawnym formatem daty ISO 'June 29, 2000' nie jest poprawnym formatem daty ISO '0000-99-99' jest poprawnym formatem daty ISO

Programisci programujacy wczesniej w jezyku Perl i ci, ktrzy uzywali juz wyrazen regularnych uwazaja taka kontrole poprawnosci za latwa i wydajna. Ci zas, ktrzy nie znaja wyrazen regularnych moga wybrac inne metody kontroli poprawnosci, opisane w nastepnych dwch czesciach.

Kontrola poprawnosci za pomoca sprawdzania typw


W niektrych przypadkach wystarczy sprawdzic typ wprowadzonej danej i nie przejmowac sie wprowadzona wartoscia. Metoda ta jest odpowiednia do kontrolo prostych typw, takich jak liczby i ciagi, ale rwniez pozwala na nieco wiecej. Jezeli zostanie uzyta w polaczeniu z dodatkowym kodem kontroli poprawnosci, bedzie wystarczajaca dla wielu aplikacji. Ponizszy przyklad sprawdza typy zmiennych, aby upewnic sie, ze zostaly wprowadzone tylko liczby.
<html> <head> <title>Kontrola liczb przy uzyciu kontroli typw</title> </head> <body> <?php $aValue1 = "123"; $aValue2 = "123.446"; $aValue3 = "1.56e18"; $aValue4 = "3 male swinki"; if ( is_numeric( $aValue1 ) == True ) print( "'$aValue1' jest liczba<br>" ); else print( "'$aValue1' nie jest liczba<br>" );

47

PHP Kompendium wiedzy

if ( is_numeric( $aValue2 ) == True ) print( "'$aValue2' jest liczba<br>" ); else print( "'$aValue2' nie jest liczba<br>" ); if ( is_numeric( $aValue3 ) == True ) print( "'$aValue3' jest liczba<br>" ); else print( "'$aValue3' nie jest liczba<br>" ); if ( is_numeric( $aValue4 ) == True ) print( "'$aValue4' jest liczba<br>" ); else print( "'$aValue4' nie jest liczba<br>" ); ?> </body> </html>

Skrypt przedstawiony na wydruku 7 interpretuje pierwsze trzy wartosci jako liczby natomiast ostatnia nie. Wiecej na temat funkcji kontroli typw znajduje sie przy opisie funkcji is_xxx() w czesci Funkcje zmiennych w skorowidzu funkcji na koncu ksiazki.

Klasa Validator
Jedna z najpiekniejszych cech oprogramowania typu open-source jest dostepnosc swietnych narzedzi uzupelniajacych podstawowy produkt. Dodatkowe oprogramowanie dla PHP mozna pozyskac z wielu zrdel. Witryna Webmasters Net (http://www.thewebmasters.net) zawiera nieco swietnych klas i modulw z kodem zrdlowym. Do kontroli poprawnosci przeznaczona jest klasa Validator zawierajaca wiele funkcji upraszczajacych wiele zadan i oszczedzajacych czas. Przykladowymi funkcjami kontroli poprawnosci sa is_email(), is_url() i is_phone() przeznaczone do sprawdzania adresw e-mail, URL i numerw telefonw. Wiecej informacji na temat tej klasy i innych dostarczanych przez Webmasters Net znajduje sie w czesci PHP Tools and Extras ich witryny. Wydruk 3.8. Kontrola poprawnosci danych przy uzyciu klasy Validator
<?php error_reporting( 0 ); include( "../include/class.Validator.php3" ); $aValidator = new Validator; $aPhoneNum1 = "(208) 359-1540"; $aPhoneNum2 = "+1 208-359-1540"; $aPhoneNum3 = "support@intechra.net"; if ( $aValidator->is_phone( $aPhoneNum1 ) == True ) print( "'$aPhoneNum1' jest prawidlowym numerem telefonu<br>" ); else print( "'$aPhoneNum1' nie jest prawidlowym numerem telefonu<br>" ); if ( $aValidator->is_phone( $aPhoneNum2 ) == True ) print( "'$aPhoneNum2' jest prawidlowym numerem telefonu<br>" ); else print( "'$aPhoneNum2' nie jest prawidlowym numerem telefonu<br>" ); if ( $aValidator->is_phone( $aPhoneNum3 ) == True ) print( "'$aPhoneNum3' jest prawidlowym numerem telefonu<br>" ); else print( "'$aPhoneNum3' nie jest prawidlowym numerem telefonu<br>" ); /* Funkcja is_email kontroluje nie tylko poprawnosc formatu adresu email ale rwniez sprawdza, czy istnieje w Internecie podany host Oczywiscie wymaga to podlaczenia z Internetem. W chwili pisania tego przykladu host 'invalidhost.com' nie byl zarejestrowany. */ $aEmail1 = "blake@intechra.net"; $aEmail2 = "john"; $aEmail3 = "nobody@invalidhost.com"; if ( $aValidator->is_email( $aEmail1 ) == True ) print( "'$aEmail1' jest prawidlowym adresem email<br>" ); else print( "'$aEmail1' nie jest prawidlowym adresem email<br>" ); if ( $aValidator->is_email( $aEmail2 ) == True ) print( "'$aEmail2' jest prawidlowym adresem email<br>" ); else print( "'$aEmail2' nie jest prawidlowym adresem email<br>" ); if ( $aValidator->is_email( $aEmail3 ) == True ) print( "'$aEmail3' jest prawidlowym adresem email<br>" ); else print( "'$aEmail3' nie jest prawidlowym adresem email<br>" ); ?>

Rozdzial 3 Formularze i cookie

48

Klasa Validator jest poteznym zestawem funkcji przyspieszajacych tworzenie oprogramowania, ale tak jak w przypadku wszystkich narzedzi zewnetrznych nalezy sprawdzic, czy spelnia twoje wymagania.

Cookie
Z powodu trwajacej debaty na temat uzycia cookie, wiekszosc programistw WWW i uzytkownikw jest zaznajomiona z koncepcja cookie. Cookie sa plikami tekstowymi zapisanymi na komputerze klienta i sa one ze swojej natury niewinne. Jednak wielu uzytkownikw nie przyjmuje cookie wyslanych do przegladarek z powodu plotek na temat ich wykorzystania. Jezeli twoja aplikacja opiera swoje dzialanie na cookie, niektrzy uzytkownicy nie beda mogli jej uzywac. Jednak jezeli korzystasz z cookie, ale nie wymagasz ich do prawidlowej pracy, twoja aplikacja bedzie dzialala z wiekszoscia przegladarek. PHP posiada tylko jedna funkcje przeznaczona do tworzenia cookie, setcookie(). Poniewaz cookie sa wysylane jako czesc naglwka HTTP, funkcja setcookie() musi byc wywolana przed wyslaniem jakichkolwiek danych do przegladarki lub nalezy zastosowac buforowanie wyjscia w celu opznienia wysylania danych do przegladarki do chwili zdefiniowania wszystkich cookie. To samo ograniczenie obowiazuje rwniez dla funkcji header(). Dowolne cookie odeslane do aplikacji przez przegladarke jest automatycznie konwertowane na zmienna PHP tak samo, jak dzieje sie to w przypadku metod GET i POST. Cookie moga przenosic wartosci skalarne jak rwniez tablice wartosci. Funkcja setcookie() jest zdefiniowana w sposb nastepujacy:
int setcookie( string nazwa, string wartosc, int czas, string sciezka, string domena, int bezpieczny )

Wszystkie argumenty funkcji poza nazwa sa opcjonalne. Jezeli funkcja jest wywolana tylko z nazwa, cookie o podanej nazwie jest usuwane. Dowolny z ciagw moze zostac opuszczony podajac pusty ciag (""). Dowolna wartosc numeryczna moze zostac opuszczona podajac wartosc zero. Argument czas jest standardowym czasem z systemu Unix w postaci liczby, ktra mozna uzyskac jako wynik funkcji mktime() lub time(). Parametr bezpieczny wskazuje, ze cookie moze byc przesylane jedynie przez polaczenie bezpieczne (HTTPS). Nalezy pamietac o nastepujacych pulapkach i czestych bledach uzycia cookie: Ustawione cookie nie beda widoczne w skrypcie do czasu jego powtrnego zaladowania. Przegladarki rznie obsluguja cookie. Sprawdz aplikacje na mozliwie duzej ilosci przegladarek. Kazda przegladarka przechowuje cookie niezaleznie. Oznacza to, ze jezeli uzytkownik obejrzy witryne przy uzyciu jednej przegladarki i zostanie ustawione cookie, to cookie nie bedzie dostepne, jezeli uzytkownik ponownie obejrzy witryne za pomoca innej przegladarki. Wiecej oglnych informacji na temat cookie mozna znalezc w specyfikacji cookie firmy Netscape, ktra jest dostepna pod adresem http://www.netscape.com/newsref/std/cookie_spec.html. Ponizsze dwa przyklady pokazuja uzycie funkcji setcookie(). Wydruk 3.9 pokazuje jak ustawiac i wyswietlac cookie. Na wydruku 3.10 pokazane jest jak uzywac buforowania wyjscia w polaczeniu z funkcja setcookie(). Wydruk 3.9. Uzycie cookie
<?php // Sprawdzenie czy istnieje zmienna cookie $LastTime if ( !empty( $LastTime ) ) { $aMessage = "Ostatnia wizyta miala miejsce "; $aMessage .= date( "d F Y", $LastTime ); $aMessage .= " o "; $aMessage .= date( "h:i:s a", $LastTime ); } else { $aMessage = "Nie byles tu przez ostatnie "; $aMessage .= "dwa tygodnie."; } // Ustawienie cookie waznego przez dwa tygodnie $aTwoWeeks = time() + ( 60 * 60 * 24 * 14 ); setcookie( "LastTime", time(), $aTwoWeeks ); // sprawdzenie istnienia niezwykle waznej tablicy z cookie $aValMessage = ""; if ( !empty( $CookieArray ) ) { $aValMessage = "Wartosci: " . $CookieArray[0]; $aValMessage .= ", " . $CookieArray[1];

49

PHP Kompendium wiedzy

$aStartValue = $CookieArray[1] + 1; } else { $aValMessage = "Wartosci nie sa dostepne!"; $aStartValue = 0; } // usuniecie niezwykle istotnej tablicy wartosci setcookie( "CookieArray[0]" ); setcookie( "CookieArray[1]" ); // dodanie niezwykle istotnej tablicy wartosci setcookie( "CookieArray[0]", $aStartValue, $aTwoWeeks ); setcookie( "CookieArray[1]", $aStartValue + 1, $aTwoWeeks ); ?> <html> <head> <title>Uzycie cookie</title> </head> <body> <?php print( $aMessage . "<br><br>" . $aValMessage ); ?> </body> </html>

Wydruk 3.10. Uzycie setcookie() razem z buforowaniem wyjscia


<?php /* Uruchomienie buforowania wyjscia. Jezeli funkcja ob_start() jest zakomentowana, skrypt spowoduje blad. */ ob_start(); ?> <html> <head> <title>Uzycie setcookie() wraz z buforowaniem wyjscia</title> </head> <body> <?php setcookie( "anyname", "anyvalue", time() + 60 ); ?> Dziala swietnie. </body> </html> <?php ob_end_flush(); ?>

Ostatnia uwaga na temat cookie W poprzedniej wersji PHP jezeli chciales ustawic wiele cookie za pomoca jednego skryptu, musiales wywolywac setcookie() w odwrotnej kolejnosci do tej, w jakiej chciales obslugiwac cookie. Na przyklad, jezeli chciales usunac cookie a nastepnie ustawic nowe o tej samej nazwie, nalezalo najpierw wywolac setcookie(), aby ustawic nowa wartosc a nastepnie usunac poprzednia wartosc. W PHP4 zostalo to usuniete. Nalezy wywolywac setcookie() w takiej kolejnosci jak sie spodziewasz, ze beda przetwarzane przez przegladarke. Proces ten jest pokazany na wydruku 3.9.

Mimo, ze debata na temat tego, czy nalezy uzywac cookie bedzie nadal trwala, ich tworzenie w PHP jest latwe i proste. Dalsze rozwazania na temat cookie beda kontynuowane w rozdziale 7 Sesje i stan aplikacji.

Wazne zagadnienia programowania dla WWW


Czesc ta zawiera niektre tematy, jakie musza brac pod uwage programisci przechodzacy z pisania zwyklych aplikacji na aplikacje oparte o WWW. Problemy te powstaja zwykle w czasie przetwarzania i wykorzystywania danych przeslanych z formularza HTML.

Obsluga nieprawidlowych danych


Pierwszym problemem jest sposb obslugi nieprawidlowych danych. W tradycyjnych aplikacjach dane wprowadzone przez uzytkownika sa czesto kontrolowane natychmiast po ich wprowadzeniu. Pozwala to natychmiast informowac o nieprawidlowych danych. W aplikacjach WWW nie ma niezawodnego mechanizmu kontroli danych po wyjsciu z poszczeglnych pl, wiec cala kontrola poprawnosci jest przeprowadzana na serwerze. Oznacza to, ze jezeli istnieje blad w danych, uzytkownik nie bedzie o nim wiedzial az do chwili Rozdzial 3 Formularze i cookie 50

przeslania danych formularza. Dlatego w trakcie tworzenia aplikacji musisz sie zdecydowac, w jaki sposb reagowac na bledy. Istnieje kilka sposobw reagowania na bledy, przytoczymy tutaj dwa z nich. Pierwsza metoda jest wypisywanie bledw i nakazanie uzytkownikowi, aby wrcil do poprzedniej strony i poprawil dane. Wedlug mnie jest to najmniej pozadany sposb reakcji na bledy, ale jest najprostszy do zrealizowania. Jezeli do formularza wpisywane jest bardzo malo danych (jedno lub dwa pola) metoda ta bedzie do zaakceptowania. Jezeli jednak tworzysz duzy formularz nie nalezy uzywac tej metody, poniewaz moze ona wymagac ponownego wprowadzenia wszystkich danych. Niektre przegladarki nie utrzymuja wartosci formularza po uzyciu przycisku Wstecz. Druga metoda obslugi nieprawidlowych danych jest ponowne pokazanie strony formularza z zainicjowanymi wszystkimi polami i zaznaczonymi nieprawidlowymi pozycjami. Mozesz utworzyc taki formularz przesylajac dane z formularza do tego samego skryptu. Metoda taka wymaga bardziej zaawansowanego projektowania, ale skutkuje powstaniem solidniejszej i bardziej uzytecznej aplikacji, poniewaz ten sam skrypt moze byc uzyty do pobierania nowych danych, zmiany danych istniejacych i kontroli poprawnosci tych danych. Na wydruku 3.11 pokazane jest w jaki sposb mozna uzyc jednego skryptu do zbierania i kontroli poprawnosci danych na prostym formularzu uzywanym do wpisywania adresw e-mail i numerw telefonw. Wydruk 3.11. Inteligentna obsluga nieprawidlowych danych
<?php error_reporting( 0 ); // na poczatku przestawiamy skrypt na zbieranie nowych danych. $aCurPhoneVal = ""; $aCurEmailVal = ""; $aPhoneTextCol = "black"; $aEmailTextCol = "black"; if ( !empty( $Submit ) ) { /* Jezeli zmienna $Submit jest zainicjowana jestesmy tutaj po przeslaniu danych do skryptu. Prbujemy sprawdzic wartosci zmiennych formularza. */ include( "../include/class.Validator.php3" ); $aValidator = new Validator; $aValidPhone = $aValidator->is_phone( $Phone ); $aValidEmail = $aValidator->is_email( $Email ); if ( $aValidPhone && $aValidEmail ) { // Dane sa prawidlowe, przechodzimy do odpowiedniej strony header( "Location:thanks.html\n" ); } else { // Dane nieprawidlowe, wyrzniamy je $aCurPhoneVal = $Phone; $aCurEmailVal = $Email; if ( $aValidPhone == False ) $aPhoneTextCol = "red"; if ( $aValidEmail == False ) $aEmailTextCol = "red"; } } ?> <html> <head> <title>Inteligentna obsluga nieprawidlowych danych</title> </head> <body> <?php if ( empty( $Submit ) ) { ?> Prosze wprowadzic numer telefonu i adres email. <br> <?php } else { // if ?> We wprowadzonych danych wystapily bledy. Sprawdz dane oznaczone kolorem czerwonym. <?php } // end if ?> <form action="handle_errors.phtml" method="post"> <font color="<?php print( $aPhoneTextCol );?>"> Numer telefonu:</font> <input type="text" name="Phone"

51

PHP Kompendium wiedzy

value="<?php echo $aCurPhoneVal;?>"> <br> <font color="<?php print( $aEmailTextCol );?>"> Adres e-mail:</font> <input type="text" name="Email" value="<?php echo $aCurEmailVal;?>"> <br> <input type="submit" name="Submit" value="Wyslij"> </form> </body> </html>

W skrypcie na wydruku 11, gdy strona jest otwierana bezposrednio, zmienna $Submit jest pusta, wiec formularz jest wyswietlany z pustymi polami. Gdy uzytkownik kliknie przycisk Wyslij, strona jest ladowana po raz drugi, ale tym razem zmienna $Submit nie jest pusta, wiec sprawdzana jest poprawnosc danych. Jezeli oba pola maja poprawne dane, wywolywana jest funkcje header(), ktra powoduje przekierowanie przegladarki do nowej strony zawierajacej podziekowanie. Jezeli ktres pole zawiera nieprawidlowa wartosc, formularz wywolywany jest ponownie, ale tym razem pola maja wartosci wprowadzone poprzednio przez uzytkownika. Dodatkowo, aby zaznaczyc wystapienie bledu, nieprawidlowe dane sa wyswietlane kolorem czerwonym. Metoda ta pozwala na szybka identyfikacje przez uzytkownika danych, ktre wymagaja poprawienia i nie wymaga ponownego wprowadzenia calej zawartosci formularza. Jezeli tworzysz aplikacje WWW, ktra wymaga od uzytkownika wprowadzania danych nalezy rozwazyc uzycie podobnej metody do obslugi blednych danych. Jezeli twoja aplikacja bedzie niewygodna lub wymagac bedzie ponownego wprowadzania danych, na pewno nie bedzie lubiana. Przedstawione metody nie sa jedynymi stosowanymi do obslugi blednych danych, ale ilustruja one podstawy tworzenia aplikacji WWW. Wybr metody obslugi bledw moze byc kluczowa decyzja przy projektowaniu aplikacji.

Obsluga i formatowanie wyswietlanych danych


W zwyklej aplikacji wyswietlanie danych wprowadzonych przez uzytkownika nie wymaga zwykle formatowania lub przetwarzania. Czasami formatowane sa liczby, aby wyswietlac wartosci walutowe lub dodac separatory tysiecy, ale zwykle nie ma zbyt duzo klopotu przy wyswietlaniu danych wprowadzonych przez uzytkownika. W przypadku programowania dla WWW wyswietlanie danych wprowadzonych do formularza w postaci strony WWW jest sprawa krytyczna. Dzieje sie tak, poniewaz przegladarka interpretuje caly tekst otrzymany z serwera WWW. Jezeli dostarczysz uzytkownikom formularz a nastepnie bedziesz wyswietlal wpisane dane, niektrzy uzytkownicy beda dodawac znaczniki HTML, aby sprawdzic co sie stanie. Pamietajac o tym pomysl o formularzu, w ktrym uzytkownicy beda mogli wpisywac swoje uwagi. Zalzmy, ze stworzysz formularz w ktrym zapisywane beda: nazwa uzytkownika, adres e-mail oraz tresc uwagi. Po wprowadzeniu tekstu wyswietlasz komunikat w celu weryfikacji a nastepnie przetwarzasz ten komunikat. Pomyslowi lub zlosliwi uzytkownicy moga prbowac przetestowac twj serwer WWW dodajac znaczniki HTML lub kod JavaScript w tresci komunikatu. Zwykle nie jest to niebezpieczne, ale na pewno skutkuje rznymi efektami ubocznymi. Aby uniknac tego problemu zawsze nalezy przetwarzac dane wprowadzone do formularza przed ich wyswietleniem. PHP posiada kilka funkcji pomagajacych w tym zadaniu. Sa to funkcje strip_tags() i htmlentities(). Funkcja strip_tags() usuwa wszystkie znaczniki z ciagu oprcz tych, ktre zostaly podane w dodatkowym opcjonalnym parametrze. Funkcja htmlentities() konwertuje specjalne znaki HTML na odpowiadajace im symbole HTML. Na przyklad znaki < i > sa zastepowane przez &lt; i &gt;. Formularz i skrypt na wydruku 3.12 pokazuje obrbke danych do ponownego wyswietlenia. Wydruk 3.12. Obrbka danych do wyswietlenia.
<html> <head> <title>Pobieranie danych do wyswietlenia</title> </head> <body> <form action="safedisplay.phtml" method="post"> Wprowadz tekst:<br> <textarea cols="40" rows="6" name="TheText"></textarea> <br><br> Wybierz metode filtrowania: <select name="FilterType" size="1"> <option value="0">brak</option>

Rozdzial 3 Formularze i cookie

52

<option value="1">strip_tags()</option> <option value="2">htmlentities()</option> </select> <br><br> <input type="submit" name="Submit" value="Wyslij"> </form> </body> </html> <!-- Skrypt safedisplay2.phtml --> <?php error_reporting( 255 ); switch ( $FilterType ) { case 0 : // brak $aDisplayText = $TheText; break; case 1 : // strip_tags $aDisplayText = strip_tags( $TheText ); break; case 2 : // htmlentities $aDisplayText = htmlentities( $TheText ); break; } ?> <html> <head> <title>Bezpieczne wyswietlenie danych uzytkownika</title> </head> <body> <?php print( $aDisplayText ); ?> </body> </html>

Rysunki 3.3. do 3.6. pokazuja formularz wejsciowy i wyniki dzialania skryptu. Rysunek 3.3. zawiera formularz wprowadzania danych. Rysunek 3.4. pokazuje co sie dzieje, jezeli nie ma filtrowania. Rysunki 3.5. i 3.6. pokazuja wyniki filtrowania danych z formularza za pomoca funkcji odpowiednio strip_tags() i htmlentities(). Rysunek 3.3. Formularz wprowadzania danych

53

PHP Kompendium wiedzy

Rysunek 3.4. Wyswietlanie bez filtrowania

Rysunek 3.5. Wyswietlanie ze strip_tags()

Rozdzial 3 Formularze i cookie

54

Rysunek 3.6. Wyswietlanie z htmlentities()

Jezeli dokladnie przyjrzysz sie tym rysunkom zauwazysz, ze widac niespodziewane wyniki po wyswietleniu danych. Na przyklad pojedynczy apostrof jest wyswietlany na stronie jako sekwencja \'. Rwniez znaki konca linii wprowadzone w polu tekstowym nie sa uwzgledniane w wyswietlanym tekscie. Pierwsze z zaklcen jest powodowane przez dyrektywe konfiguracji --enable-magic-quotes oraz opcje pliku php.ini magic_quotes_gpc, magic_quotes_runtime i magic_quotes_sybase. Jezeli jest ona uaktywniona, wszystkie apostrofy, cudzyslowy, NUL1 i znaki backslash pochodzace z zewnetrznych zrdel, na przyklad formularzy i bazy danych, sa automatycznie poprzedzane ukosnikiem. Jest to szczeglnie przydatne, jezeli dane te beda zapisywane w bazie danych, poniewaz nie bedziesz musial recznie oznaczac tych znakw w ciagu SQL. Aby wyswietlic taki ciag, nalezy wywolac funkcje strip_slashes(), ktra usuwa te dodatkowe znaki. Jezeli chodzi o problem ze znakami nowej linii, nalezy pamietac, ze HTML nie interpretuje znaku CR ani LF jako znaku podzialu wiersza, chyba, ze wystapi on w bloku <pre></pre>. PHP posiada funkcje nl2br(), ktra konwertuje znaki nowej linii na znaczniki <br>. Na wydruku 13 znajduje sie ten sam formularz i skrypt co na wydruku 12, ale z dodatkowymi opcjami ktre powoduja wywolanie funkcji strip_slashes() i nl2br(). Wydruk 3.13. Ulepszona obrbka danych do wyswietlenia
<html> <head> <title>Pobieranie danych do wyswietlenia</title> </head> <body> <form action="safedisplay2.phtml" method="post"> Wprowadz tekst:<br> <textarea cols="40" rows="6" name="TheText"></textarea> <br><br> Wybierz metode 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="Wyslij"> </form> </body> </html> <!-- Skrypt safedisplay2.phtml --> <?php
1

Znak o kodzie zero (przyp. tlum.)

55

PHP Kompendium wiedzy

error_reporting( 0 ); switch ( $FilterType ) { case 0 : // brak $aDisplayText = $TheText; break; case 1 : // strip_tags $aDisplayText = strip_tags( $TheText ); break; case 2 : // htmlentities $aDisplayText = htmlentities( $TheText ); break; } if ( $DoSS == "on" ) $aDisplayText = stripslashes( $aDisplayText ); if ( $DoNB == "on" ) $aDisplayText = nl2br( $aDisplayText ); ?> <html> <head> <title>Bezpieczne wyswietlenie danych uzytkownika</title> </head> <body> <?php print( $aDisplayText ); ?> </body> </html>

Rysunek 3.7. Formularz wprowadzania danych

Rozdzial 3 Formularze i cookie

56

Rysunek 3.8. Wyswietlanie przefiltrowane przez strip_tags(), strip_slashes() i nl2br()

Po wprowadzeniu zmian pokazanych na wydruku 3.13, formularz wprowadzania danych i postac danych wynikowych jest taka, jak widac na rysunku 3.7. i 3.8. Jezeli wczesniej miales doswiadczenie jedynie ze zwyklymi aplikacjami, musisz pamietac o tych pulapkach stosowania przegladarki jako warstwy prezentacji aplikacji. Oprcz pamietania o wspomnianych problemach nalezy rwniez zwrcic uwage, ze kazda przegladarka dziala nieco inaczej. Szczeglowe omwienie tych problemw znajduje sie w rozdziale 9 Niezaleznosc od przegladarki.

Podsumowanie
Rozdzial ten zawiera opis podstaw przetwarzania formularzy przy uzyciu PHP. Poniewaz PHP zostal zaprojektowany jako jezyk programowania dla WWW, upraszcza on znacznie proces interakcji z formularzami HTML. Wazniejsze od prostego pobierania danych od uzytkownikw jest prawidlowa obsluga tych danych i zabezpieczanie serwera i uzytkownikw przed nieprawidlowymi lub niebezpiecznymi danymi. W rozdziale tym omwiono niektre narzedzia umozliwiajace obsluzyc nieprawidlowe dane i zabezpieczyc przed szkodliwymi danymi. W rozdziale tym omwiono rwniez proces zapamietywania i odczytywanie cookie na komputerze klienta. Wszystkie te tematy razem stanowia podstawe do tworzenia interaktywnych aplikacji WWW.

57

PHP Kompendium wiedzy

Rozdzial 4. Operacje na plikach


Wstep
Obsluga plikw jest zawarta we wszystkich nowoczesnych jezykach programowania. Zdolnosc do tworzenia, czytania, zapisu i innych operacji na plikach lub innych obiektach systemu plikw jest niezbedna do zrealizowania obslugi sesji i serializacji. Do obslugi plikw i innych obiektw systemu plikw PHP posiada funkcje podobne do tych spotykanych w jezyku C. Tak jak C, w funkcjach sluzacych do odczytu i zapisu, PHP uzywa uchwytw plikw oraz pozwala na tworzenie uchwytw (pozwalajacych na operacje innymi typami strumieni danych, takimi jak gniazda i potoki). Zdolnosc ta powoduje, ze rwnie latwo mozna zapisac dane do pliku jak rwniez wyslac je poprzez potok do innego programu.

Odczyt i zapis plikw


Jedna z glwnych rznic przy pisaniu aplikacji opartych o siec WWW w stosunku do zwyklych aplikacji, jest sposb utrzymywania stanu aplikacji. W przypadku zwyklego programu, uzytkownik uruchamia go, wykonuje kilka komend i konczy dzialanie programu. W czasie pracy programu stan aplikacji jest utrzymywany w pamieci. W aplikacjach opartych o siec WWW stan musi byc utrzymywany przez serwer WWW, poniewaz klientem jest zwykle prosta przegladarka WWW. Szczeglowe przedstawienie zarzadzania stanem aplikacji mozna znalezc w rozdziale 7 Sesje i stan aplikacji. W chwili obecnej wystarczy wiedziec, ze do utrzymywania stanu aplikacji i tworzenia innych mechanizmw przechowywania danych mozna uzyc plikw. Wazne jest, aby uzywajac plikw, pamietac o zagadnieniach bezpieczenstwa. Poniewaz aplikacja bedzie dzialac w kontekscie serwera WWW, pliki beda mialy uprawnienia uzytkownika przy pomocy ktrego uruchamiany jest serwer WWW. W przypadku Apache domyslnie jest to uzytkownik nobody, ktrego uprawnienia ograniczaja dostep przez aplikacje do obiektw systemu plikw. Nalezy uwazac, aby korzystajac z plikw nie naruszyc systemu bezpieczenstwa serwera WWW. W wiekszosci przypadkw uzycie bazy danych zamiast plikw jest o wiele bardziej bezpieczne i praktyczne. Oczywiscie istnieje wiele sytuacji gdy narzut czasowy wprowadzany przez baze danych lub wymagania aplikacji powoduja, ze pliki sa jedynym sensownym rozwiazaniem. Na wydruku 4.1 pokazane zostalo w jaki sposb mozna zrealizowac liczniki dostepu do stron witryny. Do tego celu wykorzystane zostaly podstawowe operacje na plikach, otwarcie, odczyt, zapis i zamkniecie prostego pliku sladu. W przykladzie tym nie zostaly wykorzystane wszystkie dostepne w PHP funkcje operujace na plikach. Bardziej szczeglowy opis wszystkich funkcji znajduja sie w skorowidzu funkcji na koncu ksiazki. Wydruk 4.1. Uzycie plikw do zliczania odwolan do stron witryny
<?php /* Plik ten moze byc dolaczany do dowolnego skryptu PHP. Powoduje to automatyczne zliczanie odwolan do strony. UZYCIE: Wystarczy dolaczyc ten plik. Tworzy on zmienna globalna $aPageAccessCount, ktra zawiera ilosc odwolan do skryptu ktry dolacza ten plik. */ error_reporting( 0 ); $aLogFilePath = "/www/auto_logs/access.log"; $aCountArray = array(); // Sprawdzenie czy plik istnieje if ( is_file( $aLogFilePath ) == True ) { // Otwarcie i odczytanie pliku. Format pliku to oddzielone tabulatorami // pary opisujace kolejne skrypty: // sciezka-do-skryptu licznik $aFile = fopen( $aLogFilePath, "r" );

while( !feof( $aFile ) ) { $aLine = fgets( $aFile, 1024 ); $aTempArray = explode( "\t", $aLine ); if ( count( $aTempArray ) == 2 ) { $aCountArray[$aTempArray[0]] = $aTempArray[1]; } } fclose( $aFile ); } // Ustawienie globalnego licznika odwolan do strony // i uaktualnienie tablicy temp $aPageAccessCount = $aCountArray[$PATH_TRANSLATED] + 1; $aCountArray[$PATH_TRANSLATED] = $aPageAccessCount; // Zapis calej tablicy do pliku $aFile = fopen( $aLogFilePath, "w" ); foreach ( $aCountArray as $aKey => $aValue ) { fputs( $aFile, "$aKey\t$aValue\n" ); } fclose( $aFile ); ?>

Na wydruku 4.1 pokazujemy uzycie jednego pliku do przechowywania licznikw odwolan do dowolnej liczby stron witryny. Nie jest to efektywny sposb, ale pokazuje idee takiego licznika. W skrypcie tym sprawdzamy za pomoca funkcji is_file() czy istnieje plik sladu. Jezeli plik ten istnieje, jego kolejne linie sa odczytywane i analizowane. Kazda linia zawiera pelna sciezke dostepu do skryptu, znak tabulacji i wartosc licznika. Linia taka jest dzielona przy pomocy funkcji explode() na nazwe skryptu i wartosc licznika a nastepnie wartosci te sa zapisywane w tablicy asocjacyjnej. Jezeli chcesz, mozesz uzyc tej tablicy do wyswietlenia licznikw dla wszystkich stron witryny a nie tylko biezacej strony. Po wypelnieniu tablicy uaktualniany jest licznik odwolan do biezacej strony (rozpoznawanej przy uzyciu zmiennej globalnej PHP $PATH_TRANSLATED) i wartosc ta jest przypisywana do zmiennej $aPageAccessCount. Na koniec cala tablica jest zapisywana do pliku sladu. Na wydruku 4.2 pokazane jest strona demonstrujaca jak latwo mozna uzyc tego licznika. Jezeli szukasz takiego mechanizmu do twojej witryny, nalezy pamietac, ze jest to bardzo nieefektywne rozwiazanie. Bardziej efektywne jest odczytywanie i zapis tylko jednej wartosci a nie calego pliku. Wydruk 4.2. Uzycie skryptu z wydruku 4.1
<?php include( "auto_counter.php" ); ?> <html> <head> <title>Strona testowa 1</title> </head> <body> Strona ta byla ogladana <b> <?php print( $aPageAccessCount ); ?> </b> razy. </body> </html>

Uzycie gniazd
PHP umozliwia dostep do surowych gniazd TCP/IP, za pomoca ktrych mozna komunikowac sie z innymi aplikacjami za pomoca dowolnego protokolu. Niektre z bardziej znanych protokolw TCP/IP, na przyklad HTTP, POP3 i SMTP posiadaja swoje implementacje w PHP, wiec nie musisz w tych przypadkach uzywac surowych gniazd. Na wydruku 4.3 pokazano sposb dostepu za pomoca gniazd do serwera quotd, ktry zwraca cytat dnia. Protokl quotd jest bardzo prosty. Po zestawieniu polaczenia serwer wysyla strumien danych tekstowych a nastepnie zamyka polaczenie. Z perspektywy klienta wystarczy jedynie zestawic polaczenie, odczytac dane a nastepnie zakonczyc polaczenie. 59 PHP Kompendium wiedzy

Wydruk 4.3. Uzycie gniazd


<html> <head> <title>Przyklad wykorzystania serwera QOTD: Uzycie gniazd w PHP</title> </head> <body> <?php // otwarcie gniazda serwera qotd $aFile = fsockopen( "208.129.36.164", 17 ); // odczytanie wszystkich danych ze strumienia while ( !feof( $aFile ) ) { $aLine = fgets( $aFile, 1024 ); print( "$aLine<br>" ); } fclose( $aFile ); ?> </body> </html>

Uzycie potokw
Tak jak w przypadku gniazd, potoki sa traktowane jak kolejny uchwyt pliku. Jedyna rznica pomiedzy plikiem i potokiem jest to, ze potok jest jednokierunkowym strumieniem danych. Potok moze byc uzyty do odczytu danych wyjsciowych z programu lub skryptu. Na wydruku 4.4 pokazane jest uzycie potoku do odczytania wyniku zapytania do polecenia whois, ktre jest dostepne w wiekszosci systemw Unix. Ten prosty skrypt i formularz pozwalaja na wprowadzenie zapytania dla whois. Skrypt ten ilustruje rwniez czesta praktyke uzywania tego samego skryptu do wyswietlenia formularza i przetworzenia jego danych. Wydruk 4.4. Skrypt przetwarzajacy zapytanie whois
<?php /* whois.php */ // sciezka do programu whois $whois_prog = '/usr/bin/whois'; if ( !is_file( $whois_prog ) ) { // nie udalo sie znalezc programu echo "Nie moge znalezc $whois_prog!<br>"; exit; } ?> <html> <head> <title>Whois: Uzycie potokw w PHP</title> </head> <body> <?php if ( $REQUEST_METHOD == 'POST' ) { // otwarcie potoku do polecenia whois if ( $aFile = popen( "$whois_prog $WhoisQuery", "r" ) ) { // odczytanie wszystkich danych z potoku while ( !feof( $aFile ) ) { $aLine = fgets( $aFile, 1024 ); print( "$aLine<br>" ); } pclose( $aFile ); } else { echo "Nie moge otworzyc $whois do odczytu!<br>"; } print( "<hr>" ); } ?> <form action="<?php echo $PHP_SELF ?>" method="post"> Wprowadz zapytanie <b>whois</b>: <input type="text" name="WhoisQuery"> <input type="submit" name="Submit" value="Submit"> </form> </body> </html>

Rozdzial 4 Operacje na plikach

60

Klasa File
W poprzednim rozdziale wspominalismy, ze do PHP dostepne sa swietne narzedzia dodatkowe pochodzace z rznych zrdel. Klasa File dostepna z WebMasters Net (http://www.theWebMasters.net) jest przydatnym narzedziem, szczeglne wtedy, gdy twoja aplikacja intensywnie wykorzystuje pliki. Klasa ta zawiera wiele czesto uzywanych funkcji PHP operujacych na plikach i hermetyzuje kontrole bledw, dzieki czemu mozesz wiecej czasu poswiecic logice aplikacji zamiast zajmowac sie pisaniem podstawowych konstrukcji kontroli bledw. Na wydruku 4.5 pokazany jest skrypt wyswietlajacy nazwy wszystkich plikw w biezacym katalogu w postaci laczy. Gdy uzytkownik kliknie lacze, skrypt zamieszczony na wydruku 4.6 wyswietla jego zawartosc uzywajac celu klasy File do odczytania jego zawartosci. Wydruk 4.5. Uzycie klasy File do wyswietlenia zawartosci biezacego katalogu
<?php include( "class.File.php3" ); ?> <html> <head> <title>Uzycie klasy File</title> </head> <body> Ponizej znajduje sie lista plikw w biezacym katalogu.<br> Kliknij nazwe pliku aby zobaczyc ich zawartosc.<br><br> <?php $aFileClass = new File(); $aDirContents = $aFileClass->get_files( "." ); for ( $nIndex = 0; $nIndex < count( $aDirContents ); $nIndex++ ) { $aCurFile = $aDirContents[$nIndex]; print( "<a href=\"disp_file.phtml?fn=$aCurFile\">" ); print( "$aCurFile</a><br>" ); } ?> </body> </html>

Wydruk 4.6. Wyswietlenie zawartosci pliku za pomoca klasy File


<?php include( "./class.File.php3" ); ?> <html> <head> <title>Uzycie klsy File</title> </head> <body> <?php print( "The file <b>$fn</b>:<br><br>" ); $aFileClass = new File(); $aFileCont = $aFileClass->read_file( $fn ); print( "<pre>" ); print( nl2br( htmlentities( $aFileCont ) ) ); print( "</pre>" ); ?> </body> </html>

Podsumowanie
Zdecydowanie sie na uzycie plikw w aplikacji opartej na WWW jest jedna z krytycznych decyzji w fazie projektowania aplikacji. Noe wszystkie aplikacje uzywaja plikw, ale aby efektywnie korzystac z rznych typw strumieni danych, na przyklad gniazd i potokw, nalezy poznac sposoby korzystania z uchwytw plikw i funkcji operujacych na plikach. Rozdzial ten zawiera nie tylko opis podstawowych operacji na plikach i systemie plikw, ale rwniez przedstawia dodatkowa klase ulatwiajaca operacje na plikach. Opis operacji na plikach zawarty w tym rozdziale oraz opis formularzy zamieszczony w rozdziale poprzednim stanowia odpowiednia podstawe do nastepnego rozdzialu, Wysylanie plikw przez formularz.

61

PHP Kompendium wiedzy

Rozdzial 5. Wysylanie plikw przez formularz


Wstep
Poprzednie dwa rozdzialy omawialy niezbedne podstawy dla tego rozdzialu, poniewaz wysylanie plikw wymaga poznania zarwno formularzy HTML, jak i funkcji systemu plikw. Obsluga przesylania plikw w PHP jest bardzo latwa. PHP posiada wbudowany mechanizm pozwalajacy na odebranie pliku wyslanego z przegladarki zgodnej z RFC 1867. Wiekszosc nowoczesnych przegladarek jest zgodnych z tym dokumentem, poniewaz zostal on wlaczony do standardu HTML 3.2. Jezeli pozwolisz uzytkownikom na wysylanie plikw za pomoca formularza, musisz rozwazyc dopuszczalne typy plikw oraz ich wielkosci. Mechanizm wbudowany w PHP dziala swietnie dla malych plikw, ale jezeli masz zamiar przesylac duze pliki nalezy sie zastanowic nad zastosowaniem innego mechanizmu, a przyklad anonimowego FTP. Mozesz rwniez pomyslec o stworzeniu dodatkowego mechanizmu przesylania plikw, jezeli sa one niezbedne do dzialania aplikacji.

Wysylanie pojedynczego pliku


Formularz przy pomocy ktrego mozna przesylac pliki rzni sie kilkoma szczeglami od zwyklego formularza HTML. Znacznik <FORM> musi posiadac atrybut ENCTYPE ustawiony na multipart/form-data zamiast domyslnego application/x-www-form-urlencoded. Musisz rwniez umiescic na formularzy znacznik <INPUT> typu file. Wydruk 5.1. zawiera prosty formularz HTML zawierajacy jeden znacznik <INPUT>. Wydruk 5.1. Formularz HTML ze znacznikiem <INPUT>
<html> <head> <title>Formularz do przesylania plikw</title> </head> <body> <form action="upload_single.phtml" method="post" enctype="multipart/form-data"> Wyslij plik: <input type="file" name="thefile"><br><br> <input type="submit" name="Submit" value="Wyslij"> </form> </body> </html>

Po wyslaniu danych formularza z wydruku 5.1, PHP tworzy automatycznie cztery zmienne globalne, ktre opisuja przeslany plik: $thefile Zmienna zawiera nazwe pliku tymczasowego w ktrym znajduje sie plik przeslany na serwer. $thefile_name Zmienna ta zawiera nazwe pliku na komputerze z ktrego zostal wyslany. $thefile_size Zmienna zawiera wielkosc przeslanego pliku w bajtach. $thefile_type Zmienna ta zawiera typ MIME przesylanego pliku (o ile przegladarka udostepnia taka informacje). Nazwy tych zmiennych sa tworzone w oparciu o nazwe znacznika <INPUT> w formularzu, tak jak jest to pokazane na Wydruku 5.1. Piszac skrypt obslugujacy przesylanie pliku nalezy pamietac, ze PHP automatycznie usuwa plik tymczasowy po zakonczeniu skryptu, wiec jezeli nie skopujesz go, plik zostanie stracony. Skrypt na wydruku 5.2 zawiera kod obslugi przesylania pliku poprzez formularz z Wydruku 1 i jezeli plik jest rysunkiem (w formacie GIF lub JPEG) mniejszym od 100 kB, jest on wyswietlany. Jezeli przeslany plik nie ma wlasciwego typu lub jest wiekszy, wyswietlany jest komunikat bledu.

Wydruk 5.2. Obsluga przesylania pliku


<?php $aErrors = ""; 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 ); $aNewName = $aCurBasePath . "/uppics/" . $thefile_name; copy( $thefile, $aNewName ); } else { $aErrors .= "Za duzy plik !!!"; } } else { $aErrors .= "Plik nie jest typu gif ani jpeg"; } } else { $aErrors .= "Nie wybrano pliku"; } ?> <html> <head> <title>Wyswietlenie przeslanego pliku</title> </head> <body> <?php if ( $aErrors != "" ) { print( "<b>Wystapil blad</b>: $aErrors<br>" ); } else { print( "Przeslany plik:<br><br>" ); print( "<img src=\"uppics/$thefile_name\" border=\"0\">" ); } ?> </body> </html>

W przykladzie zamieszczonym na wydruku 5.2. nie wzieto pod uwage, ze nie wszystkie przegladarki wysylaja typu MIME pliku. Opuszczono rwniez inne zagadnienia kontroli bledw, na przyklad kontrole poprawnosci wykonania funkcji copy. Jednak przyklad ten mial za zadanie pokazanie jak latwo mozna obsluzyc za pomoca PHP operacje przesylania pliku. W przykladzie tym na poczatku sprawdzane jest, czy zostal wybrany plik do przesylania. Jezeli nie zostal wybrany plik, zmienna $thefile_name jest pusta. Nastepnie sprawdzane jest, czy plik ma odpowiednia wielkosc i typ MIME. Jezeli obie wartosci zostana zaakceptowane, przy pomocy wyrazenia dirname($PATH_TRANSLATED) odczytywany jest biezacy katalog na serwerze WWW. Funkcja dirname() zwraca nazwe katalogu z podanej sciezki. Zmienna $PATH_TRANSLATED jest zmienna PHP i zawiera pelna sciezke do biezacego skryptu. Dodajac /uppics/ i oryginalna nazwe pliku na komputerze lokalnym, tworzymy nowa sciezke. Na koniec, przeslany plik jest kopiowany z katalogu tymczasowego do katalogu okreslonego przez przed chwila skonstruowana sciezke. Nalezy pamietac, ze aby operacja kopiowania sie udala, docelowy katalog musi posiadac odpowiednio ustawione uprawnienia. Korzystajac z Apache w systemie Linux oznacza to, ze uprawnienia do katalogu musza pozwolic na zapis przez uzytkownika nobody. PHP posiada mechanizm pozwalajacy na ograniczanie w skrypcie wielkosci przesylanych plikw. Jest to realizowane przez dodanie do formularza ukrytego pola o nazwie MAX_FILE_SIZE. Na wydruku 5.3 pokazany jest formularz identyczny z tym z wydruku 5.1, ale dodane zostalo pole MAX_FILE_SIZE ograniczajace wielkosc przesylanych plikw do 100 kB. Wydruk 5.3. Ograniczenie wielkosci przesylanego pliku za pomoca MAX_FILE_SIZE
<html> <head>

63

PHP Kompendium wiedzy

<title>Formularz do przesylania plikw</title> </head> <body> <form action="upload_single.phtml" method="post" enctype="multipart/form-data"> <INPUT TYPE="hidden" name="MAX_FILE_SIZE" value="102400"> Wyslij plik: <input type="file" name="thefile"><br><br> <input type="submit" name="Submit" value="Wyslij"> </form> </body> </html>

Pulapki
PHP domyslnie ogranicza wielkosc plikw, jakie mozna przesylac uzywajac tego mechanizmu, do 2 megabajtw. Ta wielkosc jest wazniejsza od zmiennej formularza MAX_FILE_SIZE. Wartosc ta moze byc zmieniona przez ustawienie wartosci upload_max_filesize w pliku php.ini, lub ustawienie dyrektywy w pliku Apache.conf (wiecej szczeglw znajduje sie w rozdziale o opcjach konfiguracji, ktry znajduje sie na koncu ksiazki). Gdy osiagnieta zostanie graniczna wielkosc pliku (zarwno ustawiona w formularzu jak i globalne maksimum), PHP generuje blad, przerywa przesylanie i ustawia nazwe pliku na none. Mimo tego, ze ta graniczna wielkosc pliku jest ustawiana w celu chronienia serwera WWW, sieje ona zniszczenie w twoich aplikacjach. Poniewaz blad przekroczenia wielkosci przesylanego pliku wystepuje przed wykonaniem jakiejkolwiek linii skryptu, nie ma mozliwosci przechwycenia generowanego ostrzezenia generowanego przez mechanizm przesylania plikw. Oznacza to, ze jezeli opcja konfiguracji display_errors ma wartosc On (domyslnie) w przegladarce bedzie sie pojawial komunikat bledu. Jezeli nie chcesz aby pojawial sie ten komunikat, musisz ustawic w pliku php.ini opcje konfiguracji display_errors na Off. Mozesz nastepnie ustawic opcje log_errors na On a error_log na wartosc odpowiednia dla twojego srodowiska. Jezeli uzywasz Linuksa i Apache, ustawienie error_log na stderr spowoduje, ze wszystkie bledy PHP trafia do dziennika bledw Apache. Aplikacja twoja moze sprawdzac zmienne przesylu plikw i odpowiednio obslugiwac bledy. Jezeli uzytkownikowi nie uda sie przesyl pliku, zmienna $thefile bedzie miala wartosc none, a $thefile_name bedzie zawierala odpowiednia wartosc. Innym problemem, nad jakim nalezy sie zastanowic w trakcie pisania skryptu obslugi przesylania plikw jest to, ze zanim rozpocznie sie wykonywanie skryptu musi zostac przeslany caly plik lub maksymalna okreslona ilosc bajtw. Jezeli wiec twoja aplikacja dopuszcza przesylanie duzych plikw, ale akceptuje jedynie niektre typy plikw, twoi uzytkownicy moga dosyc dlugo czekac zanim zobacza komunikat o odrzuceniu przesylanego pliku.

Przesylanie wielu plikw


Jezeli chcesz przeslac kilka plikw uzywajac jednego formularza mozesz skorzystac z tablicy PHP do przeslania danych o przychodzacych plikach. Ponizszy przyklad pokazuje uzycie tablicy do przeslania czterech plikw. Wydruk 5.4. Przesylanie czterech plikw
<html> <head> <title>Formularz do przesylania plikw</title> </head> <body> Prosze podac cztery pliki rysunkw do przeslania: <form action="upload_multiple.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="Wyslij"> </form> </body> </html>

Wydruk 5.5. Obsluga czterech przesylanych plikw


<?php $aBasePath = dirname( $PATH_TRANSLATED ); // kazdy przeslany plik nalezy skopiowac

Rozdzial 5 Wysylanie plikw przez formularz

64

// i zapamietac ich nowe sciezki do pzniejszego wykorzystania for ( $nIndex = 0; $nIndex < count( $thefiles ); $nIndex++ ) { if ( !empty( $thefiles_name[$nIndex] ) ) { $aType = $thefiles_type[$nIndex]; if ( ( $aType == "image/gif" ) || ( $aType == "image/pjpeg" ) || ( $aType == "image/jpeg" ) ) { $aNewName = $aBasePath . "/uppics/" . $thefiles_name[$nIndex]; copy( $thefiles[$nIndex], $aNewName ); $aNewNames[] = $thefiles_name[$nIndex]; } } } ?> <html> <head> <title>Wyswietlanie przeslanego rysunku</title> </head> <body> <?php $aCount = count( $aNewNames ); print( "Przeslano <b>$aCount</b> rysunki:<br><br>" ); foreach( $aNewNames as $aNewName ) { print("<img src=\"uppics/$aNewName\" border=\"0\"><br><br>"); } ?> </body> </html>

Bezpieczenstwo
Jezeli dopuszcza sie dostarczanie jakichkolwiek danych do aplikacji, nalezy brac pod uwage kazda ewentualnosc. Jezeli pozwalasz na przesylanie plikw musisz sie upewnic, ze pliki te zostana wlasciwie obsluzone na serwerze. Na przyklad, jezeli tworzysz witryne do ktrej programisci moga przesylac wlasne skrypty nie nalezy pozwalac na wykonywanie tych skryptw na serwerze. Mozna je jedynie odebrac i wyswietlic w postaci czystego tekstu i nie mozna zakladac, ze mozna je bezpiecznie uruchomic. Nawet pozwolenie na wyswietlenie przeslanych plikw niesie ze soba potencjalne zagrozenie. Na wydruku 5.6. pokazany jest prosty przyklad w jaki sposb mechanizm wyswietlania plikw moze spowodowac dziure w systemie bezpieczenstwa. Wydruk 5.6. Naruszenie bezpieczenstwa podczas obslugi przeslanych plikw
<?php include( "class.File.php3" ); // skopiowanie przeslanego pliku $aCurBasePath = dirname( $PATH_TRANSLATED ); $aNewName = $aCurBasePath . "/uploads/" . $thefile_name; copy( $thefile, $aNewName ); ?> <html> <head> <title>Naruszenie bezpieczenstwa przy przesylaniu pliku</title> </head> <body> <?php // wyswietlenie zawartosci pliku print( "Plik <b>$aNewName</b>:<br><br>" ); $aFileClass = new File(); $aFileCont = $aFileClass->read_file( $thefile ); print( "<pre>" ); print( nl2br( htmlentities( $aFileCont ) ) ); print( "</pre>" ); ?> </body> </html>

Jest to oczywiscie wymyslony przyklad. W przykladzie tym przeslany plik jest kopiowany do nowego katalogu, ale wyswietlajac plik odczytywany i wysylany do przegladarki jest plik tymczasowy. W rzeczywistosci 65 PHP Kompendium wiedzy

prawdopodobnie odczytasz i wyswietlisz plik znajdujacy sie na sciezce zapamietanej w $aNewName. Dla potrzeb tej prezentacji poprzedni plik pokazuje w jaki sposb zle napisany skrypt narusza system bezpieczenstwa. Aby wykorzystac niedoskonalosc skryptu ktos moze wpisac do przegladarki nazwe skryptu i podac nazwe dowolnego pliku na serwerze. Na przyklad wprowadzenie takiego adresu URL spowoduje wyswietlenie zawartosci pliku /etc/passwd (zakladajac, ze bedzie on wykonywany na systemie Uniksowym):
http://serwer.com/sciezka/upload_flaw.phtml?thefile=/etc/passwd

Mozna przetestowac to na komputerze z Uniksem, ze niebezpieczenstwo jest rzeczywiste. Nawet mimo tego, ze serwer WWW pracuje jako uzytkownik nobody, plik /etc/passwd musi byc mozliwy do odczytania przez wszystkich uzytkownikw. W rozdziale o formularzach kladlem nacisk na to, ze nie wolno zakladac, ze wszyscy uzytkownicy aplikacji beda uzywali jej zgodnie z twoimi zamiarami. Tak samo jest i teraz. Niektrzy uzytkownicy beda chcieli rozmyslnie wykorzystac slabosci aplikacji a inni nieswiadomie spowoduja jej awarie. Nalezy dokladnie przemyslec wszystkie mozliwe skutki uboczne pozwolenia na przesylanie plikw na serwer WWW.

Podsumowanie
W rozdziale tym pokazane zostaly sposoby odczytywania i wykorzystania plikw przeslanych przez przegladarki zgodne z dokumentem RFC 1867. Zostaly przytoczone przyklady obslugi jednego pliku jak rwniez tablicy plikw. Na koncu rozdzialu znajduje sie mala czesc ilustrujaca w jaki sposb zle napisany skrypt moze stworzyc dziure w systemie bezpieczenstwa serwera. Dopuszczenie do przesylania plikw do aplikacji moze byc w wielu przypadkach uzyteczne, ale nalezy pamietac, ze niektrzy uzytkownicy moga nie posiadac dostatecznie szybkiego lacza aby efektywnie korzystac z tego mechanizmu, wiec dobrym pomyslem jest zapewnienie jeszcze jednego sposobu na dostarczanie plikw do aplikacji.

Rozdzial 5 Wysylanie plikw przez formularz

66

Rozdzial 6. Wsplpraca z bazami danych


Wstep
Jedna z najwazniejszych cech nowoczesnych jezykw programowania lub narzedzi programistycznych jest zdolnosc wsplpracy z baza danych. Jest to spowodowane tym, ze systemy zarzadzania relacyjnymi bazami danych (SZRBD) posiadaja wiele bardzo wydajnych i niezwykle uzytecznych mechanizmw zarzadzania danymi, jak na przyklad indeksowanie, relacje pomiedzy danymi, obsluga transakcji, kaskadowe operacje wykonywane na danych i wiele innych. PHP pozwala na dostep do danych przy uzyciu bogatego zestawu funkcji zwiazanych z bazami danych.

Wprowadzenie
Jak mozna wywnioskowac na podstawie dokumentacji, autorzy PHP uwazaja obsluge baz danych za jedna z najwazniejszych i najsilniejszych cech PHP. Obslugiwane sa miedzy innymi takie bazy danych: Adabas D InterBase Solid dBase mSQL Sybase Empress MySQL Velocis FilePro Oracle Unix dbm Informix PostgreSQL Mictosoft SQL Server ODBC Obslugujac ODBC, PHP moze zostac uzyty do prawdopodobnie dowolnej istniejacej bazy danych. Z powodu ogromnej ilosci obslugiwanych baz danych jest niemozliwe szczeglowe omwienie obslugi kazdej z nich w tej ksiazce. Dodatkowo, jezyk SQL jest sam w sobie niezwykle bogatym i wydajnym narzedziem, ktre rwniez nie zostanie odpowiednio dokladnie opisane w tej ksiazce. Najlepiej posilkowac sie dokumentacja odmiany SQL zaimplementowanej w uzywanej przez ciebie bazie danych. Zakladamy w tym rozdziale, ze czytelnicy znaja podstawy SQL w stopniu wystarczajacym do zrozumienia przykladw zamieszczonych na wydrukach. W rozdziale tym skupimy sie na przykladach uzycia MySQL i ODBC. Wybralem MySQL poniewaz jest to wydajna baza danych dostepna na zasadach licencji GNU General Public License (GPL) i jest powszechnie uzywana do wsplpracy z PHP. ODBC wybralem, poniewaz do wiekszosci baz danych dostepne sa sterowniki tego standardu. Przyklady ilustruja zastosowanie jezyka PHP i nie zawsze pokazuja najlepsze zastosowania SQL oraz dzialania na bazach danych.

Funkcje baz danych


Kazda z obslugiwanych baz danych posiada wlasny zestaw funkcji PHP. Nazwy funkcji zwiazanych z MySQL rozpoczynaja sie od mysql_ i podobna zasada obowiazuje w przypadku innych baz (W skorowidzu funkcji na koncu ksiazki znajduje sie kompletna lista funkcji zwiazanych z bazami danych). Mimo, ze kazda z baz danych ma wlasny zestaw funkcji, istnieje wsplny model dostepu do kazdego z typw baz danych. Pseudokod opisujacy pobieranie danych z dowolnego systemu bazy danych przedstawiony jest na wydruku 6.1. Wydruk 6.1. Pseudokod opisujacy pobieranie danych z bazy
<?php polacz_z_Baza(); wybierz_baze(); wyslij_wyrazenie_SQL();

pobierz_wynik(); while ( istnieje_wiersz ) pobierz_wiersz(); zamknij_polaczenie(); ?>

Nastepne dwie czesci zawieraja szczegly konfiguracji i uzycia MySQL i ODBC.

MySQL
MySQL jest swietna baza danych dla wiekszosci projektw. Oficjalna witryna MySQL jest http://www.mysql.com. Na tej witrynie znajduje sie najnowsza wersja systemu oraz dokumentacja opisujaca instalacje i konfiguracje MySQL w rznych srodowiskach.

Rozpoczynamy prace z MySQL


W zaleznosci od twoich potrzeb i typu serwera, mozesz albo sciagnac zrdla MySQL, dystrybucje binarna albo RPM. Najszybsza metoda zainstalowania MySQL na systemie Linux dzialajacym na platformie Intel jest sciagniecie pliku RPM i zainstalowanie go. Przy uzyciu tej metody instalowane sa wszystkie elementy serwera, wiec mozesz od razu zaczynac prace. Jezeli uzywasz systemu dzialajacego w oparciu o Win32, najszybsza metoda pozyskania serwera jest sciagniecie skompresowanej instalacji binarnej. PHP4 posiada wbudowana obsluge MySQL, wiec nie musisz ponownie kompilowac PHP aby uzywac funkcji mysql_. Jednak jezeli korzystasz z wbudowanej obslugi MySQL, nie mozna uzywac innych modulw odwolujacych sie do MySQL, na przyklad mod_auth_mysql i mod_perl. Jezeli potrzebujesz modulw uzywajacych MySQL, musisz przekompilowac PHP podajac opcje konfiguracji --with_mysql=/sciezka/do/mysql.

Uzycie MySQL
Po zainstalowaniu i uruchomieniu MySQL mozna rozpoczac pisanie skryptw PHP, ktre korzystaja z danych umieszczonych w bazie danych. Skrypt zamieszczony na wydruku 6.2 pokazuje jak proste jest uzycie MySQL do pobrania danych z bazy. Tabela ktrej bede uzywal w dwch kolejnych przykladach zostala utworzona za pomoca nastepujacego kodu SQL:
CREATE TABLE employees ( id tinyint(4) DEFAULT '0' NOT NULL auto_increment, first varchar(20), last varchar(20), adress varchar(255), position varchar(50), PRIMARY KEY (id), UNIQUE id (id) )

Wydruk 6.2. Pobieranie danych z bazy danych MySQL


<html> <head> <title>Pobieranie danych z MySQL</title> </head> <body> <?php // Ukrywamy komunikaty bledw i sami je obslugujemy $aDBLink = @mysql_connect( "db.server.com", "user", "pass" ); if ( !empty( $aDBLink ) ) { // wybr bazy danych MySQL if ( mysql_select_db( "mydb", $aDBLink ) == True ) { $aSQL = "select * from employees"; // Wykonanie zapytania SELECT $aQResult = mysql_query( $aSQL, $aDBLink ); if ( $aQResult == True ) { // Pobranie wiersza danych i wypisanie dwch pl while ( $aRow = mysql_fetch_array( $aQResult ) ) { $aFName = $aRow["first"]; $aPos = $aRow["position"]; print( "$aFName, $aPos<br>" );

Rozdzial 6 Wsplpraca z bazami danych

68

} mysql_free_result( $aQResult ); } else { print( "Blad wykonania zapytania<br>" ); } } else { print( "Blad wyboru bazy danych<br>" ); } } else { print( "Blad przy podlaczaniu do bazy danych<br>" ); } ?> </body> </html>

Po uruchomieniu skryptu z wydruku 6.2, prbuje sie on podlaczyc do serwera bazy danych MySQL dzialajacego na komputerze db.serer.com podajac nazwe uzytkownika i haslo. Symbol @ umieszczony przed funkcja mysql_connect() powoduje zablokowanie wypisywania bledw i ostrzezen. Podczas testowania mozesz opuscic ten symbol, ale w normalnej pracy nalezy go uzywac i stosowac wlasne procedury obslugi bledw. Nastepna czynnoscia wykonywana przez skrypt jest wybranie odpowiedniej bazy danych, w naszym przypadku mydb. Jezeli sie to powiodlo, przy pomocy funkcji mysql_query() zadawane jest zapytanie do bazy danych. W naszym przykladzie jest to zapytanie SELECT, ktre powoduje pobranie rekordw z bazy danych. Moze byc to dowolne zapytanie, na przyklad: INSERT, UPDATE, ADD TABLE lub dowolne inne zapytanie SQL. Wynik funkcji jest rzny od zero w przypadku powodzenia i zero w przypadku bledu. Dodatkowo, jezeli zapytanie jest typu SELECT, wynik funkcji jest identyfikatorem wyniku przekazywanym do funkcji mysql_result(), mysql_fetch_array(), mysql_fetch_lengths(), mysql_fetch_object(), i mysql_fetch_row(), ktre sa uzywane do odczytania wynikowych danych. W naszym przykladzie uzywamy funkcji mysql_fetch_array() do odczytania wiersza z wynikowych danych a nastepnie wyswietlane sa dane z odpowiednich pl. Funkcje mysql_fetch_array() i mysql_fetch_row() sa podobne do siebie i zwracaja jeden wiersz wyniku w postaci tablicy. Funkcja mysql_fetch_array() zwraca wynik w postaci tablicy asocjacyjnej indeksowanej nazwami kolumn. Wywolanie funkcji mysql_fetch_row() zwraca tablice indeksowana liczbami. Wywolanie jednej z tych funkcji zwraca kolejny wiersz danych zwracanych przez zapytanie i przesuwa wewnetrzny wskaznik do nastepnego wiersza. Jezeli nie ma wiecej danych, funkcja zwraca False. Wywolanie funkcji mysql_fetch_array() nie jest zauwazalnie wolniejsze niz wywolanie mysql_fetch_row(), a dostarcza o wiele wiecej danych. Uzywajac skryptu z wydruku 6.2 jako podstawy, mozna napisac wszystkie mozliwe aplikacje oparte na bazie danych. Funkcje MySQL posiadaja dodatkowo kilka cech, ktre nie sa dostepne dla wszystkich baz obslugiwanych przez PHP. Dostarczone sa specjalizowane funkcje do tworzenia i usuwania baz danych oraz funkcje umozliwiajace odczytanie struktury bazy danych. Na przyklad za pomoca funkcji mysql_list_tables() mozna uzyskac liste wszystkich tabel w bazie danych. Jedna z moich ulubionych funkcji dla MySQL jest mysql_insert_id(). Uzywajac pl o atrybucie auto_increment mozna po prostu zapisac dane do tabeli a nastepnie odczytac unikalny identyfikator rekordu za pomoca funkcji mysql_insert_id(). Na wydruku 6.3 mamy formularz, ktry pozwala na wprowadzenie danych nowego pracownika do bazy uzywanej na wydruku 6.2. Skrypt korzysta z funkcji mysql_insert_id() w celu zrealizowania potwierdzenia operacji wstawienia danych. Wydruk 6.3. Wstawianie rekordu do bazy danych MySQL
<?php /* Funkcja InsertRecord Wstawia mowy rekord do tabeli employees. W przypadku powodzenia operacji zwraca identyfikator nowego rekordu a w przypadku bledu wartosc ujemna wskazujaca na przyczyne bledu. */ function InsertRecord( $aFirstName, $aLastName, $aAddr, $aPos ) { // Przygotowanie wyrazenia SQL INSERT $aSQL = "insert into employees ( first, last, address, "; $aSQL .= "position ) values ( '$aFirstName', '$aLastName', "; $aSQL .= "'$aAddr', '$aPos' )"; // Przylaczenie do serwera i wykonanie instrukcji INSERT

69

PHP Kompendium wiedzy

$aDBLink = @mysql_connect( "db.server.com", "root", "" ); if ( !empty( $aDBLink ) ) { if ( mysql_select_db( "mydb", $aDBLink ) == True ) { $aQResult = mysql_query( $aSQL, $aDBLink ); if ( $aQResult == True ) { $aResult = mysql_insert_id( $aDBLink ); } else { // print( "Blad wykonania zapytania<br>" ); $aResult = -1; } } else { // print( "Blad wyboru bazy danych<br>" ); $aResult = -2; } } else { // print( "Blad przy podlaczaniu do bazy danych<br>" ); $aResult = -3; } return $aResult; } ?> <html> <head> <title>Przyklad MySQL: Wstawianie danych do bazy </title> </head> <body> <?php if ( $REQUEST_METHOD == 'POST' ) { // Nastapilo przeslanie danych formularza $aResult = InsertRecord( $FirstName, $LastName, $Address, $Position ); if ( $aResult > 0 ) { print( "Dodano nowy wiersz, ID = $aResult<br>" ); } else { print( "Blad funkcji InsertRecord. Kod bledu = $aResult<br>" ); } print( "<hr>" ); } ?> Prosze wpisac dane nowego pracownika:<br> <form action="<?php echo $PHP_SELF ?>" method="post"> Imie: <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="Wyslij"> </form> </body> </html>

W skrypcie z wydruku 6.3, funkcja IndertRecord() zawiera cala logike wstawienia nowego rekordu do bazy danych. Zwraca on identyfikator nowego rekordu (wartosc przypisywana przez MySQL do kolumny id) lub wartosc ujemna oznaczajaca jedna z trzech obslugiwanych sytuacji blednych. Realistycznie patrzac, Ten typ aplikacji powinien zawierac o wiele wiecej kodu odpowiedzialnego za obsluge bledw, na przyklad sprawdzanie pustych pl, ale dla naszych potrzeb kod ten nie zostal rozmyslnie wprowadzony. Poniewaz pole id w tabeli employees jest polem typu auto_increment, MySQL automatycznie generuje jednoznaczne wartosci tego pola przy kazdym wstawieniu rekordu. W naszym przykladzie wartosc ta jest odczytywana za pomoca funkcji mysql_insert_id(). Przyklad ten mial na celu pokazanie prostoty korzystania z baz danych w PHP. Wiecej przykladw uzycia baz danych w aplikacjach WWW mozna znalezc w rozdziale 15 Witryny oparte o baze danych. Znajduja sie tam bardziej zlozone przyklady zawierajace obsluge bledw i skomplikowane zapytania. Rozdzial 6 Wsplpraca z bazami danych 70

MySQL jest wydajna baza danych posiadajaca funkcje wystarczajace do tworzenia wiekszosci typw aplikacji WWW. Jest ona szybka, solidna i zawiera wiekszosc funkcji dostepnych w komercyjnych bazach danych. Jednak w czasie pisania tej ksiazki MySQL nie zawieral mechanizmu transakcji. Niedostepne sa rwniez niektre elementy SQL, na przyklad podzapytania. Jezeli jeszcze nie wybrales swojego systemu bazy danych, spisz swoje wymagania i porwnaj ze specyfikacja dostepnych systemw. W przypadku tworzenia aplikacji o wysokiej jakosci koszt bazy nie jest jedynym czynnikiem jaki nalezy brac pod uwage. Jezeli twoja firma posiada system bazy danych inny niz MySQL, nastepna czesc zawiera informacje na temat ODBC, ktre pomoga podlaczyc sie do twoich istniejacych danych.

ODBC
Open Database Connectivity (ODBC) to powszechnie stosowany interfejs API (application programming interface) sluzacy do laczenia sie z bazami danych. Jest on oparty na specyfikacji Call Level Interface pochodzacym z X/Open oraz ISO/IEC i jako jezyka dostepu do danych uzywa SQL. Istnieje kilka implementacji ODBC API dla systemw Uniksowych. W systemie Windows ODBC jest zwykle instalowany razem z systemem.

Podstawy ODBC
PHP moze obslugiwac praktycznie kazda implementacje ODBC, ale musi byc w tym celu odpowiednio skonfigurowany, poniewaz ODBC nie jest w chwili obecnej domyslna opcja. W PHP istnieja cztery opcje konfiguracji zwiazane z ODBC: --with-unixODBC, --with-custom-ODBC, --with-iodbc oraz --with-openlink. Opcje te sa lepiej opisane w skorowidzu na koncu ksiazki. W rozdziale tym przyklady korzystaja z implementacji ODBC unixODBC (http://www.unixodbc.org/). Jest on dostepny na zasadach licencji GPL lub LGPL i jest bardzo latwy do instalacji i konfigurowania. ODBC tym rzni sie od MySQL i innych API baz danych tym, ze wszystkie odwolania do bazy danych wykonuje za posrednictwem sterownika bazy danych. Oznacza to, ze najpierw musisz zainstalowac program zarzadzajacy sterownikami, na przyklad unixODBC, a nastepnie sterownik do twojego systemu bazy danych. Na rysunku 6.1. pokazane sa powiazania pomiedzy komponentami aplikacji PHP opartej o ODBC. Aplikacja wywolujac funkcje, na przyklad odbc_connect(), kontaktuje sie z zarzadca sterownikw. Zarzadca ten jest odpowiedzialny za zaladowanie odpowiedniego sterownika bazy danych i przekazanie do niego zadania. Sterownik bazy danych wywoluje odpowiednia funkcje bazy danych, ktra realizuje nasze zadanie. Rysunek 6.1. PHP Application - aplikacja PHP Komponenty Driver Manager - zarzadca sterownikw aplikacji PHP Database Driver - sterownik do bazy danych korzystajacej z DBMS - SZRBD PHP Poniewaz ODBC wymaga zastosowania zarzadcy sterownikw oraz sterownika odpowiedniej bazy danych, instalacja i konfiguracja ODBC jest nieco bardziej skomplikowana niz konfiguracja MySQL. Rwniez kazdy z uzywanych sterownikw baz danych musi zostac zainstalowany i skonfigurowany. W ksiazce tej zostanie opisana instalacja i konfiguracja zarzadcy sterownikw unixODBC oraz sterownika ODBC-ODBC Bridge (OOB), ktry mozna uzyskac z Easysoft Limited, http://www.easysoft.com/. Sterownik OOB powoduje wzrost komplikacji struktury, ale posiada tak duzo zalet, ze jest wart zainteresowania. Sterownik ten pozwala na dostep do baz danych zainstalowanych na rznych platformach za pomoca wlasnego modelu klient-serwer. NA rysunku 6.2. zilustrowano sposb uzycia sterownika OOB. Rysunek 6.2. PHP Application - aplikacja PHP Dodajemy Driver Manager - zarzadca sterownikw sterownik OOB The OOB driver - sterownik OOB OOB Client - klient OOB Network - siec OOB Server - serwer OOB Driver Manager - zarzadca sterownikw Database Driver - sterownik do bazy danych 71 PHP Kompendium wiedzy

DBMS - SZRBD Zaleta stosowania sterownika OOB jest to, ze mozesz dzieki niemu uzywac ODBC w aplikacjach dzialajacych na serwerze WWW i korzystac z danych z bazy danych dzialajacej na innym komputerze (ktry moze dzialac na innym systemie operacyjnym). Dla przykladu w moim testowym systemie zainstalowalem Oracle 8i na serwerze Windows NT i utworzylem prosta baze danych. Nastepnie w moim linuksowym serwerze WWW dodalem sterownik OOB. Sterownika tego mozna uzywac do podlaczania sie do dowolnej bazy zgodnej z ODBC, dzialajacej na dowolnej platformie. Dodatkowym utrudnieniem jest to, ze uzywajac OOB nalezy kolejno zainstalowac klienta i serwer OOB na oddzielnych komputerach. Na szczescie na witrynie Easysoft bardzo latwo jest odszukac i zaladowac odpowiednie programy. Kolejne trzy czesci omawiaja instalowanie zarzadcy sterownikw unixODBC, kompilacje PHP z obsluga unixODBC oraz instalowanie sterownika OOB. Czesci te sa przeznaczone dla uzytkownikw Linuksa i zakladamy, ze potrafisz kompilowac programy dla tego systemu oraz, ze masz zainstalowane wszystkie niezbedne kompilatory i narzedzia. Instalowanie i kompilowanie unixODBC Po sciagnieciu i rozpakowaniu plikw unixODBC, musisz skompilowac zarzadce sterownikw. W instalacji unixODBC znajduje sie standardowy skrypt sluzacy do konfigurowania srodowiska kompilacji. W celu skompilowania mojej konfiguracji PHP uzylem nastepujacych opcji:
./configure --disable--drivers --disable-threads --prefix=/usr/local/unixODBC --disable-gui

Poniewaz mialem juz potrzebny sterownik, nie potrzebowalem aby unixODBC dodal swoje sterowniki wewnetrzne. Powodem wylaczenia watkw jest to, ze moja instalacja PHP jest w postaci dynamicznie ladowanego modulu (--with-apxs) a Apache nie obsluguje domyslnie watkw. Skompilowanie tego modulu z obsluga watkw spowodowaloby awarie Apache w trakcie ladowania modulu. Wylaczylem rwniez obsluge graficznego interfejsu uzytkownika, poniewaz nie mam na moim serwerze zainstalowanego srodowiska XWindows. Kompilowanie PHP z obsluga unixODBC Po skompilowaniu i zainstalowaniu zarzadcy sterownikw unixODBC nalezy przekompilowac PHP z wlaczona obsluga unixODBC. Odpowiednia opcja konfiguracji jest --with-unixODBC=/sciezka/do/unixODBC. Uzyta sciezka musi byc taka sama jak sciezka uzyta w opcji --prefix podczas kompilowania unixODBC. W moim przypadku jest to /usr/local/unixODBC. Jezeli statycznie laczysz PHP z Apache, musisz rwniez przekompilowac Apache. Jezeli korzystasz z dynamicznego laczenia, wystarczy wylaczyc Apache, zainstalowac nowy modul PHP i powtrnie uruchomic Apache. Instalowanie sterownika OOB W moim przypadku musialem zainstalowac serwer OOB na komputerze z Windows NT i skonfigurowac go tak, aby przyjmowal zadania. Wykonalem to uruchamiajac program instalacyjny i wykonujac wszystkie kroki w programie instalacyjnym. Wszystko zadzialalo bez problemw. Nastepnie sciagnalem i zainstalowalem oprogramowanie klienta na serwerze z systemem Linux. Proces ten byl niespodziewanie latwy, poniewaz dostepny byl program instalacyjny prowadzacy uzytkownika przez kolejne kroki procedury instalacyjnej. Mozna rwniez skorzystac z witryny Easysoft, gdzie na podstawie konkretnej konfiguracji otrzymamy szczeglowy opis tego jak sciagnac i zainstalowac serwer i klienta OOB. Konfigurowanie OOB Po zainstalowaniu calego oprogramowania nalezy utworzyc nazwy zrdel danych (DSN) zarwno na kliencie jak i na serwerze. Zrdla danych sa mechanizmem specyficznym dla ODBC sluzacym do opisywania sposobu wsplpracy z systemem bazy danych. W Windows tworzy sie DSN poprzez program Zrdla danych ODBC dostepny w Panelu sterowania. OOB wymaga utworzenia systemowego DSN a nie DSN uzytkownika. Program ten zawiera plik pomocy opisujacy sposb tworzenia systemowych DSN. Rozdzial 6 Wsplpraca z bazami danych 72

Aby utworzyc DSN na Linuksie nalezy zmienic przy pomocy graficznego narzedzia unixODBC lub edytora tekstowego pliki odbcinst.ini i odbc.ini. Plik odbcinst.ini jest uzywany do opisu nazw sterownikw i laczy nazwy z plikami sterownikw. Mj plik wyglada nastepujaco:
[OOB] Driver = /usr/local/easysoft/oob/client/libesoobclient.so Setup = /usr/local/easysoft/oob/client/libesoobsetup.so FileUsage = 1

Plik odbc.ini zawiera opis zrdel danych. Swoje zrdlo skonfigurowalem nastepujaco (serwer i haslo jest oczywiscie zmyslone):
[localdsn] Server=satabase.server.com Driver=OOB Port=8888 Transport=tcpip LogonUser=prodplaner LogonAuth=password TargetDSN=LocalOracle TargetUser=prodplaner TargetAuth=password

Korzystanie z ODBC
Po zainstalowaniu i skonfigurowaniu wszystkich komponentw korzystanie z ODBC w PHP jest bardzo podobne do korzystania z MySQL. Na wydruku 6.4 znajduje sie skrypt, ktry jest odpowiednikiem ODBC skryptu umieszczonego na wydruku 6.2. Tabela uzywana w tym przykladzie jest odpowiednikiem uzywanej w poprzednim przykladzie. Wydruk 6.4. 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.ini"); // Ukrywamy komunikaty bledw i sami je obslugujemy $aDBLink = @odbc_connect( "localdsn", "prodplanner", "agdec" ); if ( !empty( $aDBLink ) ) { $aSQL = "select * from employees"; $aQResult = @odbc_exec( $aDBLink, $aSQL ); if ( $aQResult == True ) { $aRow = array(); $aRowNum = 1; while ( odbc_fetch_into( $aQResult, $aRowNum, &$aRow ) ) { $aFName = $aRow[1]; $aPos = $aRow[4]; print( "$aFName, $aPos<br>" ); $aRowNum++; } odbc_free_result( $aQResult ); } else { print( "Blad wykonania zapytania<br>" ); } } else { print( "Blad podlaczenia do bazy danych<br>" ); } ?> </body> </html>

Wydruk 6.4 jest wlasciwie taki sam jak wydruk 6.2. Mimo, ze nazwy funkcji sa inne, koncepcja jest nieomal identyczna. Jedyna zauwazalna rznica jest wywolanie putenv() na poczatku skryptu. Wywolanie to umieszcza w srodowisku programu sciezke do pliku inicjalizujacego ODBC. Nie jest to potrzebne, jezeli w ten sam sposb ustawiles srodowisko serwera WWW. Dodatkowo, na wydruku 6.4 do pl tabeli odwolujemy sie dla 73 PHP Kompendium wiedzy

uproszczenia za pomoca numer a nie nazwy. Dostepne sa funkcje ODBC zapewniajace obsluge transakcji, kursorw i wiele innych. W skorowidzu funkcji na koncu ksiazki znajduja wszystkie funkcje do obslugi ODBC.
Uwaga na temat polaczenia do baz danych W poprzednim przykladzie polaczenie do baz danych bylo realizowane za pomoca podstawowych funkcji xxx_connect(). PHP posiada rwniez zdolnosc tworzenia trwalych polaczen za pomoca funkcji pxxx_connect(). Uzycie polaczenia trwalego poprawia wydajnosc aplikacji, poniewaz sam PHP utrzymuje polaczenie z baza danych, wiec moze byc ono wielokrotnie uzywane. Po utworzeniu polaczenia za pomoca odpowiedniej kombinacji host-uzytkownik-haslo, PHP ciagle dostarcza tego samego polaczenia do kolejnych wywolan polaczenia. W bazach danych utworzenie polaczenia trwa zwykle dlugo (na przyklad w Oracle), wiec uzycie trwalych polaczen moze miec ogromny wplyw na oglna wydajnosc aplikacji.

PHPLIB
Jak wspomnialem w poprzednich rozdzialach, dostepne sa swietne biblioteki do wykorzystania przez programistw PHP. Jedna z najczesciej uzywanych bibliotek, PHP Base Library (PHPLIB) jest dostepna pod adresem http://phplib.netuse.de. Zawiera ona klasy dosteu do baz danych, obslugi sesji, narzedzi autoryzacji i wiele, wiele innych. Klasy dostepu do bazy danych w PHPLIB tworza warstwe abstrakcji dla kilku baz danych obslugiwanych przez PHP. Warstwa ta zapewnia wsplny interfejs dla bazowych funkcji baz danych, wiec programisci moga latwo zmieniac typ bazy danych bez koniecznosci nauki nowego zestawu funkcji lub wielu zmian w kodzie. W czasie pisania ksiazki PHPLIB obslugiwal MySQL, PostgreSQL, mSQL, Oracle 7, Oracle 8, Sybase, Microsoft SQL Sever i bazy ODBC. Ponizszy wydruk ilustruje sile modulu obslugujacego bazy danych z pakietu PHPLIB. W skrypcie umieszczonym na wydruku 6.5. pokazany zostal sposb uproszczenia skryptu z wydruku 6.2. Wydruk 6.5. Uzycie PHPLIB do powtrzenia wynikw z wydruku 6.2
<?php include ( "db_mysql.inc" ); // Dziedziczymy po klasie DB_Sql aby uzyc jej z // nasza baza MySQL class MySQLDBTest extends DB_Sql { var $Host = "208.129.36.163"; var $Database = "mydb"; var $User = "root"; var $Password = ""; } // Tworzenie egzemplarza nowej klasy MySQLDBTest $aDB = new MySQLDBTest; $aDB->query( "select * from employees" ); while( $aDB->next_record() ) { $aFName = $aDB->f( "first" ); $aPos = $aDB->f( "position" ); print( "$aFName, $aPos<br>" ); } ?>

Dostarczona przez PHPLIB klasa DB_Sql ukrywa w sobie szczegly procesu laczenia i wyboru bazy danych oraz zawiera kod obslugi bledw. Pozwala to osiagnac w wyniku kod, ktry jest latwiejszy do czytania, utrzymania i uruchamiania. Klasa DB_Sql nie jest przeznaczona do bezposredniego uzywania. Zamiast tego powinna byc tworzona klasa dziedziczaca po niej, w ktrej ustawiane sa zmienne specyficzne dla twojego srodowiska pracy. Jezeli PHP bedzie obslugiwal klasy abstrakcyjne, jest to idealny kandydat do takiej wlasnie implementacji. Na wydruku 6.5 definiowana jest klasa pochodna MySQLDBTest, w ktrej zawarte sa dane opisujace polaczenie z MySQL. Nastepnie tworzony jest obiekt tej klasy, na ktrym wykonywane sa operacje. Najwieksza zaleta korzystania z klas PHPLIB ujawnia sie, gdy zachodzi potrzeba wymiany bazy danych. Ponizszy wydruk pokazuje jak latwo mozna zamienic skrypt z wydruku 6.5, aby zamiast z MySQL korzystal z Oracle poprzez sterownik ODBC. Wydruk 6.6. Skrypt z wydruku 6.5 korzystajacy z Oracle i ODBC
<?php putenv("ODBCINI=/usr/local/openlink/odbc.ini"); include( "db_odbc.inc" ); // Dziedziczymy po klasie DB_Sql aby uzyc jej z // baza danych Oracle poprzez ODBC

Rozdzial 6 Wsplpraca z bazami danych

74

class OracleDBTest extends DB_Sql { var $Database = "localdsn"; var $User = "prodplanner"; var $Password = "agdec"; } // Tworzenie egzemplarza nowej klasy OracleDBTest $aDB = new OracleDBTest; $aDB->query( "select * from employees" ); while( $aDB->next_record() ) { $aFName = $aDB->f( "first" ); $aPos = $aDB->f( "position" ); print( "$aFName, $aPos<br>" ); } ?>

Jedyna widoczna zmiana pomiedzy wydrukami 5 i 6 jest funkcja include(), ale znaczenie tej zmiany jest olbrzymie. Skrypt z wydruku 6.5 korzystal z danych z bazy MySQL dzialajacej na tym samym komputerze co serwer WWW. Skrypt z wydruku 6.6 pobiera dane z bazy Oracle zainstalowanej na serwerze z Windows NT. Z powodu prostoty projektu i implementacji PHPLIB moze byc on uzyteczny dla programistw pracujacych w zlozonych, heterogenicznych srodowiskach, jak rwniez w prostych instalacjach skladajacych sie z jednego serwera. Biblioteka ta zapewnia jednakowy interfejs dostepu do rznych baz danych, co powoduje bardzo latwe ponowne uzycie istniejacego kodu. Wiecej informacji na temat klas zawartych w PHPLIB mozna odnalezc na witrynie http://phplib.netuse.de/.

Przechowywanie danych z formularzy


Omwienie formularzy HTML jest potrzebne w rozdziale dotyczacych baz danych, poniewaz formularze sa najczesciej uzywanym mechanizmem uzywanym do wprowadzania danych w aplikacjach WWW. Tak jak opisano w rozdziale 3, Formularze i cookie, PHP dostarcza wielu funkcji potrzebnych przy uzywaniu formularzy i baz danych. W przy domyslnych ustawieniach PHP automatycznie oznacza we wszystkich zmiennych GET, POST i COOKIE apostrofy, cudzyslowy, ukosniki i znaki NUL. Powoduje to, ze wartosc przekazana z formularza jest od razu gotowa do uzycia w zapytaniu SQL. Jezeli zablokowales ta opcje, musisz uzyc funkcji addslashes() zanim skorzystasz w zapytaniu SQL z ciagu przekazanego z formularza. Dodatkowo, wszystkie wartosci, ktre beda wyswietlane musza zostac przed wyswietleniem przetworzone za pomoca funkcji stripslashes(). Tak jak we wszystkich aplikacjach, dane wpisane do formularza HTML musza byc sprawdzone przed ich zapisaniem do bazy danych. Mechanizmy kontroli poprawnosci danych byly opisane w rozdziale 3. Wynikiem braku kontroli danych moze byc niezadowolenie uzytkownikw z aplikacji a nawet zalamanie systemu bezpieczenstwa serwera. Na przyklad, niektre komunikaty bledw generowane przez baze danych moga zawierac takie informacje na temat uzywanej bazy danych, ktrych na pewno nie chcialbys pokazywac uzytkownikom. Nalezy byc przygotowanym na sytuacje, ze niektrzy uzytkownicy moga prbowac wyszukac slabe punkty w aplikacji. Aby zabezpieczyc sie przed niektrymi typami atakw nalezy zawsze uzywac atrybutu maxlength w polach tekstowych oraz kontrolowac typ i postac danych. Jak wspomniano w rozdziale 3, tam gdzie jest to mozliwe nalezy zastepowac procedury kontroli danych przez takie mechanizmy, ktre ze swojej natury ograniczaja pomylki. Pola wyboru, przyciski opcji i inne tego typ elementy pozwalaja na duza elastycznosc i ograniczaja mozliwosc bledu przy wprowadzaniu danych. Tworzac alternatywne mechanizmy wprowadzania danych nalezy pamietac o mozliwosci korzystania z bazy danych przy tworzeniu poczatkowego zestawu danych. Umieszczenie takiego zestawu opcji w bazie danych skutkuje w dluzszym okresie stworzeniem aplikacji latwiejszej do zarzadzania. Na przyklad na wydruku 6.7 pokazane zostalo tworzenie listy wyboru zawierajacej kraje oraz stany USA. Oczywiscie mozna wybrac stan w USA a nastepnie Afryke poludniowa. Przyklad ten pokazuje jedynie koncepcje. W skrypcie tym uzywane sa tabele us_states oraz world_countries. Kazda z tabel zawiera identyfikator oraz nazwe. Identyfikator jest przekazywany jako wartosc formularza. Wydruk 6.7. Uzycie tabel slownikowych do generacji listy opcji
<?php include ( "./db_mysql.inc" ); class MySQLDBTest extends DB_Sql

75

PHP Kompendium wiedzy

{ var var var var $Host $Database $User $Password = = = = "208.129.36.163"; "mydb"; "root"; "";

} function GetGenOpts( $aTableName, $aCurSel = "" ) { $aResult = ""; $aDB = new MySQLDBTest; $aSQL = "select ID, Name from $aTableName order by Name"; $aDB->query( $aSQL ); while( $aDB->next_record() ) { $aName = $aDB->f( "Name" ); $aID = $aDB->f( "ID" ); if ( $aID == $aCurSel ) { $aResult .= "<option value=\"$aID\" selected>$aName</option>"; } else { $aResult .= "<option value=\"$aID\">$aName</option>"; } } return $aResult; } ?> <html> <head> <title>Formularz wyboru stanu USA oraz kraju</title> </head> <body> <form action="some_place.phtml" method="post"> <table> <tr> <td> Wybierz stan USA: </td> <td> <select name="us_state" size="1"> <?php print( GetGenOpts( "us_states", "ID" ) ); ?> </select> </td> </tr> <tr> <td> Wybierz kraj: </td> <td> <select name="world_country" size="1"> <?php print( GetGenOpts( "world_countries", "ZA" ) ); ?> </select> </td> </tr> </form> </body> </html>

Na rysunku 6.3. pokazany jest formularz. Funkcja GetGenOpts() moze byc uzyta do tworzenia listy opcji z kazdej tablicy posiadajacej kolumny ID oraz Name. Opcjonalny parametr $aCurSel moze zostac uzyty do okreslenia wybranej pozycji na formularzu, jezeli formularz jest uzyty do edycji danych a nie do wprowadzania nowych danych. Uzycie tabel slownikowych pozwala rwniez na natychmiastowe zmiany w aplikacji o ile zajdzie taka potrzeba. Jezeli masz liste akceptowanych przez ciebie kart kredytowych, nalezy ja przechowywac w bazie danych zamiast statycznie definiowac na stronie HTML, poniewaz w razie zmiany tej listy, nie trzeba przegladac wszystkich stron szukajac odwolan. Zamiast tego mozna po prostu zmienic wartosci w tabeli bazy danych. Aplikacja zostanie natychmiast zmieniona sie bez modyfikacji jednej linii kodu.

Rozdzial 6 Wsplpraca z bazami danych

76

Rysunek 6.3. Dynamicznie generowany formularz do wprowadzania danych

Kolejny raz musimy powtrzyc, ze najlepszym zabezpieczeniem przed nieprawidlowymi danymi jest dobrze skonstruowany mechanizm wprowadzania danych. Jezeli umiescisz na formularzu pole tekstowe, zawsze musisz zweryfikowac poprawnosc danych, zanim trafia one do serwera bazy danych. Udostepniajac aplikacje, nie mozesz zapomniec o bezpieczenstwie bazy danych. Zawsze nalezy zabezpieczyc baze danych w taki sposb, aby mozliwy byl dostep do niej jedynie za pomoca aplikacji. Oczywiscie, w aplikacji nie powinny znajdowac sie pola umozliwiajace wykonanie dowolnego zapytania SQL. Nalezy rwniez przetestowac aplikacje za pomoca danych, ktre moga spowodowac blad. Sprbuj wprowadzic do pl tekstowych apostrofy oraz znaki backslash. Mozna rwniez wpisac srednik i po nim wyrazenie SQL. Na przyklad, spjrzmy na przyklad aplikacji, ktra pobiera identyfikator a nastepnie wykonuje wyrazenie SQL:
select * from table where ID = wprowadzona_wartosc

Spodziewasz sie, ze wprowadzona_wartosc bedzie jedna wartoscia, wiec mozna ja wkleic do wyrazenia SQL. Mimo, ze przypadek ten jest dosc nieprawdopodobny, ktos moze wpisac do formularza napis 1; drop database. Wynikowe wyrazenie SQL bedzie nastepujace:
select * from table where ID = 1; drop database

Mimo, ze jest nieprawdopodobne, aby przyklad ten spowodowal jakiekolwiek szkody, to jednak mozesz odszukac podobne przyklady, ktre moga spowodowac naruszenie bezpieczenstwa, lub uszkodzenie bazy danych. W oparciu o typ tworzonej aplikacji, powinienes okreslic poziom wymaganego bezpieczenstwa i kontroli poprawnosci.

Wykorzystanie mozliwosci bazy danych


Czesc ta nie jest zwiazana bezposrednio z wykorzystaniem baz danych z PHP jest to dodatek poswiecony pisaniu aplikacji wykorzystujacych bazy danych. Moze on znajdowac sie rwniez w rozdziale poswieconym inzynierii programowania. Wszyscy, ktrzy nie pisali zbyt wielu aplikacji w srodowisku wielowarstwowym, powinni dokladnie przeczytac ten fragment i stosowac go podczas pisania wlasnych aplikacji WWW korzystajacych z bazy danych. Zanim zaczalem pisac aplikacje dla WWW, tworzylem w wiekszosci aplikacje Windows wykorzystywane przez jednego uzytkownika. We wszystkich przypadkach bazy danych uzywal jeden uzytkownik i dzialala na tym samym komputerze. Srodowisko takie jest bardzo wygodne, poniewaz nie trzeba robic zadnych zalozen dotyczacych wsplbieznosci a system bazy danych jest zwykle czyms wiecej niz posrednikiem sluzacym do odczytu i zapisu danych. 77 PHP Kompendium wiedzy

W przypadku tworzenia aplikacji dla srodowiska wielowarstwowego, baza danych pelni o wiele wazniejsza role. Potrzebna jest zwykle nowoczesna baza danych, ktra potrafi zarzadzac wsplbieznoscia, uprawnieniami uzytkownika, transakcjami i to odbierajac wiele rwnoczesnych zadan w tym samym czasie. Oprcz wykonywania tych krytycznych funkcji, wiekszosc nowoczesnych baz danych posiada ogromna ilosc funkcji, ktre pomagaja w pisaniu aplikacji. Niezaleznie od tego, czy serwer bazy danych i serwer WWW umieszczony jest na tym samym komputerze, czy na osobnych maszynach, powinienes wszedzie tam gdzie jest to mozliwe wykorzystywac sile systemu zarzadzania baza danych. W mojej ostatniej stalej pracy trafilem na swietny przyklad. Zadaniem bylo powielenie kilku wierszy danych z tabeli zmieniajac w nowych wierszach zawartosc kilku pl. Znaleziony przeze mnie kod wygladal mniej wiecej tak:
wybierz wszystkie wiersze do kopiowania dla kazdego wiersza inicjuj nowy ciag zawierajacy wyrazenie INSERT wybierz nowy klucz glwny w bazie danych jezeli te dane powinny byc skopiowane bez zmian skopiuj istniejace dane do wyrazenia INSERT w przeciwnym wypadku dodaj nowe wartosci do wyrazenia INSERT wykonaj wyrazenie INSERT z wyrazenia koniec dla kazdego wiersza

Nie mam zamiaru smiac sie z programisty, ktry pisal ten fragment, ale fragment ten prezentuje styl kodowania brute-force czesty u mlodych lub niedoswiadczonych programistw. Fragment ten wymaga 1+ (2*ilosc wierszy) odwolan do bazy danych. Pierwsze wywolanie pobiera wszystkie wiersze i nastepnie dla kazdego z nich jest potrzebne jedno wywolanie do wygenerowania nowego klucza glwnego i jedno dla wykonania instrukcji INSERT. Caly fragment mozna zredukowac do jednego wyrazenia SQL wykonywanego w calosci przez baze danych:
INSERT INTO tabela SELECT sequence.nextval AS PRIMARY KEY, inne_pola FROM tabela

Wyrazenie to opiera sie na generatorze sekwencji do wygenerowania nowego klucza glwnego, ktry to mechanizm musi posiadac baza danych, ale pokazuje w jaki sposb wykorzystujac odpowiednio SQL mozna uniknac pisania sporej ilosci kodu oraz poprawic wydajnosc aplikacji. Jezeli zdarzy ci sie pisac kod formatujacy, filtrujacy badz sortujacy dane pobierane z bazy danych, przyjrzyj sie dokladniej swojemu zapytaniu SQL. Mozesz skorzystac z wbudowanych funkcji bazy danych lub zastosowac bardziej skomplikowany kod SQL do osiagniecia oczekiwanych wynikw. W jednym z ostatnich projektw musialem posortowac wiersze opisujace personel w oparciu o rznice wieku liczac od okreslonej daty. Na przyklad, musialem okreslic pozycje rekordu osoby w oparciu o to, jak bardzo jej wiek jest zblizony do 30 lat. Dodatkowo kazdej osobie przypisywana byla wartosc, bedaca liczba od 0 do 10, obliczana w oparciu o to jak blisko wiek osoby jest zblizony do zalozonych wymagan wiekowych. Kazdy, ktrego wiek byl oddalony od zalozonego o wiecej niz 10 lat otrzymywal ta sama ocene. Ponizsze wyrazenie moze wygladac na dosyc skomplikowane, ale otrzymujemy wszystkie potrzebne dane bez potrzeby pisania dodatkowego kodu manipulujacego wynikami:
SELECT concat (firstname, ' ', surneme) as fullname, ROUND(MAX(0, (10-ABS((30-ROUND(((TO_DAYS(NOW()) - TO_DAYS(birthdate))/365))))))) AS age_dif FROM persons ORDER BY age_diff DESC

Kazdy z wierszy wyniku zawiera imie i nazwisko osoby oraz liczbe oznaczajaca zadana wartosc. Wszystko czego potrzebujemy, to w petli odczytac wyniki i wyswietlic je na ekranie. Na poczatku wyniku znajda sie osoby o wieku najblizszym 30 lat. Jednym z najwazniejszych problemw przypisaniu aplikacji dla WWW jest uzycie wlasciwych narzedzi i wlasciwych ludzi do realizacji poszczeglnych fragmentw projektu. Nastepna duza czesc ksiazki, Zarzadzanie projektem przy tworzeniu aplikacji WWW zawiera wiecej informacji na temat inzynierii programowania dla aplikacji WWW.

Podsumowanie
Rozdzial ten zawiera opis uzycia baz danych razem z PHP. Poniewaz PHP obsluguje wiele typw baz danych, skupilismy sie na bazie MySQL oraz dostepowi poprzez ODBC. Zamieszczona zostala rwniez krtka dyskusja na temat inzynierii programowania i wykorzystaniu mozliwosci baz danych. Dalsze informacje na temat Rozdzial 6 Wsplpraca z bazami danych 78

uzycia baz danych znajduja sie w rozdzialach 15, 16 i 17. Najobszerniejsze przyklady znajduja sie w rozdziale 15 Witryny oparte o baze danych.

79

PHP Kompendium wiedzy

Rozdzial 7. Sesje i stan aplikacji


Wstep
W rozdziale 4 Operacje na plikach zostalo przedstawione wykorzystanie plikw do utrzymania stanu sesji, ale nie zawiera on oglnego opisu problemu utrzymywania stanu. W standardowych aplikacjach stan jest automatycznie utrzymywany w zmiennych przechowywanych w pamieci komputera, plikach oraz bazach danych wykorzystywanych przez program. Stan programu jest zawsze znany, poniewaz caly model dzialania programu jest dosyc prosty: uzytkownik uruchamia program, wykonuje swoje zadania a nastepnie zamyka program. Jezeli uzytkownik chwilowo przelaczy zadanie a nastepnie powrci do niego, stan aplikacji nie zmieni sie. Gdy uzytkownik konczy prace, niezbedne dane sa serializowane oraz zapisywane i sesja pracy programu sie konczy. W aplikacjach WWW zarzadzanie danymi sesji jest bardziej zlozone. Jest to powodowane faktem, ze zarwno przegladarka jak i serwer WWW nie byly projektowane do uruchamiania aplikacji WWW. Poniewaz aplikacje WWW sa ze swojej natury aplikacjami wielodostepnymi, w utrzymanie sesji jest zaangazowany zarwno serwer jak i klient. Pod pojeciem klienta kryja sie tutaj poszczeglni uzytkownicy. Serwer korzysta z danych przekazanych mu przez klientw podczas kolejnych odwolan do stron do sledzenia i utrzymywania danych sesji. PHP pozwala na stosowanie kilka metod utrzymywania stanu sesji. W PHP4 wbudowano funkcje do obslugi sesji, ale dostepne sa rwniez moduly zewnetrzne realizujace to samo zadanie. Inna metoda jest napisanie w PHP wlasnego mechanizmu zarzadzania sesjami.

Podstawy mechanizmu sesji


Jak napisalem we wprowadzeniu, obsluga sesji w sieci WWW wymaga wsplpracy pomiedzy przegladarka klienta i serwerem WWW. Gdy sesja zaczyna sie, serwer WWW tworzy unikalny identyfikator sesji (ID) i przekazuje go do klienta. Zwykle identyfikator ten jest przechowywany w cookie na komputerze klienta. Nastepnie przegladarka wysyla ID do serwera razem z kazdym zadaniem przeslania strony. Serwer wykorzystuje ID do odczytania i odtworzenia wszystkich potrzebnych danych aplikacji. Po zakonczeniu aplikacji dane sa usuwane z serwera. Na rysunku 7.1. pokazany zostal schemat komunikacji pomiedzy klientem a serwerem WWW (w tym przypadku jest to serwer 1U produkowany przez Penguin Computing) w przypadku rozpoczynania sesji oraz wykorzystywania zmiennych.

Rysunek 7.1. Rozpoczynanie sesji oraz uzycie zmiennych sesji

Wbudowany w PHP mechanizm zarzadzania sesjami


W wersji 4 do PHP wprowadzono mechanizm zarzadzania sesjami. Funkcje obslugi sesji sa dokladnie opisane w skorowidzu funkcji na koncu ksiazki. Wszystkie nazwy funkcji obslugi sesji rozpoczynaja sie od sesion_. Wykorzystujac sesje w PHP nalezy wykonac nastepujace podstawowe operacje: 1. Rozpoczecie sesji za pomoca session_start(). 2. Zarejestrowanie nazw zmiennych sesji za pomoca session_register(). 3. Uzycie zmiennych sesji. System zarzadzania sesjami w PHP mozna w duzym stopniu konfigurowac. Mozna zmienic sposb przesylania identyfikatora sesji, miejsce przechowywania zmiennych sesji na serwerze oraz czestotliwosc usuwania przerwanych sesji. Poniewaz dostepne jest wiele opcji konfiguracji, czesc ta zostanie podzielona na czesci o wzrastajacym stopniu skomplikowania.

Rozpoczecie pracy z sesjami w PHP


Wydruki 7.1 i 7.2 pokazuja, jak latwe jest uzycie sesji w PHP wykorzystujace domyslne ustawienia. Na wydruku 7.1 zamieszczony jest skrypt inicjujacy wszystkie zmienne sesji uzywane w aplikacji oraz lacze do skryptu z wydruku 7.2, ktry wykorzystuje zmienne sesji ze skryptu na wydruku 7.1. Wydruk 7.1. Uruchamianie sesji i inicjowanie zmiennych
<?php session_start(); session_register( "aUser", "aAccount" ); $aUser = "Cidnie"; $aAccount = "1016"; ?> <html> <head> <title>Podstawy sesji: Strona 1</title> </head> <body> <?php print( "Uzytkownik: $aUser<br>" ); print( "Konto: $aAccount<br>" ); ?> <br><br> <a href="listing2.phtml">Przejscie do strony 2</a> </body> </html>

Wydruk 7.2. Uzycie zmiennych sesji z wydruku 7.1


<?php session_start();

81

PHP Kompendium wiedzy

?> <html> <head> <title>Podstawy sesji: Strona 2</title> </head> <body> <?php print( "Uzytkownik: $aUser<br>" ); print( "Konto: $aAccount<br>" ); ?> </body> </html>

Pierwszym krokiem skryptu z wydruku 7.1 jest uruchomienie sesji poprzez wywolanie funkcji session_start(). W domyslnej konfiguracji PHP uzywa cookie do przechowywania identyfikatora sesji. Funkcja session_start() posiada te same ograniczenia co funkcje set_cookie() i header(). Funkcje te musza byc wywolywane przed wyslaniem do przegladarki jakichkolwiek informacji lub musi zostac wlaczone buforowanie danych wyjsciowych. Chociaz mozna zmienic sposb przesylania identyfikatora sesji, najprostsza metoda jest wykorzystanie domyslnego mechanizmu cookie. Pozostale metody zostana opisane pzniej. Po rozpoczeciu sesji, zostaja zarejestrowane dwie zmienne, aUser oraz aAccount. Gdy uzytkownik kliknie lacze prowadzace do strony 2, przegladarka samoczynnie wysle identyfikator sesji do serwera. W skrypcie z wydruku 7.2 w trakcie wywolania funkcji session_start(), PHP korzysta z identyfikatora sesji do odczytania wszystkich zmiennych sesji. Na rysunkach 7.2. i 7.3. pokazane sa wyniki dzialania skryptw umieszczonych odpowiednio na wydrukach 1 i 2. Rysunek 7.2. Wynik dzialania skryptu z wydruku 7.1

Rysunek 7.3. Wynik dzialania skryptu z wydruku 7.2

Mozliwe jest wyswietlenie biezacego identyfikatora sesji wypisujac na ekran zawartosc zmiennej Dodatkowo, w domyslnej konfiguracji na Apache i Linuksa, dane sesji sa przechowywane w katalogu /tmp w plikach o nazwach w postaci sess_$PHPSESSID. Po uruchomieniu poprzedniego przykladu odszukalem plik sess_e66b342b4e76889f8f25105db11820c6, ktry zawieral: aUser|s:6:"Cidnie";aAccount|s:4:"1016";.
$PHPSESSID.

Rozdzial 7 Sesje i stan aplikacji

82

Domyslne ustawienia PHP dotyczace zarzadzania sesjami sa latwe do uzycia i wystarczaja dla wiekszosci aplikacji WWW. Jednak w niektrych przypadkach cookie moga nie byc pozadana metoda przesylania identyfikatora sesji, a w przypadku niektrych duzych aplikacji WWW uzycie plikw na serwerze WWW moze utrudniac skalowanie aplikacji. Nastepne dwie czesci zawieraja omwienie sposobu rozwiazania tych problemw.

Przesylanie identyfikatora sesji bez uzycia cookie


Jezeli aplikacja absolutnie wymaga zastosowania zmiennych sesji, do przesylania identyfikatora sesji mozesz uzyc innego mechanizmu niz cookie. Nalezy pamietac, ze niektrzy uzytkownicy maja w swoich przegladarkach wlaczona obsluge cookie. Pierwsza z metod jest reczne przesylanie identyfikatora sesji w postaci zmiennej GET lub POST. Na wydruku 7.3 pokazany jest skrypt, ktry pokazuje w jaki sposb nalezy zmienic kod z wydruku 7.1, aby identyfikator sesji byl przesylany jako zmienna GET. Wydruk 7.3. Reczne przesylanie identyfikatora sesji za pomoca metody GET
<?php session_start(); session_register( "aUser", "aAccount" ); $aUser = "Cidnie"; $aAccount = "1016"; ?> <html> <head> <title>Reczne przesylanie identyfikatora sesji: Strona 1</title> </head> <body> <?php print( "Uzytkownik: $aUser<br>" ); print( "Konto: $aAccount<br>" ); ?> <br><br> <a href="listing2.phtml?<?=SID?>">Przejscie do strony 2</a> </html>

Nalezy zauwazyc, ze kod jest taki sam jak na wydruku 7.1, poza laczem w trzecim wierszu od konca. W tym przypadku do adresu URL zostala doklejona stala PHP SID. Stala ta jest zdefiniowana jako SessionName=SessionID, ponizszy kod jest semantycznie identyczny z odpowiednia linia z wydruku 7.3:
<a href="listing2.phtml?<?php echo session_name() . "=" . session_id()?>"> Przejscie do strony 2</a>

SID,

Nalezy pamietac, ze SID jest stala a nie zmienna, wiec jezeli bedziesz chcial wydrukowac $SID zamiast nie otrzymasz takiego samego wyniku. Na wydruku 7.3 zastosowany zostal skrt <?=SID?>. Zapis taki jest rwnowazny z <?php echo SID;?> zakladajac, ze w czasie kompilacji PHP uzyto opcji --enable-short-tags. Wydruk 7.3 ilustruje mechanizm recznego przesylania identyfikatora sesji w programie, ale nie pokazuje jak mechanizm ten wplywa na tworzenie aplikacji. Korzystajac z tego mechanizmu, kazde lacze i kazdy formularz w aplikacji musi zawierac identyfikator sesji. Jezeli nie dodasz identyfikatora do jednego lacza, SID zostanie utracony, a aplikacja bedzie zle dzialac. Na szczescie PHP posiada opcje automatycznego przeksztalcania laczy, ktry to mechanizm rozwiazuje ten problem za ciebie. Jezeli chcesz przesylac identyfikator sesji przy uzyciu metod GET i POST, mozesz uaktywnic ten mechanizm kompilujac PHP z opcja --enable-transsid. Po przebudowaniu PHP kod z wydruku 7.3 moze byc zmieniony na nieco prostszy, pokazany na wydruku 7.4. Wydruk 7.4. Przetwarzanie wzglednych adresw URL przez PHP w celu przekazywania identyfikatora sesji
<?php session_start(); session_register( "aUser", "aAccount" ); $aUser = "Cidnie"; $aAccount = "1016"; ?> <html> <head> <title>Automatyczne przesylanie identyfikatora sesji: Page 1</title> </head> <body> <?php print( "Uzytkownik: $aUser<br>" ); print( "Konto: $aAccount<br>" ); ?> <br><br> <a href="listing2.phtml">Przejscie do strony 2</a>

83

PHP Kompendium wiedzy

</html>

Rznica pomiedzy wydrukiem 3 i 4 jest taka, ze na wydruku 7.4 nie ma odwolania do stalej SID w laczu. Mozna rwniez zauwazyc, ze wydruk 7.4 jest praktycznie identyczny z wydrukiem 7.1, ale wynik jego dzialania jest rzny z powodu zmiany konfiguracji. Gdy uzytkownik kliknie lacze, URL bedzie zawieral ciag PHPSESSID=xxx, tak samo jak w przypadku skryptu z wydruku 7.3. Kod ten dziala, poniewaz PHP szuka na stronie wzglednych adresw URL i dodaje do nich potrzebna wartosc identyfikatora sesji. Aby to pokazac, nastepny skrypt zawiera kilka wzglednych laczy i kilka bezwzglednych. Pokazujemy rwniez w jaki sposb PHP przetworzyl lacza. Wydruk 7.5. Przyklady automatycznego uzupelniania laczy przez PHP
<?php session_start(); session_register( "aUser", "aAccount" ); $aUser = "Cidnie"; $aAccount = "1016"; ?> <html> <head> <title>Uzupelnianie adresw URL</title> </head> <body> <?php print( "Uzytkownik: $aUser<br>" ); print( "Konto: $aAccount<br>" ); ?> <br><br> <a href="listing2.phtml">Lacze 1</a> <br><br> <a href="listing2.phtml?MyVar=1234">Lacze 2</a> <br><br> <a href="http://www.php.net/">Lacze 3</a> <br><br> <a href="http://localhost/listing2.phtml">Lacze 4</a> <br><br> <form action="listing2.phtml"> <input type="submit" name="Submit" value="Przycisk przeslania danych formularza"> </form> </html>

Po uruchomieniu skryptu, do przegladarki zostal wyslany nastepujacy kod HTML:


<html> <head> <title>Uzupelnianie adresw URL</title> </head> <body> Uzytkownik: Cidnie<br>Konto: 1016<br> <br><br> <a href="listing2.phtml?PHPSESSID=9771f86dc94e367cf1c62e0339d02c4b">Lacze 1</a> <br><br> <a href="listing2.phtml?MyVar=1234&PHPSESSID=9771f86dc94e367cf1c62e0339d02c4b"> Lacze 2</a> <br><br> <a href="http://www.php.net/">Lacze 3</a> <br><br> <a href="http://localhost/listing2.phtml">Lacze 4</a> <br><br> <form action="listing2.phtml"><INPUT TYPE="HIDDEN" NAME="PHPSESSID" VALUE="9771f86dc94e367cf1c62e0339d02c4b"> <input type="submit" name="Submit" value="Przycisk przeslania danych formularza"> </form> </html>

Poniewaz pierwsze dwa lacza sa laczami wzglednymi, zostaly do nich dolaczone dane na temat sesji. Lacze 3 nie jest oczywiscie laczem wzglednym, wiec identyfikator sesji nie zostal dolaczony. Dzialanie takie bylo przewidziane. Lacze 4 pokazuje jak ostroznym nalezy byc uzywajac funkcji automatycznego uzupelniania laczy. W tym przypadku jest to bezwzgledny adres URL, chociaz strona ta znajduje sie na tym samym serwerze. PHP uzupelnia jedynie adresy URL zapisane w postaci laczy wzglednych. Do przykladu zostal dolaczony formularz, poniewaz PHP potrafi rwniez uzupelniac formularz tak, aby zawieral on wartosc identyfikatora sesji. Oznacza to, ze aplikacja korzystajaca z formularzy rwniez bedzie prawidlowo dzialala. Jedyna wada tego mechanizmu jest to, ze dziala on jedynie dla metody POST. Jezeli bedziesz chcial uzyc formularza korzystajacego z metody GET, aplikacja nie bedzie dzialala prawidlowo. Mimo, ze atrybut ACTION zostanie prawidlowo zmodyfikowany, przegladarka nie dodaje zmiennej PHPSESSID do ciagu zapytania (przetestowane na najnowszych wersjach Netscape i Internet Explorer). Rozdzial 7 Sesje i stan aplikacji 84

Przesylanie identyfikatora sesji za pomoca metod GET i POST pozwala uniknac niektrych problemw z cookie i jest latwe do zrealizowania. Jezeli zamierzasz skorzystac z automatycznego uzupelniania adresw, powinienes rwniez sie zastanowic, jaki wplyw bedzie to mialo na wydajnosc aplikacji. PHP musi przeciez podczas kazdego uruchomienia strony odszukac wszystkie lacza na stronie i zmienic URL. Aby sprawdzic wplyw tego mechanizmu na wydajnosc stworzylem przykladowa strone WWW oraz skrypt, ktry odczytywal ja z serwera i zapamietywal czas potrzebny na jej odczytanie. Przykladowa strona zawierala 14 laczy z ktrych 12 bylo laczami wzglednymi, ktre wymagaly przepisania. Strona miala wielkosc 9,55 kB. Uzylem skryptu z wydruku 7.6 do odczytania strony kolejno 1000 razy. Skrypt uruchamialem z aktywna opcja --enable-trans-sid, oraz bez niej. Wydruk 7.6. Skrypt do sprawdzania wydajnosci
<?php function getmicrotime() { $mtime = microtime(); $mtime = explode( " ", $mtime); $mtime = $mtime[1] + $mtime[0]; return ($mtime); } $aStartTime = getmicrotime(); $aFileName = "http://localhost/ch07/listing5.phtml"; for ($nIndx = 0; $nIndex < 1000; $nIndex++) { $aData = file( $aFileName ); } $aEndTime = getmicrotime(); $aTotTime = $aEndTime - aStartTime; print( "Czas calkowity: $aTotTime\n"); ?>

Test byl uruchamiany wiele razy, aby obliczyc srednia rznice czasw wykonania. Zanotowano srednio 9% zysk wydajnosci w przypadku zablokowania opcji --enable-trans-sid. Mimo, ze rznica taka moze byc w wiekszosci witryn malo znaczaca, moze ona byc wazna w przypadku silnie obciazonych witryn. Zanim zastosujesz ktres z rozwiazan, powinienes przeprowadzic wlasne testy sprawdzajace wplyw zastosowanego mechanizmu na wydajnosc.
Blad w PHP Jak wspominalismy w tej czesci, PHP wersja 4.0.1 poziom poprawek 2, zawieral blad w mechanizmie automatycznego uzupelniania adresw URL. Blad ten poprawiono w wersji 4.0.2. Jezeli chcesz korzystac z tej funkcji, upewnij sie, ze masz zainstalowana wlasciwa wersje PHP.

Zapisywanie zmiennych sesji w bazie danych


Po wybraniu mechanizmu przesylania identyfikatora sesji, nalezy zdecydowac, gdzie beda zapisywane wartosci samych zmiennych sesji. PHP posiada mechanizm zapisywania zmiennych sesji w dowolnie wybrany sposb. Do napisania dowolnego mechanizmu obslugi sesji wystarczy zdefiniowac szesc funkcji i zarejestrowac je w PHP. Funkcje te wraz z ich parametrami sa przedstawione ponizej. bool open( string save_path, string sess_name ); Funkcja ta jest wywolywana w trakcie inicjalizacji sesji. Mozna jej uzyc do wstepnej inicjalizacji sesji. Pierwszy argument jest sciezka podana w jako wartosc zmiennej konfiguracji session.save_path okreslonej w pliku php.ini, lub ostatnia wartosc przekazana do funkcji session_save_path(). Drugi argument jest nazwa sesji okreslona przez parametr session.name zdefiniowany w pliku php.ini, lub ostatnia wartoscia przekazana do funkcji session_name(). Wartosciami domyslnymi sa odpowiednio /tmp i PHPSESSID. bool close(); Funkcja jest wywolywana w celu zakonczenia sesji. mixed read( string sess_id ); Funkcja jest uzywana do odczytania zawartosci sesji. Jezeli dane sesji nie sa dostepne, powinien zostac zwrcony pusty ciag (""). Jezeli wystapi blad, powinna zostac zwrcona wartosc False. Jezeli istnieja dane sesji, powinny zostac zwrcone w postaci serializowanej. Dane te powinny byc dokladnie takie same, jak przekazane przez PHP do funkcji write(). bool write( string sess_id, string value ); Funkcja jest wywolywana w przypadku koniecznosci zapamietania danych sesji. Dane przekazane do parametru value sa danymi sesji w postaci serializowanej. 85 PHP Kompendium wiedzy

Funkcja jest wywolywana podczas wywolania w skrypcie funkcji session_destroy(). Powinna usunac wszystkie dane zwiazane z sesja. bool gc( int max_lifetime ); Funkcja ta jest wywolywana w czasie rozpoczynania sesji. Jest ona wywolywana z czestotliwoscia okreslona przez parametr konfiguracji session.gc_probability. Funkcja jest przeznaczona do usuwania nieuzywanych danych sesji. Podczas swojego dzialania powinna usunac wszystkie dane nie uzywane przez max_lifetime sekund. Usuwanie niepotrzebnych danych sesji jest omwione w nastepnej czesci rozdzialu. Po utworzeniu funkcji obslugi sesji nalezy zarejestrowac je za pomoca funkcji session_set_save_handler(). Po tej operacji PHP bedzie wywolywalo wszedzie tam gdzie jest to potrzebne nowe funkcje. Do zilustrowania tego mechanizmu przygotowany zostal skrypt na wydruku 7.7, ktry zawiera 7 funkcji obslugi zmiennych, ktre jedynie wypisuja swoja nazwe i parametry wywolania. Funkcja read() z tego skryptu zwraca dla celw testowych wartosci dwch zmiennych sesji. Wydruk 7.7. Zdefiniowany przez uzytkownika mechanizm obslugi sesji: mysession.php
bool destroy( string sess_id );
<?php function mysess_open( $aSavePath, $aSessionName ) { print( "mysess_open( $aSavePath, $aSessionName )<br>" ); return True; } function mysess_close() { print( "mysess_close()<br>" ); return True; } function mysess_read( $aKey ) { print( "mysess_read( $aKey )<br>" ); return "aUser|s:6:\"Cidnie\";aAccount|s:4:\"1016\";"; } function mysess_write( $aKey, $aVal ) { print( "Wywolanie mysess_write!\n\nWlasnie tutaj!\n\n" ); print( "mysess_write( $aKey, $aVal )<br>" ); return True; } function mysess_destroy( $aKey ) { print( "mysess_destroy( $aKey )<br>" ); return True; } function mysess_gc( $aMaxLifetime ) { print( "mysess_gc( $aMaxLifetime )<br>" ); return True; } session_set_save_handler( "mysess_open", "mysess_close", "mysess_read", "mysess_write", "mysess_destroy", "mysess_gc" ); ?>

Aby pokazac w jaki sposb PHP wywoluje nowe funkcje, uzyjemy skryptu z wydruku 7.8. Dodatkowo ustawilem wartosc session.gc_probability na 100, wiec funkcja czyszczenia pamieci jest wywolywana na poczatku kazdej sesji. Wydruk 7.8. Testowanie mysession.php
<?php include( "./mysession.php" ); session_start(); ?> <html> <head> <title>Wlasny mechanizm obslugi sesji</title> </head> <body> <?php print( "Uzytkownik: $aUser<br>" ); print( "Konto: $aAccount<br>" ); $aUser = "Katie"; $aAccount = "2026"; print( "Uzytkownik: $aUser<br>" ); print( "Konto: $aAccount<br>" ); ?> </body> </html>

Rozdzial 7 Sesje i stan aplikacji

86

Rysunek 7.4. Wynik dzialania skryptu mysession.php

Gdy uruchomilem ten skrypt, wynik nie byl taki, jakiego sie spodziewalem. W przegladarce nie bylo informacji na temat wywolania funkcji write() i close(). Jak mozna zauwazyc dodalem nawet dodatkowa instrukcje print() aby dokladniej sprawdzic co sie stalo. Wynik w przegladarce jednak nadal nie byl prawidlowy. Po dokladniejszym sprawdzeniu odkrylem, ze wynik dzialania obu funkcji znajduje sie w pliku error_log serwera Apache. Oznacza to, ze w ktryms momencie wyjscie zostalo tymczasowo przekierowane z stdout na stderr. W wyniku tego przekierowania nie mozna wyslac zadnych danych do przegladarki zarwno w funkcji write(), jak i close(). Problem ten jednak nie wplywa na wlasciwy system obslugi sesji. Trzeba powiedziec, ze ten efet moze nie powtrzyc sie w przypadku uzycia innej platformy i serwera, poniewaz sposb obslugi standardowego wyjscia danych i bledw moze byc inny. Na przyklad w przypadku serwera Xitami dzialajacego na Windows widoczne byly wszystkie spodziewane dane. Po poznaniu zasady dzialania mechanizmu, stworzenie prawdziwego mechanizmu obslugi sesji bedzie dosyc latwe. Jezeli chcesz uzywac zmiennych sesji, powinienes przechowywac je w bazie danych a nie w pliku. Idea ta moze byc z poczatku malo zrozumiala, ale nalezy pamietac, ze zapisywanie danych aplikacji na serwerze WWW moze ograniczac skalowalnosc aplikacji. Jezeli aplikacja zostanie rozdzielona na kilka serwerw WWW i zastosowany zostanie mechanizm rwnowazenia obciazenia pomiedzy serwerami, uzycie plikw do obslugi sesji moze spowodowac zalamanie aplikacji. Awaria ta bedzie wynikala z tego, ze kazde zadanie moze byc kierowane do innego serwera w klastrze. Jezeli poczatkowe dane zostana zapisane na serwerze pierwszym, a kolejne zadanie bedzie przekazane do serwera dwa, to dane sesji beda nieosiagalne. Jezeli wszystkie dane sesji beda przechowywane w bazie danych, zmienne sesji beda dostepne dla wszystkich serwerw WWW w klasterze. Nastepny wydruk zawiera prosty przyklad uzycia bazy danych MySQL do przechowywania danych sesji. W celu poprawienia czytelnosci kodu, przyklad korzysta z klasy DB_Sql pochodzacej z pakietu PHPLIB omwionej w rozdziale 6 Wsplpraca z bazami danych. Do przechowywania danych sesji korzystamy z tabeli zdefiniowanej w nastepujacy sposb:
CREATE TABLE Sessions ( SessionId char(32) not null, LastUpdated datetime not null, DataValue text, PRIMARY KEY (SessionID), INDEX (LastUpdated ) );

Tabela ta zawiera pole do przechowywania identyfikatora sesji, pole data/czas do zapamietywania czasu ostatniej zmiany oraz dane w postaci pola tekstowego typu BLOB. Pole LastUpdated posiada indeks w celu poprawienia wydajnosci w trakcie odzyskiwania nieuzytkw. Caly kod funkcji obslugi sesji zamieszczony jest na wydruku 7.9. Wydruk 7.9. Obsluga sesji przy uzyciu bazy danych MySQL
<?php include ( "db_mysql.inc" ); // Specjalizacja klasy DB_Sql do wykorzystania na naszym // serwerem bazy danych MySQL class MySQLDB extends DB_Sql { var $Host = "localhost"; var $Database = "mydb"; var $User = "root";

87

PHP Kompendium wiedzy

var $Password = "root"; } function mysess_open( $aSavePath, $aSessionName ) { // nie trzeba nic robic return True; } function mysess_close() { // nie trzeba nic robic return True; } function mysess_read( $aKey ) { $aDB = new MySQLDB; $aSQL = "select DataValue from Sessions where SessionID='$aKey'"; $aDB->query( $aSQL ); if ( $aDB->num_rows() == 1 ) { $aDB->next_record(); $aData = $aDB->f( "DataValue" ); return $aData; } else { // Wstaw wiersz dla biezacej sesji aby uproscic funkcje write $aSQL = "insert into Sessions values ( '$aKey', NOW(), '' )"; $aDB->query( $aSQL ); return ""; } } function mysess_write( $aKey, $aVal ) { $aDB = new MySQLDB; $aData = addslashes( $aVal ); $aSQL = "update Sessions set DataValue='$aData', "; $aSQL .= "LastUpdated=NOW() where SessionID='$aKey'"; $aDB->query( $aSQL ); return True; } function mysess_destroy( $aKey ) { $aDB = new MySQLDB; $aSQL = "delete from Sessions where SessionID = '$aKey'"; $aDB->query( $aSQL ); return True; } function mysess_gc( $aMaxLifetime ) { $aDB = new MySQLDB; $aSQL = "delete from Sessions where UNIX_TIMESTAMP(NOW()) "; $aSQL .= "- UNIX_TIMESTAMP(LastUpdated) > $aMaxLifetime"; $aDB->query( $aSQL ); return True; } session_set_save_handler("mysess_open", "mysess_close", "mysess_read", "mysess_write", "mysess_destroy", "mysess_gc"); ?>

mysess_open()

Kod z wydruku jest calkiem prosty jak na tak duza zmiane mechanizmu obslugi sesji. Funkcje i mysess_close() nie sa w tym przypadku uzywane, poniewaz nie sa potrzebne. Wszystkie dane sesji sa przechowywane w jednej tabeli, wiec wartosci przekazane do mysess_open() nie sa uzywane, a po zakonczeniu sesji nie trzeba niczego usuwac. Interesujacymi funkcjami sa mysess_read(), mysess_write(), mysess_destroy() oraz mysess_gc(). W funkcji mysess_read() do bazy jest kierowane zapytanie majace za zadanie odczytac dane zwiazane z identyfikatorem sesji. Jezeli dane te zostana odnalezione sa zwracane. Jezeli nie ma jeszcze rekordu w bazie, tworzony jest nowy rekord z pustym polem DataValue i zwracany jest pusty ciag (""). Powodem takiego dzialania jest to, ze gdy pzniej beda zapisywane dane sesji nie bedzie koniecznosci sprawdzania, czy istnieje juz odpowiedni rekord w bazie danych. Funkcja mysess_write() za kazdym wywolaniem uaktualnia pola DataValue oraz LastUpdated. Funkcja mysess_destroy() usuwa rekord zwiazany z identyfikatorem sesji. Funkcja mysess_gc() usuwa wszystkie wiersze, ktrych wartosc pola LastUpdated wskazuje ze nie rekord nie byl uaktualniany przez ostatnie $aMaxLifetime sekund. Ponizszy kod pokazuje sposb wykorzystania mechanizmu sesji partego o baze danych.
<?php

Rozdzial 7 Sesje i stan aplikacji

88

include( "./mysql_session.php" ); session_start(); session_register( "aUser", "aAccount" ); $aUser = "Cidnie"; $aAccount = "1016"; ?> <html> <head> <title>Obsluga sesji z wykorzystaniem MySQL: Strona pierwsza</title> </head> <body> <?php print( "Uzytkownik: $aUser<br>" ); print( "Konto: $aAccount<br>" );?> <br><br> <a href="mysql_session_mgmt2.phtml?<?=SID?>">Przejscie do nastepnej strony</a> </body> </html>

Poprzedni przyklad pokazuje jak latwo mozna utworzyc i uzywac wlasny mechanizm przechowywania danych sesji w PHP. W przykladzie tym mozna zastosowac kilka optymalizacji i usprawnien ulepszajacych dzialanie, ale przyklady maja za zadanie pokazac oglna idee. Jezeli potrzebujesz w swojej aplikacji zastosowac zmienne sesji, PHP zawiera rozwiazania pozwalajace na dowolna implementacje takiego mechanizmu.

Inne funkcje i opcje dotyczace sesji


PHP posiada jeszcze kilka nie omwionych jeszcze funkcji obslugi sesji. Funkcje session_name(), session_module_name(), session_save_path() i session_id() moga byc uzyte do odczytywania lub ustawiania odpowiednio, biezacej nazwy sesji, nazwy modulu, sciezki zapisu i identyfikatora. Mialem klopot wymyslic projekt, w ktrym bylaby zalecana zmiana tych parametrw w czasie pracy. Jezeli twoja zmienna posiada tak duzo zmiennych sesji, ze musisz korzystac z dzielenia ich przy pomocy tych funkcji powinienes powaznie rozwazyc zastosowanie sugestii zamieszczonych w czesci Inzynieria programowania a sesje, umieszczony w dalszej czesci rozdzialu. W pliku php.ini znajduja sie nastepujace opcje konfigurujace mechanizm sesji: sessions.save_handler. Opcja ta pozwala na zdefiniowanie nazwy programu obslugi uzywanego do zapisywania i odczytywania danych zwiazanych z sesja. Mozliwe sa wartosci files, user i mm. Opcja ta moze byc odczytywana lub zmieniana w czasie pracy za pomoca funkcji session_module_name(). Ustawienie jej wartosci na files powoduje zapisywanie danych sesji w pliku na serwerze WWW. Ustawienie na user, oznacza, ze aplikacja posiada wlasny mechanizm obslugi. Wartosc mm powoduje korzystanie z wsplnej pamieci serwera WWW. Jezeli wywolasz funkcje session_set_save_handler(), wartosc opcji jest niejawnie przestawiana na user. Wartoscia domyslna jest files. session.save_path. Opcja okresla argument przekazywany do funkcji obslugi sesji. Jezeli uzywasz wbudowanego mechanizmu przechowywania danych, jest to nazwa katalogu gdzie sa tworzone pliki. Wartoscia domyslna jest /tmp. session.name. Opcja okresla nazwe sesji, uzywana rwniez jako nazwa cookie. Powinna zawierac jedynie znaki alfanumeryczne. Wartoscia domyslna jest PHPSESSID. session.auto_start. Opcja okresla, czy modul sesji automatycznie uruchamia sesje na poczatku strony. Domyslna wartoscia jest 0 (wylaczony). session.lifetime. Pozwala okreslic w sekundach czas waznosci cookie wysylanego do przegladarki. Wartosc 0 oznacza do zamkniecia przegladarki. Wartoscia domyslna jest 0. session.serialize_handler. Opcja pozwala na zdefiniowanie nazwy programu obslugi uzywanego do serializacji i deserializacji danych. Dostepny jest wewnetrzny format PHP (o nazwie php) oraz WDDX (o nazwie wddx). WDDX jest dostepny jedynie po skompilowaniu PHP z obsluga WDDX. Wartoscia domyslna jest php. session.gc_probability. Opcja okresla prawdopodobienstwo w procentach uruchomienia funkcji gc (usuwania nieuzytkw) podczas obslugi zadania. Usuwanie nieuzytkw polega na usuwaniu zmiennych sesji zapisanych na serwerze WWW. Poniewaz czesto niemozliwe jest okreslenie, kiedy sesja sie zakonczyla, PHP wywoluje funkcje usuwania nieuzytkw usuwajaca zmienne sesji, ktre nie byly uaktualniane przez okreslony czas (patrz session.gc_maxlifetime). Wartoscia domyslna jest 1, co oznacza, ze 1% uruchomien sesji powoduje wykonanie funkcji usuwania nieuzytkw. Jezeli do PHP Kompendium wiedzy 89

przesylania identyfikatora sesji uzywane sa metody GET i POST, nalezy zwiekszyc ta wartosc. Powodem tego jest mozliwosc zapisania jako zakladki adresu URL, ktry posiada dolaczony identyfikator sesji. Prawdopodobnie nie chcesz, aby uzytkownicy po dluzszym czasie kontynuowali stara sesje. session.gc_maxlifetime. Opcja okresla ilosc sekund, po ktrych dane sa uwazane za nieuzytki i usuwane. Domyslnie jest to 1440 sekund (24minuty). W zaleznosci od aplikacji mozesz wydluzac lub skracac ten czas. session.referer_check. Opcja okresla, czy identyfikatory sesji odwolujace sie do zewnetrznych witryn sa usuwane. Jezeli identyfikator sesji jest przesylany w adresie URL, uzytkownicy nie zdajac sobie sprawy ze skutkw moga publikowac identyfikator sesji. Sytuacja taka moze prowadzic do problemw z bezpieczenstwem serwera, ktrych mozna uniknac stosujac ta opcje. Domyslnie jest ustawiona na 0. session.entropy_file. Opcja pozwala na podanie sciezki do zewnetrznego zrdla (pliku), ktre bedzie uzywane jako dodatkowe zrdlo entropii do generowania identyfikatorw sesji. Moga to byc /dev/random lub /dev/urandom, dostepne we wielu systemach Unix. session.entropy_length. Opcja pozwala okreslic ilosc bajtw, ktre nalezy odczytac z pliku okreslonego w poprzedniej opcji. Domyslnie jest to 0 (wylaczone). session.use_cookies. Opcja pozwala na zdecydowanie czy do przechowywania identyfikatora sesji na komputerze klienta uzywane beda cookie. Domyslnie jest to 1 (wlaczone). PHP zapewnia ogromna elastycznosc przy obsludze sesji. Projektujac aplikacje korzystajaca ze zmiennych sesji nalezy rozwazyc wszystkie dostepne opcje. Mimo, ze uzycie cookie wydaje sie najprostszym rozwiazaniem, moze to spowodowac powazne problemy, poniewaz uzytkownicy moga wylaczyc obsluge cookie. Inne metody przesylania identyfikatora sesji wymagaja wiecej pracy, ale korzystne jest wczesniejsze planowanie. Polecam metode przesylania identyfikatora sesji w adresie URL, poniewaz metoda ta wymaga podjecia decyzji na temat stron, ktre beda uzywaly mechanizmu sesji. Polecam rwniez uzycie projektu witryny opartego na szablonach (szczegly w rozdziale 12 Oddzielanie kodu HTML od PHP), poniewaz powoduje on, ze reczne przesylanie identyfikatora sesji jest o wiele prostsze niz w przypadku projektu pokazanego w tym rozdziale.

Uzycie PHPLIB do obslugi sesji


W rozdziale 6 Wsplpraca z bazami danych przedstawialismy PHPLIB, jako swietna biblioteke zawierajaca niektre zaawansowane funkcje do tworzenia aplikacji opartych o PHP. PHPLIB byla jedna z pierwszych (i prawdopodobnie najbardziej znana) bibliotek klas zawierajacych obsluge sesji w PHP. Koncepcyjnie jest ona podobna do rozwiazania zastosowanego w PHP4. Obsluga sesji w PHPLIB jest oparta w calosci o kod PHP, wiec jest mozliwa do rozbudowy i konfiguracji poprzez dziedziczenie i rozbudowe klasy bazowej. Posiada ona rwniez niektre opcje inicjalizacji, ktre moga byc bardzo uzyteczne w naszych aplikacjach. Obsluga sesji w PHPLIB oparta jest o klase kontenerowa zdefiniowana w PHPLIB. Uzywana jest jedna z klas pochodnych po klasach CT_xxx, przeznaczonych do obslugi przechowywania zmiennych sesji. Powoduje to, ze PHPLIB mozna rozszerzyc w sposb, ktry pozwala na przechowywanie zmiennych sesji w praktycznie dowolnym miejscu. PHPLIB wymaga rwniez, aby funkcje obslugi strony sygnalizowaly poczatek i koniec strony, oraz ktra z funkcji PHPLIB jest uzywana na stronie. Wydruk 7.10 zawiera skrypt ilustrujacy uzycie PHPLIB do zapisu zmiennych sesji w bazie MySQL. Przyklad ten jest identyczny z przedstawionym na wydruku 7.9, oprcz tego, ze korzysta on z cookie do przechowywania identyfikatora sesji na komputerze klienta. Wydruk 7.10. Obsluga sesji w PHPLIB
<?php include( "page.inc" ); include( "ct_sql.inc" ); include( "session.inc" ); include( "db_mysql.inc" ); // Specjalizacja klasy DB_Sql do polaczenia z // naszym serwerem MySQL class MySQLDB extends DB_Sql { var $Host = "localhost"; var $Database = "mydb"; var $User = "root";

Rozdzial 7 Sesje i stan aplikacji

90

var $Password = "root"; } class MySQLCt extends CT_Sql { var $classname = "MySQLCt"; var $database_table = "active_sessions"; var $database_class = "MySQLDB"; } class MySqlSession extends Session { var $classname = "MySqlSession"; // obsluga przechowywania var $mode = "cookie"; var $lifetime = 0; // uzycie cookie sesji var $that_class = "MySQLCt"; // nazwa uzywanego kontenera } page_open( array( "sess" => "MySqlSession" ) ); $sess->register( "aUser" ); $sess->register( "aAccount" ); $aUser = "Cidnie"; $aAccount = "1016"; ?> <html> <head> <title>Obsluga sesji w PHPLIB: Pierwsza strona </title> </head> <body> <?php print( "Uzytkownik: $aUser<br>" ); print( "Konto: $aAccount<br>" ); ?> <br><br> <a href="phplib_session_mgmt2.phtml">Nastepna strona</a> </body> </html> <?php page_close(); ?>

PHPLIB jest niezmiernie elastycznym narzedziem do zarzadzania danymi sesji. Tak jak PHP posiada on mechanizmy zapewniajace zapisywanie danych sesji w liku, pamieci wspldzielonej oraz tabeli bazy danych. Kod z wydruku 7.10 jest nieco bardziej skomplikowany, ale doswiadczeni programisci na pewno zauwaza, ze jest on bardzo latwo rozszerzalny poprzez dziedziczenie bazowych klas obslugi sesji. Pierwsza klasa pochodna, MySQLDB jest klasa niezbedna do nawiazania polaczenia z naszym serwerem bazy danych. Kolejna klasa, MySQLCt jest klasa pochodna po klasie kontenerowej CT_Sql, ktra jest podstawowa klasa kontenerowa zapewniajaca zapisywanie danych w bazach danych SQL. Zawiera ona odwolanie do klasy MySQLDB, ktra jest uzywana do zrealizowania dostepu do tabel. Ostatnia klasa, MySQLSession rozszerza bazowa klase Session i ustawia klase MySQLCt jako klase zapisujaca wszystkie dane sesji. Tabela bazy danych wymagana przez mechanizm obslugi sesji w PHPLIB posiada nastepujaca strukture:
CREATE TABLE active_sessions ( sid varchar(32) not null, name varchar(32) not null, val text, changed varchar(14) not null, PRIMARY KEY (name, sid), KEY changed (changed) );

Po utworzeniu klas pochodnych PHPLIB wykorzystuje funkcje page_open() do dodania funkcji sesji do biezacej strony. Wywolanie tej funkcji powoduje utworzenie globalnej zmiennej $sess, ktra jest wykorzystywana w kolejnych wywolaniach obslugi sesji. Podstawowe funkcje klasy Session w PHPLIB sa praktycznie identyczne z mozliwosciami wbudowanego mechanizmu PHP. Po utworzeniu klasy rejestrowane i wykorzystywane sa zmienne sesji. Jedynym dodatkowym wymaganiem jest wywolanie w skrypcie funkcji page_close() do zaznaczenia konca skryptu. Tak jak we wbudowanym mechanizmie sesji PHP, PHPLIB pozwala na wykorzystanie cookie lub zmiennych GET i POST do przesylania identyfikatora sesji. PHPLIB posiada rwniez narzedzia do tworzenia klas kontenerowych uzywanych do zapisywania zmiennych sesji na dowolnie wymyslonym serwerze. Dodatkowa funkcja PHPLIB jest mozliwosc dostarczania pliku inicjalizujacego uzywanego do inicjalizacji zmiennych sesji na poczatku kazdej sesji. Ponizszy kod pokazuje przyklad takiego pliku inicjalizujacego:
<?php global $lang; $lang = "pl"; $sess->register("lang"); // jezyk aplikacji // domyslnie polski

91

PHP Kompendium wiedzy

global $cur; $cur = "PLN"; $sess->register("cur"); global $cart; $cart = new Shop_Cart; $sess->register("cart"); ?>

// waluta aplikacji // domyslnie zlotwki

// utworzenie obiektu wzka na zakupy // zdefiniowanego w local.inc // zarejestrowanie obiektu

Mimo, ze PHP posiada wbudowany mechanizm sesji zblizony do rozwiazania zastosowanego w PHPLIB, moze byc przydatny dostep do calego kodu zrdlowego PHP, na przyklad aby wykonac niektre optymalizacje. Mozesz rwniez stosowac PHPLIB do realizowania sesji w starszych wersjach PHP, ktre nie posiadaja wbudowanego mechanizmu sesji.

Tworzenie wlasnego mechanizmu sesji


W niektrych przypadkach w aplikacji moze nie byc potrzebny kompletny mechanizm sesji. W wielu wypadkach jedyna dana, jaka musimy przesylac pomiedzy stronami, jest klucz glwny lub identyfikator. W takich przypadkach bardziej efektywne bedzie przesylanie identyfikatora pomiedzy stronami aplikacji za pomoca zmiennych GET i POST. Majac ta wartosc mozesz odczytac z bazy danych wszystkie potrzebne na stronie dane. Rozwiazanie to jest proste do zrealizowania i nie wymaga zadnych dodatkowych narzutw wprowadzanych przez przedstawione w tym rozdziale narzedzia obslugi sesji. Z drugiej strony, przesylanie identyfikatora wymaga nieco dokladniejszego projektowania aplikacji. Dodatkowo przesylanie wartosci identyfikatora otwartym tekstem moze powodowac naruszenie bezpieczenstwa, wiec korzystajac z tej metody zaleca sie uzywanie odpowiedniej mechanizmu szyfrowania. Tak jak w przypadku wszystkich innych aspektw projektowania aplikacji nalezy wykona dokladna analize potrzeb aplikacji i na jej podstawie wybrac wlasciwy schemat zarzadzania sesjami. Wybr niewlasciwego narzedzia na poczatku calego procesu moze byc kosztowne i prowadzic w dluzszej perspektywie do problemw z konserwacja i rozwojem aplikacji.

Inzynieria programowania a sesje


Zmienne sesji moga byc niezmiernie istotne we wielu aplikacjach WWW. Sa one elastyczne i latwe do uzycia, ale tak jak wszystkie inne narzedzia programistyczne powinny byc uzywane ostroznie i wedlug projektu. Poniewaz zmienne sesji sa bardzo latwe do uzycia, czesto sa naduzywane w takim samym stopniu, jak zmienne globalne przy pisaniu tradycyjnych aplikacji. Projektujac aplikacje WWW nalezy szczeglowo rozwazyc wszystkie zastosowania, w ktrych nalezy skorzystac ze zmiennych sesji. Decyzja uzycia zmiennej sesji powinna byc oparta na takich samych przeslankach, jak decyzja uzycia zmiennej globalnej. Steve McConnell, autor ksiazki Code Complete (Microsoft Press, 1993) uwaza, ze powodem uzycia zmiennej globalnej moga byc nastepujace przypadki: Przechowywanie wartosci globalnych. Dane globalne, to dane odzwierciedlajace stan calej aplikacji, na przyklad tryb pracy (wersja prbna, pelna). Moze byc to duze zbiory danych uzywane w calej aplikacji, na przyklad tabele slownikowe. Zastepowanie nazwanych stalych. Poniewaz PHP posiada stale, zastosowanie to nie jest dopuszczalne. Uproszczenie uzycia bardzo czesto uzywanych danych. Czasami niektre dane sa tak czesto uzywane w aplikacji, ze wystepuja w liscie parametrw kazdej procedury. Eliminowanie wedrujacych danych. Czasami wartosci sa przekazywane do procedury tylko po to, aby mogly byc przekazane do kolejnej. Gdy procedury w takim lancuchu nie korzystaja z takich danych, sa one nazywany danymi wedrujacymi. Lista ta wskazuje powody rozwazane uzycia zmiennych globalnych przy programowaniu zwyklych aplikacji, ale decyzja uzycia zmiennej sesji powinna byc oparta na tych samych kryteriach. Badz ostrozny przy uznawaniu zmiennej za zmienna sesji, poniewaz wydaje sie wystepowac w kazdej procedurze i na kazdej stronie witryny WWW. Takie podejscie najczesciej prowadzi do naduzywania danych globalnych i zmiennych sesji. Nalezy pamietac, ze po zdefiniowaniu w aplikacji zmiennych sesji, kazda strona bioraca udzial w sesji musi zaladowac wszystkie zmienne sesji nawet, gdy nie korzysta z zadnej. Nalezy rwniez Rozdzial 7 Sesje i stan aplikacji 92

unikac uzycia zmiennych sesji jedynie dlatego, ze zapewniaja one wygodniejszy dostep do danych zwiazanych z sesja. W jednym z moich ostatnich kontraktw natrafilem na swietny przyklad nieprawidlowego uzycia zmiennych sesji. W aplikacji uzytkownicy mogli utworzyc zbir danych i udostepnic je do modyfikacji przez innego uzytkownika. Uzytkownicy, ktrym dane byly udostepniane byli doradcami, ktrym pierwsi uzytkownicy ufali. Gdy uzytkownik udostepnial dane doradcy, dane o tym byly zapisywane w bazie danych. Tabela uprawnien zawierala identyfikator pierwotnego uzytkownika i doradcy oraz identyfikator danych udostepnianych przez uzytkownika. Gdy doradca logowal sie do aplikacji, musial na poczatku wybrac zbir danych do ogladania. W aplikacji byly ustawiane zmienne sesji, ktre zawieraly identyfikator konta doradcy, oraz identyfikator przegladanych danych klienta. Jezeli te identyfikatory bylyby jedynymi zmiennymi sesji, nie bylo by problemu. Jednak ktos zdecydowal, aby nie korzystac z bazy danych do sprawdzania uprawnien i w zmiennej sesji przesylana byla lista zleconych identyfikatorw danych. Za kazdym razem, gdy doradca otwieral w programie zbir danych, lista ta byla uaktualniana (wraz z tabela uprawnien). Nastepnie, gdy element danych byl pobierany z bazy, jego identyfikator byl poszukiwany w zawartosci zmiennej sesji zamiast w bazie danych. Glwnym problemem powodowanym przez takie podejscie byly klopoty z synchronizacja danych. Jezeli pierwotny uzytkownik uaktualnil tabele uprawnien w czasie, gdy doradca byl zalogowany w aplikacji, doradca mial dostep tylko do danych zleconych w trakcie rozpoczynania sesji. Dodatkowo, rozwijanie aplikacji wedlug tego modelu bylo frustrujace, poniewaz programista nie wiedzial czy uzywac danych z bazy danych czy ze zmiennych sesji. Takie niefortunne dzialanie bylo spowodowane tym, ze pierwszy programista nie zapewnil realizacji dwch celw. Po pierwsze, zmienne sesji zostaly zastosowane, aby wyeliminowac odwolania do baz danych (aby przyspieszyc ladowanie strony) przy pobieraniu danych o uprawnieniach. Po drugie, zmienne sesji byly uzywane do uproszczenia sprawdzania uprawnien w kodzie strony. Pierwszy cel nie zostal zrealizowany, poniewaz programista nie laduje jawnie zmiennych sesji, sa one automatycznie odczytywane z trwalego nosnika. Na wszystkich stronach aplikacji dane o uprawnieniach sa ladowane z serwera WWW i po zakonczeniu strony ponownie zapisywane. Proces ten powoduje, ze nawet strony, ktre nie korzystaja z uprawnien, sa spowolnione przez proces ladowania zmiennych sesji. Ladowanie danych uprawnien z bazy danych jedynie na stronach, ktre wymagaja tych informacji, jest o wiele bardziej efektywne. Drugi cel nie zostal spelniony, poniewaz programista nie korzystal w pelni z wydajnosci bazy danych. Na wielu stronach kod wygladal nastepujaco:
WYIERZ wszystkie potrzebne dane z konta pierwotnego uzytkownika DLA KAZDEGO WIERSZA JEZELI identyfikator tego wiersza znajduje sie na liscie uprawnien w zmiennej sesji wyswietl lub wykorzystaj dane W PRZECIWNYM WYPADKU ignoruj ten wiersz, poniewaz doradca nie powinien go widziec

Jak wspominalismy w rozdziale 6 Wsplpraca z bazami danych, nalezy wykorzystywac mozliwosci bazy danych do poprawienia wydajnosci aplikacji. Poprzedni przyklad kodu moze byc zastapiony zapytaniem, w ktrym tabela z danymi jest polaczona z tabela z uprawnieniami. Spowoduje to usuniecie ogromnej ilosci kodu i wyeliminuje koniecznosc przechowywania listy uprawnien w danych sesji. Zmienne sesji sa niezmiernie potrzebne przy programowaniu aplikacji WWW, ale powinny byc uzywane rozwaznie. W trakcie projektowania nalezy rozwazyc wszystkie alternatywne sposoby uzyskana tego samego efektu. Wiekszosc aplikacji WWW wymaga zastosowania tylko kilku zmiennych sesji. Gdy chcesz zastosowac zmienna sesji, postaw sobie nastepujace pytania: Czy ta zmienna jest uzywana w calym programie? Jezeli ta wartosc jest uzywana na kazdej stronie aplikacji, jest to swietny kandydat na zmienna sesji. Na przyklad, jezeli aplikacja korzysta z logowania uzytkownikw, dobrze jest przechowywac identyfikator uzytkownika w zmiennej sesji. Czy zmienna ta jest unikalna dla tej sesji? Jezeli jest to na pewno dana zwiazana z sesja, zapamietaj ja w zmiennej sesji. Na przyklad, jezeli tworzysz wzek na zakupy, musisz prawdopodobnie przechowywac jego identyfikator w zmiennej sesji. Jednak jezeli aplikacja korzysta z kilku trwalych wzkw na zakupy w ktrych uzytkownik moze przechowywac zamwienie w czasie kilku sesji, prawdopodobnie nie potrzebujesz zmiennej sesji, ale dobrze zaprojektowanej bazy danych. Czy dana jest dana kluczowa? Pytanie to jest zwiazane z pierwszym. Jezeli aplikacja korzysta ze zmiennych sesji do przechowywania identyfikatora uzytkownika, unikaj przechowywania innych danych 93 PHP Kompendium wiedzy

zwiazanych z uzytkownikiem w zmiennej sesji. Zamiast tego, w razie potrzeby skorzystaj z identyfikatora do odczytania potrzebnych danych. Na przyklad, jezeli aplikacja personalizuje strony, nie przechowuj zmiennych potrzebnych do tego celu w sesji. Przechowuj w sesji identyfikator i wykorzystaj kilka funkcji odczytujacych dane potrzebne do personalizacji. Struktura taka nie tylko eliminuje powtrzenia danych, ale rwniez pozwala uzytkownikowi na zmiane swoich ustawien w jednej sesji i natychmiastowe odzwierciedlenie tego w drugiej rwnoleglej sesji. Czy aplikacja na pewno potrzebuje zmiennych sesji? Pytanie to moze wydawac sie oczywiste, ale czesto jest pomijane z powodu latwosci uzywania zmiennych sesji. To, ze uzytkownik przeglada witryne i przeprowadza jakies operacje niekoniecznie oznacza, ze potrzebna jest sesja. Zmienne sesji nie powinny zastepowac innych mechanizmw przechowywania danych. Jezeli odpowiedz na te pytania nie zgadza sie z zasugerowanymi odpowiedziami, nalezy rozwazyc zastosowanie innych metod przechowywania danych. Sesje sa swietnym narzedziem, ale nieprawidlowo uzywane moga doprowadzic do stworzenia aplikacji pelnej bledw i trudnej do utrzymania.

Podsumowanie
W PHP dostepne jest kilka swietnych narzedzi do stworzenia mechanizmu sesji. Nalezy wybrac mechanizm, ktry najlepiej pasuje do potrzeb i ktrego zastosowanie bedzie przynosilo owoce w dluzszym czasie a nie tylko bedzie mial krtkoterminowy wplyw na kodowanie aplikacji. Nieprawidlowe uzycie zmiennych sesji moze doprowadzic do stworzenia aplikacji trudnej do rozwijania, ktra posiada trudne do zidentyfikowania bledy.

Rozdzial 7 Sesje i stan aplikacji

94

Rozdzial 8. Uwierzytelnianie
Wstep
W poprzednim rozdziale Sesje i stan aplikacji omwione zostaly sposoby sledzenia uzytkownikw witryny WWW w celu zapewnienia ciaglosci pracy aplikacji. Ten rozdzial poswiecony bedzie sposobom upewnienia sie, ze uzytkownicy maja wystarczajace uprawnienia do pracy w aplikacji. Istnieja rzne schematy uwierzytelniania przeznaczone do rznych zadan. Wiekszosc serwerw WWW posiada narzedzia przeznaczone do autoryzacji uzytkownikw w oparciu o uprawnienia i pliki serwera. W tym rozdziale zajmiemy sie uwierzytelnianiem opartym na mechanizmach serwera, ale jedynie w oparciu o serwer Apache na Linuksie (Windows i IIS rwniez umozliwiaja uwierzytelnianie, ale nie zostanie ono tutaj opisane). W dalszej czesci rozdzialu przedstawiony zostanie rwniez mechanizm niezalezny od serwera i platformy.

Podstawowe uwierzytelnianie w Apache


Rozdzial ten rozpoczniemy omwieniem podstawowego schematu uwierzytelniania dostepnego w serwerze WWW Apache oraz problemami zwiazanymi z ta metoda. Osoby znajace dyrektywy uwierzytelniania Apache oraz przeznaczenie plikw .htaccess i innych plikw konfiguracyjnych serwera Apache nie dowiedza sie tutaj zbyt wiele nowego. Nawet w prostej witrynie moze byc potrzebne ograniczenie dostepu do niektrych stron. Wykorzystanie mechanizmu uwierzytelniania dostarczanego przez serwer WWW jest zwykle szybkim i efektywnym sposobem zrealizowania takiego mechanizmu. Na przyklad moze byc niezbedne stworzenie zbioru stron przeznaczonych do administracji witryna, za pomoca ktrych mozna przegladac i zmieniac wybrane elementy witryny. Strony te nie moga byc dostepne dla wszystkich uzytkownikw, ale administrator musi miec do nich dostep z dowolnej przegladarki. Aby zrealizowac takie zalozenia mozesz przeniesc wszystkie strony administracyjne do osobnego podkatalogu w drzewie katalogw witryny WWW oraz zmienic konfiguracje Apache tak, aby dostep do stron znajdujacych sie w tym katalogu wymagaly autoryzacji. Odpowiednie dyrektywy konfiguracji moga znajdowac sie w pliku httpd.conf lub .htaccess w chronionym katalogu. Jezeli masz dostep do plikw konfiguracyjnych Apache powinienes skorzystac z nich zamiast z pliku .htaccess. Korzystanie z pliku .htaccess jest mniej efektywne od wykorzystania standardowych plikw konfiguracyjnych, poniewaz jest on odczytywany za kazdym zadaniem pliku z katalogu zawierajacego plik .htaccess. Jednak jezeli witryna jest umieszczona na dzierzawionym serwerze, prawdopodobnie nie bedziesz mgl zmienic plikw konfiguracyjnych i zrestartowac serwera WWW w celu pobrania zmienionej konfiguracji. Na wydruku 8.1 zamieszczony jest wydruk prostej strony HTML zawierajacej lacze do podkatalogu ze strona administracyjna. Strona administracyjna znajduje sie w katalogu wymagajacym uwierzytelniania, wiec klikniecie tego lacza spowoduje, ze przegladarka wyswietli standardowe okno uwierzytelniania, pokazane na rysunku 8.1. Wydruk 8.2 zawiera dyrektywy konfiguracji Apache ktre powoduja wyswietlenie okna logowania. Wydruk 8.1. Prosta strona HTML z laczem do stron administracyjnych
<html> <head> <title>Proste uwierzytelnianie Apache</title> </head> <body> <a href="admin/index.phtml">Przejdz do strony administratora</a> </body> </html>

Wydruk 8.2. Dyrektywy konfiguracji Apache wlaczajace podstawowe uwierzytelnianie


AuthUserFile /www/auth_users AuthName Adminstrative

AuthType Basic <Limit GET> require valid-user </Limit>

Rysunek 8.1. Okno dialogowe uwierzytelniania w przegladarce

Wiecej informacji na temat uzycia uwierzytelniania Apache mozna znalezc w Sieci oraz we wielu swietnych ksiazkach poswieconych serwerowi Apache. Ten rodzaj uwierzytelniania wymaga wsplpracy pomiedzy przegladarka i serwerem. Mechanizm ten wyglada nastepujaco: gdy uzytkownik musi zostac autoryzowany, serwer WWW wysyla zadanie 401 do przegladarki a przegladarka odpytuje uzytkownika i odsyla wprowadzone przez niego dane do serwera. Jezeli serwer zaakceptuje uwierzytelnianie, chroniony zasb jest udostepniony uzytkownikowi. Przegladarka wysyla wprowadzone dane do serwera podczas zadania sprowadzenia wszystkich kolejnych stron az do zakonczenia pracy przegladarki. PHP posiada zmienne globalne, ktrych mozesz uzyc w aplikacji w celu odczytania danych autoryzacji. Mozesz skorzystac ze zmiennych $PHP_AUTH_USER oraz $PHP_AUTH_PW do odczytania nazwy uzytkownika i hasla. Wydruk 8.3 zawiera strone wyswietlajaca dane autoryzacji. Na rysunku 8.2. pokazana jest zawartosc tej strony po przejsciu do niej poprzez lacze znajdujace sie na stronie z wydruku 8.1. Wydruk 8.3. Wyswietlanie zawartosci 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>" ); print( "PHP_AUTH_PW: $PHP_AUTH_PW<br>" ); ?> </body> </html>

Rysunek 8.2. Zmienne autoryzacji w PHP

Schemat autoryzacji Apache zapewnia podstawowy stopien bezpieczenstwa witryny. Jest on szczeglnie uzyteczny w sytuacjach, gdy chcesz chronic wszystkie strony i inne zasoby znajdujace sie we fragmencie drzewa Rozdzial 8 Uwierzytelnianie 96

katalogw witryny. Ograniczeniem stosowania tej metody jest koniecznosc dodawania i usuwania uzytkownikw poprzez wykonanie odpowiednich polecen na serwerze. W nastepnej czesci zostanie opisane w jaki sposb mozna wykorzystac PHP do aktualizacji pliku hasel, co pozwoli na stworzenie narzedzia WWW do dodawania i usuwania uzytkownikw.

Aktualizacja pliku .htaccess przy uzyciu PHP


Jezeli podstawowe uwierzytelnianie serwera WWW jest wystarczajace w tworzonej aplikacji, mozna przy uzyciu PHP stworzyc narzedzie administracyjne upraszczajace zarzadzanie uzytkownikami. Mozna udostepnic to narzedzie zaufanym osobom, ktrzy beda mogli operowac uzytkownikami bez koniecznosci udostepniania im bezposredniego dostepu do serwera. Programisci zespolu The Webmasters Net (http://www.theWebmasters.net/) stworzyli dwie klasy sluzace do zarzadzania uzytkownikami i grupami plikw dla celw podstawowego uwierzytelniana. Do manipulacji standardowym plikiem Apache htpasswd mozna wykorzystac klase Htpasswd. Na wydruku 8.4 pokazany zostal przyklad, jak mozna wykorzystac te klase do autoryzacji uzytkownika, przy uzyciu bardzo malej ilosci kodu. Przyklad korzysta z tego samego pliku, ktry zostal uzyty w poprzednim przykladzie. Wydruk 8.4. Sprawdzanie poprawnosci autoryzacji uzytkownika za pomoca klasy Htpasswd
<html> <head> <title>Szybkie sprawdzenie uzytkownika z uzyciem klasy Htpasswd</title> </head> <body> <?php include( "./class.Htpasswd.php3" ); $aHTPasswd = new Htpasswd("/www/auth_users"); if ( !$aHTPasswd->EXISTS ) { print( "Blad autoryzacji<br>" ); } else { if ( $aHTPasswd->verifyuser( "phpbook", "phpbook" ) ) { print( "phpbook to prawidlowy uzytkownik<br>" ); } else { print( "phpbook nie jest prawidlowym uzytkownikiem<br>" ); } } ?> </body> </html>

Klase Htpasswd mozna rwniez wykorzystac do dodawania nowych uzytkownikw, usuwania uzytkownikw, zmiany hasla, sprawdzania poprawnosci uzytkownika oraz zmiany jego nazwy. Przy pomocy tej klasy mozna napisac obszerne narzedzie do administracji uzytkownikami, ktre bedzie pomocne przy zarzadzaniu mechanizmem podstawowego uwierzytelniania serwera. Skrypty na wydruku 8.5, 8.6 i 8.7 zawieraja skrypty pokazujace, w jaki sposb mozna polaczyc wszystkie te operacje w jednym formularzu. Wydruk 8.5 zawiera pierwsza czesc skryptu. Jest ona uzywana do inicjalizacji skryptu i okreslenia czy strona jest ogladana pierwszy raz, czy zostala wywolana w wyniku zadania POST. Skrypt ten jest podobny do wielu przytoczonych do tej pory przykladw, ktre przesylaja dane do samego siebie i sa uzywane zarwno do wyswietlania jak i do zmiany danych. Wydruk 8.5. Uzycie klasy Htaccess do zarzadzania uzytkownikami
<?php include( "./class.Htpasswd.php3" ); $aHTPasswd = new Htpasswd("/www/auth_users"); if ( !$aHTPasswd->EXISTS ) { print( "Blad krytyczny<br>" ); exit; } if ( $REQUEST_METHOD == 'POST' ) { switch ( $acttype ) {

97

PHP Kompendium wiedzy

case 'none' : break; case 'add' : $aHTPasswd->addUser( $NewUserName, $NewUserPass ); print( "<b>Dodano uzytkownika $NewUserName</b><br>" ); break; case 'delete' : $aUserName = $aHTPasswd->USERS[$CurUserRow]["user"]; $aHTPasswd->deleteUser( $aUserName ); print( "<b>Usunieto uzytkownika $aUserName</b><br>" ); break; case 'rename' : $aUserName = $aHTPasswd->USERS[$CurUserRow]["user"]; $aHTPasswd->renameUser( $aUserName, $RenameName ); print( "<b>Nazwa uzytkownika zmieniona z $aUserName na $RenameName</b><br>" ); break; case 'changepass' : $aUserName = $aHTPasswd->USERS[$CurUserRow]["user"]; $aHTPasswd->changePass( $aUserName, $ChangePass ); print( "<b>Zmieniono haslo dla uzytkownika $aUserName</b><br>" ); break; } } ?>

$acttype

Jezeli skrypt ten zostanie wywolany w wyniku zadania POST, na podstawie wartosci zmiennej formularza podejmowana jest decyzja co do kolejnej akcji. Zmienna posiada piec mozliwych wartosci: none, add, delete, rename oraz changepass. W zaleznosci od wyboru uzytkownika podejmowana jest odpowiednia akcja. W skrypcie zalozono, ze wszystkie potrzebne dane sa prawidlowo wypelnione. Oczywiscie, aby program mgl byc normalnie uzywany niezbedne jest dodanie kodu kontroli poprawnosci. W nastepnej czesci skryptu ustawiana jest zmienna $acttype. Dla wszystkich przyciskw znajdujacych sie na formularzu zdefiniowana jest odpowiednia akcja. Do ustawiania ukrytej zmiennej formularza $acttype wykorzystujemy JavaScript. Wydruk 8.6. Ustawianie zmiennej $acttype
<html> <head> <title>Prosty program zarzadajacy uzytkownikami</title> <script language="JavaScript"> <!-function DoSubmit( aType ) { document.mainform.acttype.value = aType; document.mainform.submit(); } //--> </script> </head>

Ostatnia czesc skryptu pokazana na wydruku 8.7 jest po prostu strona HTML zawierajaca formularz. Kod PHP jest jedynie uzywany do wstawiania istniejacych uzytkownikw do listy SELECT. Kazdy przycisk na formularzu zawiera atrybut onClick, ktry powoduje wywolanie przedstawionej funkcji JavaScript, ktra realizuje wyslanie danych formularza do odpowiedniej strony. Wydruk 8.7. 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 zarzadzajacy uzytkownikami</h1> <h2>Dodanie uzytkownika</h2> Nazwa nowego uzytkownika: <input type="text" name="NewUserName"><br> Haslo: <input type="password" name="NewUserPass"><br> <input type="button" value="Dodaj" onClick="DoSubmit( 'add' );"> <hr> <h2>Zmiana uzytkownika</h2> <table> <tr> <td> <select name="CurUserRow" size="10"> <?php $nIndex = 0; foreach( $aHTPasswd->USERS as $aUser ) { print( "<option value=\"$nIndex\">$aUser[user]</option>" ); $nIndex++; } ?>

Rozdzial 8 Uwierzytelnianie

98

</select> </td> <td> Usuniecie zaznaczonego uzytkownika: <input type="button" value="Usun" onClick="DoSubmit( 'delete' );"> <br><br> Zmiana nazwy zaznaczonego uzytkownika: <input type="text" name="RenameName"><input type="button" value="Zmiana nazwy" onClick="DoSubmit( 'rename' );"><br><br> Zmiana hasla dla zaznaczonego uzytkownika: <input type="password" name="ChangePass"><input type="button" value="Zmiana hasla" onClick="DoSubmit( 'changepass' );"><br><br> </td> </tr> </table> </form> </body> </html>

Na rysunku 8.3. pokazana jest strona bezposrednio o dodaniu uzytkownika scott. Jak mwilismy wczesniej, skrypt ten nie jest kompletnym narzedziem zarzadzajacym uzytkownikami, a jedynie pokazuje sposb wykorzystania klasy Htpasswd. Mozna rwniez skorzystac z dostarczanej przez The Webmasters Net klasy Htgroup do tworzenia i zarzadzania grupami uzytkownikw. Rysunek 8.3. Program zarzadzajacy uzytkownikami w dzialaniu

Podstawowe uwierzytelnianie za pomoca PHP


Poprzednie dwie czesci opisywaly podstawowe uwierzytelnianie serwera Apache do ochrony fragmentw witryny WWW (zwykle katalogw). W niektrych przypadkach moze byc wymagane zabezpieczenie tylko niektrych stron aplikacji lub nie jest mozliwa modyfikacja odpowiednich plikw na serwerze WWW. W takim przypadku mozesz wykorzystac PHP do wysylania odpowiednich naglwkw do serwera i w ten sposb bezposrednio zadac autoryzacji. 99 PHP Kompendium wiedzy

Tak jak w przypadku wysylania innych danych naglwka, nalezy albo wysylac dane naglwkw przed wyslaniem jakichkolwiek danych strony, albo korzystac z buforowania wyjscia. Na wydruku 8.8 zamieszczony jest prosty skrypt zadajacy autoryzacji. Skrypt ten jest w postaci pliku dolaczanego, auth_include.inc, wiec bedzie go mozna latwo dodawac do wszystkich stron wymagajacych autoryzacji. Wydruk 8.8. Skrypt auth_include.php
<?php $aDoAuth = True; if ( isset( $PHP_AUTH_USER ) ) { if ( ( $PHP_AUTH_USER == "ryan" ) && ( $PHP_AUTH_PW == "dentist" ) ) { // prawidlowa nazwa uzytkownika i haslo $aDoAuth = False; } } if( $aDoAuth == True ) { Header( "WWW-Authenticate: Basic realm=\"My Realm\"" ); Header( "HTTP/1.0 401 Unauthorized" ); echo "Nie udalo sie zalogowanie do systemu.\n"; exit; } ?>

Skrypt ten na poczatku pracy sprawdza, czy ustawiona jest zmienna $PHP_AUTH_USER. Jezeli tak, to wartosci zmiennych $PHP_AUTH_USER i $PHP_AUTH_PW sa porwnywane z prawidlowa nazwa uzytkownika i haslem aplikacji. Jezeli sprawdzenie to sie powiedzie, nie ma potrzeby wysylania do przegladarki naglwka autoryzacji. Jezeli porwnanie nie uda sie skrypt wysyla do przegladarki naglwek HTTP 401, ktry powoduje wyswietlenie okna autoryzacji. Proces ten jest powtarzany az do podania wlasciwych danych autoryzacji, albo do przerwania uwierzytelniania przez uzytkownika. Dolaczenie tego pliku na poczatku dowolnego skryptu powoduje koniecznosc autoryzacji uzytkownika skryptu. Prawdziwy system uwierzytelniania nie powinien miec zaszytych nazw uzytkownikw i hasel w samym skrypcie. Zamiast tego nalezy wykorzystac baze danych lub usluge katalogowa (na przyklad LDAP) lub nawet pliki zawierajace dane uwierzytelniania. Jedna z zalet takiego podejscia jest mozliwosc odwolania uwierzytelnienia uzytkownika poprzez ponowne wyslanie naglwka HTTP 401. Mozna to wykorzystac do ponownego logowania uzytkownika po okreslonym czasie bezczynnosci lub do chronienia rznymi haslami rznych czesci aplikacji. PHP posiada wystarczajaco duzo narzedzi i elastycznosci aby mozna bylo napisac dowolny system autoryzacji uzytkownikw. Poprzednia metoda jest oparta o mozliwosc obslugi przez przegladarki wywolan HTTP 401 ale metoda ta posiada wiele ograniczen. Nastepna metoda jest bardziej niezalezna od platformy i posiada bardziej elastyczne podejscie do uwierzytelniania.

Kompletny system uwierzytelniania oparty o PHP


Wykorzystanie metody autoryzacji opisanej w poprzedniej czesci jest latwe i proste. Wiekszosc programistw WWW wykorzystywalo juz pliki .htaccess do zabezpieczania katalogw, wiec sposb ten jest zwykle dobrze znany. W tej czesci skupimy sie na implementacji, ktra nie polega na wywolaniach HTTP 401 z serwera, wymuszajacych na przegladarce wyswietlenie okna uwierzytelniania. Glwnym powodem uzycia tego typu implementacji jest zwiekszenie elastycznosci aplikacji. Ponizsza implementacja wykorzystuje klase Auth z PHPLIB. Jest to ekstremalnie solidna i elastyczna implementacja, ale przez o wymaga sporo zachodu, zanim mozna bedzie ja wykorzystac. Jednak po jej zaprogramowaniu jest swietnym zamiennikiem metody opisanej w poprzedniej czesci. Jezeli nie korzystamy z mechanizmw przegladarki przy wyswietlaniu okna uwierzytelniania, musimy sami tworzyc formularz HTML sluzacy do pobierania danych niezbednych dla naszej aplikacji. Dodatkowo, PHPLIB pozwala na stworzenie autoryzacji opartej na uprawnieniach, wiec do kazdej strony mozna przypisac wymagany poziom uprawnien dla kazdego z uzytkownikw. Mechanizm uwierzytelniania realizowany przez PHPLIB jest w wielu punktach podobny do mechanizmu obslugi sesji. Do dzialania wymaga on sesji PHPLIB. Schemat autoryzacji PHPLIB jest uruchamiany podczas wywolania funkcji PHPLIB page_open() i zazadanie wlasnosci sess. Gdy zostanie zazadana ta wlasnosc, Rozdzial 8 Uwierzytelnianie 100

PHPLIB sprawdza zalogowanie uzytkownika. Jezeli uzytkownik nie podawal wczesniej danych autoryzacji, PHPLIB wyswietla zdefiniowana przez uzytkownika strone. Strona ta pobiera dowolne dane, jakich aplikacja wymaga do prawidlowej autoryzacji uzytkownika. Nastepnie PHPLIB wywoluje dostarczona przez uzytkownika funkcje sprawdzajaca uprawnienia uzytkownika. Jezeli funkcja ta zaakceptuje uzytkownika, PHPLIB wyswietla strone a w przeciwnym wypadku nastepuje ponowne uwierzytelnianie. Na rysunku 8.4. pokazana jest interakcja pomiedzy klientem, serwerem WWW (i tym razem jest to 1U z Penguin Computing) oraz aplikacja PHP. Rysunek 8.4. Interakcja w schemacie autoryzacji PHPLIB

Z powodu elastycznosci jaka zapewnia PHPLIB wymagane jest wykonanie kilku niezbednych krokw zanim uzyjemy naszej klasy autoryzacji. Po pierwsze, na wydruku 8.9 pokazane sa klasy zdefiniowane przez uzytkownika niezbedne do stworzenia klasy Auth i klas ja wspomagajacych (Klasy sesji i bazy danych sa identyczne jak te, ktrych uzywalismy w rozdziale 7). W naszym przypadku dane autoryzacji znajduja sie w tabeli bazy danych MySQL. Tabela uzyta do autoryzacji jest zdefiniowana nastepujaco:
CREATE TABLE MyAuth ( FirstName varchar(20) SurName varchar(30) password varchar(20) PRIMARY KEY (FirstName, ); NOT NULL, NOT NULL, NOT NULL, SurName)

Wydruk 8.9. Przygotowanie klas uzywanych przez klase PHPLIB Auth


<?php include( "page.inc" ); include( "ct_sql.inc" ); include( "session.inc" ); include( "db_mysql.inc" ); include( "auth.inc" ); class MySQLDB extends DB_Sql { var $Host = "localhost"; var $Database = "mydb"; var $User = "root"; var $Password = "root"; } class MySQLCt extends CT_Sql { var $classname = "MySQLCt"; var $database_table = "active_sessions"; var $database_class = "MySQLDB"; } class MySqlSession extends Session { var $classname = "MySqlSession"; // Obsluga przechowywania var $mode = "cookie"; var $lifetime = 0; // uzycie cookie sesji var $that_class = "MySQLCt"; // wybr kontenera var $allowcache_expire = 0; } class Sample_Auth extends Auth { var $classname = "Sample_Auth"; var $lifetime = 20; // 20 minut (0 == ciagle) function auth_loginform() { include( "./sample_lform.htinc" ); } function auth_validatelogin() { global $FirstName, $SurName, $Password; $aDB = new MySQLDB; $aSQL = "select * from MyAuth where ( FirstName = "; $aSQL .= "'$FirstName' ) and ( SurName = '$SurName' )";

101

PHP Kompendium wiedzy

$aSQL .= "and ( Password = '$Password' )"; $aDB->query( $aSQL ); if ( $aDB->num_rows() > 0 ) { return $FirstName; } else { return False; } } } ?>

Klasa Sample_Auth dziedziczaca po klasie bazowej Auth zapewnia dzialanie specyficzne dla biezacej aplikacji. Zdefiniowane sa odpowiednie funkcje auth_loginform() i auth_validatelogin(). Funkcja auth_loginform() jest wywolywana, gdy klasa Auth wymaga uwierzytelnienia uzytkownika. Mozesz uzyc instrukcji print() do stworzenia formularza HTML potrzebnego do zalogowania, ale zwykle dolaczenie pliku jest latwiejsze. Na wydruku 8.10 pokazany jest plik uzyty w tym przykladzie. Wydruk 8.10. Przykladowy formularz logowania (sample_lform.htinc)
<?php global $FirstName; global $SurName; $aCurFirstName = ""; $aCurSurName = ""; if ( !empty( $FirstName ) ) { $aCurFirstName = $FirstName; } if ( !empty( $SurName ) ) { $aCurSurName = $SurName; } ?> <html> <head> <title>Formularz autoryzacji dla PHPLIB</title> </head> <body> <form action="<?=$this->url()?>" method="post"> <table> <tr> <td> Imie: </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> Haslo: </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 sa nieprawidlowe, sprbuj jeszcze raz.. </td> </tr> <?php } ?> </table>

Rozdzial 8 Uwierzytelnianie

102

</form> </body> </html>

Strona ta jest zaprojektowana jedynie do wyswietlania przez klase Auth. Na poczatku sprawdza, czy zmiene formularza maja jakies wartosci. Moze to sie zdarzyc, gdy wyswietlamy formularz po nieudanej autoryzacji uzytkownika W tym przypadku klasa Auth ponownie wyswietla formularz logowania. Wartosci zmiennych formularza sa przenoszone do pl formularza FirstName i SurName jedynie z grzecznosci (ale uzytkownik nie musi ponownie wpisywac tych danych). Nastepnie strona wyswietla trzy pola tekstowe do wprowadzenia imienia, nazwiska i hasla uzytkownika. Dane formularza sa wysylane do strony okreslonej przez $this->url(). W kontekscie tej strony zmienna $this wskazuje na biezacy obiekt klasy pochodnej po Auth. Funkcja url() zwraca strone, na ktrej byl uzytkownik zanim obiekt klasy interweniowal i wywolal nasza strone autoryzacji. Na koniec definiujemy ostrzezenie jakie zobaczy uzytkownik gdy poda niewlasciwe dane. Gdy dane formularza zostana przeslane do oryginalnej strony, Auth sprawdza ponownie dane autoryzacji. Aby to zrobic wywoluje ona zdefiniowana przez uzytkownika funkcje auth_validatelogin(). Na wydruku 8.11 pokazujemy funkcje uzyta w naszym przykladzie. Wydruk 8.11. Funkcja auth_validatelogin()
function auth_validatelogin() { global $FirstName, $SurName, $Password; $aDB = new MySQLDB; $aSQL = "select * from MyAuth where ( FirstName = "; $aSQL .= "'$FirstName' ) and ( SurName = '$SurName' )"; $aSQL .= "and ( Password = '$Password' )"; $aDB->query( $aSQL ); if ( $aDB->num_rows() > 0 ) { return $FirstName; } else { return False; } }

Funkcja odwoluje sie do zmiennych globalnych $FirstName, $SurName i $Password, zdefiniowanych w formularzu logowania. Ich wartosci sa wyszukiwane w tabeli MySQL zawierajacej trzy kolumny: FirstName, SurName i Password. Jezeli odnaleziony zostanie rekord w tabeli opisujacy biezacego uzytkownika, funkcja auth_validatelogin() zwraca imie uzytkownika (oczywiscie uzycie imienia jako identyfikatora uzytkownika nie bylo by zbyt dobrym pomyslem). Jezeli nie ma pasujacego rekordu, zwracana jest wartosc False. Na wydruku 8.12 pokazana zostala typowa strona WWW wykorzystujaca o autoryzacji klase Auth. W przykladzie wyswietlane sa cztery lacza do innych podobnych stron, wymagajacych autoryzacji. Ostatnia strona z listy zapewnia wylogowanie uzytkownika. Wydruk 8.12. Prosta strona wykorzystujaca klase Auth
<?php // bez buforowania (z witryny php.net) include( "./auth_phplib.php" ); page_open( array( "sess" => "MySqlSession", "auth" => "Sample_Auth" ) ); header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header ("Cache-Control: no-cache"); header ("Pragma: no-cache"); ?> <html> <head> <title>Przyklad uzycia klasy PHPLIB Auth</title> <META HTTP-EQUIV="Expires" CONTENT="-1"> <META HTTP-EQUIV="Pragma" CONTENT="no-cache"> </head> <body> <h2>Strona glwna</h2> Posiadasz uprawnienia do ogladania tej strony! <ul> <li><a href="test_auth_phplib.phtml">Strona glwna</a></li> <li><a href="test_auth_phplib2.phtml">Strona druga</a></li> <li><a href="test_auth_phplib3.phtml">Strona trzecia</a></li> <li><a href="test_auth_phplib_logout.phtml">Wylogowanie</a></li>

103

PHP Kompendium wiedzy

</ul> </body> </html> <?php page_close(); ?>

Pierwsza strona dolacza prosty plik uwierzytelniania a nastepnie wywoluje funkcje PHPLIB page_open(), ktra uaktywnia sesje i mechanizm uwierzytelniania. Na koncu strony wywolywana jest funkcja page_close(), ktra zapisuje dane sesji. Zmienne uwierzytelniania sa przesylane pomiedzy stronami przy pomocy mechanizmu sesji. Druga i trzecia strona jest funkcjonalnie identyczna z pierwsza. Strona Wylogowanie, zawiera na dole strony nastepujacy kod wymuszajacy wylogowanie uzytkownika:
<?php $auth->logout(); page_close(); ?>

Funkcja $auth->logout() moze byc wywolana w dowolnym momencie, a wymusza ona ponowne wywolanie autoryzacji uzytkownika na nastepnej stronie. Kilka wierszy w tym przykladzie nie jest zwiazane z mechanizmem uwierzytelniania. Wywolania funkcji header() oraz znaczniki <META> zapewniaja, ze przegladarka nie bedzie przechowywala strony w buforze. Kod ten jest dosyc wazny, poniewaz buforowane strony moga mylic uzytkownikw, ktrzy nie beda wiedzieli, czy sa juz zalogowani. Szczeglne klopoty sprawia Microsoft Internet Explorer, wiec podjeto szczeglne srodki zapewniajace prawidlowe dzialanie przykladw. Podczas testowania tego przykladu nie stwierdzilismy zadnych problemw w IE 5.5, wszystkich wersjach Netscape, WebTV i Opera. Jak wczesniej wspomnielismy, PHPLIB jest niezwykle elastycznym narzedziem, pozwalajacym na stworzenie wlasnego mechanizmu uwierzytelniania. Mozna stworzyc skomplikowane lub proste schematy uwierzytelniania, w zaleznosci od wymagan aplikacji. Zaleta tego podejscia jest mozliwosc tworzenia wlasnych formularzy logowania, porwnywanie wpisanych danych z danymi przechowywanymi na dowolnym nosniku informacji, oraz mozliwosc latwego wylogowania uzytkownika. Umieszczenie w aplikacji systemu zabezpieczen wydaje sie bardziej efektywne, szczeglnie dla poczatkujacych uzytkownikw, ktrzy moga byc zaskoczeni systemowymi oknami dialogowymi.

Podsumowanie
W tym rozdziale zostalo omwionych wiele aspektw uwierzytelniania uzytkownikw w aplikacjach PHP. Pierwsze kilka omwionych metod jest mocno zalezne od platformy, ale sa latwe do implementacji. Ostatnia metoda, wymagajaca uzycia klas PHPLIB jest bardziej zlozona, ale o wiele bardziej elastyczna i calkowicie przenosna pomiedzy serwerami WWW i systemami operacyjnymi. Jezeli aplikacja wymaga jakiegos typu uwierzytelniania uzytkownikw, powinienes w fazie projektowania okreslic specyficzne wymagania tej aplikacji. Niektre mechanizmy uwierzytelniania nie posiadaja wystarczajacej elastycznosci. Inne moga nie zapewniac dostatecznego poziomu bezpieczenstwa. Przy pomocy tego rozdzialu mozna skojarzyc twj potrzeby z oferowanymi przez poszczeglne metody mozliwosciami.

Rozdzial 8 Uwierzytelnianie

104

Rozdzial 9. Niezaleznosc od przegladarki


Wstep
Podczas pisania standardowych aplikacji interfejs uzytkownika jest tworzony dla potrzeb aplikacji i zwykle jest on przeznaczony dla jednej platformy. Nie przewiduje sie niespodziewanych zmian tego interfejsu w czasie dzialania programu w zaleznosci od uzytkownika, ktry uzywa aplikacji. W czasie pisania aplikacji dla WWW, interfejs uzytkownika nie jest juz tak niezmienny, poniewaz moze byc on odtwarzany przez rzne typy przegladarek na rznych platformach. Tworzenie aplikacji niezaleznej od przegladarki wymaga mozliwosci wykrywania typu przegladarka i wykorzystywania jej mozliwosci. Mimo, ze wiekszosc nowoczesnych przegladarek bedzie wyswietlalo aplikacje w podobny sposb, zawsze istnieja rznice. Jezeli aplikacja wymaga jakiejs wlasnosci przegladarki, nalezy tak napisac aplikacje, aby sprawdzala typ uzytej przegladarki i odpowiednio reagowala. PHP pozwala na kilka metod wykrywania rodzaju przegladarki, rozpoczynajac od stworzenia wlasnego rozwiazania do uzycia narzedzi firm trzecich. W rozdziale tym przedstawimy przyklady wielu metod, z ktrych bedziesz mgl wybrac odpowiednia dla twojej aplikacji.

Rozpoczynamy
Na najbardziej podstawowym poziomie, PHP pozwala na odczytanie typu przegladarki poprzez zmienna globalna $HTTP_USER_AGENT. Ciag ten jest wysylany przez przegladarke do serwera wraz z kazdym zadaniem. Jezeli wystarczy ci proste rozpoznanie typu przegladarki, mozna wykorzystac bezposrednio zmienna $HTTP_USER_AGENT. Na przyklad, sposb wykrycia przegladarki Internet Explorer przy uzyciu porwnywania ciagw zamieszczony jest na wydruku 9.1. Wydruk 9.1. Wyswietlanie podstawowych danych na temat przegladarki
<html> <head> <title>Szybkie sprawdzenie typu przegladarki</title> </head> <body> <?php $aPos = strpos( $HTTP_USER_AGENT, "MSIE" ) ; if ( $aPos === False ) { print( "To <b>nie</b> jest MS Internet Explorer!<br>" ); } else { print( "Przegladarka MS Internet Explorer!<br>" ); } ?> </body> </html>

W przykladzie tym sprawdzamy, czy przegladarka klienta to Internet Explorer. Przyklad opiera sie na tym, ze zwracana nazwa przegladarki w wiekszosci wersji Internet Explorera zawiera fragment MSIE. Mozna wykorzystac te informacje do wyswietlenia odpowiedniego komunikatu, lub przekierowac uzytkownika do innej czesci witryny, ktra jest zoptymalizowana do wyswietlania stron w okreslonej przegladarce. Metoda ta sprawdza sie w niektrych przypadkach, ale jest zbyt prosta, aby obslugiwac ogromna ilosc prawidlowych ciagw user agent. Kilka przegladarek zmienilo format tego ciagu podczas jednej ze zmiany wersji, wiec rozpoznanie okreslonej przegladarki moze byc problematyczne, jezeli potrzebujesz dokladnej informacji o przegladarce. Na przyklad, niektre wersje Internet Explorera zawieraly nastepujace ciagi user agent: Microsoft Internet Explorer/4.40.305beta (Windows 95)[en]

Mozilla/2.0 (compatible; MSIE 3.02; Update a; AOL 3.0; Windows 95)[en] Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.0)[en] Rznice w zawartosci tego ciagu powoduja, ze sprawdzanie ich zawartosci staje sie nieporeczne. Istnieje tak wiele kombinacji przegladarek, wersji, platform i jezykw, ze dokladne rozpoznanie choc jednego przegladarki staje sie problematyczne. W rzeczywistosci znajomosc jedynie typu przegladarki nie jest tak wazne. Zamiast tego lepiej wiedziec, czy przegladarka obsluguje okreslone mozliwosci, na przyklad JavaScript lub ramki. Te informacje nie sa zawarte w ciagu informacji o przegladarce. Nastepna czesc omawia rozwiazanie tego problemu w oparciu o PHP.

Wewnetrzne funkcje PHP


Rozpoznawanie typu serwera ma zwykle sluzyc do poznania mozliwosci przegladarki. Z powodu ogromnej ilosci kombinacji przegladarek i platform, trudno jest stworzyc oglne rozwiazanie tego problemu. Na szczescie PHP zawiera kilka metod dokladniejszego rozpoznania serwera za pomoca funkcji get_browser().

nalezy sciagnac z W czasie pisania ksiazki podejmowane byly dodatkowe ulepszenia do istniejacej w sieci plik PHP funkcji get_browser(). Odkrylem, ze plik browser.ini dostepny z firmy cyScape browscap.ini, (wspomnianej juz wczesniej) wymaga kilku zmian aby dzialal z PHP 4.0 z poprawka 2. ktry jest Pierwsza z nich jest dodanie pustej linii na koncu pliku. Bez dodatkowego znaku konca linii dostepny z wielu w trakcie uruchamiania PHP generowany jest blad skladni. witryn w Sieci. Drugim, o wiele bardziej skomplikowany problem jest zwiazany z sama struktura W czasie pisania pliku. Typowo, plik browscap.ini jest zwyklym plikiem konfiguracyjnym w ktrym kazda ksiazki plik byl sekcja reprezentuje okreslona przegladarke. Kazda z sekcji odwoluje sie do sekcji wyzszego dostepny bez rzedu, wiec zdefiniowana jest pewnego rodzaju struktura. Tym sposobem w sekcji opisujacej zadnych oplat z nowa przegladarke zdefiniowane sa tylko nowe mozliwosci a istniejace wczesniej znajduja witryny cie w opisie starszej przegladarki. Problem wynika z tego, ze w czasie odczytu pliku PHP http://www.cysca konwertuje jego zawartosc na male litery. Konwersja ta powoduje, ze PHP nie potrafi pe.com/browscap odszukac nadrzednej sekcji, poniewaz nie wszystkie nazwy zapisane sa malymi literami. Aby . Po jego rozwiazac ten problem wykonalem prosty skrypt konwertujacy wszystkie linie pliku sciagnieciu i browscap.ini na male litery: zainstalowaniu w <?php serwerze WWW, $aArray = file( "./browscap.ini" ); $aNewFile = fopen( "./browscap.ini", "w" ); nalezy zmienic foreach( $aArray as $aLine ) plik php.ini. { $aNewFile = strtolower( $aLine ); Odszukaj opcje fputs( $aNewFile, $aNewLine ); konfiguracji } fclose ($aNewFile ); browscap i zmien ?> na pelna Skutkiem ubocznym takiej zmiany jest to, ze wszystkie wywolania funkcji ja sciezke do pliku get_browser() musza zawierac wywolanie funkcji strtolower(). Jednak po wprowadzeniu browscap.ini. Po takich zmian funkcja get_browser() dziala tak, jak sie tego spodziewamy. ponownym uruchomieniu serwera WWW bedzie mozna korzystac z danych zawartych w pliku. W czasie pisania ksiazki plik browscap.ini zawieral ponad 2100 rznych przegladarek. Wykorzystanie funkcji get_browser() wraz z plikiem browscap.ini upraszcza proces rozpoznawania mozliwosci przegladarki i rozszerza jego zakres. Na wydruku 9.2 pokazany jest przyklad uzycia funkcji get_browser(). Tak jak opisane zostalo we wskazwce Dodatkowe informacje na temat Browscap pierwszym krokiem powinno byc przekonwertowanie zawartosci $HTTP_USER_AGENT na male litery. Nastepnie, przy uzyciu metody udokumentowanej w http://www.php.net/, ciag identyfikacyjny przegladarki jest zmieniany do wlasciwej Rozdzial 9 Niezaleznosc od przegladarki 106

Dodatkowe informacje na temat Browscap

Aby uzyc funkcji


get_browser()

postaci przed wywolaniem funkcji get_browser(). Do zamiany okreslenia jezyka (na przyklad [en]) na gwiazdke, ktra wystepuje w pliku browscap.ini, uzywana jest funkcja eregi_replace(). Wydruk 9.2. Uzycie funkcji get_browser()
<?php function GetMassagedUA() { global $HTTP_USER_AGENT; $aUserAgent = strtolower( $HTTP_USER_AGENT ); $aUserAgent = eregi_replace( "\[[a-z]{2,}\]", "*", $aUserAgent ); if ( strpos( $aUserAgent, '*' ) === False ) { $aUserAgent .= '*'; } return $aUserAgent; } ?> <html> <head> <title>Mozliwosci przegladarki</title> </head> <body> <h1>Mozliwosci przegladarki</h1> <?php $aUserAgent = GetMassagedUA(); print( "<h2>$aUserAgent</h2>" ); $array = (array) get_browser( $aUserAgent ); if ( count( $array ) > 1 ) { while ( list( $key, $value ) = each ($array) ) { $aValue = stripslashes( $value ); echo ("<b>$key=</b> $aValue<br>"); } } else { print( "<i>brak danych przegladarki</i><br>" ); } ?> </body> </html>

Na rysunku 9.2. w przegladarce Netscape 4.7.

107

PHP Kompendium wiedzy

Rysunek 9.2. Wynik dzialania skryptu z wydruku 9.1 wykonywanego w przegladarce Netscape 4.7

Lista dostepnych mozliwosci pokazuje potege funkcji get_browser(). W kodzie zamieszczonym na wydruku 9.2, wszystkie mozliwosci sa wyswietlane poprzez rzutowanie zwracanego obiektu na tablice i przegladanie kolejnych par klucz-wartosc. Mozna rwniez sprawdzic kolejno kazda z mozliwosci korzystajac bezposrednio z obiektu i uzywajac zapisu $obiekt->mozliwosc. Na wydruku 9.3 pokazujemy przyklad sprawdzenia, czy przegladarka obsluguje ramki. Wydruk 9.3. Uzycie get_browser() do sprawdzenia obslugi ramek
<?php function GetMassagedUA() { global $HTTP_USER_AGENT; $aUserAgent = strtolower( $HTTP_USER_AGENT ); $aUserAgent = eregi_replace( "\[[a-z]{2,}\]", "*", $aUserAgent ); if ( strpos( $aUserAgent, '*' ) === False ) { $aUserAgent .= '*'; } return $aUserAgent; } ?> <html> <head> <title>Obsluga ramek?</title> </head> <body> <?php $aUserAgent = GetMassagedUA(); print( "<h2>$aUserAgent</h2>" ); $aBrowsCap = get_browser( $aUserAgent ); if ( $aBrowsCap->frames == 1 ) { print( "Przegladarka obsluguje ramki<br>" ); } else { print( "Przegladarka nie obsluguje ramek<br>" );

Rozdzial 9 Niezaleznosc od przegladarki

108

} ?> </body> </html>

Funkcja get_browser() dostarcza duzo informacji i jest dobra na poczatek, gdy aplikacja wymaga rozpoznania typu przegladarki w czasie pracy. Jednak posiada ona kilka znaczacych ograniczen. Jak wspomnialem wczesniej, uzycie pliku browscap.ini, dostepnego w Internecie, rwniez niesie ze soba klopoty. Pewnosc dzialania funkcji wymaga, aby plik browscap.ini byl czesto uaktualniany, aby podazac za zmianami w najnowszych dostepnych przegladarkach. Na przyklad nasz plik browscap.ini nie pozwalal na prawidlowe rozpoznanie przegladarek Internet Explorer 5.5 i Opera 4.02. Problem tkwi w tym, ze uaktualnienie i rozeslanie pliku browscap.ini wymaga sporo czasu. Jezeli twoja aplikacja wymaga dokladnego wykrywania mozliwosci biezacej przegladarki, w nastepnej czesci opisane zostanie narzedzie jednej z firm, ktre swietnie spelnia swoje zadanie.

BrowserHawk
Komponent BrowserHawk, dostepny z firmy cyScape jest swietnym narzedziem do wykrywania mozliwosci serwera. Jest on dostepny w formie obiektu COM, jezeli wykorzystujesz serwer z Windows, lub jako Java bean dla innych platform. Obsluga jezyka Java jest dostepna w PHP4, ale nie jest domyslnie wlaczona. Aby wykorzystac Java bean, lub inny kod Java na serwerze, PHP musi byc przekompilowane z opcja konfiguracji -with-java. Niezbedne jest rwniez zainstalowanie maszyny wirtualnej Java (JVM) na serwerze. Wiele dystrybucji Linuksa zawiera JVM i w wielu przypadkach pakiet ten jest instalowany automatycznie. Dodatkowo komponent BrowserHawk wymaga kilku dodatkowych modulw. Jednym z nich jest Simple API for XML (SAX) dostepny pod adresem http://www.megginson.com/SAX/. Wymagane moduly servletw mozna znalezc we wielu miejscach, w tym w najnowszych JVM pochodzacych od rznych dostawcw. Potrzebny bedzie na przyklad dostep do klasy javax.servlet.http.HttpServlet. Po sciagnieciu i zainstalowaniu wymaganych klas Javy, nalezy skonfigurowac PHP, aby mgl skorzystac z BrowserHawk. Taj jak w przypadku kazdej innej klasy Java nalezy podac polozenie pliku z klasami Javy korzystajac ze zmiennej java.class.path w pliku php.ini. Ponizej znajduje sie przyklad:
java.class.path=/usr/share/kaffe/Klasses.jar:/homeblake/php4.0.1pl2/ext/java/php_java.jar:/home/blake/bhawk/ lib/bhawk4j.jar:/home/blake/java/sax2.jar:/home/blake/java/servlet.jar:/home/blake/bhawk:

Zapis taki wskazuje, ze klasy wymagane przez BrowserHawk sa dostepne dla PHP w katalogach ../bhawk4j.jar, ../sax2.jar i ../servlet.jar. Wpisana jest tutaj rwniez sciezka bez okreslenia pliku (/home/blake/bhawk), ktra okresla polozenie plikw licencyjnych i danych pakietu BrowserHawk. Sciezka ta powinna wskazywac na katalog, w ktrym zostal zainstalowany BrowserHawk. Po ustawieniu wszystkich tych elementw konfiguracji i przekompilowaniu PHP z obsluga Javy, nalezy sprawdzic konfiguracje za pomoca funkcji phpinfo(). Wywolanie funkcji phpinfo() powoduje wyswietlenie duzej ilosci danych w postaci tabel HTML. Na wydruku 9.3. pokazana jest ta czesc informacji, ktra wskazuje na dostepnosc Javy. Rysunek 9.3. Wynik dzialania funkcji phpinfo() pokazujacy dostepnosc Javy

109

PHP Kompendium wiedzy

Po skonfigurowaniu obslugi Javy i BrowserHawk w PHP, wykorzystanie komponentw BrowserHawk jest latwe. Na wydruku 9.4 znajduje sie kod, ktry pokazuje w jaki sposb stworzyc obiekt BrowserHawk i wykorzystac go do odczytania kilku podstawowych danych o przegladarce. Wydruk 9.4. Przyklad wykorzystania BrowserHawk
<html> <head> <title>Przyklad wykorzystania BrowserHawk</title> </head> <body> <h1>Przyklad wykorzystania BrowserHawk</h1> <?php print( "<h2>$HTTP_USER_AGENT</h2>" ); $aBrowserHawk = new Java( "com.cyscape.browserhawk.BrowserHawk" ); $aBrowserInfo = $aBrowserHawk->getBrowserInfo( "$HTTP_USER_AGENT" ); // Czy przegladarka obsluguje ActiveX? if ( $aBrowserInfo->getActiveXControls() == True ) { print( "Przegladarka obsluguje kontrolki ActiveX<br>" ); } else { print( "Przegladarka nie obsluguje kontrolek ActiveX<br>" ); } ?> </body> </html>

Na wydruku 9.4 pokazujemy w jaki sposb mozna sprawdzic obsluge ActiveX i tak samo latwo mozna sprawdzic kazda z wlasciwosci BrowserHawk. W tabeli 9.1. zamieszczone sa metody odczytujace informacje na temat mozliwosci przegladarki dostepne w BrowserHawk. Typ Metoda Zastosowanie Boolean getActiveXControls() Sprawdza, czy przegladarka obsluguje kontrolki ActiveX. Boolean getAOL() Sprawdza, czy uzytkownik witryny korzysta z przegladarki firmowanej przez America Online (AOL) (na sieci AOL). double getAOLVersion() Zwraca numer wersji przegladarki AOL. int getAuthenticodeUpdate() Zwraca numer wersji Authenticode obslugiwanego przez przegladarke. Boolean getBackgroundSounds() Sprawdza, czy przegladarka potrafi odgrywac dzwiek w tle. Boolean getBeta() Sprawdza, czy przegladarka jest w wersji beta. java.lang.String getBrowser() Zwraca oglna nazwe przegladarki, na przyklad Netscape lub IE (Internet Explorer). Boolean getCDF() Sprawdza, czy przegladarka obsluguje Channel Definition Format (CDF) uzywany do prenumerowania zawartosci WWW z mozliwoscia automatycznej aktualizacji. Boolean getCompressGZip() Sprawdza, czy przegladarka przyjmuje dane w skompresowanym formacie GZip. Boolean getCookies() Sprawdza, czy przegladarka obsluguje cookie. Boolean getCrawler() Sprawdza, czy przegladarka jest szperaczem sieciowym lub innym programem wykorzystywanym do indeksowania zawartosci witryny. Boolean getDHML() Sprawdza, czy przegladarka obsluguje skrypty DHTML(). java.lang.String getFileUpload() Sprawdza, czy przegladarka obsluguje Rozdzial 9 Niezaleznosc od przegladarki 110

Boolean Boolean Boolean java.lang.String

getFontColor() getFontSize() getFrames() getFullversion()

Boolean Boolean java.lang.String Boolean Boolean double java.lang.String int double java.lang.String Boolean Boolean java.lang.String Boolean java.lang.String

getGold() getHDML() getIPAddr() getJavaApplets() getJavaScript() getJavaScriptVer() getLanguage() getMajorver() getMinorver() getMinorverlet() getMouseOver() getMSN() getOSDetails() getPDA() getPlatform()

Boolean

getPNG()

Boolean Boolean Boolean java.lang.String

getProxy() getSSL() getSSLActive() getSSLCipherSuite()

mozliwosc przesylania plikw do serwera (przegladarki zgodne z RFC 1867). Sprawdza, czy przegladarka potrafi wyswietlac kolorowy tekst. Sprawdza, czy przegladarka potrafi wyswietlac rzne wielkosci tekstu. Sprawdza, czy przegladarka obsluguje ramki. Zwraca kompletna wersje przegladarki zawierajaca wyzsza i nizsza czesc numeru oraz litery, o ile wystepuja. Sprawdza, czy jest to wersja Gold przegladarki Netscape Navigator. Zwraca True, jezeli obsluguje HDML (poprzednik WAP). Zwraca adres IP klienta. Sprawdza, czy przegladarka obsluguje applety Java. Sprawdza, czy przegladarka obsluguje JavaScript. Zwraca numer wersji JavaScript obslugiwanego przez przegladarke. Zwraca wybrany przez uzytkownika jezyk. Zwraca wyzsza czesc numeru wersji przegladarki. Zwraca nizsza czesc numeru wersji przegladarki. Zwraca litere nizszej czesci numeru przegladarki, o ile wystepuje. Sprawdza, czy przegladarka obsluguje efekt JavaScript, mouseover. Sprawdza, czy uzytkownik korzysta z sieci Microsoft Network (MSN). Zwraca szczegly na temat systemu operacyjnego (OS) systemu uzytkownika. Zwraca True, jezeli przegladarka jest urzadzeniem PDA na przyklad PalmPilot. Zwraca bardziej oglne dane (w porwnaniu do getOSDetails()) na temat platformy uzytkownika. Sprawdza, czy przegladarka obsluguje format rysunkw PNG (Potrable Network Graphics). Sprawdza, czy uzytkownik jest polaczony poprzez serwer Proxy. Sprawdza, czy przegladarka obsluguje protokl SSL (Secure Socket Layer). Sprawdza, czy uzytkownik jest polaczony poprzez aktywne polaczenie SSL. Zwraca zestaw szyfrowania SSL dla biezacej sesji. Dostepny jedynie w przypadku PHP Kompendium wiedzy

111

aktywnej sesji SSL. Sprawdza wielkosc klucza SSL obslugiwana przez przegladarke. Dostepne jedynie w przypadku aktywnego polaczenia SSL. Boolean getStyleSheets() Sprawdza, czy przegladarka obsluguje kaskadowe arkusze stylu (CSS). Boolean getTableBGColor() Sprawdza, czy przegladarka obsluguje ustawianie kolorw dla poszczeglnych komrek tabeli HTML. Boolean getTableBGImage() Sprawdza, czy przegladarka obsluguje ustawianie rysunkw tla dla poszczeglnych komrek tabeli HTML. Boolean getTables() Sprawdza, czy przegladarka obsluguje wyswietlanie tabel. Boolean getVBScript() Sprawdza, czy przegladarka obsluguje VBScript. double getVersion() Zwraca wersje przegladarki. int getVersionpos() Zwraca pozycje w numerze wersji przegladarki, ktry jest umieszczony w ciagu identyfikacyjnym przegladarki. Boolean getWAP() Zwraca True dla urzadzen obslugujacych WML i WAP (Wireles Application Protocol), na przyklad telefony komrkowe z WAP. java.lang.String getWAPDeviceModel() Zwraca model urzadzenia WAP, o ile jest znany. java.lang.String getWAPGateway() Zwraca szczegly bramy UP.Link, o ile jest wykorzystywana. int getWAPMaxDeckSize() Zawiera przyblizona maksymalna ilosc bajtw, jaka moze obsluzyc urzadzenie. java.lang.String getWAPSubscriberID() Automatycznie ustawiany na identyfikator abonenta dla uzytkownika WAP. Boolean getWin16() Sprawdza, czy przegladarka pracuje w 16 bitowym systemie operacyjnym Windows, jak na przyklad Windows 3.1. Boolean getXML() Sprawdza, czy przegladarka obsluguje bezposrednie wyswietlanie plikw XML. Jedyna wada przy uzywaniu komponentu BrowserHawk jest to, ze jest on zaprojektowany dla uzytkownikw JSP, wiec niektre metody moga nie byc bezposrednio dostepne poprzez PHP. Niektre zaawansowane funkcje raportujace nie moga byc wykorzystane, poniewaz opieraja sie na obiektach specyficznych dla JSP. Mimo to, standardowe obiekty zwracaja wystarczajaco duzo danych dla wiekszosci zastosowan i sa stale aktualne dla najnowszych przegladarek. Przewaga uzycia komponentu BrowserHawk nad innymi metodami opisanymi w tym rozdziale jest jego dokladnosc i elastycznosc. BrowserHawk uaktualnia swoja baze danych w razie potrzeby. W dokumentacji znajduje sie informacja, ze rozpoznaje on okolo 9 razy wiecej przegladarek, niz mozna to zrobic korzystajac z browscap. BrowserHawk jest rwniez zaprojektowany, aby sprawdzal o wiele wiecej wlasnosci przegladarki, niz jest to stosowane w innych metodach. Jezeli aplikacja opiera sie na dostarczaniu danych specyficznych dla przegladarki lub polega na bardzo specyficznych wlasnosciach przegladarki, BrowserHawk zapewnia najlepsze rozpoznawanie przegladarki. Aplikacja bedzie nadal dzialala prawidlowo, niezaleznie od ciaglych zmian w technologiach przegladarek.
int getSSLKeySize()

Rozdzial 9 Niezaleznosc od przegladarki

112

Wykorzystanie danych o przegladarce


Pierwszym zadaniem podczas tworzenia aplikacji niezaleznej od przegladarki jest rozpoznanie mozliwosci przegladarki uzytkownika. O wiele wazniejszym krokiem jest zadecydowanie w jaki sposb zostana wykorzystane te dane. Tak jak w przypadku innych decyzji podejmowanych w czasie projektowania, zalezy ona od wymagan stawianych aplikacji. Niektre mozliwosci przegladarki i wlasnosci aplikacji, takie jak animowane podpowiedzi, lub obsluga kaskadowych arkuszy stylw nie sa krytyczne. Brak innych wlasnosci moze calkowicie zatrzymac aplikacje, na przyklad zdolnosc przegladarki do nawiazania polaczenia szyfrowanego SSL lub obsluga wysylania plikw. Projekt aplikacji powinien zawierac liste wymaganych wlasnosci przegladarki i zapewniac elegancka obsluge sytuacji, gdy nie mozna skorzystac z ktrejs z wymaganych wlasnosci. Na wydruku 9.5. zamieszczony zostal przyklad w jaki sposb mozna zrealizowac elegancka obsluge braku wymaganej wlasnosci przegladarki. Dodatkowo, mozna sprbowac warunkowo dostarczac niektrych elementw w zaleznosci od zdolnosci przegladarki do ich wyswietlania. Na wydruku 9.6 pokazano przyklad takiego dzialania. Wydruk 9.5. Eleganckie zakonczenie aplikacji w przypadku braku obslugi przesylania plikw
<?php $aBrowserHawk = new Java( "com.cyscape.browserhawk.BrowserHawk" ); $aBrowserInfo = $aBrowserHawk->getBrowserInfo( "$HTTP_USER_AGENT" ); ?> <html> <head> <title>Wysylanie pliku</title> </head> <body> <h1>Wysylanie pliku</h1> <form action="someurl.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="Wyslij"> <?php } else { ?> Przegladarka nie obsluguje wysylania plikw.<br><br> prosze przeslac pliki poczta na adres files@my.domain.com. <?php } ?> </form> </body> </html>

Jezeli przegladarka posiada obsluge wysylania plikw, skrypt ten wyswietla formularz wysylania pliku. Jezeli przegladarka nie obsluguje tej funkcji, wyswietlany jest napis informujacy uzytkownika o mozliwosci przeslania pliku za pomoca poczty elektronicznej. W rzeczywistosci mechanizm taki jest niezbedny, aby uzytkownicy aplikacji uwazali ja za przyjazna. Wybierajac taki mechanizm nalezy zwrcic uwage, aby uzytkownicy mogli zrozumiec dlaczego wykonanie operacji sie nie powiodlo. Wiekszosc ludzi nie chce widziec komunikatw typu Twoja przegladarka nie obsluguje RFC 1867. Jezeli aplikacja moze dzialac pomimo tego, ze operacja sie nie udala, nie wyswietlaj ponownie tego komunikatu. Nalezy po prostu zapewnic mozliwie najwieksza dostepna ilosc funkcji. Wydruk 9.6. Warunkowe dostarczanie tresci w zaleznosci od mozliwosci przegladarki
<?php $aBrowserHawk = new Java( "com.cyscape.browserhawk.BrowserHawk" ); $aBrowserInfo = $aBrowserHawk->getBrowserInfo( "$HTTP_USER_AGENT" ); if ( $aBrowserInfo->getPNG() == True ) { $aImage = "Logo.png"; } else { $aImage = "Logo.gif"; } ?> <html> <head> <title>Nasze logo</title> </head> <body> <h1>Nasze logo</h1>

113

PHP Kompendium wiedzy

<img src="<?=$aImage?>" width="180" height="70" alt="" border="0"> </body> </html>

Skrypt ten wyswietla grafike w formacie PNG jezeli przegladarka potrafi wyswietlic ten format, w przeciwnym wypadku wysylany jest rysunek w formacie GIF. Przyklad ten jest prosty, ale ilustruje podstawowa zasade dzialania. Zamiast wykorzystywac zmienne do wysylania rznych danych, aplikacja moze skorzystac z informacji o mozliwosciach przegladarki do wyswietlenia calkowicie innej sekcji witryny. Na przyklad mozna stworzyc witryne zoptymalizowana dla ogladania jej przez przegladarki WebTV. Systemy takie maja zwykle ograniczona wielkosc ekranu i zwykle mniej mozliwosci wyswietlania rznych czcionek. Dlatego trzeba inaczej projektowac taka witryne aby poprawic widocznosc wszystkich elementw. Ponizszy kod jest prostym przykladem sposobu implementacji takiego przypadku. Zakladamy, ze jest to glwna strona witryny.
<?php $aBrowserHawk = new Java( "com.cyscape.browserhawk.BrowserHawk" ); $aBrowserInfo = $aBrowserHawk->getBrowserInfo( "$HTTP_USER_AGENT" ); if ( $aBrowserInfo->getBrowser() == "WebTV" ) { // Przegladarka WebTV, przekierowanie do stron zoptymalizowanych dla WebTV header( "Location: http://mysite.com/webtv/\n" ); } else { // To nie jest przegladarka WebTV, przekierowanie do standardowych stron header( "Location: http://mysite.com/main/\n" ); } ?>

W przykladzie tym, uzytkownicy przegladarek WebTV sa kierowani na odpowiednio zoptymalizowane strony. Inni uzytkownicy sa kierowani do zwyklego zestawu stron przeznaczonych dla innych typw przegladarek. Przyklad ten moze byc rozszerzony, aby wykrywal przegladarki dzialajace na komputerach typu PDA lub inne specyficzne typy przegladarek. Wada takiego rozwiazania jest to, ze jezeli uzytkownik wysle znajomemu lacze do strony przeznaczonej dla innej przegladarki niz uzywa ten znajomy, wyglad strony nie bedzie odpowiedni dla biezacego typu przegladarki. Dodatkowo mechanizm ten wymaga, aby kazda strona posiadala kilka rwnoleglych stron przeznaczonych dla odpowiednich typw przegladarek. Wprowadzenie takiego projektu jest nieporeczne dla duzych witryn. Lepszym rozwiazaniem przy tworzeniu stron specyficznych dla przegladarki jest wylaczenie kluczowych rzniacych sie elementw i umieszczenie ich w osobnych plikach dla kazdego typu przegladarki. Tego typu mechanizm moze byc zaimplementowany przy uzyciu systemu szablonw, ktre beda opisane w rozdzialach 13 i 14. Tam tez przytoczymy przyklady implementacji takiego scenariusza.

Podsumowanie
Wykrywanie mozliwosci przegladarki moze byc niezmiernie wazne dla wielu aplikacji WWW. W czasie projektowania aplikacji nalezy poznac ograniczenia rznych przegladarek, zanim zatwierdzimy realizacje specyficznych funkcji. Nastepnie, w oparciu o wymagania projektu nalezy wykorzystac narzedzia do wykrywania przegladarki i wlaczania niektrych funkcji. Nalezy unikac sytuacji, gdy przegladarka wyswietla niezrozumialy komunikat bledu w przypadku, gdy funkcja jest niedostepna. Nalezy dazyc do zapewnienia zestawu funkcji niezaleznych od uzywanego typu przegladarki.

Rozdzial 9 Niezaleznosc od przegladarki

114

Rozdzial 10. Uruchamianie


Wstep
Uruchamianie aplikacji WWW jest rwnie krytycznym procesem jak uruchamianie innych typw aplikacji. Problemem jest to, ze moze byc trudno zdalnie uruchamiac program, szczeglnie gdy nie masz odpowiednich uprawnien do administracji serwerem WWW. W tym rozdziale zaprezentowane zostana porady i narzedzia, ktre moga usprawnic uruchamianie aplikacji. Dodatkowo, niektre czesci rozdzialu sa przypomnieniem zasad inzynierii programowania, poniewaz mozna uniknac ogromnej pracy przy uruchamianiu aplikacji, jezeli jej projekt jest odpowiednio przygotowany. Z powodu ogromnego zainteresowania jakie wzbudzilo programowanie aplikacji WWW, powstalo wiele narzedzi (miedzy innymi PHP) do tworzenia takich aplikacji. Narzedzia te zostaly stworzone na podstawie istniejacych juz narzedzi, na przyklad ASP i JSP, inne natomiast zostaly stworzone jedynie w celu tworzenia interaktywnych aplikacji WWW. Niespodziewanie, narzedzia spelniajace zasady inzynierii programowania sa tu w mniejszosci. Prawdopodobnie brak ten jest spowodowany potrzeba zaistnienia na rynku jako pierwsze narzedzie lub z faktu, ze pierwszymi projektantami nowej technologii nie byli bardziej zaawansowani programisci. Niezaleznie od powodu, do tego nowego srodowiska programowania nalezy zaadaptowac wszystkie istniejace zasady inzynierii programowania. Pierwsza czesc rozdzialu zawiera przypomnienie zasad inzynierii programowania. Jest ona dolaczona do tego rozdzialu, poniewaz zbyt duzo czasu spedzonego przy uruchamianiu jest zwykle powodowane bledami przy tworzeniu projektu.

Inzynieria programowania a uruchamianie


W rozdziale 3 Formularze i cookie doszlismy do wniosku, ze mozna uniknac sprawdzania poprawnosci niektrych danych w przypadku zastosowania lepszego mechanizmu wprowadzania danych. Tak samo, pisanie lepszego (bardziej defensywnego) kodu powoduje ogromne zmniejszenie czasu straconego w czasie uruchamiania. Projekt aplikacji WWW musi byc tak samo dokladnie przemyslany, jak projekt kazdej innej aplikacji. Tworzenie swietnej aplikacji wymaga wlasciwego projektu, zgodnosci z standardami tworzenia oprogramowania, sprawdzania oprogramowania, testowania modulw oraz uruchamiania. Uruchamianie jest koniecznie ostatnie na tej liscie, poniewaz zaklada sie, ze kod przeszedl wszystkie wczesniejsze wymagane kroki. Kolejne czesci zawieraja przeglad kazdego z tych krokw i zakladaja, ze posiadasz pewna wiedze inzynierii programowania.

Projekt aplikacji
Identyfikacja wstepnych zalozen aplikacji przed napisaniem jakiegokolwiek kodu jest krytyczna w przypadku kazdego projektu. W duzych projektach takie planowanie moze zajac tygodnie lub miesiace. W malych projektach moga zostac zapisane na skrawku papieru w przeciagu kilku minut. W kazdym z tych przypadkw kluczowe jest przemyslenie wymagan aplikacji, oraz wymyslenie mozliwie wielu mozliwych rozwiazan przed rozpoczeciem pisania kodu. Dane z firm TRW i IBM wskazuja, ze wprowadzenie zmian do aplikacji w poczatkowym okresie programowania (przed faza programowania) jest 10 do 200 razy tansze niz wprowadzanie tych samych zmian na koncu tego procesu (McConnell, 1993). W zaleznosci od projektu, identyfikacja wymaganych funkcji aplikacji moze wymagac wykonania sporej pracy. Wstepny podzial aplikacji na moduly moze uproscic ten proces. W aplikacji WWW modulami takimi moga byc wsplpraca z baza danych, autoryzacja uzytkownika, obsluga stanu, id. Po zdefiniowaniu zadan

poszczeglnych modulw nalezy w razie potrzeby podzielic je na mniejsze fragmenty i zapisac przeznaczenie kazdego fragmentu. W malych aplikacjach dobra strategia jest podzial modulw na pliki kodu badz klasy obiektowe. Oprcz zdefiniowania wymagan funkcjonalnych aplikacji, nalezy rozwazyc architekture systemu. Nalezy tu pomyslec o rodzaju stosowanego systemu zarzadzania relacyjna baza danych (SZRBD) i innych mniej oczywistych elementach, na przyklad jak beda zorganizowane pliki kodu, jak radzic sobie ze zmianami, oraz czy niektre moduly nalezy zakupic, czy tez pisac je od poczatku. Mimo, ze PHP moze dzialac na wielu serwerach WWW i platformach systemowych, kazda z takich kombinacji posiada indywidualne cechy. Nalezy poswiecic nieco czasu na zdefiniowanie powodw, dla ktrych nalezy wybrac okreslony sprzet i serwer. Ilosc funduszy dostepnych na poczatku projektu rzadko jest dobrym powodem wyboru platformy. Wybr bazy danych jest rwnie istotny, jezeli aplikacja ma byc wysoce dynamiczna. Dodatkowo nalezy pomyslec, czy serwer WWW i baza danych beda pracowac na tym samym komputerze, czy osobno. W zaleznosci od wielkosci i charakteru aplikacji, moze byc to krytyczne zagadnienie. Nastepnie, nalezy zaprojektowac organizacje kodu. Zdefiniuj konwencje nazywania plikw i katalogw, co uprosci identyfikacje kodu. Wymysl alternatywny plan na wypadek, gdy istnieje duze prawdopodobienstwo zmian. Jezeli przewidujesz wystepowanie zmian, napisz aplikacje lokalizujaca zmiany w kilku modulach a buforujaca reszte. Taki typ projektowania jest istotny szczeglnie, gdy korzystasz przy tworzeniu aplikacji z narzedzi pochodzacych z innych zrdel lub oprogramowania w wersji beta. Tworzenie zastepnikw takiego kodu jest latwe do zaimplementowania i w dluzszym okresie czasu umozliwia latwiejsze utrzymanie aplikacji. Na koniec nalezy zadecydowac, ktre moduly aplikacji zostana stworzone przy pomocy gotowych narzedzi pochodzacych od zewnetrznych dostawcw. Decyzja tworzyc czy kupic jest dosyc skomplikowana. W zaleznosci od harmonogramu projektu, mozesz nie i miec wystarczajaco duzo czasu, aby dostatecznie przetestowac dostepne narzedzia. Jednak mozesz rwniez nie miec wystarczajaco duzo czasu na stworzenie ich od poczatku. Aby zmniejszyc wplyw tej decyzji na projekt mozna stworzyc wlasne funkcje posrednie ukrywajace implementacje. Wlasciwe zaprojektowanie aplikacji wymaga czasu. W przypadku dobrego systemu faza projektowania zajmuje 20 do 30 procent czasu tworzenia systemu (McConnell, 1993). Trzeba pamietac, ze ten czas jest zuzywany na projektowanie wysokiego poziomu, do projektowania szczeglw implementacji rwniez potrzebny jest czas.

Definiowanie standardw programowania


Zdefiniowanie standardw programowania ulatwia dlugoterminowe utrzymanie projektw o dowolnej wielkosci. Nawet male aplikacje programowane przez jednego programiste moga korzystac z odpowiednio stosowanego zbioru standardw programowania. Taki standard obejmuje sposoby nazywania, komentowania oraz konwencje ukladu. Niektre z nich, na przyklad uklad kodu, sa mniej wazne, poniewaz nowoczesne edytory potrafia przeformatowac kod, jednak inne, jak na przyklad konwencje nazw plikw i katalogw moga miec ogromne znaczenie przy konserwacji kodu2.

Przeglad oprogramowania
Przeglad oprogramowania dostarcza mozliwosci zrealizowania kilku celw za jednym razem. Na przyklad, przeglad oprogramowania pozwala na sprawdzenie kodu z standardami kodowania. Pozwalaja rwniez mniej doswiadczonym programistom na korzystanie z wiedzy bardziej doswiadczonych kolegw. Sa rwniez jednym z bardziej efektywnych metod zapewnienia odpowiedniej jakosci oprogramowania. Analizy przegladw oprogramowania stosowanych przy tworzeniu prawdziwych aplikacji pokazaly, ze pozwalaja na wykrywanie bledw z prawdopodobienstwem pomiedzy 55 a 60%. Ten wynik nalezy zestawic z jedynie 25% prawdopodobienstwem dla testowania modulw, 35% dla testowania funkcji oraz 45% dla testowania integracyjnego. Dodatkowo, przeglady takie zwiekszaja w duzych projektach oglna wydajnosc zespolu. W
Przypis tlumacza. Z powodu luznego traktowania typw w PHP szczeglnie wazne wydaje sie odpowiednie nazywanie zmiennych. Dobrym pomyslem moze byc stosowanie tzw. notacji wegierskiej, gdzie nazwa zmiennej zaczyna sie od liter okreslajacych jej typ, np.: nIlosc to zmienna przechowujaca liczby calkowite, sTytul zawiera ciag znakw, a bIstnieje to zmienna logiczna.
2

Rozdzial 10 Uruchamianie

116

niektrych przypadkach powoduja one 80 do 90% spadek awarii oraz 10 do 25% wzrostu wydajnosci (McConnell, 1993). Przeglad powinien byc przeprowadzany zarwno podczas testowania jak i podczas implementacji. Przeglad projektu pozwala na identyfikacje jego wad w momencie, gdy ich usuwanie jest najprostsze i najtansze. Mozna wykorzystac kilka metod realizacji przegladu. Niektre z nich sa formalna inspekcja kodu inne przegladem oglnym lub czytaniem kodu. W przypadku formalnej inspekcji kodu, kilku czlonkw zespolu zbiera sie razem w celu odszukania bledw. Prowadzacy spotkanie prowadzi je do przodu i pilnuje, aby jedynym tematem byla identyfikacja bledw. Formalna inspekcja kodu nie powinna zawierac dyskusji na temat rozwiazan. W przypadku przegladu oglnego grupa programistw nieformalnie dyskutuje na temat kodu zadajac pytania. Gdy zidentyfikowany zostanie blad, moga powstac sugestie na temat sposobu jego usuniecia, ale glwnym celem jest nadal jego identyfikacja. Czytanie kodu poswiecone jest jedynie dla kodu programu, a nie pracy grupowej. Zwykle czesc kodu jest przekazywana dwm lub wiecej osobom, ktre niezaleznie pracujac identyfikuja bledy. Wynik ich pracy jest przekazywany autorowi kodu. W zaleznosci od rozmiaru i organizacji projektu uzycie jednej z metod ma przewage nad inna. Na przyklad w przypadku, gdy pracujesz sam lub w malym zespole, mozesz skorzystac z zatrudnienia osoby, ktra wykona taki przeglad metoda czytania kodu. Niezaleznie od wybranej metody, przeprowadzenie przegladu kodu jest najbardziej efektywna metoda identyfikacji problemw w projekcie badz implementacji.

Testowanie
Zwykle testowanie nie jest pomijane, ale czesto jest przeprowadzane przypadkowymi metodami. Tak jak w przypadku innych projektw, testowanie aplikacji WWW powinno zawierac testowanie na rznych poziomach: testowanie funkcji, testowanie modulw oraz testowanie integracyjne. Testowanie kazdego modulu powinno byc odpowiednio zaplanowane. Z testami zwiazany jest okreslony zbir oczekiwan i wymagan. W malych projektach testowanie moze wymagac jedynie wymyslenia kilku prostych przypadkw uzycia aplikacji a nastepnie sprawdzenie kazdego przypadku. Wieksze projekty moga zawierac ludzi, ktrzy zajmuja sie jedynie testowaniem, ale kazdy z programistw powinien byc odpowiedzialny za dostarczenie testerom dostatecznie duzo danych, aby ich praca byla efektywna. Kazdy twrca kodu powinien rwniez byc odpowiedzialny za testowanie swoich modulw na poziomie funkcji lub strony.

Uruchamianie
Uruchamianie jest ostatnim etapem w procesie tworzenia aplikacji, poniewaz w momencie, gdy nastepuje uruchamianie powinny byc ukonczone procesy projektowania, programowania i czesc testowania. Uruchamianie moze byc przeprowadzane w trakcie kazdej z fazie testowania jako czesc tego procesu. Wszystkie zmiany wprowadzone do kodu w trakcie procesu uruchamiania powinny zostac ponownie przetestowane na wszystkich poziomach testowania, poniewaz zmiany mogly wprowadzic nowe bledy. Uruchamianie powinno byc gruntownym procesem przeznaczonym do identyfikacji zrdla problemu. Nie powinno byc prostym lataniem, ktre naprawi bledne przypadki, ale nie zapewni trwalego rozwiazania. Kazdy, kto bierze udzial w testowaniu powinien znac zrdlo problemu w momencie, gdy stwierdza sie usuniecie problemu. Znalezienie zrdla problemu powoduje stworzenie kompletnego rozwiazania zamiast obchodzenia problemu. W zaleznosci od natury problemu, czasami czasowe rozwiazania moga byc wystarczajace, ale musza zostac odpowiednio udokumentowane. Rozwiazywanie problemw powinno brac pod uwage priorytety. W tej ksiazce prawdopodobnie nie zostanie opisane wszystko na temat prawidlowej inzynierii programowania. Najwazniejsze jest, aby pamietac, ze inzynieria programowania jest rwnie wazna w aplikacjach WWW jak w pozostalych aplikacjach oraz o tym, ze wlasciwe stosowanie zasad inzynierii moze ograniczyc naklad pracy wymagany przy uruchamianiu. Nastepna czesc zawiera opis kilku technik i narzedzi specyficznych dla aplikacji PHP.

117

PHP Kompendium wiedzy

Programowanie defensywne
Zanim zaczniesz uruchamiac program, powinienes podjac kroki, prowadzace do napisania kodu zawierajacego duzo mniej bledw. Taki sposb programowania jest nazywany programowaniem defensywnym. Takie programowanie polega na odpowiednim komentowaniu bledw, wewnetrznym sprawdzaniu stanu procedur w trakcie procesu programowania. Sposb komentowania jest indywidualny dla kazdego programisty, ale powinno byc zgodne ze standardami. Jako minimum, programisci powinni opisywac przeznaczenie funkcji, klasy lub dolaczanego pliku oraz zawsze komentowac niejasne fragmenty kodu. Do sprawdzania stanu funkcji, PHP, tak jak wiele jezykw wysokiego poziomu, posiada funkcje assert(). Funkcja assert() oblicza wartosc przekazanego parametru i podejmuje okreslone akcje w przypadku, gdy jego wartosc wynosi False. W PHP do funkcji assert() mozna przekazac zarwno ciag jak i wartosc Boolean. Jezeli przekazany zostal ciag, jest on wykonywany jako blok kodu PHP. Opcje asercji w pliku php.ini (assert.active, assert.warning, assert.bail, assert.callback i assert.quiet_eval) lub opcje przekazane jako parametr wywolania funkcji assert_options() definiuja akcje jaka podejmuje funkcja assert(). W tabeli 10.1 zamieszczone sa rzne opcje asercji. Tabela 10.1. Opcje asercji i ich opis Opcja Domyslnie Opis assert_active 1 Wlacza wykonywanie assert(). assert_warning 1 Wyswietla ostrzezenie PHP przy kazdej nieudanej asercji. assert_bail 0 Konczy wykonanie w przypadku nieudanej asercji. assert_quiet_eval 0 Wylacza raportowanie bledw w czasie obliczenia wyrazenia asercji. assert_callback (null) Nazwa funkcji uzytkownika wykonywanej w przypadku nieudanej asercji. Funkcja assert() jest zaprojektowana jedynie do wykorzystywania w czasie tworzenia programu i nie powinna byc uzywana w czasie normalnej pracy. Aplikacja powinna dzialac identycznie z wywolaniami funkcji assert(), jak i bez nich. Na wydruku 10.1 pokazany zostal przyklad uzycia funkcji assert() do kontroli poprawnosci parametrw wejsciowych. Wydruk 10.1. Uzycie funkcji assert() do kontroli poprawnosci parametrw wejsciowych
<?php function ArrayAverage( $aArray ) { $aTotal = 0; // Apostrofy ozanczaja ciag nie interpretowany przez PHP assert( 'is_array( $aArray )' ); foreach( $aArray as $aElement ) { assert( 'is_numeric( $aElement )' ); $aTotal += $aElement; } return ( $aTotal / count( $aArray ) ); } ?>

Funkcja ArrayAverage() umieszczona na wydruku 10.1 spodziewa sie jako parametru tablicy wartosci numerycznych (liczb lub ciagw zawierajacych liczby) i zwraca srednia z wartosci w tablicy. Wyrazenie assert() jest wykorzystywane do kontroli poprawnosci parametru przekazanego do funkcji a pzniej do sprawdzania, czy tablica zawiera wartosci numeryczne. Nalezy zwrcic uwage, ze do assert() mozna przekazac ciag, ktry jest wykonywany jako kod PHP, wiec jezeli wykorzystywane sa zmienne nalezy zapewnic, ze PHP nie podstawi zbyt wczesnie wartosci zmiennej w miejsce jej nazwy. Aby tego uniknac nalezy uzywac ciagw w apostrofach. Testowy skrypt dla funkcji z wydruku 10.1 jest zamieszczony na wydruku 10.2. Wydruk 10.2. Uzycie funkcji ArrayAverage()
<?php include( "./arrayfunc.php" ); ?> <html> <head> <title>Testowanie asercji</title> </head> <body>

Rozdzial 10 Uruchamianie

118

<?php $aResult = ArrayAverage( array( 1, 2, 3, 4, 5 ) ); print( "ArrayAverage( array( 1, 2, 3, 4, 5 ) ) = $aResult<br>" ); $aResult = ArrayAverage( array( 10.1, "5.5", 3, "4", 5 ) ); print( "ArrayAverage( array( 10.1, \"5.5\", 3, \"4\", 5 ) ) = $aResult<br>" ); $aResult = ArrayAverage( array( 1, 2, "cat", 4, 5 ) ); print( "ArrayAverage( array( 1, 2, \"cat\", 4, 5 ) ) = $aResult<br>" ); $aResult = ArrayAverage( 1, 2 ); print( "ArrayAverage( 1, 2 ) = $aResult<br>" ); ?> </body> </html>

Testowy skrypt wywoluje funkcje ArrayAverage() cztery razy. Pierwsze dwa razy przekazywane sa wlasciwe wartosci, natomiast ostatnie dwa razy przekazane wartosci sa nieprawidlowe. Na rysunku 10.1. pokazany jest wynik dzialania skryptu. Nalezy zauwazyc, ze poniewaz PHP wewnetrznie wymusza typy zmiennych, powoduje to, ze wywolanie ArrayAverage(array(1, 2, "cat", 4, 5)) udaje sie bez zadnych ostrzezen (poza generowanymi przez asercje). Rysunek 10.1. Testowanie funkcji ArrayAverage()

Podejmowane przez funkcje assert() dzialania zaleza od ustawien asercji. Poprzedni przyklad wyorzystywal domyslne ustawienia asercji. Przyjemna cecha asercji jest to, ze gdy assert.active jest ustawione na False, przestaja one dzialac. Aby zmienic ta opcje nalezy albo wywolac funkcje assert_options( ASSERT_ACTIVE, False) lub ustawic odpowiednio dyrektywe konfiguracji. Wykorzystujac opcje konfiguracji mozna instalowac aplikacje w srodowisku z wylaczonymi asercjami a pracowac na innym, gdzie asercje sa aktywne. Istnieje jeszcze jedna funkcja pomagajaca w programowaniu defensywnym, error_reporting(). Funkcja ta jako argumentu wymaga liczby calkowitej okreslajacej poziom raportowania bledw. Argument ten jest traktowany jako maska bitowa, wiec mozna podac zestaw kilku ustawien. PHP posada zestaw stalych uzywanych razem z ta funkcja. Sa one nastepujace: Wartosc 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

E_USER_NOTCE 1024 Dodatkowo istnieje rwniez stala E_ALL, ktra uaktywnia wszystkie informacje o bledach. Tworzac aplikacje powinno sie przestawic poziom raportowania bledw na E_ALL, co spowoduje wyswietlanie wszystkich informacji o bledach w kodzie. Ustawienie to jest rwniez wazne w trakcie dolaczania do aplikacji zewnetrznej biblioteki. Na wydruku 10.3 zamieszczony jest przyklad kodu generujacy ostrzezenia w przypadku ustawienia maksymalnego poziomu raportowania bledw. Przy standardowych ustawieniach skrypt nie powoduje wyswietlenia zadnego komunikatu. Wydruk 10.3. Przyklad uzycia funkcji error_reporting()
<html> <head> <title>Poziomy raportowania bledw</title> </head> <body> <?php $aArray = array( "state" => "Idaho", "county" => "Madison", "city" => "Rexburg", "country" => "US" ); // standardowy poziom raportowania bledw print( "aArray[state] = " . $aArray[state] . "<br>" ); error_reporting( E_ALL ); print( "aArray[state] = " . $aArray[state] . "<br>" ); ?> </body> </html>

Na rysunku 10.2. pokazane sa wyniki dzialania tego przykladu. Jak mozna zauwazyc, ustawienie bardziej restrykcyjnego poziomu raportowania bledw moze spowodowac wykrycie bledw w kodzie, ktre moga spowodowac rzne efekty uboczne w czasie tworzenia aplikacji. W tym przypadku problem moze wydawac sie niewinny, ale jezeli zdefiniujemy stala o nazwie state reprezentujaca stan dzialania aplikacji, problem przestanie byc niewinny. Na wydruku 10.4 pokazujemy skrypt z taka wlasnie stala. Wyniki jego dzialania sa widoczne na rysunku 10.3. Wydruk 10.4. Drugi przyklad uzycia funkcji error_reporting() oraz stalej
<?php // Stan dzialania aplikacji define( state, 3 ); // Pozostaly kod uzywajacy stalej state ?> <html> <head> <title>Poziomy raportowania bledw</title> </head> <body> <?php $aArray = array( "state" => "Idaho", "county" => "Madison", "city" => "Rexburg", "country" => "US" ); // domyslny poziom raportowania print( "aArray[state] = " . $aArray[state] . "<br>" ); error_reporting( E_ALL ); print( "aArray[state] = " . $aArray[state] . "<br>" ); ?> </body> </html>

Rysunek 10.2. Wynik dzialania skryptu error_reporting()

Rozdzial 10 Uruchamianie

120

Rysunek 10.3. Wynik dzialania drugiego skryptu error_reporting()

W obu przykladach, gdy poziom raportowania bledw byl ustawiony na standardowy poziom, nie byly generowane zadne ostrzezenia i program wykonywal sie nieomal bezblednie. Jednak po dodaniu w drugim przykladzie stalej, swietnie dzialajacy nagle przestal dzialac. Problem taki moze byc bardzo trudny do odszukania, jezeli stala taka bylaby zdefiniowana w dolaczanym pliku. Przyklad ten pokazuje zalety zastosowania ustawienia poziomu raportowania bledw na maksimum. Wszystkie wyswietlane ostrzezenia powinny zostac zlikwidowane, aby uniknac wystepowania bledw w przyszlosci. W zaleznosci od twojego srodowiska, mozesz ustawic poziom raportowania bledw na maksymalny w trakcie rozwijania aplikacji i na minimalny na serwerze produkcyjnym. Takie ustawienie powoduje, ze w przegladarkach uzytkownikw nie pojawiaja sie ostrzezenia i komunikaty bledw. Jednak osobiscie uwazam, ze najlepiej ustawic na serwerze produkcyjnym poziom raportowania na maksimum, ale skierowac strumien bledw do pliku dziennika. Mozna to zrealizowac ustawiajac zmienne konfiguracji display_errors, log_errors i error_log na odpowiednio Off, On i stderr. Powoduje to, ze PHP nie wyswietla bledw w przegladarce a zamiast tego kieruje wszystkie bledy do pliku stderr. Jezeli uzywasz Apache, plikiem stderr dla Apache jest dziennik bledw. Jezeli chcesz, mozesz skorzystac z innej lokalizacji dziennika. Gdy zostanie wykonany skrypt z wydruku 10.3 po skonfigurowaniu PGP w sposb wspomniany powyzej, na ekranie nie pojawia sie ostrzezenia, a w pliku dziennika bledw Apache znajda sie nastepujace pozycje:
[06-Dec-2001 20:53:22] 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 - assumed 'state' in c:\helion\php4devguide\site\ch10\error_reporting.phtml on line 12 [06-Dec-2001 20:54:45] PHP Warning: Use of undefined constant state - assumed 'state' in c:\helion\php4devguide\site\ch10\error_reporting.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:51] PHP Warning: Undefined offset: 3 in c:\helion\php4devguide\site\ch10\error_reporting_2.phtml on line 17 [06-Dec-2001 20:54:53] PHP Warning: Use of undefined constant state - assumed 'state' in c:\helion\php4devguide\site\ch10\error_reporting.phtml on line 12

Nastepnym krokiem podczas programowania defensywnego moze byc napisanie wlasnego mechanizmu rejestrujacego. W dowolnych miejscach aplikacji mozesz sprawdzac stan niektrych funkcji lub raportowac bledy wewnetrzne i kontynuowac prace. PHP posiada funkcje error_log() przy pomocy ktrej mozna dodawac wlasne zapisy do pliku sladu aplikacji. Prototyp funkcji error_log() wyglada nastepujaco:
int error_log(string komunikat, int typ [, string cel [, string naglowki]])

Pierwszy parametr, komunikat, zawiera zapisywane dane. Drugi z parametrw okresla gdzie zostanie zapisany komunikat. Lista prawidlowych wartosci parametru typ znajduje sie w tabeli 10.2. Tabela 10.2. Wartosci parametru typ Wartosc Opis 0 Parametr komunikat jest wysylany do systemowego mechanizmu rejestrowania PHP przy uzyciu mechanizmu rejestrowania zapewnianego przez system operacyjny lub pliku w zaleznosci od ustawienia zmiennej konfiguracji error_log. 1 Komunikat jest wysylany poczta elektroniczna na adres podany w parametrze cel. Jedynie ten typ zapisu wykorzystuje parametr naglowki. Do obslugi tego typu komunikatu wykorzystywana jest ta sama funkcja wewnetrzna, co w funkcji mail(). PHP Kompendium wiedzy 121

Komunikat jest wysylany poprzez polaczenie PHP uzywane do uruchamiania zdalnego. Opcja ta jest dostepna jedynie w przypadku, gdy wlaczone jest uruchamianie zdalne. W tym przypadku parametr cel okresla nazwe komputera lub adres IP oraz opcjonalnie numer portu uzywanego do odbierania informacji uruchamiania. 3 Komunikat jest dolaczany na koniec pliku o nazwie cel. W czasie pisania ksiazki typ 2 nie byl dostepny. Kod zrdlowy zawieral komentarz informujacy, ze zdalne uruchamianie nie jest jeszcze dostepne. Inne typy komunikatw dzialaja w sposb opisany w tabeli. Na wydruku 10.5 pokazany jest przyklad uzycia funkcji error_log(). Wydruk 10.5. Uzycie funkcji error_log()
<html> <head> <title>Rejestrowanie bledw</title> </head> <body> <?php // Zapisanie bledu do dziennika systemowego error_log( "MJ BLAD: wystapil blad!", 0 ); // Wyslanie bledu przez e-mail error_log( "MJ BLAD: wystapil blad!", 1, "app_errors@intechra.net", "From: error_logger@myhost.com\r\n" ); // Zapisanie bledu w pliku sladu aplikacji error_log( "MJ BLAD: wystapil blad!", 3, "/tmp/error.log" ); ?> Wystapily bledy. </body> </html>

Pierwsze wywolanie funkcji error_log() zapisuje komunikat bledu w systemowym dzienniku bledw. W tym przykladzie blad ten wysylany do dziennika bledw Apache. Drugie wywolanie skutkuje wyslaniem poczty elektronicznej do odbiorcy okreslonego w parametrze cel. Informacje zawarte w dodatkowych naglwkach sa utworzone przy uzyciu tych samych zasad, co w przypadku funkcji mail(). Ostatnie wywolanie powoduje dodanie komunikatu bledu do pliku, w tym przypadku /tmp/error.log. Wykorzystanie tego mechanizmu nie jest w doslownym znaczeniu uruchamianiem, ale jego zastosowanie moze zaoszczedzic czas spedzony przy wlasciwym uruchamianiu, powodujac eliminacje niektrych bledw i przeoczen juz w fazie programowania. Jak wczesniej wspomnialem, unikanie uruchamiania programu poprzez tworzenie poprawnego kodu jest o wiele cenniejsze od najlepszych narzedzi uzywanych przy uruchamianiu.

Wlasna obsluga bledw


Tak jak prawie kazdy element PHP mechanizm obslugi bledw mozesz dostosowac do wlasnych potrzeb, aby spelnial wymagania stawiane przez aplikacje. Jak pokazane zostalo na koncu poprzedniego przykladu, funkcja error_log() pozwala na skonstruowanie prostego mechanizmu rejestrowania wlasnych bledw wystepujacych w aplikacji, ale nie pozwala na obsluge bledw generowanych przez PHP. Nie pozwala rwniez na przechwytywanie komunikatw generowanych przez funkcje assert(). Na szczescie PHP pozwala w inny sposb obslugiwac takie przypadki. Funkcja set_error_handler() pozwala zarejestrowac funkcje w PHP, ktra bedzie wywolywana za kazdym razem, gdy wygenerowany zostanie komunikat bledu. Funkcja set_error_handler() wymaga podania jednego argumentu nazwy funkcji obslugi bledw. Prototyp takiej funkcji wyglada nastepujaco:
function ErrorCallBack( int nr_bledu, string ciag_bledu, string nazwa_skryptu, int nr_lini, array kontekst)

Na wydruku 10.6 zamieszczony jest przyklad sposobu rejestrowania i uzycia funkcji obslugi bledw. Wydruk 10.6. Wykorzystanie set_error_handler()
<?php function myErrorHandler( $aErrorNo, $aErrorStr, $aFile, $aLine, $aContext) { switch ( $aErrorNo ) { case E_ERROR: $aErrorType = "E_ERROR"; // nie powinien wystapic break; case E_WARNING: $aErrorType = "E_WARNING";

Rozdzial 10 Uruchamianie

122

break; case E_PARSE: $aErrorType = "E_PARSE"; // nie powinien wystapic break; case E_NOTICE: $aErrorType = "E_NOTICE"; break; case E_CORE_ERROR: $aErrorType = "E_CORE_ERROR"; // nie powinien wystapic break; case E_CORE_WARNING: $aErrorType = "E_CORE_WARNING"; // nie powinien wystapic break; case E_COMPILE_ERROR: $aErrorType = "E_COMPILE_ERROR"; // nie powinien wystapic break; case E_COMPILE_WARNING: $aErrorType = "E_COMPILE_WARNING"; // nie powinien wystapic break; case E_USER_ERROR: $aErrorType = "E_USER_ERROR"; break; case E_USER_WARNING: $aErrorType = "E_USER_WARNING"; break; case E_USER_NOTICE: $aErrorType = "E_USER_NOTICE"; break; default: $aErrorType = "UNKNOWN ERROR TYPE"; break; } print( print( print( print( "<table border=\"1\"><tr><td>" ); "<b>$aErrorType</b>: <i>$aErrorStr</i><br>" ); "w pliku $aFile linia $aLine<br>" ); "</td></tr></table>" );

} set_error_handler( "myErrorHandler" ); error_reporting( E_ALL ); ?> <html> <head> <title>Wlasna obsluga bledw</title> </head> <body> <?php trigger_error( "Test bledw", E_USER_ERROR ); $aArray = array( "state" => "Idaho", "county" => "Madison", "city" => "Rexburg", "country" => "US" ); print( "aArray[state] = " . $aArray[state] . "<br>" ); ?> </body> </html>

W skrypcie na wydruku 10.6 zostala zdefiniowana funkcja obslugi bledw myErrorHandler(), ktra wyswietla komunikaty bledw w obramowanej tabeli zawierajacej jedna komrke, co pomaga w odrznieniu komunikatu bledu od reszty kodu HTML. Po zainstalowaniu funkcji obslugi, skrypt powoduje dwa bledy. Pierwszy jest generowany przy uzyciu funkcji PHP trigger_error(). Drugi blad (ostrzezenie) jest identyczny jak blad pokazany na wydruku 10.3. Na rysunku 10.4. pokazany zostal wynik dzialania skryptu. Rysunek 10.4. Dzialanie funkcji set_error_handler()

123

PHP Kompendium wiedzy

Uzywajac funkcji set_error_handler() nalezy pamietac, ze PHP nie przekazuje do funkcji obslugi bledw typu E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR oraz E_COMPILE_WARNING. Obsluga tego typu bledw przez uzytkownika nie jest bezpieczna. Z tego powodu w kodzie funkcji obslugi bledw z wydruku 10.6. pojawily sie komentarze nie powinien wystapic.
Uwaga na temat set_error_handler() Funkcja set_error_handler() jest dostepna w PHP od wersji 4.0.1. Dodatkowo, funkcja uzyta w tym przykladzie posiada piec parametrw, w tym nazwe skryptu, numer linii i dane kontekstu. Parametry te sa dostepne dopiero w wersji 4.0.2. Wczesniejsze wersje mialy tylko dwa parametry: typ komunikatu i komunikat.

W skrypcie z wydruku 10.6 nie sa wykorzystane dane na temat kontekstu. Beda one opisane w nastepnej czesci rozdzialu. Dane te zawieraja nazwy i wartosci zmiennych istniejacych w skrypcie w momencie wystapienia bledu. Rwniez funkcja assert() pozwala na zdefiniowanie wywolywanej funkcji. Aby to zrealizowac nalezy skorzystac z funkcji assert_options(). Funkcja obslugujaca nieudane asercje jest zdefiniowana w nastepujacy sposb:
function AssertCallback ($NazwaPliku, $NrLinii, $Asercja )

Uwaga na temat assert_options() W PHP do wersji 4.0.2 wlacznie, w funkcji assert_options() wystepowal maly blad. Wystepowal on w przypadku wywolania funkcji w postaci assert_options(ASSERT_CALLBACK), w celu odczytania ustawionej funkcji obslugi. Mimo, ze w dokumentacji napisano, ze wywolanie takie zwrci jedynie nazwe biezacej funkcji obslugi, to dodatkowo oprcz zwracania nazwy, biezace ustawienie funkcji obslugi bylo czyszczone. Dlatego jezeli chcesz uzyc funkcji assert() z funkcja obslugi upewnij sie, ze nie jest wywolywana pzniej funkcja assert_options() w celu sprawdzenia nazwy zarejestrowanej funkcji. Blad ten zostal zauwazony i poprawiony w wersjach PHP powyzej 4.0.2.

Na wydruku 10.7. pokazany zostal przyklad zdefiniowania i uzycia funkcji wywolywanej przez assert(). Wydruk 10.7. Wykorzystanie funkcji wywolywanej przez callback()
<?php error_reporting( E_ALL ); function MyACallback( $aFileName, $aLineNum, $aAssertion ) { print( "<table border=\"1\"><tr><td>" ); print( "<b>assert()</b> nieudane: <i>$aAssertion</i><br>" ); print( "w pliku $aFileName w linii $aLineNum<br>" ); print( "</td></tr></table>" ); } // zarejestrowanie funkcji obslugi assert_options( ASSERT_CALLBACK, "MyACallback" ); // wylaczenie normalnych ostrzezen assert_options( ASSERT_WARNING, 0 ); ?> <html> <head> <title>Wlasna obsluga asercji</title> </head> <body> Nieudana asercja. <?php assert( "1 == 2" ); ?> </body> </html>

Kod z wydruku jest podobny do tego z wydruku 10.6. Wywolanie asercji powoduje wyswietlenie jednokomrkowej tabeli. Jezeli nie zostanie opcja ASSERT_WARNING, oprcz informacji zdefiniowanych przez uzytkownika wyswietlony zostanie standardowy komunikat PHP. Na rysunku 10.5. pokazany jest wynik dzialania skryptu z wydruku 10.7.

Rozdzial 10 Uruchamianie

124

Rysunek 10.5. Uzycie funkcji zdefiniowanej dla assert()

PHP posiada elastyczny mechanizm obslugi bledw. Pozwala on dzieki temu pisac kod latwiejszy do uruchamiania i pzniejszego utrzymania. W nastepnej czesci polaczymy wszystkie przedstawione do tej pory techniki, co w efekcie pozwoli lepiej uruchamiac programy w calym cyklu produkcyjnym.

Zaawansowana obsluga bledw


Po omwieniu technik obslugi bledw mozemy rozpoczac tworzenie oglnego narzedzia do obslugi bledw. Motywacja do napisania tego fragmentu byl brak dostarczanych przez PHP narzedzi, ktre automatycznie lacza rzne typy danych o bledach. Oprcz tego, PHP 3 posiadal mozliwosc zdalnego uruchamiania, ktra nie zostala przeniesiona do PHP 4. Pozwalal on przesylac dane za pomoca protokolu TCP/IP do innego komputera. Opcja ta prawdopodobnie niedlugo sie pojawi, ale na razie musza wystarczyc podstawowe techniki obslugi bledw opisane w tym rozdziale. Przyklad przytoczony w tej czesci jest niezwykle dlugi, wiec zostanie omwiony we fragmentach. Modul ten znajduje sie w jednym pliku, MyDebug.php i bedzie on okreslony jako modul MyDebug. Jest on tak utworzony, ze moze byc latwo dolaczony do dowolnego skryptu PHP. Po dolaczeniu pliku wykonywany jest kod pokazany na wydruku 10.8. Wydruk 10.8. Dolaczanie modulu MyDebug
ParseConfig( getenv( "MYDEBUG_CONFIG" ) ); if ( $aMyDebugType & MYDEBUG_DISPLAYFILE ) { // jezeli nie mozna zapisac do pliku sladu // poinformuj o tym uzytkownika i wylaczyc zapis do pliku if ( CheckFileSanity( $aMyDebugFile ) == False ) { error_log( "MyDebug nie udalo sie otworzyc pliku $aMyDebugFile", 0 ); $aMyDebugType &= ~MYDEBUG_DISPLAYFILE; } } if ( $aMyDebugType & MYDEBUG_DISPLAYFILE ) { $aFileHandle = fopen( $aMyDebugFile, "a" ); } if ( $aMyDebugType & MYDEBUG_DISPLAYIP ) { $aSocketHandle = fsockopen( "udp://$aMyDebugIP", $aMyDebugPort ); } // Teraz rejestrujemy funkcje obslugi i funkcje porzadkujace set_error_handler( "MyErrHandler" ); assert_options( ASSERT_CALLBACK, "MyAssertHandler" ); assert_options( ASSERT_WARNING, 0 ); register_shutdown_function( "MyDebugShutdown" );

Pierwsza linia z wydruku 10.8. powoduje przetworzenie ciagu konfiguracji MyDebug, ktry jest przechowywany w zmiennej srodowiska serwera. Na przyklad, plik konfiguracyjny Apache moze zawierac kod podobny do nastepujacego:
SetEnv MYDEBUG_CONFIG FILE=/tmp/mydebug.log; MAIL=mydebug@intechra.net;IP=myserver.com:5400;

125

PHP Kompendium wiedzy

Ta opcja konfiguracji jest specyficzna dla modulu MyDebug i nie jest dostepna jako standardowa czesc Apache czy PHP. Przyklad ten pokazuje, ze mozna ustawiac zmienne srodowiska, poprzez pliki konfiguracyjne serwera WWW i sa one dostepne w kodzie PHP. Zmienna MYDEBUG_CONFIG definiuje miejsca, gdzie MyDebug bedzie zapisywal bledy. W tym przypadku modul bedzie zapisywal bledy do pliku (/tmp/mydebug.log), wysylal na adres e-mail (mydebug@intechra.net)oraz do gniazda UDP (myserver.com:5400). W normalnej pracy wybiera sie zwykle jedna z metod zapisu bledw, ale modul MyDebug pozwala na stosowanie wielu jednoczesnych miejsc zapisu bledw. Funkcja ParseConfg() analizuje ciag konfiguracji i ustawia odpowiednie zmienne globalne. Po przeanalizowaniu ciagu konfiguracyjnego sprawdzane sa wszystkie pliki uzywane do zapisu, aby miec pewnosc, ze mozna do nich zapisywac dane. Jezeli modul MyDebug nie moze zapisac danych do pliku, zapisywanie do niego jest wylaczane. Nastepnie otwierane sa wszystkie potrzebne pliki i gniazda. Gniazdo jest otwierane uzywajac UDP, co nie wymaga istnienia procesu nasluchu. Wlasnosc ta jest uzyteczna szczeglnie wtedy, gdy zapisywanie jest aktywne na serwerze produkcyjnym, ale nie zawsze jest aktywny proces nasluchu. Nastepnie modul MyDebug rejestruje funkcje obslugi bledw i asercji. Ostatnia operacja jest zarejestrowanie funkcji wywolywanej po zakonczeniu programu, co pozwala na eleganckie zakonczenie dzialania modulu. Na wydruku 10.9 pokazana jest funkcja konczaca program. Wydruk 10.9. Funkcja konczaca program
function MyDebugShutdown( ) { global $aFileHandle, $aSocketHandle, $aMyDebugType; if ( $aMyDebugType & MYDEBUG_DISPLAYFILE ) { fclose( $aFileHandle ); } if ( $aMyDebugType & MYDEBUG_DISPLAYIP ) { fclose( $aSocketHandle ); } }

Funkcja ta zamyka wymagane pliki oraz gniazdo sieciowe. Funkcje konczaca moze zarejestrowac dowolny skrypt. PHP pozwala na rejestrowanie wielu funkcji konczacych, ktre sa wykonywane w czasie konczenia pracy skryptu. Choc ten fakt nie jest odnotowany w dokumentacji, funkcje te sa wywolywane w tej samej kolejnosci, co zostaly zarejestrowanie. Poniewaz kolejnosc ta nie zostala udokumentowana, skrypty twoje nie powinny polegac na kolejnosci wykonywania funkcji konczacych lub musisz sam to przetestowac. Mozna przekazac dodatkowe argumenty do funkcji register_shutdown_function(). PHP przekaze je do funkcji koncowej. Nalezy rwniez pamietac, ze w funkcji koncowej nie mozna wysylac zadnych danych do przegladarki. Po skonfigurowaniu modulu MyDebug, obsluguje on bledy za pomoca funkcji z wydruku 10.10. Wydruk 10.10. Funkcje obslugi bledw
// Funkcja obslugi ustawiana przez set_error_handler() function MyErrHandler( $aErrorNo, $aErrorStr, $aFile, $aLine, $aContext) { MyDebug( $aErrorStr, $aFile, $aLine, MYDEBUG_ERRCALLBACK, $aErrorNo, $aContext ); } // Funkcja obslugi dla funcji assert_options() function MyAssertHandler( $aFileName, $aLineNum, $aAssertion ) { MyDebug( "asercja( $aAssertion ) nieudana", $aFileName, $aLineNum, MYDEBUG_ASSERTCALLBACK ); }

Obie funkcje przekazuja parametry do glwnej funkcji obslugi bledw, ktra moze rwniez zostac wywolana bezposrednio ze skryptu. Glwna funkcja obslugi bledw to przedstawiona na wydruku 10.11. funkcja MyDebug(). Wydruk 10.11. Funkcja MyDebug()
// Funkcja MyDebug jest glwna funkcja obslugi function MyDebug( $aMessage, $aFile, $aLine, $aCallType = MY_DEBUG_INTERNAL, $aErrType = 0, $aErrContext = array() ) { global $aMyDebugType; for ( $aDisplayType = MYDEBUG_DISPLAYFILE; $aDisplayType <= MYDEBUG_DISPLAYIP; $aDisplayType++ ) {

Rozdzial 10 Uruchamianie

126

if ( $aDisplayType & $aMyDebugType ) { $aType = FormatType( $aCallType, $aDisplayType ); $aMessage = FormatMsg ( $aCallType, $aMessage, $aErrType, $aDisplayType ); if ( $aCallType == MYDEBUG_ERRCALLBACK ) { $aContext = FormatContext( $aErrContext, $aDisplayType ); } else { $aContext = ""; } MyDebugOutput( $aType, $aMessage, $aFile, $aLine, $aContext, $aDisplayType ); } } }

Funkcja MyDebug() formatuje rzne parametry w zaleznosci od typu medium zapisu (plik, e-mail lub TCP/IP). Nastepnie wywoluje funkcje MyDebugOutput() (wydruk 10.12), ktra wysyla dane do prawidlowego miejsca. Funkcje formatujace z wydruku 10.11 zostana omwione pzniej. Wydruk 10.12. Funkcja MyDebugOutput()
function MyDebugOutput( $aType, $aMessage, $aFile, $aLine, $aContext, $aDisplayType ) { global $aFileHandle, $aSocketHandle, $aMyDebugEmail; switch( $aDisplayType ) { case MYDEBUG_DISPLAYFILE: $aMsg = "$aType: '$aMessage' wystapil w $aFile w lini $aLine. "; if ( $aContext != "" ) { $aMsg .= "Dane kontekstu:\n{$aContext}\n"; } else { $aMsg .= "\n"; } fputs( $aFileHandle, $aMsg ); break; case MYDEBUG_DISPLAYEMAIL: $aMsg = "$aType: '$aMessage' wystapil w $aFile w linii $aLine. "; if ( $aContext != "" ) { $aMsg .= "Dane kontekstu:\n{$aContext}\n"; } else { $aMsg .= "\n"; } mail($aMyDebugEmail, "Raport MyDebug", $aMsg, "From: mydebug@host.com\r\n"); break; case MYDEBUG_DISPLAYIP: $aMsg = "$aType|$aMessage|$aFile|$aLine|$aContext^^"; fputs( $aSocketHandle, $aMsg ); break; } }

Funkcja MyDebugOutput() wysyla dane do wlasciwych miejsc. Jest ona zaskakujaco prosta, jezeli pomysli sie o efektywnosci kazdej z tych opcji. Kazda funkcja formatujaca uzyta w module MyDebug posiada mechanizm zamiany wewnetrznego numeru bledu na postac czytelna dla czlowieka. Na przyklad funkcja FormatType() przedstawiona na wydruku 10.13 formatuje kod typu bledu. Wydruk 10.13. Funkcja FormatType()
Funkcja formatuje typ komunikatu w oparciu o to gdzie bedzie wyswietlony */ function FormatType( $aCallType, $aDisplayType ) { switch( $aDisplayType ) { case MYDEBUG_DISPLAYFILE: case MYDEBUG_DISPLAYEMAIL: switch ( $aCallType ) { case MYDEBUG_INTERNAL: return "INTERNAL"; /*

127

PHP Kompendium wiedzy

break; case MYDEBUG_ERRCALLBACK: return "ERROR CALLBACK"; break; case MYDEBUG_ASSERTCALLBACK: return "ASSERT CALLBACK"; break; } break; case MYDEBUG_DISPLAYIP: return $aCallType; break; } }

Jezeli dane sa wysylane poprzez TCP/IP, nie jest przeprowadzane formatowanie. Sam numer typu jest wysylany do zdalnego komputera. W innym wypadku numer typu jest zamieniany na czytelny ciag. Inne funkcje konwertujace uzyte w MyDebug dzialaja podobnie. Jedyna funkcja formatujaca, ktra jest wyraznie inna, jest funkcja formatujaca kontekst bledu, FormatContext(). Funkcja ta jest wywolywana jedynie wtedy, gdy blad zostanie obsluzony przez funkcje zarejestrowana za pomoca set_error_handler(). Dane kontekstu udostepniane przez PHP zawieraja wszystkie zmienne bedace w zasiegu w momencie wystapienia bledu. Dane te sa przesylane w postaci tablicy asocjacyjnej z nazwami zmiennych i ich wartosciami. Analiza tych danych wymaga wykorzystania funkcji rekurencyjnej, poniewaz w kontekscie moga znajdowac sie tablice. Funkcja zamieszczona na wydruku 10.14. analizuje dane kontekstu, przeksztalcajac je na postac czytelna dla czlowieka. Wydruk 10.14. Analiza danych kontekstu
/* Funkcja formatuje typ komunikatu w oparciu o to gdzie bedzie wyswietlony. Funkcja oparta o funkcje rekurencyjna FormatContextR */ function FormatContext( $aErrContext, $aDisplayType ) { // od tej pory wszystkie wyswietlane typy // otrzymuja ten sam ciag kontekstu $aString = ""; $aDelim = "\n"; FormatContextR( $aErrContext, $aString, $aDelim ); return $aString; } function FormatContextR( $aErrContext, &$aString, $aDelim ) { foreach( $aErrContext as $aVarName => $aVarValue ) { if ( is_array( $aVarValue ) == True ) { $aString .= "$aVarName = array( "; FormatContextR( $aVarValue, $aString, "," ); $aString .= " )$aDelim"; } else { $aString .= "$aVarName = {$aVarValue}{$aDelim}"; } } }

Funkcja FormatContext() ustawia kilka parametrw i wywoluje funkcje rekurencyjna FormatContextR(). Funkcja rekurencyjna przeglada tablice zmiennych kontekstu i zapisuje kazda pare nazwa-wartosc do wynikowego ciagu. Jezeli napotkana zostanie tablica, rekurencyjnie jest wywolywana funkcja FormatContextR(). W zaleznosci od miejsca wystapienia bledu, kontekst lokalny moze zawierac sporo danych. Jezeli blad wystapi w glwnej czesci skryptu, w zasiegu znajda sie wszystkie zmienne globalne, w tym zmienne srodowiska i zmienne GET i POST. Wszystkie te zmienne znajda sie w danych kontekstu. Jezeli blad wystapi w funkcji, kontekst bedzie zawieral jedynie zmienne lokalne funkcji. Do skryptu testujacego (wydruk 10.15.) dolaczylismy modul MyDebug oraz ustawilismy zmienna konfiguracji na zapisywanie do pliku tekstowego. Po jego uruchomieniu na koncu pliku sladu znalazl sie ciag bledu. Ponizszy tekst nie jest calym plikiem, jedynie wynikiem wystapienia ostatniego bledu w skrypcie:
ERROR CALLBACK: 'Typ bledu PHP: E_USER_ERROR - error in sum' wystapil w c:\helion\php4-devguide\site\ch10\test_mydebug.phtml w lini 16. Dane kontekstu: a = 1 b = 2 aArray = array( 0 = spring,1 = summer,2 = autumn,3 = winter, )

Wydruk 10.15. Skrypt testowy


<?php

Rozdzial 10 Uruchamianie

128

include_once( "./mydebug.php" ); ?> <html> <head> <title>Test modulu MyDebug</title> </head> <body> Nieudana asercja.<br><br> <?php function sum( $a, $b ) { $aArray = array( "spring", "summer", "autumn", "winter" ); trigger_error( "error in sum", E_USER_ERROR ); } assert( "1 == 2" ); trigger_error( "Blad testowy", E_USER_ERROR ); $aArray = array( "state" => "Idaho", "county" => "Madison", "city" => "Rexburg", "country" => "US" ); print( "<br><br>aArray[state] = " . $aArray[state] . "<br>" ); sum( 1, 2 ); ?> </body> </html>

Skrypt testowy przedstawiony na wydruku 10.15. nie robi nic, poza generowaniem bledw. Wynik funkcja sum() nie jest nigdzie uzywany, ale jest ona umieszczone w tym skrypcie, aby pokazac jak wywolanie funkcji wplywa na dane kontekstu przekazywane przez PHP. Linie z opisem bledu zamieszczone bezposrednio przed wydrukiem 15 sa wygenerowane przy wywolaniu funkcji sum(). Aby pokazac elastycznosc tego modulu, napisana zostala aplikacja Windows, ktra realizuje proces nasluchu portu TCP/IP i wyswietla przychodzace dane. Jest to prosta aplikacja Delphi, ktra odczytuje pakiety UDP przychodzace do portu 5400. Po odczytaniu danych formatuje linie i wyswietla je. Na rysunku 10.6. pokazana zostala ta aplikacja po odebraniu kilku komunikatw wygenerowanych przez PHP. Rysunek 10.6. Aplikacja nasluchu dla MyDebug

Jednym z powodw atrakcyjnosci jezyka PHP jest to, ze jest on niezwykle rozszerzalny. Modul MyDebug jest napisany calkowicie w PHP dodajac do niego niezwykle uzyteczne funkcje (kompletne zrdla modulu MyDebug sa dostepne wraz z wszystkimi przykladami kodu z tej ksiazki). Modul ten nie jest kompletny i moze byc rozwijany na wiele sposobw. Na przyklad, wykorzystanie poczty elektronicznej do raportowania bledw jest niezwykle nieefektywne, ale mozna wykorzystac poczte elektroniczna do raportowania jedynie krytycznych bledw i ostrzezen, co pozwoli na wykorzystanie tej opcji w srodowisku produkcyjnym. Niezmiernie istotny jest fakt, ze wszystkie te opcje sa zrealizowane calkowicie w PHP. Nie wszystkie narzedzia programowania dla WWW sa tak elastyczne.

Podsumowanie
W tym rozdziale przedstawione zostaly informacje na temat technik programowania defensywnego, ktre pozwalaja na unikniecie mozliwie duzo pracy przy uruchamianiu. W chwili obecnej PHP nie posiada programu do uruchamiania skryptw, podobnego do tych, ktre sa dostepne we wielu nowoczesnych jezykach 129 PHP Kompendium wiedzy

programowania. Jednak przy odrobinie pomyslowosci i wykorzystujac rozszerzalnosc PHP, mozna stworzyc swietne narzedzia do uruchamiania aplikacji. Opisany zostal jeden z modulw, ktry zapewnia elastyczna obsluge bledw i moze byc modyfikowany i rozszerzany tak, aby spelnial wymagania prawie kazdego programisty.

Bibliografia
Steve McConnell. Code Complete. Seattle: Microsoft Press, 1993.

Rozdzial 10 Uruchamianie

130

Rozdzial 11. Ponowne wykorzystanie kodu


Wstep
Podczas tworzenia dowolnej aplikacji niezmiernie wazne jest wykorzystanie istniejacych modulw kodu. Pierwszym powodem jest to, ze uzywane moduly kodu stanowia podstawe kolejnych aplikacji i w dluzszym czasie polepszaja wydajnosc zespolu programistw. Poniewaz PHP pozwala na dolaczanie zewnetrznych plikw oraz na tworzenie klas, ponowne wykorzystanie kodu jest dosyc proste. W tym rozdziale ponowne wykorzystanie kodu zostanie krtko omwione z perspektywy inzynierii programowania, oraz przytoczone zostanie kilka przykladw kodu PHP nadajacego sie do powtrnego wykorzystania. W rozdziale tym omwione zostanie wykorzystanie w projektach PHP kodu napisanego w innych jezykach programowania. Taka elastycznosc pozwala programistom na przenoszenie do sieci WWW istniejacych aplikacji bez koniecznosci calkowitego przepisywania kodu.

Ponowne wykorzystanie kodu a inzynieria programowania


Ponowne wykorzystanie kodu nie polega jedynie na integracji istniejacego kodu z nowym produktem. Nowe fragmenty kodu czesto sa tworzone w sposb ulatwiajacy ich ponowne wykorzystanie. Gdy planowane jest ponowne wykorzystanie kodu, wazne sa efekty dlugoterminowe, poniewaz tworzenie takiego kodu zajmuje czesto duzo wiecej czasu i jest bardziej kosztowne w porwnaniu do tego samego kodu do jednokrotnego uzycia (McConnell, 1996). Zalety ponownego uzycia nie sa natychmiast widoczne, ale wiele firm zauwazylo okolo 58% wzrost wydajnosci rocznie w przeciagu czterech lat (McConnell, 1996). Zalety te nie beda wykorzystane, jezeli nie zostanie zastosowane odpowiednie planowanie. Ponizej przedstawione zostaly niektre wazne zagadnienia, jakie nalezy wziac pod uwage: Zaangazowanie kierownictwa w proces ponownego wykorzystania kodu. Upewnienie sie, ze tworzenie kodu do ponownego wykorzystania jest integralna czescia calego procesu produkcji oprogramowania i ze wszyscy programisci zgadzaja sie z ta idea. Skupienie sie na tworzeniu malych, precyzyjnych modulach kodu. Tworzenie kodu do ponownego wykorzystania przy uzyciu mozliwie najlepszych standardw programowania i dokumentacji. Tworzac kod nalezy miec na uwadze, ze przy pisaniu aplikacji w przyszlosci beda potrzebne podobne fragmenty. Majac to na uwadze, czesciej nalezy dzielic grupy funkcji na oddzielne moduly lub klasy. Jezeli wiadomo, ze dany fragment kodu bedzie wykorzystywany w przyszlosci, nalezy napisac go i udokumentowac w sposb zgodny z najlepszymi zaleceniami stosowanymi w zespole. Nalezy unikac uzywania danych lub zalozen specyficznych dla projektu, a zamiast tego tworzyc modul w sposb, ktry uprosci jego wykorzystanie w przyszlosci. W PHP kod nadajacy sie do powtrnego wykorzystania mozna tworzyc przy pomocy kilku metod, na przyklad tworzac oddzielne pliki z kodem zrdlowym (pliki dolaczane) lub tworzac klasy obiektowe. Wybr plikw dolaczanych lub podejscia obiektowego nie wplywa zbytnio na oglne zalozenia. Kluczem do sukcesu jest tworzenie kodu nadajacego sie do powtrnego uzycia, ktry jest odpowiednio zorganizowany i dobrze udokumentowany. Uzycie hermetyzacji i technik ukrywania danych da w efekcie maksymalne zwiekszenie wydajnosci i efektywnosci ponownie wykorzystanego kodu.

Ponowne uzycie istniejacego kodu


Z powodu natury projektw internetowych, w firmie moze nie istniec zbyt wiele fragmentw kodu do wykorzystania. Jednak ponowne wykorzystanie kodu moze jedynie wymagac przewidywania przyszlych projektw. Omwione zostana teraz niektre techniki dostepne w PHP, o ktrych nalezy pamietac przy projektowaniu aplikacji. Jezeli przenosi sie zwykla aplikacje biurowa do sieci, lub przepisuje sie z innego jezyka na PHP, prawdopodobnie istnieje wtedy kod, ktry mozna wykorzystac. Poniewaz PHP jest niezwykle rozszerzalny, istnieje wiele metod uzycia obcego kodu w aplikacjach opartych o PHP. Niektre z tych metod zostana opisane w pzniejszych czesciach.

PHP
PHP zawiera kilka narzedzi ulatwiajacych ponowne wykorzystanie kodu. Z tego powodu zostala przygotowana podstawa do tworzenia narzedzi dla PHP tworzonych przez rzne firmy. Niektre z nich zostaly wspomniane w poprzednich rozdzialach i sa wymienione na liscie zasobw internetowych, na koncu ksiazki. Najbardziej oczywista metoda ponownego wykorzystania kodu PHP jest uzycie funkcji include() lub require() do dolaczenia istniejacego kodu. Uzywane juz we wczesniejszych przykladach, funkcje te pozwalaja na dolaczanie czystego kodu PHP, HTML lub ich kombinacji. Zaczynajac od wersji PHP 4, dostepne sa funkcje include_once() i require_once(), ktre upraszczaja proces dolaczania. Funkcje te eliminuja problem wystepujacy przy wielokrotnym dolaczaniu do skryptu tego samego pliku. Na wydruku 11.1. i 11.2. przedstawiono przyklad takiego problemu i sposb jego rozwiazania. Wydruk 11.1. Plik dolaczany date_funcs.php
<?php include_once( "./format_funcs.php" ); // Zwraca ilosc dni pomiedzy datami // jako sformatowany ciag w postaci mm-dd-rrrr function GetDateDiff( $aDateStr1, $aDateStr2 ) { $aDateArray1 = explode( "-", $aDateStr1 ); assert( 'count( $aDateArray1 ) == 3' ); $aDateArray2 = explode( "-", $aDateStr2 ); assert( 'count( $aDateArray2 ) == 3' ); $aTime1 = mktime( 0, 0, 0, $aDateArray1[0], $aDateArray1[1], $aDateArray1[2] ); $aTime2 = mktime( 0, 0, 0, $aDateArray2[0], $aDateArray2[1], $aDateArray2[2] ); $aTimeDiff = abs( $aTime1 - $aTime2 ); return GetFormattedNumber( $aTimeDiff / ( 60 * 60 * 24 ) ); } ?>

Wydruk 11.2. Plik dolaczany format_funcs.php


<?php function GetFormattedNumber( $aNum ) { return number_format( $aNum, 0, '.', ' ' ); } ?>

Skrypt z wydruku 11.3. wykorzystuje funkcje z obu poprzednich plikw dolaczanych. Wydruk 11.3. Skrypt wykorzystujacy oba pliki dolaczane
<?php include( "./date_funcs.php" ); include( "./format_funcs.php" ); ?> <html> <head> <title>Problem z wielokrotnym dolaczaniem plikw</title> </head> <body> <?php $aNumVisitors = 14500; print( "Witryne odwiedzilo " ); print( GetFormattedNumber( $aNumVisitors ) ); print( " gosci " ); print( "w przeciagu ostatnich " ); print( GetDateDiff( "9-21-2000", "8-15-1992" ) ); print( " dni." ); ?> </body> </html>

Rozdzial 11 Ponowne wykorzystanie kodu

132

Problem wystepujacy w skrypcie z wydruku 11.3 wynika z tego, ze plik dolaczany date_funcs.php dolacza rwniez plik format_funcs.php. Po uruchomieniu skryptu generowany jest komunikat bledu:
Fatal error: Cannot redeclare getformattednumber() in ./format_funcs.php on line 2

Na wydruku 11.4. pokazane zostalo jak latwo mozna rozwiazac ten problem korzystajac z funkcji include_once(). Wydruk 11.4. Skrypt wykorzystujacy include_once()
<?php include_once( "./date_funcs.php" ); include_once( "./format_funcs.php" ); ?> <html> <head> <title>Problem z wielokrotnym dolaczaniem plikw</title> </head> <body> <?php $aNumVisitors = 14500; print( "Witryne odwiedzilo " ); print( GetFormattedNumber( $aNumVisitors ) ); print( " gosci " ); print( "w przeciagu ostatnich " ); print( GetDateDiff( "9-21-2000", "8-15-1992" ) ); print( " dni." ); ?> </body> </html>

Funkcje require() i require_once() dzialaja podobnie. Ten mechanizm dolaczania plikw pozwala na tworzenie wlasnych bibliotek czesto uzywanych funkcji oraz wykorzystanie kodu od zewnetrznych dostawcw. Dodatkowo PHP obsluguje tworzenie klas obiektowych, ktre mozna ponownie wykorzystywac lub rozszerzac. W poprzednich rozdzialach zostaly pokazane przyklady rozszerzania klas pochodzacych z od rznych dostawcw. Poniewaz PHP obsluguje dolaczanie modulw oraz programowanie obiektowe, naturalnie pozwala na tworzenie kodu wielokrotnego uzycia. Oprcz tego, rozszerzalnosc PHP pozwala na wykorzystanie innego istniejacego kodu.

C/C++
PHP jest napisany w C i C++. Z tego powodu mozliwa jest integracja istniejacego kodu C/C++ bezposrednio w PHP. Tak naprawde wiele z rozszerzen PHP jest bezposrednio przeniesiona z C lub C++. Na przyklad CyberCashTM Merchant Control Kit zostal napisany w C a jego funkcje sa dostepne w PHP jako funkcje cybercash_xxx(). Jezeli posiadasz istniejacy kod projektu w C lub C++, ktry ma byc przeniesiony do srodowiska WW, mozesz rozwazyc dolaczenie tego kodu do twojej instalacji PHP. Nalezy jednak pamietac, ze wymaga to sporo pracy i w efekcie moze byc mniej efektywne, niz proste przepisanie kodu na PHP. Skupmy sie teraz na tworzeniu wbudowanych funkcji PHP opartych o istniejace funkcje w C. Jezeli istniejacy kod jest napisany w C++, mozna utworzyc obiekty PHP uzywajace implementacji w C++, ale nie opiszemy tutaj tego procesu. Mozna zamiast tego napisac funkcje mapujace dla metod istniejacych obiektw C++. Zalzmy, ze mamy trzy funkcje zamieszczone na wydruku 11.5 i chcemy na ich podstawie utworzyc wewnetrzne funkcje PHP. Funkcje te sa wykorzystywane do obliczania platnosci hipotecznych i tworzenia tabel amortyzacji w USA. Pierwsze dwie funkcje zwracaja pojedyncze wartosci oznaczajace odpowiednio rate miesieczna i sume wszystkich rat. Ostatnia funkcja zwraca tabele wartosci reprezentujacych wartosc odsetek miesiecznych w racie. Uzywajac tych danych mozna wygenerowac harmonogram amortyzacji. Wydruk 11.5. Funkcje w C do konwersji na PHP
/* _fin_mpmt: oblicza miesieczna splate kredytu w oparciu o kwote kredytu (p), oprocentowanie (i) oraz czas (l) */ double _fin_mpmt (double p, double i, double l) { double j; double n; j = i / (12 * 100); n = l * 12;

133

PHP Kompendium wiedzy

return ( p* ( j/( 1 - (pow(( 1+j ), (n * -1)))))); } /* _fin_total: oblicza calkowita kwote splat w czasie trwania kredytu w oparciu o kwote kredytu (p), oprocentowanie (i) i czas (l) */ double _fin_total (double p, double i, double l) { return _fin_mpmt( p, i, l) * l * 12; } /* _fin_table: oblicza miesieczne odsetki uzywane w planie amortyzacji dla kredytw w oparciu o kwote (p), oprocentowanie (i), i czas (l) */ void _fin_table ( double p, double i, double l, double *pIntPmt) { double n, m, h, q, j, c; int nIndex; j = i / (12 * 100); n = l * 12; q = p; m = _fin_mpmt( p, i, l ); for (nIndex = 0; nIndex < n; nIndex++ ) { h = q * j; c = m - h; q = q - c; pIntPmt[nIndex] = h; } return ; }

W dystrybucji PHP dostarczany jest program o nazwie build_skel, ktry sluzy do tworzenia zbioru szkieletowych plikw konfiguracji dla nowych rozszerzen PHP. Program ten znajduje sie w katalogu ext dystrybucji PHP zawierajacej pliki zrdlowe. Aby dodac funkcje finansowe do PHP nalezy uruchomic build_skel w nastepujacy sposb:
./build_skel --extname=fin_funcs --proto=/sciezka/do/fin_funcs.proto --assign-params

Parametr extname jest nazwa nowego rozszerzenia PHP, natomiast proto jest nazwa pliku zawierajacego prototypy tworzonych funkcji. Plik prototypw powinien zawierac prototypy funkcji PHP. Dla funkcji finansowych uzyjemy nastepujacej zawartosci pliku prototypw:
double fin_mpmt ( double principle, double interest, double length ) double fin_total ( double principle, double interest, double length ) array fin_table ( double principle, double interest, double length )

Parametr assign-params powoduje, ze pliki szkieletowe dolaczaja parametry o prawidlowych typach, co zostanie opisane pzniej. Inne dostepne parametry pozwalaja kontrolowac wyglad dokumentacji, i inne ustawienia generacji kodu. Wiecej szczeglw mozna uzyskac uruchamiajac skrypt build_skel bez parametrw. Po uruchomieniu skryptu w sposb przedstawiony powyzej, tworzony jest nowy katalog ext/fin_funcs, ktry zawiera pliki rozszerzen wymagane przez PHP. Pierwsza zmiana musi zostac wprowadzona do pliku config.4m. W pliku tym zawarty jest opis omawiajacy wymagane zmiany. Plik ext/fin_funcs/config.m4 jest pokazany ponizej (komentarze zostaly usuniete):
PHP_ARG_ENABLE(fin_funcs, whether to enable fin_funcs support, [ --enable-fin_funcs Enable fin_funcs support]) if test "$PHP_FIN_FUNCS" != "no"; then AC_DEFINE(HAVE_FIN_FUNCS, 1, [ ]) PHP_EXTENSION(fin_funcs, $ext_shared) fi

Funkcja build_skel tworzy plik zrdlowy w C, ktry zawiera wymagane funkcje i dolaczone pliki naglwkw, wiec natychmiast po uruchomieniu tego narzedzia i poprawieniu pliku config.m4 mozna skompilowac PHP z obsluga nowych rozszerzen. Aby upewnic sie, ze pliki szkieletowe i konfiguracyjne sa prawidlowe, mozna wykonac nastepujace czynnosci: 1. Uruchom skrypt buildconf w glwnym katalogu PHP. 2. Uruchom skrypt configure i dodaj obsluge nowego rozszerzenia. 3. Skompiluj PHP. 4. Wykonaj skrypt testowy z katalogu z rozszerzeniem (fin_funcs.php) aby sprawdzic, czy rozszerzenie jest aktywne w PHP. Testowy modul rozszerzenia jest uaktywniany za pomoca dyrektywy konfiguracji --enable-fin_funcs. Skrypt testowy wykrywajacy, czy rozszerzenie dziala jest podobny do nastepujacego: Rozdzial 11 Ponowne wykorzystanie kodu 134

<?php if (extension_loaded( "fin_funcs" )) { // Wykonaj jedna z funkcji } else { print( "modul fin_funcs niedostepny<BR>" ); } ?>

Po skonfigurowaniu PHP, aby korzystal z nowego rozszerzenia, nalezy jeszcze uaktualnic plik extension.c, aby zawieral implementacje kazdej z funkcji. We wielu przypadkach wymaga to jedynie dolaczenia oryginalnych naglwkw i wywolaniu oryginalnych funkcji. W przykladzie z funkcjami finansowymi, funkcje sa zdefiniowane w sposb pokazany na wydruku 11.6. Nalezy zauwazyc, ze skrypt build_skel wygenerowal wiekszosc kodu w ciele kazdej funkcji. Kod dodany recznie zaznaczony jest czcionka pogrubiona. Wydruk 11.6. Funkcje finansowe dodane do PHP
/* {{{ proto double fin_mpmt(double principle, double interest, double length) */ PHP_FUNCTION(fin_mpmt) { zval **principle_arg, **interest_arg, **length_arg; double principle; double interest; double length; double aRetVal; if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &principle_arg, &interest_arg, &length_arg) == FAILURE){ WRONG_PARAM_COUNT; } convert_to_double_ex(principle_arg); principle = Z_DVAL_PP(principle_arg); convert_to_double_ex(interest_arg); interest = Z_DVAL_PP(interest_arg); convert_to_double_ex(length_arg); length = Z_DVAL_PP(length_arg); aRetVal = _fin_mpmt( principle, interest, length ); RETVAL_DOUBLE( aRetVal ); } /* }}} */ /* {{{ proto double fin_total(double principle, double interest, double length) */ PHP_FUNCTION(fin_total) { zval **principle_arg, **interest_arg, **length_arg; double principle; double interest; double length; double aRetVal; if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &principle_arg, &interest_arg, &length_arg) == FAILURE){ WRONG_PARAM_COUNT; } convert_to_double_ex(principle_arg); principle = Z_DVAL_PP(principle_arg); convert_to_double_ex(interest_arg); interest = Z_DVAL_PP(interest_arg); convert_to_double_ex(length_arg); length = Z_DVAL_PP(length_arg); aRetVal = _fin_total( principle, interest, length ); RETVAL_DOUBLE( aRetVal ); } /* }}} */ /* {{{ proto array fin_table(double principle, double interest, double length) */ PHP_FUNCTION(fin_table) { zval **principle_arg, **interest_arg, **length_arg; double principle; double interest; double length; double *pIntPmts; int n, nIndex;

135

PHP Kompendium wiedzy

if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &principle_arg, &interest_arg, &length_arg) == FAILURE){ WRONG_PARAM_COUNT; } convert_to_double_ex(principle_arg); principle = Z_DVAL_PP(principle_arg); convert_to_double_ex(interest_arg); interest = Z_DVAL_PP(interest_arg); convert_to_double_ex(length_arg); length = Z_DVAL_PP(length_arg); n = (int)length * 12; pIntPmts = emalloc( sizeof( double ) * n ); _fin_table( principle, interest, length, pIntPmts ); if (array_init(return_value)== FAILURE ) { php_error( E_ERROR, "fin_table: nie udalo sie utworzyc tablicy"); } else { for ( nIndex = 0; nindex < n; nIndex++ ) add_next_index_double( return_value, pIntPmts[nIndex]); } efree( pIntPmts ); } /* }}} */

W pierwszych dwch funkcjach do implementacji rozszerzenia wymagane bylo napisanie jednie trzech linii kodu. Pierwsza linia jest deklaracja zmiennej, druga wywoluje wewnetrzna funkcje obliczajaca wartosc a trzecia ustawia zwracana wartosc. Ostania funkcja jest utworzona w taki sposb, aby zwracala tablice PHP. Wymaga to nieco wiecej pracy od dwch pierwszych funkcji, ale wyniki tej pracy sa znaczace. Implementacja funkcji fin_table() pokazuje kilka technik waznych dla programowania dla PHP. Po pierwsze, przydzial pamieci jest przeprowadzany za pomoca funkcji emalloc(), natomiast efree() zapewnia, ze PHP wykona normalny proces odzyskiwania nieuzytkw. W implementacji fin_table() pamiec jest przydzielana dla tablicy tymczasowej zawierajacej wartosci wygenerowane przez funkcje C _fin_table(). Po wywolaniu funkcji wbudowanej, zwracana wartosc jest deklarowana przy pomocy wywolania funkcji array_init() jako tablica PHP. Nastepnie przy pomocy petli przebiegajacej po kolejnych komrkach tablicy i kolejnych wywolan funkcji add_next_index_double(), wartosci z tablicy C sa kopiowane do nowej tablicy PHP. Na koniec tymczasowa tablica jest niszczona i funkcja sie konczy. Po wbudowaniu tych funkcji w PHP, moga byc one wywolywane identycznie, jak inne wewnetrzne funkcje PHP. Na wydruku 11.7 pokazujemy przyklad uzycia nowego rozszerzenia. Wydruk 11.7. Uzycie funkcji finansowych dodanych do PHP
<html> <head> <title>Kalkulator kredytowy</title> </head> <body> <?php if ( $REQUEST_METHOD == 'POST' ) { print( "Kwota pozyczki: <b>" . number_format( $Amount ) . "</b><br>" ); print( "Oprocentowanie: <b>{$Interest}%</b><br>" ); print( "Czas splaty: <b>$Term lat</b><br><hr>" ); $aMontlyPayment = fin_mpmt( $Amount, $Interest, $Term ); print("Rata miesieczna: <b>" . number_format( $aMontlyPayment, 2 ) . "</b><br>"); print( "Suma rat: <b>" . number_format( fin_total( $Amount, $Interest, $Term ), 2 ) . "</b><br><br>" ); $aArray = fin_table( $Amount, $Interest, $Term ); ?> <table border="1"> <tr> <td> Rata nr. </td> <td> Podstawa </td> <td> Odsetki </td> </tr> <?php $nIndex = 1;

Rozdzial 11 Ponowne wykorzystanie kodu

136

foreach( $aArray as $aIntPmt ) { $aPrinciple = number_format( $aMontlyPayment - $aIntPmt, 2 ); $aIntPmt = number_format( $aIntPmt, 2 ); ?> <tr> <td> <?=$nIndex?> </td> <td> <?=$aPrinciple?> </td> <td> <?=$aIntPmt?> </td> </tr> <?php $nIndex++; } ?> </table> <?php } ?> <form action="<?=$PHP_SELF?>" method="post"> <table> <tr> <td colspan="2"> To jest prosty kalkulator rat kredytu. Wprowadz kwote pozyczki, oprocentowanie i czas splaty </td> </tr> <tr> <td> Kwota: </td> <td> <input type="text" name="Amount"> </td> </tr> <tr> <td> Oprocentowanie ("7.5" == 7.5%): </td> <td> <input type="text" name="Interest"> </td> </tr> <tr> <td> Czas splaty (w latach): </td> <td> <input type="text" name="Term"> </td> </tr> <tr> <td colspan="2"> <input type="submit" name="Submit" value="Wyslij"> </td> </tr> </table> </form> </body> </html>

Skrypt ten wyswietla formularz do wprowadzenia danych kredytu, a nastepnie wysyla je do samego siebie. Po wywolaniu go poprzez wywolanie HTTP POST, wywolywane sa funkcje finansowe i wyswietlane wyniki ich dzialania. Na rysunku 11.1. pokazany jest fragment strony bedacej wynikiem typowego wykonania programu.

137

PHP Kompendium wiedzy

Rysunek 11.1. Wykorzystanie nowych funkcji finansowych

Jak wspomniano wczesniej, jezeli masz duza biblioteke kodu C/C++ pochodzaca z istniejacych aplikacji i zamierzasz przeniesc je do srodowiska WWW, PHP posiada prosty mechanizm integracji istniejacego kodu z nowymi aplikacjami. Zaleta tego rozwiazania jest mozliwosc ponownego wykorzystania dobrze przetestowanego kodu oraz dobra wydajnosc skompilowanego kodu. Dodatkowo, funkcje napisane w C lub C++ moga realizowac funkcje, ktrych nie da sie napisac wylacznie w PHP. Na przyklad implementacja bezpiecznych gniazd zapewnia mozliwosci, ktre nie moga byc w chwili obecnej zrealizowane przy pomocy funkcji PHP. Rozwazajac integracje istniejacego kodu C/C++ z PHP nalezy wziac pod uwage, ze koszt integracji moze byc wyzszy od kosztu przepisania kodu na PHP. Przytoczony wczesniej przyklad moze byc latwo przepisany na PHP i zajmie to mniej czasu. Dodatkowo kroki podjete w czasie integracji musza byc w czesci powtrzone dla kazdej nowej wersji PHP. Jezeli zamierzasz zawsze korzystac z najnowszej wersji PHP, powoduje to koniecznosc ciaglej konserwacji istniejacej witryny. Inna mozliwoscia wykorzystania istniejacego kodu C/C++ jest jego skompilowanie i wykonywanie na serwerze WWW poprzez PHP. Metoda ta zostanie opisana w dalszej czesci rozdzialu.

Java
W rozdziale 9, Niezaleznosc od przegladarki przedstawiony zostal opis polaczenia Javy z PHP. Mozliwosc uzywania klas Javy zostala wprowadzona w PHP4. Z powodu popularnosci Javy, dostepne jest wiele klas i modulw klas Javy, oferowanych przez wielu niezaleznych dostawcw. Obsluga Javy nie jest wlaczona domyslnie do PHP, wiec nalezy przekompilowac PHP, aby mc skorzystac z tego poteznego narzedzia. Dodawanie obslugi Javy w PHP na *niksach Jezeli korzystasz z PHP na platformie *nix, musisz przekompilowac PHP w celu dodania obslugi Javy. W podreczniku PHP znajdziemy, ze nie mozna wykorzystac opcji konfiguracji --with-java, jezeli posiadasz PHP statycznie wlaczone w Apache. Opcja ta dziala, jezeli PHP jest uruchamiany jako program CGI lub dynamicznie wlaczany modul Apache. Z powodw bezpieczenstwa nie zaleca sie korzystania z PHP w postaci CGI. Jezeli serwer Apache nie posiada obslugi dynamicznych modulw, nalezy go wczesniej przekompilowac.

Rozdzial 11 Ponowne wykorzystanie kodu

138

Ponizszy skrypt powoduje przekompilowanie Apache tak, aby korzystal z dynamicznie ladowanych modulw oraz tworzy wlasciwie skonfigurowany skrypt apxs, ktry bedzie potrzebny do skompilowania PHP. W skrypcie tym zakladamy, ze bedzie on uruchomiony z glwnego katalogu instalacji Apache.
make clean ./configure --enable-module=so --enable-rule=SHARED_CORE --prefix=/www make make install

Po przekompilowaniu Apache mozna uaktywnic obsluge Javy w PHP za pomoca nastepujacego skryptu. Zakladamy w nim, ze bedzie uruchomiony z glwnego katalogu instalacji PHP.
make clean ./configure --with-apxs=/www/bin/apxs --with-java ... make make install

Opcja --with-java moze zawierac sciezke oznaczajaca katalog instalacji uzywanej maszyny wirtualnej Javy. Po zakonczeniu kompilacji mozna sprawdzic konfiguracje PHP za pomoca funkcji phpinfo(). Nalezy rwniez ustawic kilka opcji konfiguracji Javy w pliku php.ini. Pierwsza jest linia z dolaczeniem rozszerzenia (extension=libphp_java.so). Pozostale opcje zostana omwione pzniej. Dolaczanie obslugi Javy w PHP dla Windows Zamiast kompilowania specjalnej wersji PHP dla Windows, rozszerzenie Javy jest dostepne do pobrania z www.php.net. Powinienes sprawdzic ktra wersja JDK (Java Development Kit) jest zainstalowana na serwerze. Mozna to zrobic przy pomocy java -showversion. Nalezy pobrac odpowiedni plik rozszerzenia i skopiowac php_java.dll do katalogu systemowego. W Windows 95 jest to zwykle \windows\system a Windows NT \winnt\system32. Nastepnie nalezy uaktualnic plik php.ini. Nalezy doda linie ladujaca rozszerzenie (extension=php_java.dll). Nastepnie nalezy dodac odpowiednio sekcje z opcjami konfiguracji. Sa one kluczowe do prawidlowego dzialania Javy na kazdej platformie. Opcje konfiguracji Javy Niezaleznie od platformy, jezeli obsluga Javy jest aktywna w PHP, musisz dodac kilka opcji konfiguracji do pliku php.ini. W Windows sekcja ta powinna wygladac podobnie do nastepujacej:
[java] java.class.path="D:\php4\php_java.jar;D:\PHP4 book\other\RTF2HTML\lib\Scrooge_09b7.jar" java.home="D:\Program Files\JavaSoft\JRE\1.3" java.library="D:\Program Files\JavaSoft\JRE\1.3\bin\hotspot\jvm.dll"

W przypadku systemw *nix, sekcja ta jest nastepujaca:


[java] java.library.path=/usr/lib/kafee:/home/blake/php-4.0.1p12/modules java.home=/usr/lib/kaffe java.class.path=/usr/share/kaffe/Klasses.jar:/home/blake/php4.0.1.p12/ext/java/php_java.jar:/home/blake/bhawk/lib/bhawk4j.jar:/home/blake/bhawk:/home/blake/java/num berspeller.jar:/home/blake/java/sax2.jar:/home/blake/java/servlet.jar:/home/blake/java/scrooge.jar java.library=/www/libexec/libkaffevm.so

Po skonfigurowaniu obslugi Javy, w pliku php.ini musisz podac lokalizacje klas Javy lub plikw JAR. Nalezy to wykonac dla kazdej uzywanej klasy Javy, ktrej chcesz uzywac. Jak widac na zamieszczonych opcjach konfiguracji, java.class.path zawiera pelna sciezke do plikw implementacji. Tak jak jest to w przypadku kazdego jezyka umozliwiajacego tworzenie komponentw, dla Javy dostepne jest wiele narzedzi, z ktrych mozna skorzystac za pomoca jezyka obslugujacego API. Jednym z dostepnych komercyjnie modulw Javy jest konwerter RTH na HTML Scrooge, ktry mozna zaladowac z witryny www.betabeans.de. Modul ten posiada prosty interfejs uzywany do konwertowania plikw RTF na standardowy HTML. Funkcja ta moze byc wykorzystywana we wielu aplikacjach, w ktrych uzytkownicy moga wysylac takie pliki. Poniewaz RTF obsluguje rzne czcionki i uklady, wykorzystanie RTF pozwala uzytkownikowi na dostarczanie plikw bez niebezpieczenstwa bezposredniego dodawania kodu HTML do witryny. Modul Scrooge zawiera przykladowy plik RTF (pokazany na rysunku 11.2.) ktrego mozemy uzyc do sprawdzenia sily i elastycznosci modulu.

139

PHP Kompendium wiedzy

Rysunek 11.2. Przykladowy plik RTF modulu Scrooge

Uzycie modulu Scrooge jest latwe i proste. Dolaczona dokumentacja zawiera nazwe klasy Javy, oraz liste dostepnych metod i wlasciwosci. W skrypcie z wydruku 11.8 pokazane jest wykorzystanie tego modulu. Wydruk 11.8. Uzycie modulu 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.betabeans.scrooge.Scrooge"); $aArray = file ( $rtffile ); $sR2H->setOptWrapHTML( False ); $aOutput = $aR2H->convert( implode( "", $aArray) ); print( $aOutput ); } else { print ("Wybrany plk nie jest plikiem <b>RTF</b>.<BR>"); } } ?> <FORM METHOD="POST" ACTION="<?=$PHP_SELF?>" enctype="multipart/form-data"> Przesylanie pliku: <INPUT TYPE="file" NAME="rtffile"><br><br> <INPUT TYPE="submit" NAME="submit" value="Wyslij"> </FORM> </BODY> </HTML>

Skrypt ten zawiera formularz przesylania pliku, za pomoca ktrego uzytkownik moze przeslac plik RTF. Po przeslaniu danych formularza sprawdzany jest typ pliku i jezeli jest prawidlowy tworzony jest obiekt Scrooge. Rozdzial 11 Ponowne wykorzystanie kodu 140

Przeslany plik jest odczytywany do tablicy za pomoca funkcji file(), a nastepnie uzywajac funkcji implode(), tablica jest konwertowana na ciag, ktry jest przekazywany do obiektu Scrooge. Zwracana wartoscia jest ciag zawierajacy kod HTML utworzony na podstawie przeslanego pliku. Wynikowy kod HTML jest wysylany do przegladarki. Na rysunku 11.3. przedstawiony jest wynik uzyskany z przykladowego pliku RTF. nie potrafie uruchomic tego przykladu Rysunek 11.3. Wynik przetworzenia przykladowego pliku RTF na kod HTML Java jest tylko jednym z jezykw umozliwiajacych tworzenie komponentw, ktre mozna wykorzystac w srodowisku PHP. Nastepna czesc opisuje uzycie obiektw COM w PHP.

COM
COM jest z natury oparty o Windows, wiec dyskusja ta odnosic sie bedzie do PHP dzialajacego na serwerze pracujacym pod kontrola systemu Windows. Standardowa instalacja PHP dla Windows posiada obsluge COM, wiec nie jest potrzebna dodatkowa konfiguracja. Implementacja COM w PHP ewoluowala z opartego o funkcje API w wersji 3, do implementacji obiektowej w PHP 4. Powoduje to, ze uzycie COM w PHP jest bardzo naturalne. W czesci tej omwimy serwer konwersji walut Cloanto Currency Server, dostepny z witryny http://cloanto.com. Obiekt ten pozwala na przeliczanie walut pomiedzy soba i posiada wewnetrzna baze danych kursw. Baza ta jest automatycznie uaktualniana, wiec mozna uzyc tego modulu w miedzynarodowej aplikacji handlu elektronicznego w celu umozliwienia wyswietlania cen w lokalnej walucie. Obiekt ten posiada bogaty zestaw metod, ale bardzo latwo mozna uzyc podstawowych funkcji w srodowisku testowym. Na wydruku 11.9. zamieszczony jest przyklad wykorzystania tego obiektu. Rysunki 11.4. i 11.5. pokazuja formularz z cenami w dwch rznych walutach. Wydruk 11.9. Uzycie serwera konwersji walut Cloanto
<html> <head> <title>Uzycie potokw</title> </head> <body> <?php $aFreeProg = '/usr/bin/free'; if ( !is_file( $aFreeProg ) ) { print( "Nie mozna znalezc programu na serwerze<br>" ); } else { $aLines = array(); if ( $aProgFile = popen( $aFreeProg . " -t", "r" ) ) { $nIndex = 0; $aLines = array(); while ( !feof( $aProgFile ) ) { $aLine = fgets( $aProgFile, 1024 ); $aLines[$nIndex++] = $aLine; } pclose( $aProgFile ); $aCount = count( $aLines ); $aTotal = $aLines[$aCount - 2]; $aArray = split( "[ ]+", $aTotal ); $aTotalK = number_format( $aArray[1] ); $aUsedK = number_format( $aArray[2] ); $aFreeK = number_format( $aArray[3] ); ?> Calkowita ilosc dostepnej pamieci <?=$aTotalK?> KB.<br> Wolna pamiec <?=$aFreeK?> KB.<br> Uzyte <?=$aUsedK?> KB.<br> <?php } else

141

PHP Kompendium wiedzy

{ print ( "Nie mozna uzyc programu na serwerze<br>" ); } } ?> </body> </html>

Rysunek 11.4. Przyklad uzycia serwera Cloanto, wyswietlana waluta: dolary amerykanskie

Rysunek 11.5. Przyklad uzycia serwera Cloanto, wyswietlana waluta: forinty wegierskie

W skrypcie umieszczonym na wydruku 11.9. utworzona jest prosta tabela cen dla trzech rznych towarw. Dodatkowo dostepny jest formularz do wyboru lokalnej waluty. Po przeslaniu danych formularza skrypt wykorzystuje serwer Cloanto do przeliczenia cen na wybrana walute. Obiekt ten jest uzywany do uzyskania listy krajw, wsplczynnikw wymiany oraz wykonuje przeliczanie na biezaco. Jezeli tworzona jest aplikacja handlu elektronicznego, przy pomocy tego obiektu mozna dodac niezwykle przydatna dla uzytkownikw funkcje, ktra eliminuje frustrujace pomylki w liczeniu cen. Wykorzystujac serwer Cloanto wraz z wykrywaniem typu przegladarki mozna przeliczac ceny na lokalna walute bez potrzeby pytania uzytkownika o jej nazwe.

Rozdzial 11 Ponowne wykorzystanie kodu

142

Z powodu duzej ilosci programistw Windows oraz dojrzalosci modelu COM, dostepne jest wiele komponentw dla wszystkich typw projektw. Uzywajac obslugi COM w PHP mozna z latwoscia wykorzystac istniejacy kod we wlasnych projektach.

Inne metody
Prawdopodobnie posiadasz istniejacy kod, ktrego nie da sie wykorzystac przy uzyciu zadnej z przedstawionych metod. Jezeli tak sie stanie, nadal mozna go wykorzystac w PHP. Jezeli kod ten jest skryptem (na przyklad skryptem Perla) lub mozna go skompilowac do postaci wykonywalnej, da sie go zastosowac w skrypcie. PHP posiada kilka funkcji sluzacych do uruchamiania programw i skryptw na serwerze. Poniewaz tematem tego rozdzialu jest integracja, najlepsza metoda wykorzystania programw na serwerze bedzie skorzystanie z funkcji popen() do uruchamiania programw i skryptw oraz przechwytywania ich wynikw. Technika ta byla przedstawiona w rozdziale 4 Operacje na plikach, na przykladzie programu whois, dostepnego na wiekszosci systemw *nix. Na wydruku 11.10. pokazany zostal przyklad odczytywania biezacej ilosci uzytej pamieci w systemach *nix. Wydruk 11.10. Uzycie potokw do integracji PHP z istniejacymi skryptami lub programami wykonywalnymi
<html> <head> <title>Uzycie potokw</title> </head> <body> <?php $aFreeProg = '/usr/bin/free'; if ( !is_file( $aFreeProg ) ) { print( "Nie mozna znalezc programu na serwerze<br>" ); } else { $aLines = array(); if ( $aProgFile = popen( $aFreeProg . " -t", "r" ) ) { $nIndex = 0; $aLines = array(); while ( !feof( $aProgFile ) ) { $aLine = fgets( $aProgFile, 1024 ); $aLines[$nIndex++] = $aLine; } pclose( $aProgFile ); $aCount = count( $aLines ); $aTotal = $aLines[$aCount - 2]; $aArray = split( "[ ]+", $aTotal ); $aTotalK = number_format( $aArray[1] ); $aUsedK = number_format( $aArray[2] ); $aFreeK = number_format( $aArray[3] ); ?> Calkowita ilosc dostepnej pamieci <?=$aTotalK?> KB.<br> Wolna pamiec <?=$aFreeK?> KB.<br> Uzyte <?=$aUsedK?> KB.<br> <?php } else { print ( "Nie mozna uzyc programu na serwerze<br>" ); } } ?> </body> </html>

Skrypt ten otwiera potok do standardowego programu free. Program zwraca dane na temat ilosci dostepnej pamieci w komputerze. Skrypt otwiera potok, ktry powoduje uruchomienie programu. Skrypt odczytuje z potoku kolejne wiersze wyniku i wyswietla je w przegladarce. W zaleznosci od zwracanych danych moze byc niezbedna bardziej zaawansowana analiza, ale podstawowa idea jest ta sama. Technika ta moze byc uzyta dla kazdego programu, ktry zwraca wyniki na standardowe wyjscie. W przypadku systemw Unix oznacza to, ze mozna w ten sposb uzyc nieomal kazdej komendy bezposrednio z PHP Kompendium wiedzy 143

PHP. Pozwala to latwo zrealizowac odczytanie statusu systemu, zwracanie danych lub inne operacje. Jezeli trzeba przeniesc istniejacy kod do PHP, pozwala to na szybkie prototypowanie, przed zastosowaniem wczesniej opisanych metod. Pozwala to na szybsze rozpoczecie testowania funkcji aplikacji minimalizujac ilosc koniecznych prac programistycznych. Nalezy jednak zaznaczyc, ze uruchamianie programw wymaga znacznej ilosci zasobw serwera, co moze powodowac, ze aplikacja bedzie powolna i trudna do skalowania.

Podsumowanie
W PHP nie brakuje mozliwosci ponownego uzycia kodu. Planujac tworzenie biblioteki kodu w PHP przeznaczonej do wielokrotnego uzytku lub przenoszac istniejacy kod do aplikacji WWW, mozna znalezc odpowiednie rozwiazanie. Z powodu olbrzymiej ilosci istniejacych komponentw (zarwno COM jak i Javy) moze sie okazac, ze wiekszosc projektowanej aplikacji jest juz napisana. Uzywajac tych komponentw mozna znacznie zmniejszyc czas potrzebny na napisanie programu. Uzywajac ich madrze, mozna otrzymac aplikacje latwiejsza w konserwacji i skalowaniu.

Bibliografia
Steve McConnell, Rapid Development. Seattle: Microsoft Press. 1996.

Rozdzial 11 Ponowne wykorzystanie kodu

144

Rozdzial 12. Oddzielanie kodu HTML od PHP


Wstep
Przy projektowaniu zwyklych aplikacji zwykle nie bierze sie pod uwage oddzielania tworzenia interfejsu uzytkownika od tworzenia czesci wykonawczej programu. Jest to spowodowane tym, ze standardowe aplikacje wykorzystuja standardowe narzedzia tworzenia interfejsu uzytkownika, dostepne dla wiekszosci programistw. Jedynymi fragmentami tworzonymi przez inne osoby sa emblematy, rysunki przyciskw i podobne elementy wplywajace na graficzny wyglad produktu. Programowanie dla WWW, pozwala na zastosowanie o wiele bogatszego interfejsu uzytkownika i przez to bardzo czesto wymaga zatrudnienia projektantw specjalizujacych sie w tworzeniu strony graficznej aplikacji. Gdy tworzenie interfejsu i kodu jest rozdzielone pomiedzy zespolami lub osobami, oddzielenie kodu i HTML staje sie naturalne a integracja wynikw pracy wazna. Nawet w malych jednoosobowych projektach oddzielenie HTML od logiki aplikacji powoduje, ze konserwacja aplikacji jest prostsza i bardziej efektywna.

Wprowadzenie
Programowanie dla WWW jest czesto nazywane tworzeniem aplikacji wielowarstwowej, poniewaz stosowane sa tutaj oddzielne logiczne warstwy. Czesto uzywanymi nazwami warstw sa: warstwa prezentacji, warstwa aplikacji (biznesowa) oraz warstwa bazy danych. Kazda z tych warstw moze byc fizycznie oddzielona od drugiej. Najwazniejszym zadaniem przy projektowaniu wielowarstwowym jest logiczne oddzielenie warstw a nie ich fizyczna implementacja. Glwnymi zaletami podejscia wielowarstwowego przy tworzeniu aplikacji WWW sa: Mozliwosc przydzielenia zadan osobom najlepiej przygotowanym do ich realizacji. Na przyklad: graficy i projektanci przygotowuja strone graficzna aplikacji, programisci tworza logike aplikacji a projektanci baz danych projektuja i uruchamiaja infrastrukture bazy danych. Mozliwosc zmian w warstwie bez potrzeby modyfikacji innych. W praktyce nadal jest to trudne, ale wiele malych zmian ogranicza sie do pojedynczej warstwy. Mozliwosc przeniesienia badz replikacji okreslonych warstw na inny sprzet w celu zapewnienia skalowania badz nadmiarowosci. Tak jak w przypadku wszystkich aplikacji, podczas trwania projektu aplikacji dla WWW moga pojawic sie zadania wprowadzenia zmian. Jezeli zmiany te sa ograniczone do jednej warstwy, mozliwe jest, ze nie bedzie konieczne ponowne kodowanie. Celem tego rozdzialu jest pokazanie sposobw tworzenia aplikacji odpornych na zmiany w pznych stadiach rozwoju. Dodatkowo oddzielenie interfejsu uzytkownika od logiki aplikacji jest jedna z technik programowania modularnego, ktre pozwala na latwiejsze uzycie istniejacych modulw. W programowaniu tradycyjnym projekt modularny jest zwykle postrzegany jako tworzenie modulw kodu, ktre moga byc uzywane w dowolnych aplikacjach. W przypadku projektowania dla WWW, moduly moga zawierac dane bedace czescia interfejsu, np. prawa autorskie lub moga byc modulami kodu. Modularnosc wiecej wnosi do latwosci utrzymania aplikacji niz strukturalnosc i jest najwazniejszym czynnikiem zapobiegania koniecznosci tworzenia poprawek do aplikacji majacych za zadanie usuwanie bledw. Wedlug badan 89% uzytkownikw kodu zglaszalo poprawienie mozliwosci utrzymania aplikacji modularnej, a w rozleglych testach programisci osiagali o 15% lepsze wyniki pracujac nad programem modularnym niz nad niemodularnym (McConnell, 1993).

Jak wspomniano w poprzednim rozdziale, tworzenie aplikacji modularnej wymaga dodatkowych prac projektowych i podjecia odpowiednich decyzji, ale w efekcie mozna otrzymac aplikacje latwiejsza do zrozumienia i konserwacji. W ksiazce A Methodology for Client/Server and Web Application Development Roger Fournier sugeruje, ze wsplne fragmenty lub moduly aplikacji zawsze powinny byc najpierw projektowane, tworzone i testowane a nastepnie udostepniane dla calej korporacji. Komponenty te powinny zawierac nie tylko moduly kodu, ale rwniez procedury przechowywane w bazie danych, wyzwalacze i zdalne procedury (Fournier, 1998). W kolejnych czesciach zostanie opisane kilka metod implementacji tych metod. Dodatkowo w tym rozdziale jak rwniez w rozdziale 14 Witryny oparte o szablony, dolaczone sa kompletne przyklady zastosowania tych technik. Niektre przyklady w kolejnych czesciach pokazuja techniki jakich nalezy unikac.

Oddzielenie i integracja przy uzyciu wbudowanych funkcji PHP


Poniewaz PHP zawiera bogaty zestaw funkcji i narzedzi, oddzielenie modulw kodu od modulw interfejsu moze byc zrealizowane bezposrednio przy pomocy narzedzi jezyka. Czesc ta opisuje kilka sposobw zrealizowania tego zadania.

Motywacja
Pierwsza motywacja dla oddzielenia elementw HTML od kodu jest umozliwienie ponownego wykorzystania kodu oraz jego latwiejszej konserwacji. W wszystkich przykladach umieszczonych do tej pory w ksiazce, HTML i PHP byly wymieszane w celu otrzymania krtkich i prostych przykladw. W przypadku tworzenia kodu prawdziwego kodu technika ta jest niewygodna i powoduje powstanie trudnych do analizy skryptw. Dla przykladu, skrypt z wydruku 12.1 zawiera fragment strony WWW ze zintegrowanym kodem PHP i HTML. Wydruk 12.1. PHP i HTML w jednym skrypcie
<?php if ( $aShowForm == True ) { ?> <p> <font face="Arial" size="3"> <b> <?php print( $aQuestion ); ?> </b> <form action="response.php3" method="POST"> <?php if (!empty( $UserID )) { ?> <input type="Hidden" name="UserID" value="<?php print($aUserID ); ?>"> <?php } ?> <?php if ($aQuestionID != -1 ) { ?> <input type="Hidden" name="QuestionID" value="<?php print($aQuestionID ); ?>"> <?php } ?> <ul> <font face="Arial" size="2"> <!--wyswietl mozliwe odpowiedzi--> <?php if ( $aQuestionID != -1 ) { if ($aSortOrd != 0 ) //Sortowanie alfabetyczne { $aSQL = "SELECT * FROM Answers WHERE (QuestionID=$aQuestionID) ORDER BY Text"; } else { $aSQL = "SELECT * FROM Answers WHERE (QuestionID=$aQuestionID)"; } $aDB->SetSQL( $aSQL );

Rozdzial 12 Oddzielanie kodu HTML od PHP

146

Oprcz tego, ze przyklad jest niekompletny, Wydruk 12.1 pokazuje jak skomplikowana moze stac sie strona HTML z wbudowanym PHP. Nawet pomoca edytorw wyrzniajacych skladnie, zlokalizowanie blokw kodu moze byc trudne. Problemy z utrzymaniem tego typu skryptw wykraczaja jednak poza podstawowe problemy z czytelnoscia kodu. Rwnie trudno jest wprowadzac zmiany zarwno do kodu, jak i wygladu strony bez wplywania na inne elementy. Na przyklad, zalzmy, ze projektanci uaktualnia wyglad przyciskw nawigacji i musza byc one umieszczone w witrynie. Odpowiedz na pytanie kto powinien wprowadzic zmiany jest trudna, poniewaz projektanci moga nie miec wystarczajaco duzo doswiadczenia, aby nie popsuc kodu podczas wprowadzania zmian, a programisci moga byc zmuszeni uaktualniac fragmenty kodu jedynie w celu zmiany wygladu. W obu przypadkach wynikiem sa opznienia w projekcie. Mozna tego uniknac stosujac lepsze praktyki projektowe. Jezeli twoja firma zamierza dostarczac wysokiej jakosci i latwe do konserwacji aplikacje WWW, tworzenie stron za pomoca przedstawionej metody nie powinno byc stosowane. Dodatkowo, jezeli zainwestowano w projekt interfejsu, nie nalezy tego marnowac tworzac aplikacje utrudniajaca wprowadzanie prostych zmian. Teraz zostana zademonstrowane dostepne w PHP metody integrowania oddzielnych modulw kodu i projektu.

Implementacja
Najprostsza metoda integracji osobnych modulw jest wykorzystanie funkcji PHP include() lub Metoda ta wymaga umieszczenia elementw projektu HTML w osobnych plikach, ktre sa uzywane przez moduly kodu PHP w czasie ich wykonywania. Na przyklad na wydruku 12.2 i 12.3 umieszczone sa fragmenty projektu strony rozdzielonej na naglwek i stopke. Na wydruku 12.4 pokazano sposb integracji tych segmentw z dynamicznie tworzonym fragmentem strony. Wydruk 12.2. Fragment z naglwkiem HTML
require().
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Nowe ksiazki wydawnictwa Helion</title> </head> <body> <img src="logo.jpg" width="622" height="106" alt="" border="0"> <h1>Nowosci wydawnictwa Helion</h1>

Wydruk 12.3. Fragment ze stopka HTML


<br><br><br> <hr> <p> &copy; 2001 Helion. Wszystkie prawa zastrzezone. </p> </body> </html>

Wydruk 12.4. Skrypt laczacy kod z projektem


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Nowe ksiazki wydawnictwa Helion</title> </head> <body> <img src="logo.jpg" width="250" height="68" alt="" border="0"> <h1>Nowosci wydawnictwa Helion</h1>

Mimo, jest to bardzo prosty przyklad, pokazuje on w jaki sposb mozna uzyc funkcji include() w celu integracji HTML i kodu, co ulatwia tworzenie efektywnych i latwych do modyfikacji aplikacji. Na wydruku 12.1 pokazany jest wyglad wynikowej strony w przegladarce. Przyklad ten pokazuje wartosc oddzielenia kodu od HTML. Jezeli projekt naglwka lub stopki ulegnie modyfikacji, nalezy zmienic jedynie pliki HTML.

147

PHP Kompendium wiedzy

Rysunek 12.1. Laczenie HTML i kodu PHP przy uzyciu


include()

Zamiast funkcji include() lub reqiure(), mozna rwniez wykorzystac standardowe funkcje obslugi plikw dostepne w PHP w celu odczytania plikw HTML i dolaczenia ich do strony. Metoda ta pozwala na wieksza kontrole nad obsluga plikw, w tym odszukiwanie plikw i obsluge bledw. Uzycie wlasnych funkcji dolaczania plikw pozwala na to, aby w plikach HTML nie bylo zadnego kodu PHP. Kolejne wydruki zawieraja bardziej szczeglowy przyklad wykorzystania poprzedniej techniki wykorzystujac funkcje obslugi plikw zamiast funkcji include(). Dodatkowo uzyte zostaly kaskadowe arkusze stylw (CSS) w celu zapewnienia wiekszych mozliwosci zmiany wygladu strony. Na wydruku 12.5. i 12.6. ponownie jest umieszczony naglwek i stopka, natomiast na wydruku 12.7 znajduje sie warstwa logiczna strony. Dla celw tej demonstracji utworzone zostaly dwa osobne pliki CSS. Wydruk 12.5. Naglwek HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Nowe ksiazki wydawnictwa Helion</title> <link rel="STYLESHEET" type="text/css" href="css1.css"> </head> <body> <img src="logo.jpg" width="622" height="106" alt="" border="0"> <h1>Nowosci wydawnictwa Helion</h1>

Wydruk 12.6. Stopka HTML


<p class="copyright"> &copy; 2001 Helion. Wszystkie prawa zastrzezone. </p> </body> </html>

Wydruk 12.7. Skrypt aplikacji PHP


<?php function MyIncludeFile( $aFileName ) { if ( !is_file( $aFileName ) ) { // przekierunkowanie na strone bledu exit; } $aFileArray = file( $aFileName ); foreach( $aFileArray as $aLine ) { print( "$aLine" );

Rozdzial 12 Oddzielanie kodu HTML od PHP

148

} } MyIncludeFile( "./header_2.html" ); include( "./db_mysql.inc" ); // tworzenie klasy news_db class sluzace do odczytu wiadomosci class news_db extends DB_Sql { var $Host = "localhost"; var $Database = "mydb"; var $User = "root"; var $Password = "root"; } // Tworzenie obiektu klasy news_db i odczytanie wiadomosci $aDB = new news_db; $aDB->query( "select * from news order by date desc limit 5" ); while( $aDB->next_record() ) { $aNewsID = $aDB->f( "news_id" ); $aAuthor = $aDB->f( "author" ); $aTitle = $aDB->f( "title" ); $aSynopsis = $aDB->f( "synopsis" ); print( print( print( print( print( } "<h2>$aTitle</h2>" ); "<h4>autor: $aAuthor</h4>" ); "<p>$aSynopsis</p>" ); "<a href=\"full_story.phtml?news_id=$aNewsID\">pelny tekst...</a>" ); "<br><br><hr>" );

MyIncludeFile( "./footer_2.html" ); ?>

Aplikacja ta wykorzystuje mala baze danych do przechowywania tekstw wiadomosci. Tak jak w poprzednich przykladach, w przykladzie tym wykorzystane sa klasy obslugi baz danych PHPLIB. Zawartosc i struktura bazy danych nie jest istotna, poniewaz jest to przyklad rozdzielania kodu oraz technik jego integracji. Dodatkowo wazna jest elastycznosc rozwiazania wykorzystujacego pliki CSS. Mimo, ze w tekscie strony PHP znajduje sie kilka podstawowych znacznikw HTML, ich uzycie jest ograniczone a sposb ich interpretacji jest kontrolowany przez CSS. Wyglad kompletnej strony jest pokazany na rysunkach 12.2. i 12.3.

149

PHP Kompendium wiedzy

Rysunek 12.2. Przyklado wa aplikacja z pierwszym arkuszem stylw

Rozdzial 12 Oddzielanie kodu HTML od PHP

150

Rysunek 12.3. Przyklado wa aplikacja z pierwszym arkuszem stylw

Czego nalezy unikac


Korzystajac z tej metody nalezy unikac mieszania kodu programu i HTML. Dolaczane pliki HTML powinny zawierac jedynie kod HTML, a dolaczane pliki PHP jedynie kod PHP. Ulatwia to rozdzielenie odpowiedzialnosci programistw PHP i projektantw interfejsu. Nalezy unikac kodu PHP, ktry generuje kod HTML. Choc pozwala to na pisanie kodu PHP nie zawierajacego znacznikw HTML, powoduje to, ze za zmiany projektu witryny odpowiada programista PHP. Utrudnia to rwniez wprowadzanie hurtowych zmian w wygladzie calej witryny WWW.

Podsumowanie: Oddzielanie i integracja przy wykorzystaniu funkcji PHP


Tworzac mechanizm oddzielania kodu PHP od HTML nalezy pamietac o najwazniejszych celach takiego dzialania. Czasami programisci przesadzaja w swoim zapale pisania kodu i tworza mechanizmy, ktre nie spelniaja prawdziwych potrzeb. Celem oddzielenia HTML od PHP jest uproszczenie aplikacji, podzial odpowiedzialnosci pomiedzy projektantami i programistami oraz ulatwiaja konserwacje aplikacji. Celem oddzielenia HTML od PHP moze byc calkowite oddzielenie projektu od logiki aplikacji. Uzywajac przedstawionych technik i wykorzystujac przy projektowaniu pliki CSS, cel ten jest nieomal osiagniety. Jednak czasami trzeba dynamicznie wygenerowac niektre znaczniki HTML, na przyklad moze byc to generowany dynamicznie znacznik lacza. Rwniez jezeli przesylany jest identyfikator sesji lub inny identyfikator specyficzny dla aplikacji, trzeba dynamicznie generowac wszystkie lacza. W tych przypadkach jezeli wykorzystywana bedzie opisana technika integracji, niezbedne bedzie dolaczenie czesci znacznikw HTML do kodu PHP.

151

PHP Kompendium wiedzy

W nastepnej czesci zatytulowanej Wykorzystanie systemu szablonw opisuje szczegly metody umozliwiajacej calkowite oddzielenie kodu PHP od HTML. Jest to zalecana metoda, poniewaz caly HTML moze byc pod opieka projektantw.

Wykorzystanie systemu szablonw


System szablonw jest mechanizmem przeznaczonym do calkowitego oddzielenia elementw projektu HTML od kodu PHP. Oczywista zaleta wykorzystania szablonw jest umozliwienie doswiadczonym projektantom HTML na calkowite panowanie nad wszystkimi aspektami projektu. Gdy wszystkie znaczniki HTML zostana usuniete z kodu, cala warstwa projektu interfejsu aplikacji moze byc modyfikowana niezaleznie od logiki aplikacji. Tak jak przy wszystkich dotychczasowych technikach projektowania, aby osiagnac zamierzony wynik wykorzystujac szablony, wymagane sa dodatkowe prace projektowe oraz skuteczne wprowadzenia ich w zycie. Podstawowym zalozeniem jest podzial strony na jeden lub wiecej szablonw projektowych, ktre sa laczone z dynamiczna zawartoscia generowana przez kod PHP. W prostych aplikacjach plik szablonu moze byc wykorzystywany dla wszystkich stron witryny. W bardziej skomplikowanych, moze byc uzyte bardzo wiele szablonw.

FastTemplate
Mimo, ze kazdy moze zbudowac wlasny system szablonw, dostepne jest swietne narzedzie o nazwie FastNet, ktre mozna zaladowac z witryny www.thewebmasters.net. FastTemplate jest latwy do uzycia i istnieje specjalna dokumentacja dla poczatkujacych. Aby rozpoczac prace z FastTemplate nalezy utworzyc plik szablonu, zwykle z rozszerzeniem tpl. Nastepnie w kodzie nalezy wykonac nastepujace kroki: 1. Utworzenie obiektu klasy FastTemplate. 2. Uzycie metody define() do przydzielenia plikom szablonw unikalnych nazw. 3. Uzycie metody assign() do skojarzenia wartosci do zmiennych szablonu. 4. Uruchomienie metody parse() do przetworzenia pliki szablonu i przypisania wartosci do zmiennych. 5. Uzycie metod FastPrint() lub fetch() do wypisania lub odczytania przetworzonego pliku szablonu. W szablonach FastTemplate zmienne sa umieszczane w nawiasach klamrowych ({}). Przykladowy plik szablonu znajduje sie na wydruku 12.8. Wydruk 12.8. Przykladowy szablon FastTemplate
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>{TITLE}</title> </head> <body bgcolor="{BODY_COLOR}"> {BODY} <hr> <font size="1"> {COPYRIGHT} </font> </body> </html>

Przykladowy szablon pokazany na wydruku 12.8 zawiera cztery zmienne FastTemplate: TITLE, BODY_COLOR, BODY i COPYRIGHT. W najprostszym przypadku, zmienne te moga byc ustawione bezposrednio z kodu, w sposb pokazany na wydruku 12.9. Wydruk 12.9. Skrypt aplikacji
<?php include( "class.FastTemplate.php" ); $aTemplate = new FastTemplate( "." ); $aTemplate->define( array( 'basic' => 'sample_1.tpl' ) ); $aBodyText = "Bardzo krtka zawartosc strony. for ( $nIndex = 1; $nIndex <= 10; $nIndex++ ) { $aBodyText .= "$nIndex "; } ";

Rozdzial 12 Oddzielanie kodu HTML od PHP

152

$aTemplate->assign( array( 'TITLE' => 'Prosty przyklad', 'BODY_COLOR' => 'white', 'BODY' => $aBodyText, 'COPYRIGHT' => 'Helion 2001, wszystkie prawa zastrzezone' ) ); $aTemplate->parse( 'PAGE', 'basic' ); $aTemplate->FastPrint( 'PAGE' ); ?>

Pierwszym krokiem jest utworzenie obiektu klasy FastTemplate. Konstruktor wymaga jednego argumentu sciezki do pliku szablonu. W naszym przykladzie zostal wykorzystany biezacy katalog .. Nastepnie plikowi umieszczonemu na wydruku 12.8 zostaje nadana nazwa basic. W kilku kolejnych liniach generowany i zapamietywany jest rwniez test strony oraz wykorzystujac metode assign(), zmiennym FastTemplate przypisywane sa wartosci. Na koniec Szablon jest przetwarzany i zapamietywany w zmiennej PAGE, a nastepnie jej zawartosc wysylana jest do przegladarki. Wynik pokazany jest na rysunku 12.4. Rysunek 12.4. Wynik przetwarzania prostego szablonu

Po przetworzeniu szablonu przez obiekt FastTemplate, wynik jest zapisany w zmiennej, ktra moze zostac wydrukowana lub zachowana dla innych celw, lub zmienna ta moze byc uzyta w kolejnym szablonie. Ostatnia opcja pozwala na zagniezdzanie plikw szablonw. Nowymi plikami sa: plik z danymi o prawach autorskich, oraz glwny plik szablonu zamieszczone odpowiednio na wydrukach 10 i 11. Wydruk 12.10. Szablon z prawami autorskimi (copyright.tpl)
&copy; {YEARS} Helion. Wszystkie prawa zastrzezone. Dodatkowe informacje na temat praw autorskich mozna znalezc <a href="legal.phtml">tutaj</a>.

Wydruk 12.11. Glwny plik szablonu (body.tpl)


<table width="100%"> <tr> <th colspan="3"> {PAGE_HEADER} </th> </tr> <tr> <td colspan="3"> &nbsp; </td> </tr> <tr> <td align="center" valign="top"> <!-- Panel nawigacji --> <a href="index.phtml">poczatek</a><br><br> <a href="about.phtml">o nas</a><br><br> <a href="links.phtml">lacza</a><br><br> </td> <td width="90%" valign="top"> <!-- Glwna sekcja tekstu --> {PAGE_CONTENT} </td> <td width="125" valign="top"> <!-- Tutaj reklamy i inne --> </td> </tr> </table>

Kazdy z dodatkowych plikw szablonw, ktre zostaly do tej pory pokazane, zawieraja swoje zmienne FastTemplate i aby szablony dzialaly prawidlowo, musza im zostac przypisane wartosci. Jezeli nie zostanie przypisana zmienna FastTemplate, wygenerowane zostana nastepujace ostrzezenia:
[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

Dodajac nowe pliki szablonw nalezy rwniez zmienic glwny plik PHP. Na wydruku 12.12 pokazany jest nowy skrypt PHP uzywajacy zagniezdzonych szablonw. Wydruk 12.12. Zagniezdzone pliki szablonw
<?php include( "class.FastTemplate.php" ); function GetCurrentYear( ) { $aNow = getdate(); $aNowYear = $aNow["year"]; return $aNowYear; } $aTemplate = new FastTemplate( "." ); $aTemplate->define( array( 'basic' 'copyright' 'body'

=> 'sample_1.tpl', => 'copyright.tpl', => 'body.tpl' ) );

$aBodyText = "Bardzo krtka zawartosc strony. "; for ( $nIndex = 1; $nIndex <= 10; $nIndex++ ) { $aBodyText .= "$nIndex "; } $aStartYear = 1997; $aCurrentYear = GetCurrentYear(); $aYears = "$aStartYear"; for ( $nIndex = $aStartYear + 1; $nIndex <= $aCurrentYear; $nIndex++ ) { $aYears .= ", $nIndex"; } $aTemplate->assign( array( 'TITLE' 'BODY_COLOR' 'YEARS' 'PAGE_HEADER' 'PAGE_CONTENT' ) ); => => => => => 'Lepszy przyklad', 'white', $aYears, 'Lepszy przyklad', $aBodyText

$aTemplate->parse( 'BODY', 'body' ); $aTemplate->parse( 'COPYRIGHT', 'copyright' ); $aTemplate->parse( 'PAGE', 'basic' ); $aTemplate->FastPrint( 'PAGE' ); ?>

W przykladzie tym zdefiniowano dwa dodatkowe pliki szablonw nadajac im nazwy copyright i body. Poniewaz te pliki szablonw zawieraja wlasne zmienne FastTemplate, zmiennym tym nalezy przypisac wartosci. Wartosc zmiennej YEARS jest generowana automatycznie, wiec dane o prawach autorskich sa zawsze aktualne. Zmienna $aBodyText posiada identyczna wartosc jak w poprzednim przykladzie. Nalezy zauwazyc, ze w tym rozdziale zmienne BODY i COPYRIGHT nie sa ustawiane w metodzie assign(). Zamiast tego zmienne te otrzymuja wartosci przy wywolaniu metody parse() na koncu tego skryptu. Wynik dzialania tego skryptu jest pokazany na rysunku 12.5.

Rozdzial 12 Oddzielanie kodu HTML od PHP

154

Rysunek 12.5. Wynik dzialania zagniezdzonych szablonw FastTemplate

Klasa FastTemplate jest poteznym narzedziem, za pomoca ktrego mozna tworzyc bogate i zlozone projekty interfejsu. Aby lepiej zilustrowac ta technike w kolejnym przykladzie wrcimy do przykladu aplikacji dostarczajacej najnowszych wiadomosci. Zamiast wykorzystywac do tego celu pliki dolaczane, w kodzie tym wykorzystana zostanie sila klasy FastTemplate. Na wydrukach 12.13, 12.14 i 12.15 umieszczony jest kod HTML szablonw tworzacych podstawowy uklad strony, tresc i element wiadomosci. W przykladzie tym uzyty jest szablon zawierajacy prawa autorskie, wykorzystany w poprzednim przykladzie. Wydruk 12.13. Podstawowy szablon dla aplikacji dostarczajacej wiadomosci (ft_news_base.tpl)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>{TITLE}</title> <link rel="STYLESHEET" type="text/css" href="css2.css"> </head> {NEWS_BODY} </html>

Wydruk 12.14. Szablon tresci w aplikacji wiadomosci (ft_news_body.tpl)


<body> <table width="640" border="0" align="center"> <tr> <td> <img src="logo.jpg" width="250" height="68" alt="" border="0"> <h1>Nowosci 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.15. Szablon elementu wiadomosci (ft_news_item.tpl)


<h2>{NEWS_TITLE}</h2> <h4>autor: {NEWS_AUTHOR}</h4> <p>{NEWS_SYNOPSIS}</p> <a href="{FULL_STORY_URL}">wiecej...</a> <br><br><hr>

Na wydruku 12.16. zamieszczony jest skrypt generujacy strone z nowosciami. Skrypt ten jest bardziej skomplikowany niz w poprzednim przykladzie, ale wiekszosc kodu pochodzi z poprzednich przykladw. 155 PHP Kompendium wiedzy

Wydruk 12.16. Glwny skrypt aplikacji


<?php include( "class.FastTemplate.php" ); include( "./db_mysql.inc" ); error_reporting( E_ALL & ~E_NOTICE ); function GetCurrentYear( ) { $aNow = getdate(); $aNowYear = $aNow["year"]; return $aNowYear; } // Tworzenie klasy news_db do pobrania wiadomosci class news_db extends DB_Sql { var $Host = "localhost"; var $Database = "mydb"; var $User = "root"; var $Password = "root"; } $aTemplate = new FastTemplate( "." ); $aTemplate->define( array( "base" "body" "item" "copyright"

=> => => =>

"ft_news_base.tpl", "ft_news_body.tpl", "ft_news_item.tpl", "copyright.tpl" ) );

// generowanie roku dla tresci praw autorskich $aStartYear = 1997; $aCurrentYear = GetCurrentYear(); $aYears = "$aStartYear"; for ( $nIndex = $aStartYear + 1; $nIndex <= $aCurrentYear; $nIndex++ ) { $aYears .= ", $nIndex"; } $aTemplate->assign( array( "YEARS" "TITLE" => $aYears, => "Nowosci wydawnictwa Helion" ) );

// Tworzenie obiektu klasy news_db i generowanie elementw wiadomosci $aDB = new news_db; $aDB->query( "select * from news order by date desc limit 5" ); while( $aDB->next_record() ) { $aNewsID = $aDB->f( "news_id" ); $aAuthor = $aDB->f( "author" ); $aTitle = $aDB->f( "title" ); $aSynopsis = $aDB->f( "synopsis" ); $aURL = "full_story.phtml?news_id=$aNewsID"; $aTemplate->assign( array( "NEWS_TITLE" "NEWS_AUTHOR" "NEWS_SYNOPSIS" "FULL_STORY_URL" $aTemplate->parse( "NEWS_ITEMS", ".item" ); } $aTemplate->parse( "COPYRIGHT", "copyright" ); $aTemplate->parse( "NEWS_BODY", "body" ); $aTemplate->parse( "BASE", "base" ); $aTemplate->FastPrint( "BASE" ); ?> => => => => $aTitle, $aAuthor, $aSynopsis, $aURL ) );

W przykladzie tym funkcja generujaca rok dla tekstu o prawach autorskich pochodzi z poprzednich przykladw, a obsluga bazy danych z poprzedniej realizacji aplikacji wiadomosci. Zauwazmy, ze na poczatku skryptu wylaczone zostaly ostrzezenia PHP, poniewaz ostrzezenie generowane przez FastTemplate zostana omwione pzniej. W skrypcie tym zdefiniowane zostaly cztery pliki szablonw. Na poczatku skryptu inicjowane sa dwie glwne zmienne FastTemplate, YEARS i TITLE reprezentujace odpowiednio rok praw autorskich i tytul strony. Kolejna glwna funkcja skryptu jest dynamiczne dodawanie kolejnych wiadomosci. Zostalo to zrealizowane przez pobranie pieciu najnowszych wiadomosci z bazy danych i wypisanie ich przy pomocy petli. W kazdym przebiegu petli przetwarzany jest szablon item i dodawany do zmiennej FastTemplate NEWS_ITEMS. Rozdzial 12 Oddzielanie kodu HTML od PHP 156

Dodawanie to jest zrealizowane poprzez dodanie kropki (.) przed nazwa szablonu. Dlatego wlasnie w pierwszym przebiegu petli FastTemplate generuje ostrzezenie wskazujace, ze zmienna NEWS_ITEMS nie jest zainicjowana. Po ustawieniu w petli wartosci zmiennej NEWS_ITEMS przetwarzana jest reszta szablonw a nastepnie drukowana strona. Poprzedni przyklad pokazuje w jaki sposb mozna wykorzystac klase FastTemplate do generowania powtarzajacych sie elementw, takich jak tresc kolejnych wiadomosci. Podobna konstrukcja moze byc wykorzystana do tworzenia wierszy tablicy lub listy laczy. Po poznaniu podstawowych zalozen uzywanie FastTemplate staje sie niezwykle naturalne. Oczywista zaleta klasy FastTemplate jak rwniez innych systemw szablonw jest to, ze elementy projektu strony moga byc tworzone i zmieniane niezaleznie od kodu aplikacji. Mimo, ze wykorzystanie systemu szablonw wymaga nieco innego myslenia w trakcie projektowania, jest ono warte zainteresowania.

Zaawansowane techniki uzycia FastTemplate


W poprzednich rozdzialach dwa zagadnienia byly z rozmyslem odsuwane az do tego rozdzialu. Pierwsze zostalo wspomniane w rozdziale 7. Sesje i stan aplikacji, w ktrym mwiono o lepszych sposobach przenoszenia identyfikatora sesji w aplikacji. Drugie znalazlo sie w rozdziale 9. Niezaleznosc od przegladarki, gdzie znalazla sie sugestia, ze system szablonw moze byc alternatywna metoda dostarczania zawartosci zaleznej od typu przegladarki. W tej czesci skupimy sie na tych dwch zagadnieniach. Pierwsze zagadnienie, przesylanie identyfikatora sesji, powinno byc w tym momencie dosyc oczywiste. Wykorzystujac szablony projekt moze zawierac dynamiczne lacza URL generowane w kodzie PHP. Podstawowy przyklad szablonu nawigacyjnego zamieszczony jest na wydruku 12.17. Wydruk 12.17. Szablon nawigacji (navi.tpl)
<a href="{HREF_INDEX}">poczatek</a> <a href="{HREF_NEWS}">nowosci</a> <a href="{HREF_LINKS}">lacza</a>

Wlasciwe adresy URL dla laczy moga byc tak generowane, aby zawieraly identyfikator sesji, lub inny specyficzny dla aplikacji. Inna zaleta wykorzystania takich adresw jest latwa modyfikacja polozenia stron w czasie pracy aplikacji. Na wydruku 12.18 zamieszczony jest skrypt generujacy dynamiczne adresy URL dla poprzedniego szablonu. Wydruk 12.18. Szablon nawigacji
<?php include( "class.FastTemplate.php" ); session_start(); function MyGenURL( $aLinkName ) { switch( $aLinkName ) { case 'HREF_INDEX' : $aBaseURL = 'index.phtml'; break; case 'HREF_NEWS' : $aBaseURL = 'news.phtml'; break; case 'HREF_LINKS' : $aBaseURL = 'links.phtml'; break; default : $aBaseURL = 'badlink.phtml'; break; } return $aBaseURL . session_name() . "=" . session_id(); } $aTemplate = new FastTemplate( "." ); $aTemplate->define( array( 'navi' => 'navi.tpl' ) ); $aTemplate->assign( array( 'HREF_INDEX' => MyGenURL( 'HREF_INDEX' ), 'HREF_NEWS' => MyGenURL( 'HREF_NEWS' ), 'HREF_LINKS' => MyGenURL( 'HREF_LINKS' ) ) ); $aTemplate->parse( 'NAVI', 'navi' ); $aTemplate->FastPrint( 'NAVI' ); ?>

157

PHP Kompendium wiedzy

Funkcja MyGenURL() jest glwnym elementem skryptu. Pobiera ona symboliczna nazwe lacza i zwraca prawdziwa lokalizacje strony wraz z dolaczonymi danymi sesji. Funkcja taka ma dodatkowa mozliwosc obslugi nieznanych nazw laczy. Pozwala to unikac brzydkich komunikatw HTTP 404: Page Not Found spotykanych we wielu aplikacjach WWW. Wykorzystanie szablonw do dostarczania tresci zaleznych od przegladarki rwniez jest korzystne. W rozdziale 9. zasugerowane byly metody warunkowego dolaczania plikw lub przekierowania uzytkownika do katalogu odpowiadajacego uzywanej przegladarce. Uzywajac szablonw preferowana jest pierwsza metoda. Problemem z przekierowaniem jest to, ze uzytkownik moze wyslac lacze do strony do osoby uzywajacej innej przegladarki. Przyklad umieszczony na wydrukach 19., 20., 21. i 22. pokazuje w jaki sposb mozna zintegrowac tresci zalezne od typu przegladarki z szablonami. Na wydruku 12.19. pokazany jest glwny szablon strony. Wydruk 12.20. i 12.21. to strony zalezne od mozliwosci przegladarki, natomiast wydruk 12.22 zawiera skrypt PHP. Wydruk 12.19. Podstawowy szablon strony (base_basic.tpl)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>{TITLE}</title> </head> <body> {NAVI} </body> </html>

Wydruk 12.20. Menu oparte o Flash (flash_menu.tpl)


<OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0" WIDTH=320 HEIGHT=240> <PARAM NAME=movie VALUE="flash_menu.swf"> <PARAM NAME=quality VALUE=high> <PARAM NAME=bgcolor VALUE=#FFFFFF> <EMBED src="Track As Menu.swf" quality=high bgcolor=#FFFFFF WIDTH=320 HEIGHT=240 TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"></EMBED>

Wydruk 12.21. Menu HTML (html_menu.tpl)


<a href="index.phtml">poczatek</a> <a href="news.phtml">wiadomosci</a> <a href="links.phtml">lacza</a>

Wydruk 12.22. Skrypt


<?php include( "class.FastTemplate.php" ); // zakladamy, ze zmienna $aHasFlash jest ustawiana przez // prawdziwa funkcje wykrywania Flash-a $aHasFlash = False; if ( $aHasFlash == True ) { $aNaviFile = "flash_menu.tpl"; } else { $aNaviFile = "html_menu.tpl"; } $aTemplate = new FastTemplate( "." ); $aTemplate->define( array( "navi" => $aNaviFile, "base" => "base_basic.tpl" ) ); $aTemplate->assign(array("TITLE" => "Przyklad dzialania zaleznego od przegladarki")); $aTemplate->parse( "NAVI", "navi" ); $aTemplate->parse( "BASE", "base" ); $aTemplate->FastPrint( "BASE" ); ?>

Przyklad ten pokazuje, w jaki sposb mozna umieszczac na stronie menu zrealizowane w programie Macromedia FlashTM, gdy uzywana przegladarka potrafi je wyswietlic i zwykle menu HTML w przypadku korzystania z innych przegladarek. Oczywiscie powinna zostac wykorzystana prawdziwa funkcja wykrywajaca, podobna do tej zamieszczonej na witrynie firmy Macromedia. W oparciu o specyficzne potrzeby witryny mozna pomyslowo rozdzielac wiele aspektw projektu w zaleznosci od mozliwosci uzywanej przegladarki i wykorzystac system szablonw do dostarczenia najlepszej zawartosci dla kazdej z przegladarek. Rozdzial 12 Oddzielanie kodu HTML od PHP 158

Podsumowanie
Oddzielanie elementw projektu aplikacji WWW od jej logiki powoduje promowanie projektowania modularnego i dzieki temu zwiekszenie mozliwosci ponownego wykorzystania kodu oraz jego latwiejszej konserwacji. Z powodu elastycznosci PHP cel modularnego tworzenia witryn WWW moze byc osiagniety wieloma sposobami. Zalecana w tym rozdziale metoda jest wykorzystanie systemu szablonw, ktry pozwala na pelne oddzielenie wszystkich elementw projektu od kodu. Tak zupelnie na marginesie, rozdzial ten ma podloze czysto osobiste. Jakis czas temu zdalem sobie sprawe, ze nigdy nie bede projektantem graficznym ani artysta, wiec w mojej firmie poswiecilem sporo czasu na znalezienie sposobu na dolaczenie projektw profesjonalnych projektantw z moimi aplikacjami. Pozwala to osiagnac oglna poprawe witryny, poniewaz warstwa prezentacji jest odpowiedniej jakosci a ja nie musze jej tworzyc ani zmieniac samemu. Wykorzystuje klase FastTemplate w nieomal wszystkich moich obecnych projektach. Pozwala ona moim projektantom latwo stworzyc pliki szablonw stron wykorzystujac nawiasy klamrowe do zaznaczenia elementw i pozwala mi na projektowanie w pelni funkcjonalne oraz szybkie zmiany w logice aplikacji.

Bibliografia
Roger Fournier. A Mehodology for Client/Server and Web Application Development. New Jersey: Prentice Hall PTR. 1998. Steve McConnell. Code Complete. Seattle: Microsoft Press. 1993.

159

PHP Kompendium wiedzy

Rozdzial 13. Fajny PHP


Wstep
W przypadku jezyka tak poteznego i rozszerzalnego jak PHP, trudno jest poszufladkowac wszystkie fajne rzeczy, jakie mozna zrobic przy jego pomocy. Rozdzial ten zawiera opis niektrych z nich. Tematy tu omawiane sa albo zagadnieniami, ktre musialem kiedys zaprogramowac, albo odpowiedziami na pytania czesto pojawiajace sie na listach dyskusyjnych poswieconym PHP. Rozdzial ten nie opisuje oczywiscie wszystkich rozszerzen i wlasnosci PHP, ale opisuje niektre z nich, ktre nie zostaly opisane w innych czesciach ksiazki.

Wysylanie do przegladarki plikw innych niz HTML


Oglnie mwiac, PHP jest wykorzystywany do wysylania plikw HTML do przegladarki, ale moze byc on rwniez uzyty do automatyzacji sciagania plikw, lub dostarczania innych typw plikw do przegladarki. Na przyklad mozna umozliwic uzytkownikom na zapisanie fragmentu zawartosci bazy danych w formacie tekstowym, na przyklad takim jak CSV. Przyklad ten ilustruje sposb, w jaki mozna umozliwic uzytkownikom zapisanie fragmentu tabeli bazy danych. Na wydruku 13.1. umieszczono skrypt pobierajacy dane z bazy danych, formatujacy je oraz wysylajacy je do przegladarki. Wydruk 13.1. Wysylanie CSV do przegladarki
<?php include_once( "db_mysql.php" ); // Tworzenie klasy pochodnej po DB_Sql sluzacej 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 zalezy od wersji MySQL przyklad ten moze nie dzialac dobrze na wszystkich wersjach MySQL */ $aMetaData = $aDB->metadata(); $aData = ""; $aNumFields = count( $aMetaData ); for ( $nIndex = 0; $nIndex < $aNumFields; $nIndex++ ) { $aData .= "\"" . $aMetaData[$nIndex]["name"] . "\","; } // usuniecie ostatniego znaku w ciagu (,) i znaku konca linii (\n) $aData = substr( $aData, 0, strlen( $aData ) - 1 ) . "\n"; while ( $aDB->next_record() ) { $aLine = ""; for ( $nIndex = 0; $nIndex < $aNumFields; $nIndex++ ) { $aLine .= "\"" . $aDB->f( $nIndex ) . "\","; } // usuniecie ostatniego znaku w ciagu (,) i znaku konca 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=\"employees.csv\"" ); print( $aData ); ?>

Pierwsza czynnoscia realizowana przez skrypt jest zdefiniowanie klasy pochodnej po klasie DB_Sql pochodzacej z PHPLIB, ktra jest uzywana do uruchomienia zapytania na bazie danych. Wiecej informacji na ten temat znajduje sie w rozdziale 6. Wsplpraca z bazami danych. Nastepnie wykonywane jest zapytanie i pobierane z niego sa metadane. Metadane zawieraja ilosc pl oraz nazwe kazdego ze zwracanych pl. Dane te sa potrzebne do skonstruowania pierwszej linii pliku CSV. Zwykle CSV zawiera wiersz naglwka zawierajacy nazwy pl, a nastepnie umieszczone sa wiersze danych. Kazde pole w CSV jest umieszczone w cudzyslowach i oddzielona sa od siebie przecinkami. Kazdy wiersz konczy sie znakiem nowej linii. Po dodaniu wiesza naglwka, skrypt przebiega po kolejnych rekordach wyniku i konstruuje z nich sformatowane wiersze CSV. Nastepnie do przegladarki wysylane sa trzy wiersze naglwka HTML. Pierwszy zawiera wielkosc wysylanego pliku, Nastepna zawiera typ zawartosci pliku. Jest ona wazna, poniewaz przegladarka wykorzystuje te dane do rozpoznania, w jaki sposb powinna traktowac przesylane dane. Jezeli linia ta zawierala by text/html, przegladarka prbowala by wyswietlic przychodzace dane w postaci HTML. Poniewaz typem tym jest w tym przypadku application/octetstream, przegladarka nie prbuje wyswietlic tych danych, a zamiast tego pozwala zapisac je na dysku. Ostatni wiersz wskazuje przegladarce, ze dane sa wysylane razem z naglwkami oraz sugeruje nazwe dla zapisywanego pliku. Na rysunku 13.1. pokazane jest okno dialogowe wyswietlane przez Internet Explorer po uruchomieniu tego skryptu. Pierwsze dwie linie tego pliku umieszczone sa na wydruku 13.2., natomiast na rysunku 13.2. widac wyglad 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 czestym zastosowaniem przesylania zawartosci innej niz HTML do przegladarki, jest wysylanie plikw graficznych. Na przyklad mozesz miec aplikacje, ktra zapisuje male rysunki w bazie danych. Nastepnie mozna przy pomocy PHP zapisywac je oraz pobierac i wyswietlac. Ponizszy wydruk pokazuje w jaki sposb mozna pobierac rysunki poprzez formularz HTML, zapisywac je w bazie danych, a nastepnie wyswietlac je na innej stronie. Na wydruku 13.3. znajduje sie formularz HTML uzywany do przesylania rysunkw, natomiast wydruk 13.4. zawiera skrypt zapisujacy rysunki do bazy danych. Tabela MySQL uzywana do przechowywania rysunkw zdefiniowana jest nastepujaco:
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 przesylania plikw


<html> <head> <title>Przesylanie rysunkw</title> </head> <body> <form action="upload_pic.phtml" method="post" enctype="multipart/form-data"> <table> <tr> <td colspan="2"> Prosze wybrac plik z rysunkiem (jpeg lub gif) do przeslania, oraz podac jego nazwe. </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">

Rozdzial 13 Fajny PHP

162

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

Wydruk 13.4. Zapisywanie przeslanego pliku w bazie danych


<?php include_once( "db_mysql.php" ); // Utworzenie podklasy DB_Sql do zapisywania i odczytu rysunkw 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 klase PHPLIB do obslugi odwolan do bazy danych. Na poczatku sprawdzane jest, czy plik jest wlasciwego typu. Nastepnie plik jest umieszczony w zmiennej i przygotowany do 163 PHP Kompendium wiedzy

umieszczenia w bazie danych poprzez uzycie funkcji addslashes(). Nastepnie z tabeli pobierany jest nowy identyfikator i dane sa umieszczane w bazie danych. Na koncu skryptu przegladarka jest kierowana do odpowiedniego pliku w zaleznosci od tego, czy operacja sie powiodla czy nie. Aby wyswietlic rysunek, wykorzystujemy kod z wydrukw 5. i 6. Na wydruku 13.5. umieszczona jest prosta strona HTML powodujaca wyswietlenie jednego, okreslonego rysunku. Wydruk 13.6. zawiera skrypt wyswietlajacy rysunki. Wydruk 13.5. Strona HTML powodujaca wyswietlenie rysunku z bazy danych
<html> <head> <title>Wyswietlenie rysunku</title> </head> <body> <img src="show_pic.phtml?ID=1" border="0" alt=""> </body> </html>

Wydruk 13.6. Skrypt wyswietlajacy rysunki


<?php include_once( "db_mysql.php" ); // Utworzenie podklasy DB_Sql do zapisywania i odczytu rysunkw 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, obsluga bledu! Header( "HTTP/1.0 404 Not Found" ); } ?>

Mimo, ze dziwny wydaje sie znacznik <IMG> wskazujacy na skrypt PHP, nie ma jednak zadnej rznicy. Wazny kod znajduje sie w skrypcie PHP, gdzie ustawiany jest wlasciwy typ zawartosci dla rysunku z bazy danych. Skrypt powoduje pobranie odpowiedniego rysunku z bazy danych i przeslanie danych. Jezeli identyfikator rysunku ($ID) nie zostanie odnaleziony w bazie danych, skrypt zwraca standardowy kod bledu HTTP 404. Poniewaz PHP pozwala na wyslanie dowolnych naglwkw HTTP, mozna w ten sposb przesylac dowolna zawartosc. Elastycznosc ta pozwala na latwe tworzenie aplikacji o duzych mozliwosciach.

Skrypty automatyzujace
PHP nie jest jedynie jezykiem programowania dla WWW, ktry do dzialania wymaga serwera WWW, ale jest on jezykiem skryptowym, ktry moze zostac do dowolnych zadan programowych. Poniewaz jest on tak bogaty w funkcje, moze byc wykorzystany do automatyzacji zadan, ktre moga byc trudne do zrealizowania w standardowych jezykach programowania powloki lub plikach wsadowych. Dodatkowo, poniewaz PHP jest dostepny na wielu platformach, te same skrypty moga byc uzyte na wielu platformach. Wykorzystanie PHP jako osobnego narzedzia skryptowego wymaga skompilowania wersji CGI PHP. Jest to opsane w rozdziale 1., Kompilacja i instalowanie PHP 4. Majac dostepna wersje CGI mozna uruchomic dowolny skrypt PHP z linii polecen. Ponizszy przyklad pokazuje wykorzystanie PHP do generowania plikw stref DNS co jest przydatne w przypadku obslugi wielu stref. Rozdzial 13 Fajny PHP 164

Wydruk 13.7. Baza do obslugi 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 niezbednych do utworzenia plikw strefy oraz innych plikw konfiguracyjnych niezbednych do dzialania serwera DNS. Ponizej 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. Chociaz rekord ten nie jest sam szczeglnie uzyteczny, to jednak polaczony z innymi powiazanymi tabelami pozwala uzyskac informacje na temat adresw IP, serwerw pocztowych oraz serwerw SOA. Uzywajac wszystkich tych danych oraz skryptu PHP mozna niezmiernie uproscic proces uaktualniania serwera DNS. Ponizsze siedem wydrukw zawiera elementy glwnego skryptu. Wydruki 8. do 13. sa plikami szablonw uzywanych do generowania plikw wynikowych. Przyklad ten korzysta z klasy FastTemplate opisanej w rozdziale 12. Oddzielanie kodu HTML od PHP. Wydruk 13.8. Glwny szablon dla pliku strefy DNS (dns_primary.tpl)
$TTL 86400 {DOMAIN}. IN SOA {SOA_SERVER}. {ADMINISTRATOR}. ( {SERIAL} ; nr seryjny 10800 ; odswiezanie 3600 ; ponowna prba 604800 ; wygasniecie 86400 ; domyslny 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 hostw DNS (zastepuje CNAME_RECORDS z wydruku 13.8.) (dns_secondary.tpl)
{CNAME} IN CNAME {DOMAIN}.{CRLF}

Wydruk 13.10. Szablon serwerw nazw DNS (zastepuje NAMESERVERS z wydruku 13.8.) (dns_nservers.tpl)
{DOMAIN}. IN NS {NAMESERVER}.{CRLF}

Wydruk 13.11. Glwny 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 (zastepuje 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 podrzednych DNS (named_slaves.tpl)


zone "{DOMAIN}" { type slave; file "{DOMAIN_FILE}"; masters { master.com; }; };

Szablony te tworza szkielet niezbedny do utworzenia wszystkich plikw konfiguracyjnych dla serwera nazw BIND. Pierwsze trzy generuja osobne pliki stref, ktre moga posiadac rzna liczbe serwerw nazw i definicji nazw komputerw. Pozostale sa uzywane do utworzenia pliku named.conf oraz pliku podrzednego, wykorzystywanego w podrzednym 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 obslugi bazy danych dla aplikacji class genapps_db extends DB_Sql { var $Host = "localhost"; var $Database = "mydb"; var $User = "root"; var $Password = "root"; } // katalog dla plikw 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 liste serwerw nazw i zapamietaj do pzniejszego 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 hostw (rekordy CNAME) sa przechowywane w liscie rozdzielanej przecinkami w bazie danyche. Dzielenie listy i tworzenie linii dla kazdego elementu */ $tpl->clear( CNAME_RECORDS );

Rozdzial 13 Fajny PHP

166

$aCNameList = explode( ",", $aCNames ); foreach( $aCNameList as $aCName ) { $aCName = trim( $aCName ); $tpl->assign( array( CNAME => $aCName ) ); $tpl->parse( CNAME_RECORDS, ".dns_cnames"); } // dodanie linii serwerw nazw do pliku strefy $tpl->clear( NAMESERVERS ); $aNSDB->seek( 0 ) ; while ( $aNSDB->next_record() ) { $tpl->assign( array( NAMESERVER => $aNSDB->f( "name" )) ); $tpl->parse( NAMESERVERS, ".dns_nservers" ); } $aDomainFile = $aDomainName . ".db"; /* plik strefy jest tworzony tylko wtedy, gdy pole 'incl_zone_file' w bazie danych ma wartosc '!' */ if ( $aInclZoneFile == "1" ) { $tpl->parse( DNS_MAIN, "dns_main"); $aFile = fopen( "$aPath/$aDomainFile", "w" ); fwrite( $aFile, $tpl->fetch( DNS_MAIN ) ); fclose( $aFile ); print ("Plik domeny '$aDomainFile' zostal utworzony\n" ); } /* dodanie bizacej nazwy domeny do glwnego i pomocniczego pliku konfiguracyjnego */ $tpl->assign( array( DOMAIN_FILE => $aDomainFile ) ); $tpl->parse( ZONES, '.named_zones' ); $tpl->parse( SLAVES, '.named_slaves' ); } $tpl->parse( NAMED_CONF, 'named_main' ); $aFile = fopen( "$aPath/named.conf", "w" ); fwrite( $aFile, $tpl->fetch( NAMED_CONF ) ); fclose( $aFile ); print( "Glwny plik 'named.conf' utworzony\n" ); $aFile = fopen( "$aPath/named.slave", "w" ); fwrite( $aFile, $tpl->fetch( SLAVES ) ); fclose( $aFile ); print( "Plik domeny 'named.slave' utworzony\n" ); ?>

Skrypt ten odczytuje kolejne pozycje w tabeli Domains i tworzy plik strefy. Jest on utworzony za pomoca szablonw z wydrukw 8., 9. i 10. Przykladowy plik strefy pokazany jest na rysunku 13.4.

167

PHP Kompendium wiedzy

Rysunek 13.4. Przykladowy plik strefy DNS

Dodatkowo tworzony jest odpowiednio sformatowany plik named.conf. W celu stworzenia tych plikw do odczytania zapamietanego tekstu wykorzystana zostala metoda FastTemplate fetch(). Aby uruchomic ten skrypt pod Windows lub na systemach Unix nalezy uzyc polecenia php create_dns.php. Postep wykonywania skryptu jest pokazywany na standardowym wyjsciu, a pliki wynikowe sa tworzone w katalogu okreslonym na poczatku skryptu. Poniewaz PHP jest kompletnym jezykiem skryptowym, przy jego pomocy mozna napisac dowolne narzedzia automatyzujace zlozone zadania. Uzyty z mechanizmami automatycznego uruchamiania programw, na przyklad cron, PHP moze byc wykorzystany do wykonania wielu zlozonych zadan. Tworzenie plikw konfiguracyjnych dla dowolnych programw moze byc bardzo latwo wykonane przy uzyciu systemu szablonw, na przyklad pakietu FastTemplate. Poniewaz PHP jest niezwykle elastyczny, moze byc on uzyty do napisania skryptw do takich zadan jak: wysylanie masowej poczty, skladowanie i uaktualnianie bazy danych, monitorowanie sieci lub aplikacji i wiele innych.

WDDX
WDDX (Web Distributed Data Exchange) to bezplatna, oparta na XML technologia pozwalajaca aplikacjom WWW dzialajacych na dowolnych platformach, latwo wymieniac pomiedzy soba dane. Obsluga WDDX moze byc uaktywniona w PHP poprzez podanie opcji konfiguracji --enable-wddx i ponowne skompilowanie PHP. Celem WDDX jest zapewnienie spjnego interfejsu danych dla informacji przekazywanych pomiedzy aplikacjami sieciowymi. Dla przykladu, mozna wykorzystac WDDX do wspldzielenia przez partnerw danych z bazy danych. SDK dla WDDX mozna sciagnac z witryny www.wddx.org. Pakiet ten zawiera dokumentacje i przyklady uzycia WDDX. Patrzac na najbardziej podstawowym poziomie, kompilujac PHP z obsluga WDDX umozliwia sie serializacje danych w postaci pakietw WDDX oraz deserializacje pakietw danych WDDX do struktur danych Rozdzial 13 Fajny PHP 168

PHP. Aby to zilustrowac, skrypt z wydruku 13.15. tworzy kilka zmiennych i serializuje je w pakiet danych WDDX, oraz wypisuje zawartosc pakietu. Wynik serializacji pokazany jest na wydruku 13.16. Wydruk 13.15. Wykorzystanie WDDX
<html> <head> <title>Przyklad uzycia WDDX</title> </head> <body> <?php $aFirstName = "Arian"; $aAge = 25; $aArray = array( "red", "green", "blue" ); $aPacketID = wddx_packet_start( "products" ); wddx_add_vars( $aPacketID, "aFirstName" ); wddx_add_vars( $aPacketID, "aAge" ); wddx_add_vars( $aPacketID, "aArray" ); $aWDDXPacket = wddx_packet_end( $aPacketID ); print( $aWDDXPacket ); ?> </body> </html>

Wydruk 13.16. Pakiet WDDX


<wddxPacket version='1.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 przykladzie funkcja wddx_packet_start() tworzy nowy pakiet WDDX. Nastepnie do tego pakietu dodawane sa trzy zmienne PHP i pakiet jest zamykany. Pakiet danych WDDX zawiera wszystkie dane niezbedne do odtworzenia zmiennych za pomoca funkcji wddx_deserialize(). Aby pokazac jak mozna wykorzystac WDDX w systemie uzywajacym kilku jezykw programowania, w kolejnym przykladzie pakiet WDDX jest wysylany do strony WWW, gdzie jest uzywany przez JavaScript. Dane WDDX reprezentuja informacje o towarach: nazwe, cene i wage. Gdy uzytkownik wybierze z listy nazwe produktu, w polach tekstowych tylko do odczytu uaktualniana jest cena i waga wybranego produktu. Przyklad ten pokazuje w jaki sposb mozna manipulowac danymi na kliencie przy pomocy JavaScript. Na wydruku 13.17. pokazany jest szablon HTML, natomiast wydruk 13.18. zawiera skrypt PHP wykorzystujacy ten szablon. Wydruk 13.17 Uzycie WDDX do manipulacji danymi na kliencie
<html> <head> <title>{TITLE}</title> <link rel="STYLESHEET" type="text/css" href="css2.css"> <!--- Dolaczenie obslugi WDDX / Javascript ---> <SCRIPT SRC="wddx.js" LANGUAGE="JavaScript"></SCRIPT> <!--- Dolaczenie obslugi obiektu WddxDeserializer ---> <SCRIPT SRC="wddxDes.js" LANGUAGE="JavaScript"></SCRIPT> <script language="JavaScript"> <!-function show_props(obj, obj_name) { var result = ""; for (var i in obj) { result += obj_name + "." + i + " = " + obj[i] + "\n"; } return result; } function SetupProductsList() { MyDeser = new WddxDeserializer; aProducts = MyDeser.deserialize( '{PRODUCTS_WDDX}' ); } function Initialize() { SetupProductsList(); aNumProds = aProducts.ARECORDS.length; // Czyszczenie listy produktw // dodanie produktu do listy for ( var nIndex = 0; nIndex < aNumProds; nIndex++ ) { aValue = aProducts.ARECORDS[nIndex].PRODUCT_ID; aName = aProducts.ARECORDS[nIndex].DESCRIPTION;

169

PHP Kompendium wiedzy

// tworzenie nowej opcji NewOpt = new Option( aName, aValue, false, true ); // Dodanie nowego obiektu do listy SELECT document.MainForm.Product_List.options[nIndex] = NewOpt; } SetInfo(); } function SetInfo() { // ustawienie ceny i wagi zaznaczonego produktu var RowNum = document.MainForm.Product_List.selectedIndex; if ( RowNum > -1 ) { document.MainForm.Price.value = aProducts.ARECORDS[RowNum].PRICE; document.MainForm.Weight.value = aProducts.ARECORDS[RowNum].WEIGHT; } } //--> </script> </head> <body onload="Initialize()"> <form action="" name="MainForm" id="MainForm"> <table> <tr> <td colspan="3"> Wybierz towar z listy, aby zobaczyc jego cene i wage. </td> </tr> <tr> <td colspan="3"> &nbsp; </td> </tr> <tr> <th> Towar </th> <th> Cena </th> <th> Waga </th> </tr> <tr> <td> <select name="Product_List" size="1" onChange="SetInfo();"> <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. Pierwsza funkcja, show_props() jest jedynie funkcja testujaca uzywana przy wyswietlaniu wlasciwosci obiektu. Funkcja SetupProductsList() deserializuje dane towarw, ktre zostaly odczytane z bazy danych przez PHP. Funkcja korzysta z obiektu WddxDeserializer dostepnego w SDK dla WDDX. Po deserializacji pakietu danych WDDX obiekt JavaScript aProducts zawiera wszystkie dane produktw. Funkcja Initialize() inicjuje strone i jest wywolywana automatycznie przez zdarzenie strony onLoad. Ta funkcja z kolei wywoluje funkcje SetupProductsList() a nastepnie dodaje nazwy i identyfikatory produktw do listy rozwijalnej. Funkcja SetInfo() jest wywolywana po zmianie przez uzytkownika wybranego elementu w liscie rozwijalnej. Uaktualnia ona wartosci wyswietlane w polach tekstowych cena i waga. Wydruk 13.18. Przygotowanie pakietu danych WDDX
<?php

Rozdzial 13 Fajny PHP

170

include( "class.FastTemplate.php" ); include( "db_mysql.inc" ); error_reporting( E_ALL & ~E_NOTICE ); class products_db extends DB_Sql { var $Host = "localhost"; var $Database = "mydb"; var $User = "root"; var $Password = "root"; } $aTemplate = new FastTemplate( "." ); $aTemplate->define( array( "base" => "products_wddx.tpl" ) ); $aTemplate->assign( array( "TITLE" => "Products Page" ) ); $aPacketID = wddx_packet_start( "products" ); $aRecords = array(); $nIndex = 0; $aDB = new products_db; $aDB->query( "select * from Products" ); while( $aDB->next_record() ) { $aRecord = $aDB->Record; foreach( $aRecord as $aName => $aValue ) { if ( !is_numeric( $aName ) ) { $aRecords[$nIndex][$aName] = $aValue; } } $nIndex++; } wddx_add_vars( $aPacketID, "aRecords" ); $aWDDXPacket = wddx_packet_end( $aPacketID ); $aTemplate->assign( array( "PRODUCTS_WDDX" => addslashes( $aWDDXPacket ) ) ); $aTemplate->parse( "BASE", "base" ); $aTemplate->FastPrint( "BASE" ); ?>

Glwny skrypt PHP wykorzystuje klase FastTemplate w celu utworzenia kompletnej strony HTML. Glwnym dzialaniem skryptu jest odczytanie zawartosci tabeli Products i utworzenie pakietu WDDX zawierajacego odpowiednie dane, Jest to realizowane w petli przebiegajacej przez rekordy wyniku, dodajac dane do nowej tablicy, $aRecords. Jest to tablica dwuwymiarowa, gdzie pierwszy wymiar jest numeryczna reprezentacja numeru wiersza. Drugi wymiar to tablica asocjacyjna z nazwami kolumn i ich wartosciami. Jeszcze jeden fragment tego kodu wymaga skomentowania. Linia z funkcja is_numeric() jest uzywana do usuwania nadmiarowych informacji zwracanej przez niejawnie wykonywana funkcje mysql_fetch_array(). Funkcja mysql_fetch_array() zwraca wiersz z wyniku w postaci tablicy. Dane pochodzace z wyniku sa przechowywane pod indeksami numerycznymi, jak rwniez pod indeksami asocjacyjnymi gdzie jako klucze sa wykorzystywane nazwy pl. Sprawdzenie to usuwa dane indeksowane liczbami, pozostawiajac jedynie dane asocjacyjne. Na rysunku 13.5. pokazana jest wynikowa strona w przegladarce. Zawsze po wybraniu nowego towaru automatycznie jest uaktualniana cena i waga.

171

PHP Kompendium wiedzy

Rysunek 13.5. Przyklad wykorzystania danych WDDX na kliencie

Choc przyklad ten pokazuje w wykorzystanie WDDX do dostarczenia danych dla klienta, moze byc uzywany na wiele sposobw. Moze byc uzywany do przesylania firmowych danych pomiedzy serwerami, oraz latwego wspldzielenia danych pomiedzy rznymi platformami i jezykami. Jezeli planujesz wspldzielenie danych, WDDX zawiera narzedzia do szybkiego dostarczania tresci w postaci neutralnej dla platformy i jezyka.

Monitorowanie sieci
Poniewaz PHP wewnetrznie obsluguje gniazda i protokoly sieciowe, tworzenie narzedzi monitorujacych siec jest latwe. Ponizszy przyklad wykorzystuje potoki i gniazda do zrealizowania prostych funkcji monitorujacych siec. Mozna rozszerzyc ten przyklad o sprawdzanie stanu serwera nazw, serwera pocztowego itd. Przyklad ten moze byc szkieletem, ktry mozna rozszerzac o nowe funkcje. Na wydruku 13.19. zamieszczone sa trzy funkcje, phpPing(), phpTrace() i phpPageCheck(). Pierwsze dwie wykorzystuja komendy systemowe do wykonania operacji ping i traceroute. Ostatnia wykorzystuje gniazda do wyslania zadania HTTP HEAD do strony w celu sprawdzenia dostepnosci serwera i samej strony. Wydruk 13.19. Funkcje sieciowe
<?php $aPingCmd = '/bin/ping -c 4'; $aTraceCmd = '/usr/sbin/traceroute -n'; // *nix // *nix

// zwraca sredni czas wykonania komendy ping function phpPing( $aAddress ) { global $aPingCmd; $aTotalTime = 0.0; $aPingCount = 0; if ( $aFile = popen( "$aPingCmd $aAddress", "r" ) ) { // odczytanie danych z potoku while ( !feof( $aFile ) ) { $aLine = fgets ( $aFile, 1024 ); // odszukanie danych o czasie $aPos = strpos( $aLine, "time=" ); if ( $aPos > 0 ) { // wykorzystanie zmiennosci typw zmiennych PHP // do konwersji czasu na liczbe $aTime = substr( $aLine, $aPos + 5 ) * 1.0; $aTotalTime += $aTime; $aPingCount++; } } pclose( $aFile ); } return $aTotalTime / $aPingCount; }

Rozdzial 13 Fajny PHP

172

function phpTrace( $aAddress ) { global $aTraceCmd; $aTraceResults = ""; if ( $aFile = popen( "$aTraceCmd $aAddress", "r" ) ) { // odczytanie wszystkich danych z potoku while ( !feof( $aFile ) ) { $aLine = fgets ( $aFile, 1024 ); $aTraceResults .= $aLine . "<br>"; } pclose( $aFile ); } return $aTraceResults; } function phpPageCheck( $aWebPage ) { $aURL = parse_url( $aWebPage ); $aResult = False; if ( $aURL["scheme"] == "http" ) { $aRequest = "HEAD {$aURL['path']} HTTP/1.0\r\n\r\n"; $aSocket = fsockopen( $aURL["host"], 80 ); if ( $aSocket ) { fputs( $aSocket, $aRequest ); while( !feof( $aSocket ) ) { $aLine = fgets( $aSocket, 1024 ); if ( substr( $aLine, 0, 4 ) == "HTTP" ) { $aArray = explode( " ", $aLine ); if ( ( $aArray[1] >= 200 ) && ( $aArray[1] < 300 ) ) { $aResult = True; } } } } } return $aResult; } ?>

Funkcje te moga byc wykorzystane w skrypcie automatyzujacym do okresowego zapisywania wynikw do bazy danych lub do pliku, albo moga byc uzyte bezposrednio ze strony WWW. Skrypt z wydruku 13.20. pokazuje w jaki sposb uzywa sie tych funkcji. Wydruk 13.20. Wykorzystanie funkcji sieciowych
<?php include( "./net_funcs.php" ); ?> <html> <head> <title>Test funkcji sieciowych</title> </head> <body> <?php print( print( print( print( print( ?> </body> </html>

"phpPing: " . phpPing ( 'www.php.net' ) . "<br><br>" ); "phpTrace: <ul>" . phptrace( 'www.php.net' ) . "</ul><br>" ); "phpPageCheck: " ); phpPageCheck( 'http://www.php.net/' ) ? "OK" : "NOT OK" ); "<br>" );

Przyklad ten pokazuje jak latwo mozna wykorzystac PHP do wykonania podstawowego monitorowania sieci. PHP obsluguje rwniez inne protokoly sieciowe, takie jak IMAP, SNMP, NNTP i POP3, co pozwala rozszerzac przytoczony przyklad o sprawdzenie dostepnosci wszystkich rodzajw serwerw i komponentw sieciowych. 173 PHP Kompendium wiedzy

Podsumowanie
Rozdzial ten opisywal rzne zagadnienia pokazujace sile i elastycznosc PHP. Istnieja rwniez rozszerzenia do tworzenia rysunkw, analizy XML, tworzenia plikw PDF i wielu innych zadan. Poniewaz PHP jest tak rozszerzalny i rozwijany przez ogromna grupe programistw, nalezy spodziewac sie dalszego zwiekszania elastycznosci i funkcjonalnosci.

Rozdzial 13 Fajny PHP

174

Rozdzial 14. Witryny oparte o szablony


W rozdziale 12., Oddzielanie HTML od PHP zostalo opisane uzycie systemu szablonw. W tym rozdziale zostanie szczeglowo opisane wykorzystanie szablonw do tworzenia witryn. Uzycie szablonw do projektowania aplikacji umozliwia o wiele wiecej, niz jedynie oddzielanie logiki aplikacji od projektu graficznego. Szablony umozliwiaja zastosowanie zapozyczania fragmentw witryn, personalizacji, niezaleznosci od przegladarki oraz obslugi wielu jezykw. Przyklady przytoczone w tym rozdziale wykorzystuja klase FastTemplate dostepna z witryny http://www.thewebmasters.net/. Istnieja rwniez inne systemy szablonw, ale ta implementacja jest wydajna, elastyczna i latwa do nauki.

Podstawy wykorzystania szablonw


Tworzenie witryn WWW korzystajacych z systemu szablonw wymaga nieco dokladniejszego projektowania interfejsu uzytkownika, niz tworzenie tej samej aplikacji bez szablonw. Jednak korzysci wykorzystania dobrze zaprojektowanego zaczna sie ujawniac bardzo szybko. Na rysunku 14.1. pokazana jest typowa strona WWW, ktra moze byc podzielona na kilka osobnych plikw szablonw. Rysunek 14.1. Page header - naglwek strony Strona WWW navigation - panel nawigacji skladajaca sie z footer - stopka kilku plikw HTML base page - Podstawowa strona HTML szablonw Main body - Glwny obszar strony information, links, contacts, news - Informacje, lacza, kontakty, nowosci Na rysunku 14.1. pokazana jest strona skladajaca sie z jednego lub wiecej szablonw, ktre skladaja sie na strone HTML z rznymi logicznymi sekcjami strony. Na niektrych witrynach WWW moze byc wykorzystany tylko jeden szablon dla wszystkich stron witryny. W innych, kazda strona moze byc tworzona na podstawie kilku szablonw. Aby zaprojektowac witryne korzystajaca z szablonw, nalezy ocenic potrzeby witryny i zinwentaryzowac elementy znajdujace sie na stronach. Przykladem bedzie witryna pelniaca funkcje sieciowego katalogu towarw. Katalog ten jest podzielony na kategorie produktw, takie jak: ubrania, prezenty, zabawki itd. Kazda strona musi zawierac wsplne elementy nawigacyjne oraz logo calej witryny. Przegladajac wybrana kategorie produktw, powinien byc wyswietlany element graficzny oznaczajacy ta kategorie. Kazda strona produktu powinna zawierac dane o towarze, takie jak cena, waga, dostepne kolory itd. Aby stworzyc system szablonw dla takiej witryny zdefiniowano nastepujace szablony: 1. merch_base.tpl: Podstawowy plik zawierajacy oglny uklad HTML. 2. merch_header.tpl: Naglwek wsplny dla wszystkich stron witryny. 3. merch_catXXX_header.tpl: Naglwek okreslonej kategorii (XXX zastapione przez nazwe kategorii). 4. merch_navi.tpl: Panel nawigacyjny katalogu. 5. merch_body.tpl: Tresc kazdej strony. 6. merch_footer.tpl: Stopka kazdej strony. Aby pokazac jak zostaly stworzone te pliki, przedstawiona zostana teraz zawartosc kazdego z nich. Wydruki od 1. do 6 zawieraja kolejne pliki wymienione powyzej. Na wydruku 14.3 pokazany zostal plik merch_catubrania_header.tpl, wlasciwy dla kategorii produktw ubrania. Pliki dla pozostalych kategorii nie zostaly pokazane, poniewaz sa one wlasciwie takie same. Wydruk 14.1. merch_base.tpl
<html> <head>

<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.2. merch_header.tpl


<img src="merch_layout_r1_c1.gif" width="630" height="61" border="0">

Wydruk 14.3. merch_catubrania_header.tpl


<img name="merch_layout_r2_c1" src="merch_layout_r2_c1.gif" width="630" height="37" border="0"><br> <div align="center"><p>{CATEGORY_SPECIALS}</p></div>

Wydruk 14.4. merch_navi.tpl


<img src="merch_layout_r3_c1.gif" width="104" height="382" border="0" usemap="#merch_layout_r3_c1"> <map name="merch_layout_r3_c1"> <area shape="rect" coords="5,180,97,221" href="{HREF_COMPANY_INFO}" > <area shape="rect" coords="7,143,86,166" href="{HREF_CONTACT}" > <area shape="rect" coords="12,90,84,132" href="{HREF_CART}" > <area shape="rect" coords="18,56,73,80" href="{HREF_HOME}" > </map>

Wydruk 14.5. merch_body.tpl


<p> &nbsp; </p> <h3> {PRODUCT_NAME} </h3> <p> {PRODUCT_DESCRIPTION} </p> <p> {PRODUCT_PRICE} </p>

Wydruk 14.6. merch_footer.tpl


<hr> <p> &copy {COPYRIGHT_YEARS} Intechra LLC. Wszystkie prawa zastrzezone. </p>

Pliki te pokazuja jak niewiele potrzeba do stworzenia dosyc skomplikowanej witryny korzystajacej z szablonw. Niektre z tych plikw, na przyklad naglwek zawiera jedynie rysunek. Inne, jak na przyklad szablon panelu nawigacyjnego zawiera zarwno rysunek, jak i mape obrazu. Nalezy zwrcic uwage, ze szablon nawigacyjny nie zawiera aktualnych adresw URL, a jedynie zmienne szablonu Pozwala to na stworzenie wlasciwych adresw laczy, na przyklad zawierajacych identyfikator sesji. Skrypt PHP pokazany na wydruku 14.7. pokazuje w jaki sposb mozna polaczyc pliki szablonw w jedna calosc. Wydruk 14.7. Laczenie szablonw
<?php include( "class.FastTemplate.php" ); // zakladamy, ze wybrana kategoria sa ubrania $aCategoryHeader = 'merch_catubrania_header.tpl'; $aTPL = new FastTemplate( "." ); $aTPL->define( array( 'base' 'header' 'navi' 'footer' 'cat_header' 'body'

=> => => => => =>

'merch_base2.tpl', 'merch_header.tpl', 'merch_navi.tpl', 'merch_footer.tpl', $aCategoryHeader, 'merch_body.tpl'

Rozdzial 14 Witryny oparte o szablony

176

) ); $aTPL->assign( array( 'TITLE' 'CATEGORY_SPECIALS' 'PRODUCT_NAME' 'PRODUCT_DESCRIPTION' 'PRODUCT_PRICE' 'COPYRIGHT_YEARS' 'HREF_HOME' 'HREF_CART' 'HREF_CONTACT' 'HREF_COMPANY_INFO' ) ); $aTPL->parse( 'PAGE_HEADER', $aTPL->parse( 'CAT_HEADER', $aTPL->parse( 'LEFT_NAVI', $aTPL->parse( 'BODY', $aTPL->parse( 'PAGE_FOOTER', $aTPL->parse( 'BASE', $aTPL->FastPrint( 'BASE' ); ?> => 'Katalog towarw: Ubrania', 'Sprzedajemy koszulki Intechra!', 'Koszulka Intechra', 'Swietna koszulka z logo Intechra LLC!', '14.95 zl', '2001', 'index.phtml', 'cart.phtml', 'contact.phtml', 'company.phtml'

=> => => => => => => => =>

'header' ); 'cat_header' ); 'navi' ); 'body' ); 'footer' ); 'base' );

Skrypt ten wykorzystuje klase FastTemplate do analizy i polaczenia wszystkich plikw szablonw tworzacych katalog produktw. W przykladzie tym wszystkie wartosci zostaly na stale zaszyte w skrypcie w celu uproszczenia opisu. W prawdziwej aplikacji dane na temat kategorii produktu oraz wyswietlanego produktu powinny byc dostarczone poprzez formularz lub inna metode dynamicznego dostarczania danych. Skrypt ten po prostu przypisuje wartosci do wszystkich zmiennych potrzebnych we wszystkich plikach szablonw. Aby zrozumiec w jaki sposb FastTemplate analizuje strone nalezy wiedziec, ze niektre zmienne FastTemplate sa ustawiane przy uzyciu metody assign(). Na przyklad zmienna COPYRIGHT_YEARS wykorzystywana w szablonie merch_footer.tpl jest inicjowana wartoscia 2000 przy uzyciu metody assign(). Dodatkowo niektre zmienne FastTemplate sa ustawiane za pomoca metody parse(). Dla przykladu zmienna PAGE_HEADER jest ustawiana poprzez analize strony o nazwie header. Powoduje to, ze wartosc PAGE_HEADER jest juz dostepna w czasie analizy pliku merch_base.tpl, ktry w naszym przykladzie zostal nazwany base. Nalezy pamietac, ze w przypadku zaglebiania szablonw nalezy zainicjowac wszystkie wymagane zmienne szablonu przed jego analiza. Dodatkowo nalezy analizowac szablony we wlasciwej kolejnosci. Dla przykladu, jezeli w powyzszym przykladzie strona base byla by analizowana na poczatku, wiekszosc wymaganych zmiennych (takich jak PAGE_HEADER i BODY) nie bylo by dostepnych. Sila zastosowania szablonw jest mozliwosc latwego wprowadzania zmian w projekcie graficznym witryny. Na rysunku 14.2. pokazany zostal wyglad strony wygenerowanej przez skrypt z wydruku 14.6. Zmieniajac szablon o nazwie base, z zamieszczonego na wydruku 14.1. na ten z wydruku 14.8, wyglad strony ulega calkowitej zmianie. Efekt zmiany szablonu base pokazany jest na rysunku 14.3.

177

PHP Kompendium wiedzy

Rysunek 14.2. Strona wygenerowana przez skrypt z wydruku 14.7.

Wydruk 14.8. Nowy plik szablonu base


<html> <head> <title>{TITLE}</title> <link rel="STYLESHEET" type="text/css" href="new_base.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>

Rozdzial 14 Witryny oparte o szablony

178

Rysunek 14.3. Strona wygenerowana przy uzyciu nowego szablonu base

Sila systemu szablonw nie moze byc przeceniana. Tak jak to zostalo pokazane, zmieniajac zawartosc szablonu base, znacznie zmieniony zostal wyglad strony, natomiast nie zostaly wprowadzone zadne zmiany po stronie PHP. Elastycznosc ta pozwala projektantom na tworzenie i konserwacje bogatego interfejsu uzytkownika, natomiast programisci aplikacji rwnolegle tworza i konserwuja czesc logiczna. Oczywisci zachodzi niezbedna interakcja pomiedzy programistami i projektantami interfejsu, ale po zdefiniowaniu zestawu plikw szablonw i zmiennych szablonw praca obu grup moze pracowac rwnolegle. Dodatkowo, wykorzystanie szablonw pozwala programistom na wykorzystywanie zestawu prototypowych plikw interfejsu, do czasu az projektanci dostarcza im ostateczne wersje. W poprzednim przykladzie jedyna znaczaca zmiana wprowadzona w szablonie base bylo dolaczenie pliku CSS. CSS jest wartosciowym dodatkiem do wiekszosci zastosowan WWW, poniewaz stanowi on system szablonw dla HTML. Wykorzystujac CSS, mozna zmienic atrybuty wszystkich elementw HTML. Na przyklad mozna tak zdefiniowac znacznik <h3>, aby w kontekscie tej witryny wygladal w okreslony sposb. Na wydrukach 14.4. i 14.5. pokazany jest wyglad komercyjnego edytora CSS o nazwie TopStyle z firmy Bradbury Software LLC (http://www.bradsoft.com/). Edytor ten upraszcza proces tworzenia plikw CSS oraz pozwala na podglad zmienionych stylw.

179

PHP Kompendium wiedzy

Rysunek 14.4. Arkusz stylu pokazujacy mozliwosc modyfikacji znacznikw <body>, <td> i <h3>

Rysunek 14.5. Inny arkusz stylu pokazujacy mozliwosc modyfikacji znacznikw <body>, <td> i <h3>

Uzycie CSS wraz z systemem szablonw zwieksza mozliwosc wprowadzania zmian do wygladu witryny minimalizujac koniecznosc wprowadzania zmian do kodu aplikacji. Pliki CSS moga byc nawet dolaczane dynamicznie, w postaci zmiennej szablonu. Mimo, ze nie jest to optymalne rozwiazanie dla wszystkich typw witryn, pozwala zrealizowac kolejny poziom konfiguracji wygladu tworzonej aplikacji. Rozdzial 14 Witryny oparte o szablony 180

Poprzedni przyklad stanowi podstawowy szkielet dla tworzenia aplikacji WWW opartej o szablony. Jednak nie zostaly tu pokazane przyklady tworzenia powtarzajacych sie elementw. Czesto zachodzi potrzeba stworzenia tabeli zawierajacej wszystkie towary, lub liste kategorii zapisanych w bazie danych. Kolejny przyklad pokazuje, w jaki sposb mozna dolaczyc powtarzajace sie elementy, korzystajac z klasy FastTemplate. Wydruk 14.9. zawiera glwny plik szablonu. Wydruk 14.10. to zawartosc szablonu items, natomiast wydruk 14.11. szablon pojedynczego elementu. Na wydruku 14.12 znajduje sie skrypt laczacy te szablony w calosc. Wydruk 14.9. Glwny szablon kategorii
<html> <head> <title>{TITLE}</title> </head> <body> {ITEMS} </body> </html>

Wydruk 14.10. Szablon kategorii items


Do wyboru sa nastepujace kategorie produktw: <ul> {ITEM_LIST} </ul>

Wydruk 14.11. Szablon dla pojedynczej kategorii


<li><a href="show_category.phtml?cat_id={CAT_ID}">{CAT_NAME}</a></li>

Wydruk 14.12. Skrypt generujacy strone z lista kategorii


<?php include( "class.FastTemplate.php" ); $aTPL = new FastTemplate( "." ); $aTPL->define( array( 'base' => 'cat_base.tpl', 'items' => 'cat_items.tpl', 'item' => 'cat_item.tpl' ) ); $aCategories = array( "ubrania", "prezenty", "zabawki", "ksiazki" ); foreach( $aCategories as $aID => $aName ) { $aTPL->assign( array( 'CAT_ID' => $aID, 'CAT_NAME' => $aName ) ); // analiza elementu i jego dolaczenie do zmiennej szablonu // ITEM_LIST $aTPL->parse( 'ITEM_LIST', '.item' ); } $aTPL->assign( array( 'TITLE' => 'Lista kategorii' ) ); $aTPL->parse( 'ITEMS', 'items' ); $aTPL->parse( 'BASE', 'base' ); $aTPL->FastPrint( 'BASE' ); ?>

Rysunek 14.6. Lista kategorii

Przedstawiony przyklad zawiera wbudowana liste kategorii w celu wygenerowania strony z lista kategorii. Wynik dzialania skryptu przedstawiony jest na rysunku 14.6. Po raz kolejny zalzmy, ze dzial projektowy zdecydowal sie na zmiane formatu listy kategorii z listy wypunktowanej na tabele. Zmiany sa ograniczone jedynie do plikw items i item. Wykorzystujac poprzedni przyklad zmienione szablony przedstawione sa na wydrukach 13. i 14. Efekt koncowy pokazany jest na rysunku 14.7. PHP Kompendium wiedzy 181

Wydruk 14.13. Nowy szablon items


Do wyboru sa nastepujace kategorie produktw: <br><br> <table border="1"> {ITEM_LIST} </table>

Wydruk 14.14. Nowy szablon item


<tr> <td> Kategoria nr. {CAT_ID} </td> <td> <a href="show_category.phtml?cat_id={CAT_ID}">{CAT_NAME}</a> </td> </tr>

Rysunek 14.7. Lista kategorii w postaci tabeli

Przedstawiony przyklad pokazuje podstawowe kroki potrzebne do generowania listy powtarzajacych sie elementw przy uzyciu FastTemplate. Istnieje rwniez w FastTemplate inny mechanizm pozwalajacy na wyeliminowanie dodatkowych plikw zawierajacych szablon pojedynczego elementu. Aby uzyc tego mechanizmu zmienimy szablon items, oraz glwny skrypt PHP. Na wydrukach 15. i 16. zamieszczone sa zmienione pliki. Wynik dzialania tego skryptu jest taki, jak pokazany na rysunku 14.7. Wydruk 14.15. Nowy szablon items korzystajacy z dynamicznych blokw
Do wyboru sa nastepujace kategorie produktw: <br><br> <table border="1"> <!-- BEGIN DYNAMIC BLOCK: item --> <tr> <td> Kategoria nr. {CAT_ID} </td> <td> <a href="show_category.phtml?cat_id={CAT_ID}">{CAT_NAME}</a> </td> </tr> <!-- END DYNAMIC BLOCK: item --> </table>

W szablonie tym zostal zdefiniowany podszablon blok dynamiczny o nazwie item. Jest to dokladnie to samo, co stworzenie osobnego pliku zawierajacego szablon item. Zaleta takiego rozwiazania jest utrzymanie oryginalnej struktury pliku HTML oraz ograniczenie ilosci niezbednych plikw szablonw. Uzycie szablonw wymaga rwniez kilku zmian w skrypcie uzywajacym klasy FastTemplate. Zostaly one zamieszczone na wydruku 14.16. Wydruk 14.16. Nowy skrypt PHP
<?php include( "class.FastTemplate.php" ); $aTPL = new FastTemplate( "." ); $aTPL->define( array( 'base' => 'cat_base.tpl', 'items' => 'cat_items_dyn.tpl') );

Rozdzial 14 Witryny oparte o szablony

182

$aTPL->define_dynamic( 'item', 'items' ); $aCategories = array( "ubrania", "prezenty", "zabawki", "ksiazki" ); foreach( $aCategories as $aID => $aName ) { $aTPL->assign( array( 'CAT_ID' => $aID, 'CAT_NAME' => $aName ) ); // analiza elementu i jego dolaczenie do zmiennej szablonu // ITEM_LIST $aTPL->parse( 'ITEM_LIST', '.item' ); } $aTPL->assign( array( 'TITLE' => 'Lista kategorii' ) ); $aTPL->parse( 'ITEMS', 'items' ); $aTPL->parse( 'BASE', 'base' ); $aTPL->FastPrint( 'BASE' ); ?>

W skrypcie tym widoczne sa dwie wyrazne zmiany w stosunku do wydruku 14.12. Po pierwsze, w nowym skrypcie brakuje jednego wywolania metody define(). Po drugie, wykorzystana jest metoda FastTemplate define_dynamic(), ktra wskazuje systemowi FastTemplate, ze w szablonie items istnieje blok dynamiczny o nazwie item. Od tej chwili FastTemplate traktuje blok dynamiczny identycznie, jak bylby to osobny plik. Korzystajac z tego mechanizmu, niezmiernie wazne jest, aby blok dynamiczny byl poprawny skladniowo. Skladnia linii BEGIN i END musi byc poprawna i wymagane jest zachowanie odpowiedniej wielkosci liter. Blok kodu zaczyna sie od nowej linii tekstu przeznaczonej jedynie dla tej dyrektywy. W linii zawierajacej wyrazenia BEGIN i END nie powinno byc zadnego innego tekstu, mozna jedynie umieszczac tam dowolna ilosc znakw odstepu. Dyrektywa musi byc napisana dokladnie w takiej postaci, jak ponizsza linia kodu. Linia ta musi byc dokladnie taka, jak przedstawiona, z dokladnoscia do odstepw pomiedzy znakami. To samo obowiazuje dla dyrektywy END. Linie BEGIN i END nie moga rozciagac sie na wieksza ilosc linii.
<!-- BEGIN DYNAMIC BLOCK: nazwa_bloku -->

Wszystkie te przyklady tworza szkielet aplikacji WWW korzystajacych z szablonw. Nastepna czesc tego rozdzialu zawiera kilka przykladw scenariuszy stosowanych w prawdziwych aplikacjach.

Zapozyczanie
Zapozyczanie jest bardzo latwo realizowalne za pomoca witryny opartej o szablony. Zapozyczanie witryny to wykorzystanie projektu witryny partnerskiej jako podstawy wlasnej aplikacji. Dla przedstawianego wczesniej przykladu katalogu produktw, jest mozliwe aby kilka witryn dystrybutorw korzystajacych z wlasnego projektu graficznego uzywalo katalogu jako jednej z dostepnych uslug. Istnieje kilka sposobw zrealizowania takiego scenariusza w PHP, ale wykorzystujac szablony mozna zrobic to bardzo szybko. Tworzenie zapozyczonej witryn jest w zasadzie identyczne, jak tworzenie innych witryn opartych o szablony. Poniewaz aplikacja opiera sie na interfejsie z innej firmy, integracja i testowanie musi byc przeprowadzone przez obie strony, aby upewnic sie, ze wszystkie funkcje dzialaja tak, jak to zostalo zaplanowane. Tworzac aplikacje, ktra moze byc zapozyczana, nalezy zdecydowac na ile konfigurowalna powinna byc taka witryna. W niektrych przypadkach partnerzy moga umiescic dodatkowe informacje o prawach autorskich, zadac zmian w terminologii itd. W prostych przypadkach mozesz dodac jedynie kilka znakw firmowych. Aby zilustrowac to zagadnienie, ponizsze pliki szablonw sa wykorzystywane w aplikacji przedstawionej w poprzedniej czesci. W tym scenariuszu zmienione zostaly jedynie dane o prawach autorskich oraz szablon bazowy. Wydruki 17. i 18. zawieraja stopke z prawami autorskimi oraz plik bazowy. Wydruk 14.17. Szablon partnera z opisem prawa autorskich
<hr> <p> Niektre fragmenty witryny pochodza z firmy Keen Partner Company. &copy 2000 &copy {COPYRIGHT_YEARS} Intechra LLC. Wszystkie prawa zastrzezone. </p>

Wydruk 14.18. Bazowy szablon partnera


<html> <head> <title>{TITLE}</title> <link rel="STYLESHEET" type="text/css" href="new_base.css">

183

PHP Kompendium wiedzy

</head> <body bgcolor="White"> <table width="630" border="0" cellspacing="0" cellpadding="0" align="center"> <tr> Firma Keen Partner Company wykorzystuje katalog produktw firmy Intechra LLC. <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>

Zmodyfikowany zostal rwniez glwny skrypt laczacy szablony a skrypt tworzacy strone wynikowa jest rwniez tak zmieniony, aby rozpoznal wlasciwy wyglad witryny na podstawie nazwy partnera. Na przyklad glwna witryna jest dostepna poprzez adres http://www.katalog.com/, natomiast witryna partnera poprzez http://cobrand.katalog.com/. Nazwy te sa oczywiscie uzywane jedynie do testowania i nie musza byc to docelowe nazwy witryny. Po uruchomieniu glwnego skryptu sprawdzana jest nazwa witryny i wyswietlana jest odpowiednia strona. Na wydruku 14.19. pokazany jest taki skrypt. Wydruk 14.19. Glwny skrypt realizujacy zapozyczanie
<?php include( "class.FastTemplate.php" ); $aHostArray = explode( ".", $HTTP_HOST ); $aPartner = $aHostArray[0]; switch ( $aPartner ) { case "cobrand" : $aPartnerBase = "partner_base.tpl"; $aPartnerFooter = "partner_footer.tpl"; break; default : $aPartnerBase = "merch_base2.tpl"; $aPartnerFooter = "merch_footer.tpl"; break; } // Zakladamy, ze wybrana kategoria sa ubrania $aCategoryHeader = 'merch_catubrania_header.tpl'; $aTPL = new FastTemplate( "." ); $aTPL->define( array( 'base' 'header' 'navi' 'footer' 'cat_header' 'body' ) );

=> => => => => =>

$aPartnerBase, 'merch_header.tpl', 'merch_navi.tpl', $aPartnerFooter, $aCategoryHeader, 'merch_body.tpl'

$aTPL->assign( array( 'TITLE' 'CATEGORY_SPECIALS' 'PRODUCT_NAME' 'PRODUCT_DESCRIPTION' 'PRODUCT_PRICE' 'COPYRIGHT_YEARS' 'HREF_HOME' 'HREF_CART' 'HREF_CONTACT' 'HREF_COMPANY_INFO' ) ); $aTPL->parse( $aTPL->parse( $aTPL->parse( $aTPL->parse( $aTPL->parse( $aTPL->parse( 'PAGE_HEADER', 'CAT_HEADER', 'LEFT_NAVI', 'BODY', 'PAGE_FOOTER', 'BASE',

=> => => => => => => => =>

=> 'Katalog produktw: Ubrania', 'Sprzedanemy koszulki Intechra!', 'Koszulka Intechra', 'Swietna koszulka z logo Intechra LLC!', '14.95 zl', '2000', 'index.phtml', 'cart.phtml', 'contact.phtml', 'company.phtml'

'header' ); 'cat_header' ); 'navi' ); 'body' ); 'footer' ); 'base' );

Rozdzial 14 Witryny oparte o szablony

184

$aTPL->FastPrint( 'BASE' ); ?>

Po uruchamianiu tego skryptu analizowana jest zmienna $HTTP_HOST, aby sprawdzic, ktra witryna zostala wywolana. Jezeli nazwa zawiera cobrand, uzywane sa szablony partnera, natomiast w pozostalych przypadkach uzywane sa standardowe szablony. Gdy strona ta zostanie wywolana poprzez adres http://www.katalog.com, wynik jest identyczny jak na rysunku 14.3. Rysunek 14.8. przedstawia wyglad strony po wywolaniu strony poprzez adres zapozyczonej witryny. Rysunek 14.8. Zapozyczenie katalogu produktw

Personalizacja witryny
Personalizacja wydaje sie ostatnio najpopularniejszym elementem przy projektowaniu witryn. Kazdy portal i wiele duzych witryn pozwalaja na personalizowanie witryny tak, aby spelniala potrzeby uzytkownika. We wielu przypadkach personalizacja jest ograniczona do typu wyswietlanych informacji i niektrych podstawowych kolorw. Wykorzystujac szablony mozliwa jest o wiele bardziej zaawansowana modyfikacja wygladu witryny. Zamiast tworzyc przyklady dla tej czesci ksiazki, chcialbym odwolac sie do witryny, ktra wykonalem. Nie jest moim celem reklamowac ten serwis, ale jedynie pokazac jak bardzo mozna modyfikowac wyglad witryny korzystajac z dobrego systemu szablonw. Ta witryna jest http://www.HopeToAdopt.com/ i jest to sieciowy serwis dla rodzin adoptujacych dzieci. Witryna pozwala na tworzenie wlasnych profili poprzez odpowiedz na kilka prostych pytan oraz wybranie odpowiednich opcji. Najlepsza cecha witryny jest mozliwosc wybrania wlasnego tematu uzywanego w stronach informacyjnych. Kazdy z dostepnych tematw jest przedstawiony w postaci ikony na stronie. Gdy Uzytkownik kliknie ikone tematu, w bazie danych zapisywany jest wybrany identyfikator tematu i jest on uzywany pzniej przy wyswietlaniu. Na rysunku 14.10.pokazany jest wyglad witryny po wybraniu tematu kolejowego. Do stworzenia tematu potrzebne sa cztery pliki: {temat}_navi.jpg, {temat}_header.jpg, {temat}_map.tpl oraz {temat}_vars.php. Pierwsze dwie sa rysunkami uzywanymi w naglwku oraz panelu nawigacyjnym. Trzeci jest mapa obrazu dla panelu nawigacyjnego. Ostatni plik jest zbiorem zmiennych specyficznych dla szablonu, ktre sa dolaczane do pliku skryptu PHP korzystajacego z danych tematu. Przyklad takiego pliku jest pokazany na wydruku 14.20. PHP Kompendium wiedzy 185

Wydruk 14.20. Plik dolaczany specyficzny dla tematu


<?php function AddTemplateVars( &$tpl, $aCurTemplate ) { $tpl->assign( array( BODYBGCOLOR => "#FFFFFF", MAINWIDTH => 584, TOPIMGWIDTH => 584, TOPIMGHEIGHT => 128, LEFTIMGWIDTH => 137, LEFTIMGHEIGHT => 312, FILLWIDTH => 584, TABLECOLOR => "#ffadad")); } function GetTemplteValue( $aValName ) { switch ( $aValName ) { case "NavSide": return "left"; case "HasOvr" : return False; } } ?>

Rysunek 14.10. Profil uzytkownika z tematem kolejowym

Plik ten zawiera dane na temat kolorw wykorzystywanych w temacie, oraz wysokosc i szerokosc rznych rysunkw uzywanych w temacie. Dodatkowo dostepna jest funkcja zwracajaca do glwnego skryptu dane na temat tematu. Przyklad ten jest specyficzny dla aplikacji HopeToAdopt.com, ale moze sluzyc jako ilustracja elastycznosci systemu szablonw. Witryna HopeToAdopt.com jest uzywana jako dzialajacy przyklad pokazujacy sile systemu szablonw zamiast tworzenia kolejnego trywialnego przykladu. Pelny kod tej witryny nie moze byc tutaj zamieszczony, ale poprzednie przyklady zawieraja wystarczajaco duzo informacji, aby stworzyc tego typu witryne.

Rozdzial 14 Witryny oparte o szablony

186

Obsluga wielu jezykw


Coraz czestsze jest tworzenie witryn dzialajacych w kilku jezykach. Wykorzystujac system szablonw do obslugi tej funkcji pozwala na tworzenie aplikacji w jednym jezyku, a nastepnie w latwy sposb dodac pzniej kolejne jezyki. I tym razem tworzenie tak skomplikowanej aplikacji wymaga uwaznego projektowania przed rozpoczeciem prac programowych, ale efekt jest wart tej pracy. Jedna z pierwszych decyzji jest zadecydowanie, w jaki sposb beda dzielone i identyfikowane elementy wlasciwe dla jezyka. Jedna z metod jest stworzenie oddzielnych katalogw dla poszczeglnych jezykw. Druga jest umieszczenie identyfikatorw jezyka w nazwach i plikach szablonw. Metoda ta zostanie zastosowana w przykladzie. W przykladzie tym, dla kazdego jezyka wymagane sa cztery pliki: rysunek naglwka, rysunek panelu nawigacyjnego, mapa rysunku, oraz glwny plik. Nie bedziemy tu zamieszczac wszystkich plikw, pokazemy jedynie glwny skrypt i wynik dzialania. Na wydruku 14.21. zamieszczony jest glwny skrypt, ktry generuje jedna strone miedzynarodowej witryny opartej o szablony. Wydruk 14.21. Glwny skrypt miedzynarodowej witryny
<?php include( "class.FastTemplate.php" ); $aTPL = new FastTemplate( "." ); if ( empty( $Lang ) ) { $Lang = 'enu'; } $aHeaderImg $aNaviImg $aNaviMap $aBodyTpl = = = = "intl_head_{$Lang}.gif"; "intl_nav_{$Lang}.gif"; "intl_map_{$Lang}.tpl"; "body_{$Lang}.tpl";

$aTPL->define( array( 'base' => 'intl_base.tpl', 'body' => $aBodyTpl, 'navimap' => $aNaviMap ) ); $aTPL->assign( array( 'HREF_HOME' 'HREF_LINKS' 'HREF_ABOUT' 'HREF_CONTACT' 'HEADER_IMG' 'NAV_IMG' 'HREF_ENU' 'HREF_POL' 'HREF_DEU' $aTPL->parse( 'NAV_MAP', 'navimap' ); $aTPL->parse( 'BODY', 'body' ); $aTPL->parse( 'BASE', 'base' ); $aTPL->FastPrint( 'BASE' ); ?> => => => => => => => => => "intl.phtml?Lang=$Lang", "links.phtml?Lang=$Lang", "about.phtml?Lang=$Lang", "contact.phtml?Lang=$Lang", $aHeaderImg, $aNaviImg, $PHP_SELF . "?Lang=enu", $PHP_SELF . "?Lang=pol", $PHP_SELF . "?Lang=deu" ) );

Jedyna widoczna rznica w tym skrypcie, w porwnaniu z innymi przedstawionymi w tym rozdziale jest czesc na poczatku ustalajaca biezacy jezyk i korzystajaca z tej informacji w celu dolaczenia wlasciwego pliku. W przykladzie tym identyfikator jezyka jest przesylany poprzez adres URL, wiec kazde lacze w witrynie musi przesylac ta dana do kolejnej strony. W duzych aplikacjach przedstawiona metoda definiowania wszystkich mozliwych laczy staje sie nieporeczna. W praktyce kod generujacy lacza prawdopodobnie bedzie umieszczony w oddzielnym pliku dolaczanym. Niezaleznie od prostoty przedstawionego przykladu, elastycznosc i sila tego rozwiazania jest ogromna. Na rysunkach 14.12, 14.13 i 14.14 pokazana jest strona glwna w jezyku odpowiednio: angielskim, polskim i niemieckim.

187

PHP Kompendium wiedzy

Rysunek 14.12. Witryna miedzynarodowa w jezyku angielskim

Rysunek 14.13. Witryna miedzynarodowa w jezyku polskim

Rozdzial 14 Witryny oparte o szablony

188

Rysunek 14.14. Witryna miedzynarodowa w jezyku niemieckim

Podsumowanie
W rozdziale tym pokazano jak zastosowanie systemu szablonw polepsza elastycznosc i latwosc utrzymania aplikacji WWW. Dostarczone przyklady pokazuja, w jaki sposb mozna uzyc szablonw do obslugi zapozyczania, personalizacji i obslugi jezykw. Uzywanym systemem szablonw jest FastTemplate, ktry mozna uzyskac pod adresem http://www.thewebmasters.net/. Niezaleznie od rodzaju uzywanego systemu szablonw jest zalecane zapoznanie sie z tym sposobem tworzenia aplikacji WWW.

189

PHP Kompendium wiedzy

Rozdzial 15. Witryny oparte o baze danych


Wstep
W rozdziale 6. Wsplpraca z bazami danych opisane zostaly narzedzia PHP pozwalajace na dostep do baz danych. W ostatnim rozdziale dokladnie opisane jest wykorzystanie systemu szablonw do oddzielenia interfejsu aplikacji od kodu aplikacji. Rozdzialy te stanowia podstawe dla tego rozdzialu. W rozdziale tym opisane sa szczegly projektu i implementacji na wysokim poziomie, wiec nie beda opisane niskopoziomowe funkcje obslugi baz danych. Wiecej na ten temat mozna przeczytac w rozdziale 6. oraz w skorowidzu funkcji na koncu tej ksiazki.

Projekt bazy danych


W kazdym aspekcie tworzenia oprogramowania wynikiem dobrego projektu jest dobry produkt. Nieprawidlowy projekt bazy danych zwykle prowadzi do problemw z integracja, utrzymaniem i tworzeniem aplikacji. Prawidlowe projektowanie baz danych jest tematem wielu wspanialych ksiazek i jest to temat zbyt obszerny i skomplikowany, aby go tutaj przedstawic, wiec opisane zostana niektre podstawowe informacje. Pierwsza decyzja jaka nalezy podjac jest wybr systemu zarzadzania baza danych (SZRBD). Poniewaz PHP obsluguje wiele popularnych systemw baz danych, przy podejmowaniu tej decyzji powinnismy wziac pod uwage koszty, funkcjonalnosc, skalowalnosc oraz inne kluczowe aspekty bazy danych, a nie obsluga jezyka. Dla wielu aplikacji PHP swietnym systemem bazy danych jest MySQL, poniewaz PHP posiada domyslnie wbudowana obsluge MySQL. MySQL jest dostepny na zasadach licencji GNU General Public License (GPL). Posiada on obsluge duzego podzbioru SQL oraz bogate API. Informacje na temat instalacji i korzystania z MySQL znajduja sie w rozdziale 6. Przyklady w tym rozdziale sa napisane w oparciu o baze danych MySQL. Dostepne sa rwniez inne bazy danych, ktre takze maja swoje silne strony. Jezeli masz zamiar stworzyc aplikacje, ktra obslugiwac bedzie duza liczbe uzytkownikw lub potrzebujesz obslugi transakcji, powinienes rozwazyc zastosowanie Oracle lub Microsoft SQL Server. Wybr wlasciwej bazy danych dla aplikacji wymaga wyboru pomiedzy cena, dostepnoscia obslugi technicznej, skalowalnoscia i dostepnymi funkcjami. Wybr niewlasciwego systemu bazy danych moze spowodowac, ze w przypadku duzego obciazenia aplikacja bedzie miala niska wydajnosc lub odmwi posluszenstwa. Jezeli przypuszczasz, ze po stworzeniu aplikacji system bazy danych moze byc zmieniony na inny, nalezy skorzystac z posredniego API stanowiacego bufor pomiedzy aplikacja a funkcjami specyficznymi dla okreslonej bazy danych, oraz korzystac ze standardowego jezyka SQL. Dodatkowo nalezy pamietac o rznicach w obsludze standardu SQL w rznych systemach baz danych. Dla przykladu w Oracle mozna korzystac z nastepujacych podzapytan:
SELECT * FROM tabela1 WHERE id IN (SELECT id FROM tabela2)

W czasie pisania tej ksiazki MySQL nie potrafil obslugiwac takiej konstrukcji. Tworzenie kodu SQL niezaleznego od systemu bazy danych jest wyzwaniem samym w sobie, wiec zmiana systemu bazy danych na inny moze byc niepraktyczna nawet dla malych aplikacji. Po wybraniu systemu bazy danych kolejnym krokiem jest stworzenie i dokladne przetestowanie modelu danych. Jako przykladu uzyjemy sieciowego katalogu towarw, przeznaczonego dla wielu sprzedawcw lub sklepw. W tym rozdziale opisany zostanie proces projektowania i implementacji bazy danych, ktra bedzie wykorzystywana w dwch kolejnych rozdzialach. Celem jest stworzenie sieciowego katalogu, obslugujacego w

jednej bazie danych fragmenty danych przypisane do rznych sprzedawcw, a kazdy z tych sprzedawcw moze miec wiele kategorii produktw. Oglny schemat tej bazy danych jest pokazany na rysunku 15.1. Rysunek 15.1. Podstawowy model danych katalogu towarw

Rozwijajac model z rysunku 15.1, kazdy sprzedawca moze miec jedna lub wiecej kategorii produktw, a kazda z kategorii moze zawierac jeden lub wiecej produktw. Na tym poziomie szczeglowosci mozna stworzyc kompletny model danych. Na rysunku 15.2 pokazany jest kompletny model danych katalogu produktw. Jego implementacja w SQL zamieszczona jest na wydruku 15.1. Rysunek 15.2. Pelny model danych katalogu towarw

Wydruk 15.1. Implementacja modelu danych katalogu produktw


CREATE TABLE mcMerchants ( merchant_id int name varchar(50) created_date datetime internal_status int addtl_handling float mgr_email varchar(25) mgr_username varchar(30) mgr_password varchar(30) mgr_name varchar(50) primary key ( merchant_id ), index( name ), index( mgr_username ) ); CREATE TABLE mcCategories ( merchant_id int category_id int name varchar(50) not not not not default 0.0 not not not not not null, null, null, null, null, null, null, null, null,

not null, not null, not null,

191

PHP Kompendium wiedzy

created_date deleted

datetime tinyint

default 0

not null, not null,

primary key ( merchant_id, category_id ), index( name ) ); CREATE TABLE mcProducts ( merchant_id int product_id int category_id int name varchar(200) descr text has_image_file tinyint default 0 external_id varchar(100) ship_weight float price float created_date datetime deleted tinyint default 0 primary key ( merchant_id, product_id ), index( name ) ); CREATE TABLE mcProductsToCategories ( merchant_id int category_id int product_id int

not not not not not not not not not not not

null, null, null, null, null, null, null, null, null, null, null,

not null, not null, not null,

primary key ( merchant_id, category_id, product_id ) ); CREATE TABLE mcProductsOptions ( merchant_id int product_id int option_id int name varchar(100) sort_type tinyint default 0

not not not not not

null, null, null, null, null,

primary key ( merchant_id, product_id, option_id ), index( name ) ); CREATE TABLE mcProductsOptionsValues ( merchant_id int product_id int option_id int value_id int name varchar(100)

not not not not not

null, null, null, null, null,

primary key ( merchant_id, product_id, option_id, value_id ), index( name ) );

Po zaprojektowaniu i sprawdzeniu modelu danych mozna rozpoczac prace nad aplikacja. Podstawowymi zalozeniami aplikacji katalogu produktw sa: Wyswietlanie danych o produktach w logicznym i latwym do uzycia formacie. Umozliwienie sprzedawcom uaktualniania danych o produktach w dowolnym momencie z dowolnego komputera przylaczonego do sieci Internet. Umozliwienie sprzedawcom zarzadzanie kategoriami produktw i przypisywanie produktw do kategorii w dowolnym momencie z dowolnego komputera przylaczonego do sieci Internet. Mwiac prosciej, celem jest dostarczenie metody na dodawanie, zmiane i wyswietlanie dowolnej danej zawartej w katalogu produktw, wykorzystujac do tego celu Internet. W nastepnej sekcji opisane zostanie zarzadzanie tymi danymi.

Zarzadzanie danymi aplikacji


Po zaprojektowaniu i stworzeniu bazy danych mozna rozpoczac tworzenie aplikacji zarzadzajacej rekordami w bazie danych. Podstawowymi operacjami jakie mozna przeprowadzac na dowolnych danych jest Rozdzial 15 Witryny oparte o baze danych 192

dodawanie, zmiana i usuwanie. W tej aplikacji niezbedne bedzie rwniez zarzadzanie hierarchia danych. Aby spelnic to wymaganie, spelniona musi byc zasada, ze przed dodaniem jakiegokolwiek produktw, musi istniec co najmniej jedna kategoria produktw dla sprzedawcy. Majac na uwadze ta zasade, logicznym punktem startowym jest strona z mozliwoscia zarzadzania kategoriami produktw. W aplikacji tej zakladamy, ze sprzedawca moze sie zalogowac do fragmentu witryny w celu zarzadzania danymi. W aplikacji bedziemy korzystac z omwionego wczesniej systemu szablonw FastTemplate. Do podstawowego zarzadzania danymi aplikacji uzyte zostana szablony przedstawione na wydrukach od 2. do 4. Wydruk 15.2. Podstawowy szablon zarzadzania danymi aplikacji (mgmt_app_base.tpl)
<html> <head> <title>{TITLE}</title> <link rel="STYLESHEET" type="text/css" href="mgmt.css"> </head> <body bgcolor="White"> {BODY} </body> </html>

Wydruk 15.3. Szablon zarzadzania danymi aplikacji (mgmt_body.tpl)


<table width="630" align="center"> <tr> <td align="center" class="title"> {MERCHANT_NAME} </td> </tr> <tr> <td> {PAGE_BODY} </td> </tr> <tr> <td> &nbsp; </td> </tr> <tr> <td> {FOOTER} </td> </tr> </table>

Wydruk 15.4. Szablon zarzadzania danymi aplikacji stopka (mgmt_footer.tpl)


<hr> <p class="footer"> &copy; 2000 Intechra LLC. Wszystkie prawa zastrzezone. </p>

Szablony przedstawione na wydrukach od 2. do 4. stanowia podstawowy szablon aplikacji zarzadzania danymi. Szablony uzywane do stworzenia strony zarzadzania konkretna kategoria umieszczone sa na wydrukach od 5. do 7. Na wydruku 15.8. znajduje sie skrypt laczacy te szablony i wyswietlajacy dane z bazy danych. Wydruk 15.5. Szablon zarzadzania danymi aplikacji glwny szablon kategorii (mgmt_cats_ovr.tpl)
<h1> Zarzadzanie kategoriami produktw </h1> <p> Prosze uzyc ponizszych narzedzi do dodaniam edycji i usuniecia kategorii produktw. </p> <p> <a href="mgmt_cat_add.phtml">Kliknij tutaj</a> aby dodac kategorie. </p> {EXISTING_CATEGORIES}

Wydruk 15.6. Szablon zarzadzania danymi aplikacji tabela kategorii (mgmt_cats_table.tpl)


<h2> Istniejace kategorie produktw: </h2> <table cellspacing="0" cellpadding="0"> <tr> <th> &nbsp;&nbsp;Identyfikator kategorii&nbsp;&nbsp; </th> <th> &nbsp;&nbsp;Nazwa kategorii&nbsp;&nbsp; </th>

193

PHP Kompendium wiedzy

<th> &nbsp;&nbsp;Operacje&nbsp;&nbsp; </th> </tr> {CATEGORY_LIST} </table>

Wydruk 15.7. Szablon zarzadzania danymi aplikacji biezaca kategoria (mgmt_cats_item.tpl)


<tr> <td> {CAT_ID} </td> <td> {CAT_NAME} </td> <td class="small"> <a href="mgmt_cat_edit.phtml?cat_id={CAT_ID}">ZMIEN</a> <a href="mgmt_cat_del.phtml?cat_id={CAT_ID}">USUN</a> </td> </tr>

Wydruk 15.8. Aplikacja zarzadzajaca danymi zarzadzanie kategoriami (mgmt_cats.phtml)


<?php error_reporting( E_ALL & ~E_NOTICE ); session_start(); // niejawne ustawienie zmiennej sesji $aMerchantID if ( empty( $aMerchantID ) == True ) { header( "Location: login.phtml?retpage=" . urlencode( $REQUEST_URI ) . "\n" ); exit; } include( "class.FastTemplate.php" ); include( "./mgmt_db.php" ); include( "./mgmt_funcs.php" ); $aTPL = new FastTemplate( "." ); $aDB = new mgmt_db(); $aTPL->define( array( "base" "body" "footer" "page_body" "cat_table" "cat_item" => => => => => => "mgmt_app_base.tpl", "mgmt_body.tpl", "mgmt_footer.tpl", "mgmt_cats_ovr.tpl", "mgmt_cats_table.tpl", "mgmt_cats_item.tpl" ) );

$aSQL = "select category_id, name from mcCategories where ( merchant_id = $aMerchantID )"; $aDB->query( $aSQL ); if ( $aDB->num_rows() > 0 ) { while ( $aDB->next_record() ) { $aCatID = $aDB->f( "category_id" ); $aCatName = $aDB->f( "name" ); $aTPL->assign( array( "CAT_ID" => $aCatID, "CAT_NAME" => $aCatName ) ); $aTPL->parse( "CATEGORY_LIST", ".cat_item" ); } $aTPL->parse( "EXISTING_CATEGORIES", "cat_table" ); } else { $aTPL->assign( array( } $aTPL->assign( array(

"EXISTING_CATEGORIES" =>

"" ) );

"TITLE" => "MERCHANT_NAME" => ) );

"Zarzadzanie katalogiem towarw", GetMerchantName( $aDB, $aMerchantID )

$aTPL->parse( "PAGE_BODY", "page_body" ); $aTPL->parse( "FOOTER", "footer" ); $aTPL->parse( "BODY", "body" ); $aTPL->parse( "PAGE", "base" ); $aTPL->FastPrint( "PAGE" ); ?>

Pierwsza operacja jaka wykonuje skrypt jest rozpoczecie sesji i sprawdzenie identyfikatora sprzedawcy, $aMerchantID. Jezeli nie jest on ustawiony, uzytkownik jest kierowany na strone logowania. Na stronie logowania sprawdzane sa dane uzytkownika i jezeli zostanie on rozpoznany, ta zmienna sesji jest inicjowana identyfikatorem Rozdzial 15 Witryny oparte o baze danych 194

sprzedawcy. Nastepnie uzywajac identyfikatora jako filtru, skrypt ten pobiera kategorie z bazy danych. Jezeli istnieje co najmniej jedna kategoria, skrypt pobiera te dane i generuje tabele istniejacych kategorii. Na rysunku 15.3. pokazana jest strona z dwiema kategoriami testowego sprzedawcy. Rysunek 15.3. Strona zarzadza nia kategoria mi katalogu produkt w

Dodawanie kategorii jest zrealizowane za pomoca klikniecia w lacze. Jezeli istnieja kategorie, kazda z nich posiada wlasne lacza ZMIEN i USUN, na rysunku 15.3. szablony dodawania kategorii oraz skrypt umieszczone sa na wydrukach 9. i 10. Wydruk 15.9. Szablon zarzadzania danymi aplikacji dodawanie kategorii (mgmt_cat_add.tpl)
<h1> Dodawanie kategorii produktu </h1> <form action="{FORM_ACTION}" method="post"> <table> <tr> <td colspan="2"> {ERRORS} </td> </tr> <tr> <td> Nazwa kategorii: </td> <td> <input type="text" name="CategoryName"> </td> </tr> <tr> <td colspan="2"> <input type="submit" name="Submit" value="Wyslij"> </td> </tr> </table> </form>

Wydruk 15.10. Aplikacja zarzadzajaca danymi dodawanie kategorii (mgmt_cat_add.phtml)


<?php session_start(); // niejawne ustawienie zmiennej sesji $aMerchantID if ( empty( $aMerchantID ) == True ) { header( "Location: login.phtml?retpage=" . urlencode( $REQUEST_URI ) . "\n" ); exit; } include( "class.FastTemplate.php" );

195

PHP Kompendium wiedzy

include( "./mgmt_db.php" ); include( "./mgmt_funcs.php" ); $aTPL = new FastTemplate( "." ); $aDB = new mgmt_db(); $aErrors = ""; if ( $REQUEST_METHOD == 'POST' ) // Tutaj wchodzimy po wyslaniu danych z formularza { if ( IsValidCategory( $aDB, $aMerchantID, $CategoryName ) == True ) { SaveCategory( $aDB, $aMerchantID, $CategoryName ); header( "Location: mgmt_cats.phtml\n" ); exit; } else { $aErrors = "Nazwa kategorii zostala juz uzyta. "; $aErrors .= "Prosze wybrac inna nazwe kategorii."; } }

$aTPL->define( array(

"base" "body" "footer" "page_body"

=> => => =>

"mgmt_app_base.tpl", "mgmt_body.tpl", "mgmt_footer.tpl", "mgmt_cat_add.tpl" ) ); => => => => "Zarzadzanie katalogiem produktw", GetMerchantName( $aDB, $aMerchantID ), $PHP_SELF, $aErrors

$aTPL->assign( array(

"TITLE" "MERCHANT_NAME" "FORM_ACTION" "ERRORS" ) );

$aTPL->parse( "PAGE_BODY", "page_body" ); $aTPL->parse( "FOOTER", "footer" ); $aTPL->parse( "BODY", "body" ); $aTPL->parse( "PAGE", "base" ); $aTPL->FastPrint( "PAGE" ); ?>

Skrypt przedstawiony na wydruku 15.10. jest podobny do wielu innych skryptw zbierajacych i kontrolujacych dane, ktre byly opisane w tej ksiazce. Jest on uzywany do wyswietlenia formularza oraz kontroli poprawnosci wprowadzonych danych. W tym przypadku cala logika kontroli poprawnosci oraz zapamietywania nowych kategorii jest umieszczona w funkcjach IsValidCategory() i SaveCategory(). Te funkcje pomocnicze zostana zamieszczone w dalszej czesci rozdzialu na wydruku pliku mgmt_funcs.php. Funkcja sprawdzajaca poprawnosc szuka jedynie kategorii o takiej samej nazwie. Funkcje edycji i usuwania kategorii sa bardzo podobne do innych skryptw zamieszczonych juz w tej ksiazce. Przygladajac sie wydrukowi 8. mozna zauwazyc, ze lacza do usuwania i zmiany kategorii zawieraja identyfikator kategorii. Dla przykladu pelny adres URL do usuwania kategorii Ubrania to http://server.com/ch15/mgmt_cat_del.phtml?cat_id=1. Do skryptu jest przekazany identyfikator kategorii, wiec mozna na jego podstawie skonstruowac proste wyrazenie SQL DELETE. W przypadku edycji, ten sam mechanizm umozliwia wczytanie nazwy kategorii do pola tekstowego. Kod zrdlowy tych stron nie zostal tu zamieszczony, poniewaz jest on bardzo podobny do kodu z wydrukw 9. i 10. Funkcje usuwajace i zmieniajace kategorie pokazane sa na wydruku pliku mgmt_funcs.php (wydruk 15.12.). Podczas tworzenia kategorii nalezy pamietac, ze nazwa nowej kategorii nie moze znajdowac sie w bazie danych. W przypadku usuwania kategorii nalezy sprawdzic, czy nie istnieje produkt nalezacy do tej kategorii. Jezeli do kategorii naleza jakies produkty usuniecie kategorii spowodowaloby powstanie osieroconych rekordw produktw i potencjalnie bledw aplikacji. Tworzac aplikacje WWW dzialajace w oparciu o baze danych, spelnienie wszystkich zasad biznesowych w kodzie jest krytyczne do dobrego dzialania aplikacji. Niektre z zasad moga byc realizowane przez funkcje bazy danych, na przyklad wymuszanie wiezw integralnosci lub kaskadowe operacje na danych. Inne zasady moga byc realizowane w bazie danych za pomoca wyzwalaczy lub procedur przechowywanych. Pozostale zasady biznesowe musza byc realizowane w kodzie aplikacji. Tworzac kod obslugi zasad biznesowych dobra praktyka jest tworzenie funkcji obslugi wszystkich zasad. Dla przykladu nalezy uzyc funkcji DeleteEntity() zamiast wplatac w kod wyrazenia DELETE. Funkcja DeleteEntity() moze zawierac w sobie cala logike wymagana do kontroli wiezw integralnosci oraz zasad biznesowych i zwracac rzne wartosci kodu powrotu w zaleznosci od rznych bledw, jakie moga wystapic. W Rozdzial 15 Witryny oparte o baze danych 196

ten sposb poprawia sie mozliwosc pzniejszego uzycia kodu oraz ulatwia wprowadzanie do aplikacji zmian w logice. Wracajac do katalogu produktw, kolejnym krokiem jest utworzenie stron obslugi aktualnego zestawu produktw. Strony te sa logicznie identyczne ze stronami obslugi kategorii. Na rysunku 15.4 pokazana jest strona zarzadzania produktami, natomiast na wydruku 15.11. znajduje sie skrypt generujacy ta strone. Rysunek 15.4. Ekran zarzadza nia produkta mi

Wydruk 15.11. Aplikacja zarzadzania danymi zarzadzanie produktami (mgmt_prods.phtml)


<?php error_reporting( E_ALL & ~E_NOTICE ); session_start(); // niejawne ustawianie zmiennej sesji $aMerchantID if ( empty( $aMerchantID ) == True ) { header( "Location: login.phtml?retpage=" . urlencode( $REQUEST_URI )."\n" ); exit; } include( "class.FastTemplate.php" ); include( "./mgmt_db.php" ); include( "./mgmt_funcs.php" ); $aTPL = new FastTemplate( "." ); $aDB = new mgmt_db(); $aTPL->define( array( "base" "body" "footer" "page_body" "prod_table" "prod_item" => => => => => => "mgmt_app_base.tpl", "mgmt_body.tpl", "mgmt_footer.tpl", "mgmt_prods_ovr.tpl", "mgmt_prods_table.tpl", "mgmt_prods_item.tpl" ) );

$aSQL = "select a.category_id, a.product_id, a.name, a.external_id, a.price,"; $aSQL .= "b.name as cat_name from mcProducts a, mcCategories b where (a.merchant_id"; $aSQL .= "= $aMerchantID) and (a.category_id = b.category_id)"; $aDB->query( $aSQL ); if ( $aDB->num_rows() > 0 ) { while ( $aDB->next_record() ) { $aCatID = $aDB->f( "category_id" ); $aCatName = $aDB->f( "cat_name" ); $aProdID = $aDB->f( "product_id" ); $aProdName = $aDB->f( "name" ); $aProdEID = $aDB->f( "external_id" ); $aProdPrice = $aDB->f( "price" ); $aTPL->assign( array( "PROD_ID" => $aProdID,

197

PHP Kompendium wiedzy

"PROD_EID" => $aProdEID, "PROD_NAME" => $aProdName, "PROD_CAT" => $aCatName, "PROD_PRICE" => '$' . number_format( $aProdPrice, 2 ) ) ); $aTPL->parse( "PRODUCT_LIST", ".prod_item" ); } $aTPL->parse( "EXISTING_PRODUCTS", "prod_table" ); } else { $aTPL->assign( array( } $aTPL->assign( array(

"EXISTING_PRODUCTS" =>

"" ) );

"TITLE" => "MERCHANT_NAME" => ) );

"Zarzadzanie katalogiem produktw", GetMerchantName( $aDB, $aMerchantID )

$aTPL->parse( "PAGE_BODY", "page_body" ); $aTPL->parse( "FOOTER", "footer" ); $aTPL->parse( "BODY", "body" ); $aTPL->parse( "PAGE", "base" ); $aTPL->FastPrint( "PAGE" ); ?>

Strony umozliwiajace dodawanie, usuwanie i zmiane produktw nie zostaly tutaj szczeglowo przedstawione, ale sa dostepne na stronie WWW wymienionej w zasobach sieci na koncu ksiazki. Zasady biznesowe obowiazujace przy dodawaniu nowych produktw sa nastepujace: Produkt musi zostac przypisany do jednej kategorii. Nazwy produktw w kategorii musza byc unikalne. Cena produktu musi wynosic co najmniej zero. Waga towaru rwniez musi wynosic co najmniej zero. W chwili obecnej nie ma ograniczen na kasowanie produktw. Po zmianie danych produktu musza byc spelnione te same zasady biznesowe co przy dodawaniu nowego produktu. Na wydruku 15.12 zamieszczony zostal fragment pliku mgmt_funcs.php zawierajacy niektre funkcje dostepu do bazy danych oraz funkcje zasad biznesowych uzywanych w aplikacji. Wydruk 15.12. Aplikacja zarzadzajaca danymi funkcje uzytkowe (mgmt_funcs.php)
<?php function GetMerchantName( $aDB, $aMerchantID ) { $aResult = ""; $aSQL = "select name from mcMerchants where "; $aSQL .= "( merchant_id = $aMerchantID )"; $aDB->query( $aSQL ); if ( $aDB->next_record() == True ) { $aResult = $aDB->f( "name" ); } return $aResult; } function NewCategoryID( $aDB, $aMerchantID ) { $aSQL = "select ( max( category_id ) + 1 ) as new_id "; $aSQL .= "from mcCategories where ( merchant_id = $aMerchantID )"; $aDB->query( $aSQL ); if ( $aDB->next_record() ) { $aResult = $aDB->f( "new_id" ); } if ( empty( $aResult ) == True ) { $aResult = 1; } return $aResult; } function IsValidCategory( $aDB, $aMerchantID, $aCategoryName ) { $aSQL = "select category_id from mcCategories where "; $aSQL .= "( merchant_id = $aMerchantID ) and "; $aSQL .= "( upper( name ) = upper( '$aCategoryName' ) )"; $aDB->query( $aSQL ); // Jezeli istnieje rekord z ta sama nazwa kategorii,

Rozdzial 15 Witryny oparte o baze danych

198

// zwrc false return ( $aDB->num_rows() == 0 ); } function SaveCategory( $aDB, $aMerchantID, $aCategoryName ) { $aNewID = NewCategoryID( $aDB, $aMerchantID ); $aSQL = "insert into mcCategories ( merchant_id, "; $aSQL .= "category_id, name, created_date ) values "; $aSQL .= "( $aMerchantID, $aNewID, '$aCategoryName', "; $aSQL .= " NOW() )"; $aDB->query( $aSQL ); return ( $aDB->Errno == 0 ); } function DeleteCategory( $aDB, $aMerchantID, $aCategoryID ) { $aSQL = "delete from mcCategories where ( merchant_id = "; $aSQL .= "$aMerchantID ) and ( category_id = $aCategoryID )"; $aDB->query( $aSQL ); return ( $aDB->Errno == 0 ); } function UpdateCategory( $aDB, $aMerchantID, $aCategoryID, $aCategoryName ) { $aSQL = "update mcCategories set name='$aCategoryName' "; $aSQL .= "where ( merchant_id = $aMerchantID ) and "; $aSQL .= "( category_id = $aCategoryID )"; $aDB->query( $aSQL ); return ( $aDB->Errno == 0 ); } // i inne funkcje ?>

Aplikacja zarzadzajaca danymi jest jedynie malym fragmentem calego katalogu produktw. Zapewnia ona interfejs WWW do zarzadzania elementami katalogu. Inna wazna funkcja katalogu jest mozliwosc wyswietlania produktw, szukania produktw oraz odczytywania szczeglowych danych o produktach w katalogu. Nastepna czesc tego rozdzialu traktuje wlasnie o tych zagadnieniach.

Wyswietlanie danych
Aplikacja wyswietlajaca dane produktw z bazy pozwala na wyswietlanie produktw okreslonej kategorii, wyswietlanie alfabetycznej listy produktw oraz zapewnia mechanizm przeszukiwania, pozwalajacy na znalezienie okreslonego produktu. Aby odszukac produkty i kategorie biezacego sprzedawcy wykorzystywany jest identyfikator sprzedawcy, przekazywany w postaci zmiennej sesji. Zmienna ta jest ustawiana jeszcze zanim uzytkownik wejdzie na strone, na ktrej wyswietlane sa informacje o produktach. Na rysunku 15.5. znajduje sie glwna strona katalogu produktw. Strona ta pozwala na natychmiastowy dostep do danych podzielonych na kategorie oraz na przeszukiwanie katalogu. Jezeli nie ma zarejestrowanych zadnych kategorii (co oznacza brak towarw), wyswietlana jest informacja, ze dla ten sprzedawca nie ma zarejestrowanych produktw. Na wydruku 15.13. zamieszczony jest skrypt generujacy ta strone.

199

PHP Kompendium wiedzy

Rysunek 15.5. Glwna strona katalogu produkt w

Wydruk 15.13. Aplikacja zarzadzajaca danymi wyswietlanie produktw (mgmt_main.phtml)


<?php error_reporting( E_ALL & ~E_NOTICE ); session_start(); // niejawne ustawianie zmiennej sesji $aMerchantID if ( empty( $aMerchantID ) == True ) { print( "Blad wewnetrzny aplikacji. Brak identyfikatora sprzedawcy." ); exit; } include( "class.FastTemplate.php" ); include( "./mgmt_db.php" ); include( "./mgmt_funcs.php" ); $aTPL = new FastTemplate( "." ); $aDB = new mgmt_db(); $aTPL->define( array( "base" "body" "footer" "page_body" "cat_body" "cat_item" => => => => => => "mgmt_app_base.tpl", "mgmt_body.tpl", "mgmt_footer.tpl", "mgmt_main.tpl", "mgmt_main_body.tpl", "mgmt_main_cat_item.tpl" ) );

$aSQL = "select category_id, name from mcCategories where ( merchant_id = $aMerchantID )"; $aDB->query( $aSQL ); if ( $aDB->num_rows() > 0 ) { while ( $aDB->next_record() ) { $aCatID = $aDB->f( "category_id" ); $aCatName = $aDB->f( "name" ); $aTPL->assign( array( "CAT_HREF" => GetCategoryHREF( $aCatID ), "CAT_NAME" => $aCatName ) ); $aTPL->parse( "CATEGORY_LIST", ".cat_item" ); } $aTPL->parse( "CATALOG_MAIN_BODY", "cat_body" ); } else { $aTPL->assign( array("CATALOG_MAIN_BODY" =>

"Brak dostepnych produktw." ) );

Rozdzial 15 Witryny oparte o baze danych

200

} $aTPL->assign( array("TITLE" => "MERCHANT_NAME" => ) ); "Zarzadzanie katalogiem produktw", GetMerchantName( $aDB, $aMerchantID )

$aTPL->parse( "PAGE_BODY", "page_body" ); $aTPL->parse( "FOOTER", "footer" ); $aTPL->parse( "BODY", "body" ); $aTPL->parse( "PAGE", "base" ); $aTPL->FastPrint( "PAGE" ); ?>

Pliki szablonw uzyte do wygenerowania tej strony sa bardzo podobne do tych, ktre byly uzywane w skrypcie zarzadzajacym kategoriami, zamieszczonym na poprzednim wydruku. W skrypcie pokazanym na poprzednim wydruku, do generowania adresw URL dla poszczeglnych nazw kategorii, zostala wykorzystana funkcja GetCategoryHREF(). Funkcja ta wchodzi w sklad pliku mgmt_funcs.php i jest przedstawiona na wydruku 15.14. Funkcja ta pozwala na wygenerowanie przez ten skrypt serii statycznych stron na podstawie dynamicznych danych. Metoda ta zostanie opisane szczeglowo w nastepnym rozdziale. Wydruk 15.14. Funkcja GetCategoryHREF()
function GetCategoryHREF( $aCatID, $aDynamic = True ) { if ( $aDynamic == True ) { return "mgmt_prod_list.phtml?cat_id=$aCatID"; } else { return "mgmt_cat_{$aCatID}.html"; } }

Na wydruku 15.15. zamieszczony zostal skrypt wyswietlajacy produkty. Jest on uzywany do wyswietlania listy podzielonej na kategorie, listy alfabetycznej oraz wynikw wyszukiwania. Wydruk 15.15. Przyklad skryptu wyswietlajacego produkty
<?php error_reporting( E_ALL & ~E_NOTICE ); session_start(); // niejawne ustawianie zmiennej sesji $aMerchantID if ( empty( $aMerchantID ) == True ) { print( "Blad wewnetrzny aplikacji. Brak identyfikatora sprzedawcy." ); exit; } include_once( "class.FastTemplate.php" ); include_once( "mgmt_db.php" ); include_once( "mgmt_funcs.php" ); $aMerchantID = 1; if ( $REQUEST_METHOD == 'POST' ) // Tutaj wchodzimy po wyslaniu danych z formularza { $aSQL = "select a.category_id, a.product_id, a.name, a.external_id, a.price, "; $aSQL .= "a.ship_weight, a.has_image_file, a.descr, b.name as cat_name from "; $aSQL .= "mcProducts a, mcCategories b where ( a.merchant_id = $aMerchantID) "; $aSQL .= "and ( a.category_id = b.category_id ) and ( ( upper( a.name ) like "; $aSQL .= "upper( '%{$SearchTerms}%' ) ) or ( upper( a.descr ) like "; $aSQL .= "upper( '%{$SearchTerms}%' ) ) ) order by a.name"; } else { if ( empty( $cat_id ) == False ) // lista wedlug kategorii { $aSQL = "select a.category_id, a.product_id, a.name, a.external_id, "; $aSQL .= "a.price, a.ship_weight, a.has_image_file, a.descr, b.name as "; $aSQL .= "cat_name from mcProducts a, mcCategories b where "; $aSQL .= "(a.merchant_id = $aMerchantID) and (a.category_id = b.category_id) "; $aSQL .= "and ( a.category_id = $cat_id ) order by a.name"; } else // lista alfabetyczna { $aSQL = "select a.category_id, a.product_id, a.name, a.external_id, a.price, "; $aSQL .= "a.ship_weight, a.has_image_file, a.descr, b.name as cat_name from "; $aSQL .= "mcProducts a, mcCategories b where (a.merchant_id = $aMerchantID) "; $aSQL .= "and (a.category_id = b.category_id) order by a.name"; } }

201

PHP Kompendium wiedzy

$aTPL = new FastTemplate( "." ); $aDB = new mgmt_db(); $aTPL->define( array( "base" "body" "footer" "page_body" "prod_item" => => => => => "mgmt_app_base.tpl", "mgmt_body.tpl", "mgmt_footer.tpl", "mgmt_prod_main.tpl", "mgmt_prod_item.tpl" ) );

$aDB->query( $aSQL ); if ( $aDB->num_rows() > 0 ) { while ( $aDB->next_record() ) { $aProdName = $aDB->f( "name" ); $aProdEID = $aDB->f( "external_id" ); $aProdPrice = $aDB->f( "price" ); $aProdWeight = $aDB->f( "ship_weight" ); $aHasImage = $aDB->f( "has_image_file" ); $aProdDescr = $aDB->f( "descr" ); $aCatName = $aDB->f( "cat_name" ); $aCatID = $aDB->f( "category_id" ); $aProdID = $aDB->f( "product_id" ); $aImageFile = "images/default.jpg"; if ( $aHasImage == True ) { $aImageFile = "images/{$aMerchID}_{$aCatID}_{$aProdID}.jpg"; } $aTPL->assign( array( "PROD_NAME" "CAT_NAME" "PROD_EID" "PROD_PRICE" "PROD_DESCR" "IMAGE_FILE" ) ); $aTPL->parse( "ITEM_LIST", ".prod_item" } } else { $aTPL->assign( array("ITEM_LIST" => "Nie ma produktw dla wybranego kryterium.")); } $aTPL->assign( array( "TITLE" => "MERCHANT_NAME" => ) ); "Zarzadzanie katalogiem produktw", GetMerchantName( $aDB, $aMerchantID ) => => => => => => ); $aProdName, $aCatName, $aProdEID, number_format( $aProdPrice, 2 ).'zl', $aProdDescr, $aImageFile

$aTPL->parse( "PAGE_BODY", "page_body" ); $aTPL->parse( "FOOTER", "footer" ); $aTPL->parse( "BODY", "body" ); $aTPL->parse( "PAGE", "base" ); $aTPL->FastPrint( "PAGE" ); ?>

Pierwsza operacja podejmowana przez skrypt jest sprawdzenie, jaki zbir danych powinien zostac wybrany. Jezeli jest on uruchomiony poprzez wywolanie POST, oznacza to, ze uzytkownik chcial wyszukiwac dane. W przeciwnym przypadku nalezy wygenerowac liste alfabetyczna, lub tylko dla jednej kategorii. Jezeli ustawiona zostala zmienna $cat_id, potrzebna jest lista dla okreslonej kategorii. W oparciu o te informacje, generowane jest odpowiednie zapytanie SQL. W zaleznosci od wyniku zapytania wynikowa strona zawiera liste produktw albo komunikat, ktry informuje uzytkownika o braku produktw dla wybranej przez niego kryteriw. Dla kazdego rekordu sprawdzany jest znacznik has_image_file. Jezeli jest on ustawiony, generowana i wykorzystywana jest standardowa nazwa pliku, natomiast w przeciwnym wypadku wyswietlany jest domyslny rysunek. Na rysunkach 15.6., 15.7., i 15.8. pokazane sa odpowiednio: lista dla pojedynczej kategorii, lista alfabetyczna oraz lista wynikw wyszukiwania. Szukana fraza bylo pol.

Rozdzial 15 Witryny oparte o baze danych

202

Rysunek 15.6. Lista dla kategori i (katego ria ubrania )

Rysunek 15.7. Alfabetycz na lista produktw

203

PHP Kompendium wiedzy

Rysunek 15.8. Lista wynikw wyszukiwa nia (szukanie pol)

W sekcji tej skupilismy sie na wyswietlaniu danych w witrynie WWW. Zwykle wyswietlanie danych z bazy danych jest duzo latwiejsze od manipulowania danymi, poniewaz wystepuje tu mniej problemw i mniej mozliwosci wystapienia bledu. Nastepne dwa rozdzialy sa zbudowane w oparciu o dane i przyklady tu zaprezentowane.

Podsumowanie
Tworzenie aplikacji WWW korzystajacych z bazy danych wymaga dokladnego projektowania i programowania, ale wynik jest wart zachodu. Po stworzeniu systemu administracyjnego aplikacja moze byc w uaktualniania dowolnym momencie i z dowolnego miejsca swiata, co skutkuje powstaniem dynamicznej witryny WWW, ktra jest bardzo latwa do zarzadzania. Najwazniejszym krokiem jest dokladne zaprojektowanie bazy danych, oraz zlokalizowanie wszystkich regul biznesowych. Jezeli te elementy zostana odpowiednio zaprojektowane i zaprojektowane, konserwacja i utrzymanie aplikacji zostanie niezwykle uproszczone.

Rozdzial 15 Witryny oparte o baze danych

204

Rozdzial 16. Generowanie statycznych stron HTML w oparciu o dynamiczne dane


Wstep
Podstawowym zastosowaniem PHP jest tworzenie stron WWW z dynamicznie zmieniajaca sie zawartoscia. Zawartoscia ta moze byc najprostszy licznik odwiedzin, az do personalizowanych stron korzystajacych z bazy danych. W niektrych jednak przypadkach w pelni dynamiczna zawartosc strony nie jest konieczna lub zbytnio obniza wydajnosc witryny. We wielu przypadkach zawartosc witryn nie jest w pelni dynamiczna. Dla przykladu, katalog produktw z poprzedniego rozdzialu jest dynamiczny jedynie w tym sensie, ze mozna zmieniac produkty, ale kazdy uzytkownik powinien zobaczyc te same produkty i kategorie. W takich sytuacjach bardziej efektywne jest jednokrotne generowanie statycznych stron HTML (po zmianie danych zrdlowych) i ich wyswietlanie w odpowiedzi na zadania uzytkownikw. Na szczescie, przy pomocy PHP mozna z latwoscia wygenerowac takie strony, wiec nie beda potrzebne zadne dodatkowe narzedzia do zamiany dynamicznej witryny na czesciowo dynamiczna.

Koncepcja
Jednym z pomyslw na stworzenie statycznych stron jest wysylanie kodu HTML do pliku zamiast do przegladarki. Mozna to latwo zrealizowac korzystajac ze standardowych funkcji obslugi plikw w PHP. Metoda ta wymaga jednak przepisania kazdej ze stron tak, aby caly kod HTML byl wlaczony w kod PHP. Dla wiekszosci witryn jest to niepraktyczne. Istnieje lepsza metoda, dzialajaca z wszystkimi istniejacymi skryptami i stronami, wymagajaca wprowadzenia jedynie minimalnych zmian. Pomysl ten zostal opisany w czesci Generowanie stron statycznych. Innym sposobem na poprawianie wydajnosci serwera jest buforowanie stron, co powoduje, ze skrypt nie uruchamia sie przy kazdym wywolaniu. Ten sposb opisany jest w czesci pod tytulem Techniki buforowania.

Generowanie stron statycznych


Poniewaz PHP jest niezwykle elastyczny, istnieja co najmniej dwa sposoby generowania statycznych stron z istniejacych skryptw PHP, przy minimalnej ilosci zmian. Pierwszym sposobem jest wykorzystanie funkcji buforujacych, drugim jest wykorzystanie klasy FastTemplate opisanej w poprzednich rozdzialach.

Uzycie buforowania
Jezeli rozmiar witryny nie jest zbyt duzy, mozna zastosowac funkcje PHP pozwalajace kontrolowac mechanizm buforowania do przechwycenia wynikowego kodu HTML i zapisania go do pliku. Skrypt z wydruku 16.1. Jest logicznie identyczny ze skryptem z wydruku7 z rozdzialu 6. Wsplpraca z bazami danych. Skrypt ten generuje kod strony na ktrej mozna wybrac stan USA oraz kraj. Listy te sa pobierane z bazy danych. Jest to dobry kandydat do stworzenia strony statycznej, poniewaz lista stanw USA oraz krajw nie zmienia sie czesto. Jezeli trzeba poprawic wydajnosc aplikacji, mozna zrezygnowac z pobierania tych elementw z bazy danych za kazdym razem, gdy uzytkownik zazada tej strony. Dzialanie takie ma jednak sens jedynie wtedy, gdy po zmianie wartosci w bazie danych trzeba powtrnie wygenerowac strone.

Wydruk 16.1. Wykorzystanie buforowania do tworzenia statycznych stron HTML z PHP


<?php ob_start(); include ( "db_mysql.php" ); class MySQLDBTest extends DB_Sql

{ var var var var $Host $Database $User $Password = = = = "localhost"; "mydb"; "root"; "root";

} function GetGenOpts( $aTableName, $aCurSel = "" ) { $aResult = ""; $aDB = new MySQLDBTest; $aSQL = "select ID, Name from $aTableName order by Name"; $aDB->query( $aSQL ); while( $aDB->next_record() ) { $aName = $aDB->f( "Name" ); $aID = $aDB->f( "ID" ); if ( $aID == $aCurSel ) { $aResult .= "<option value=\"$aID\" selected>$aName</option>"; } else { $aResult .= "<option value=\"$aID\">$aName</option>"; } } return $aResult; } ?> <html> <head> <title>Formularz wyboru krajw i stanw USA</title> </head> <body> <form action="some_place.phtml" method="post"> <table> <tr> <td> Wybierz stan USA: </td> <td> <select name="us_state" size="1"> <?php print( GetGenOpts( "us_states", "ID" ) ); ?> </select> </td> </tr> <tr> <td> Wybierz kraj: </td> <td> <select name="world_country" size="1"> <?php print( GetGenOpts( "world_countries", "ZA" ) ); ?> </select> </td> </tr> </form> </body> </html> <?php $aFileName = ereg_replace( 'phtml', 'html', $PATH_TRANSLATED ); $aFile = fopen( $aFileName, "w" ); fwrite( $aFile, ob_get_contents() ); fclose( $aFile ); ob_end_clean(); print( "Plik <i>$aFileName</i> utworzony<br>" ); ?>

Pierwsza czynnoscia wykonywana przez skrypt jest uaktywnienie buforowania przy pomocy wywolania funkcji ob_start(). Po uaktywnieniu buforowania, dane nie sa przesylane do przegladarki a tylko sa zbierane w wewnetrznym buforze. Na koncu skryptu generowana jest nowa nazwa pliku i zamieniane jest rozszerzenie pliku z phtml na html. Po utworzeniu pliku bufor jest czyszczony, a do przegladarki wysylany jest komunikat informacyjny. Do nowego pliku mozna siegnac za pomoca przegladarki zmieniajac rozszerzenie zadanego pliku z phtml na html.

Rozdzial 16. Generowanie statycznych stron HTML w oparciu o dynamiczne dane

206

Metoda ta dziala swietnie dla wielu typw stron. W praktyce skrypty generujace strony powinny byc umieszczone w obszarze serwera WWW chronionym haslem i jedynie niektrzy uzytkownicy powinni miec do nich dostep. Mozliwe jest rwniez stworzenie stron za pomoca ktrych mozna zarzadzac danymi dynamicznymi i za pomoca takiego interfejsu WWW generowac statyczne strony.

Uzycie FastTemplate
W ostatnim rozdziale tematem przykladw byl katalog produktw. Jest to kolejny przyklad witryny, gdzie aktualne dane strony nie zmieniaja sie zbyt czesto. Kategorie i produkty oferowane przez firme moga zmieniac sie raz w miesiacu lub raz w tygodniu. Katalog jednak moze byc przegladany codziennie i zawsze musi zawierac aktualne dane. Klasa FastTemplate byla uzywana w poprzednim rozdziale do stworzenia witryny katalogu. W tym rozdziale zostana omwione zmiany, jakie nalezy wprowadzic do skryptw tak, aby byla mozliwosc tworzenia stron statycznych. Po pierwsze, musi zostac zdefiniowana struktura katalogu. Dla stron kategorii kazda ze stron jest nazywana korzystajac z szablonu mgmt_cat_{$aCatID}.html. Na wydruku 16.2 znajduje sie skrypt, ktry tworzy liste kategorii produktw dla wszystkich kategorii. Jest on podobny do skryptu z wydruku 16.15. z rozdzialu 15. Witryny oparte o baze danych. W tym przypadku tworzy on liste wszystkich kategorii i zapisuje kolejne strony do osobnych plikw, wedlug wspomnianego szablonu nazw. Wydruk 16.2. Wykorzystanie klasy FastTemplate do tworzenia statycznych stron HTML z PHP
<?php error_reporting( E_ALL & ~E_NOTICE ); session_start(); // Niejawnie ustawia zmienna sesji $aMerchantID if ( empty( $aMerchantID ) == True ) { print( "Blad wewnetrzny. Brak identyfikatora sprzedawcy." ); exit; } include( "class.FastTemplate.php" ); include( "./mgmt_db.php" ); include( "./mgmt_funcs.php" ); FastTemplate( "." ); mgmt_db(); mgmt_db(); array( "base" => "mgmt_app_base.tpl", "body" => "mgmt_body.tpl", "footer" => "mgmt_footer.tpl", "page_body" => "mgmt_prod_main.tpl", "prod_item" => "mgmt_prod_item.tpl" ) ); $aSQL = "select category_id from mcCategories"; $aCatDB->query( $aSQL ); while( $aCatDB->next_record() ) { $cat_id = $aCatDB->f( "category_id" ); //print( "$cat_id<br>" ); $aSQL = "select a.category_id, a.product_id, a.name, a.external_id, "; $aSQL .= "a.price, a.ship_weight, a.has_image_file, a.descr, b.name as "; $aSQL .= "cat_name from mcProducts a, mcCategories b where "; $aSQL .= "(a.merchant_id = $aMerchantID) and (a.category_id = b.category_id)"; $aSQL .= "and ( a.category_id = $cat_id ) order by a.name"; $aDB->query( $aSQL ); if ( $aDB->num_rows() > 0 ) { while ( $aDB->next_record() ) { $aProdName = $aDB->f( "name" ); $aProdEID = $aDB->f( "external_id" ); $aProdPrice = $aDB->f( "price" ); $aProdWeight = $aDB->f( "ship_weight" ); $aHasImage = $aDB->f( "has_image_file" ); $aProdDescr = $aDB->f( "descr" ); $aCatName = $aDB->f( "cat_name" ); $aCatID = $aDB->f( "category_id" ); $aProdID = $aDB->f( "product_id" ); $aImageFile = "images/default.jpg"; if ( $aHasImage == True ) { $aImageFile = "images/{$aMerchID}_{$aCatID}_{$aProdID}.jpg"; } $aTPL->assign( array( "PROD_NAME" "CAT_NAME" "PROD_EID" "PROD_PRICE" "PROD_DESCR" "IMAGE_FILE" => => => => => => $aProdName, $aCatName, $aProdEID, '$' . number_format( $aProdPrice, 2 ), $aProdDescr, $aImageFile $aTPL = new $aDB = new $aCatDB = new $aTPL->define(

207

PHP Kompendium wiedzy

) ); $aTPL->parse( "ITEM_LIST", ".prod_item" ); } } else { $aTPL->assign( array( }

"ITEM_LIST" =>

"Brak produktw dla kategorii <i>$aCatName</i>." ) );

$aTPL->assign( array( "TITLE" => "Zarzadzanie katalogiem towarw: Kategoria $aCatName", "MERCHANT_NAME" => GetMerchantName( $aDB, $aMerchantID ) ) ); $aTPL->parse( "PAGE_BODY", "page_body" ); $aTPL->parse( "FOOTER", "footer" ); $aTPL->parse( "BODY", "body" ); $aTPL->parse( "PAGE", "base" ); $aFileName = "mgmt_cat_{$aCatID}.html"; $aFile = fopen( $aFileName, "w" ); fwrite( $aFile, $aTPL->fetch( "PAGE" ) ); fclose( $aFile ); print("Kategoria, <i>$aCatName</i>, zapisana do pliku: <b>$aFileName</b><br>"); $aTPL->Clear(); } ?>

W skrypcie tym zakladamy, ze w zmiennej sesji przekazany zostal identyfikator sprzedawcy. Podczas wykonywania swoich zadan klasa FastTemplate zapisuje cala zawartosc strony w wewnetrznych buforach. Aby zapisac te dane w dowolnej zmiennej mozna skorzystac z metody fetch(). W poprzednim przykladzie metoda fetch() jest wykorzystywana do pobrania wartosci zmiennej FastTemplate PAGE, ktra reprezentuje cala strone HTML. Wartosc ta jest zapisywana do pliku wyjsciowego, a do przegladarki wysylany jest komunikat potwierdzajacy prawidlowe wykonanie operacji. Metoda Clear() powoduje skasowanie wszystkich buforw i zmiennych FastTemplate, co umozliwia wykonanie nastepnego przebiegu petli. W poprzednim rozdziale przytoczona zostala specyficzna funkcja, GetCategoryHREF(), ktra byla uzywana w aplikacji zarzadzajacej katalogiem. Jest ona zamieszczona ponownie na wydruku 16.3. Jest ona uzywana do tworzenia lacza do strony zadanej kategorii. W trybie domyslnym zwraca ona adres strony dynamicznej, ale gdy znacznik $aDynamic zostanie ustawiony na False, zwrci adres strony statycznej. Wydruk 16.3. Funkcja GetCategoryHREF()
function GetCategoryHREF( $aCatID, $aDynamic = True ) { if ( $aDynamic == True ) { return "mgmt_prod_list.phtml?cat_id=$aCatID"; } else { return "mgmt_cat_{$aCatID}.html"; } }

Stosujac ta metode, w trakcie edycji danych mozna przegladac strony dynamiczne a pzniej generowac zbir stron statycznych. Dla wielu typw witryn generowanie statycznych stron z danych dynamicznych jest stosunkowo praktyczne i powoduje wzrost wydajnosci serwera. Jezeli dane wykorzystywane w aplikacji nie zmieniaja sie zbyt czesto, powinno sie rozwazyc generowanie statycznych stron. W przypadku mocno obciazonych witryn wzrost wydajnosci moze z latwoscia przewazyc dodatkowe komplikacje zwiazane z tworzeniem skryptw generujacych strony. Do generowania stron w regularnych odstepach czasu mozna wykorzystac odpowiednie oprogramowanie systemowe, na przyklad cron.

Techniki buforowania
Generowanie stron statycznych jest efektywne w przypadku wielu rodzajw witryn, ale aby bylo efektywne, wymaga dokladnego projektowania i programowania. W przypadku wielu aplikacji wystarczajaca powinna byc posrednia technika buforowania stron. Koncepcyjnie buforowanie jest bardzo podobne do generowania stron statycznych i nadal wymaga ingerencji w tekst kazdego ze skryptw. Gdy uzytkownik wysyla zadanie pobrania skryptu, na poczatku sprawdzane jest czy istnieje aktualna strona w buforze. Jezeli tak, zawartosc tej strony jest wysylana do przegladarki. Jezeli nie ma tej strony, jest ona generowana, umieszczana w buforze do wykorzystania przez kolejne wywolanie. To czy strona jest aktualna, zalezy od typu strony. Na przyklad w witrynie moze istniec strona powitalna z biezaca data. Jezeli na tej stronie nie ma wiecej elementw dynamicznych, musi byc ona generowana raz w ciagu dnia i jest aktualna przez 24 godziny. Inna strona moze byc strona z wiadomosciami uaktualnianymi co godzine. W tym przypadku strona jest aktualna przez godzine.

Rozdzial 16. Generowanie statycznych stron HTML w oparciu o dynamiczne dane

208

Implementacja stron buforowanych jest bardzo prosta. Mozna do tego celu wykorzystac buforowanie wyjscia lub szablony. Na wydrukach 4. i 5. zamieszczony jest przyklad z zastosowaniem buforowania wyjscia. Na wydruku 16.4. znajduja sie funkcje realizujace buforowanie, wiec moga zostac latwo dolaczone do kazdej strony. Wydruk 16.5. zawiera glwna strone, ktra wyswietla biezace dane o pogodzie wykorzystujac skrypt o nazwie MWeather. Skrypt ten jest dostepny na stronie http://sourceforge.net/prjects/mweather/. Wydruk 16.4. Funkcje buforujace (cache.php)
<?php function GetCacheFileName( $aFileName ) { return $aFileName . ".cache"; } function DumpCacheFile( $aFileName, $aExpire = 3600 ) { $aCacheFile = GetCacheFileName( $aFileName ); if ( is_file( $aCacheFile ) == True ) { $aModTime = filemtime( $aCacheFile ); $aCurTime = time(); if ( ( $aCurTime - $aModTime ) > $aExpire ) { return False; } else { readfile( $aCacheFile ); return True; } } } function SaveCacheFile( $aFileName, $aContents ) { $aCacheFile = GetCacheFileName( $aFileName ); $aFile = fopen( $aCacheFile, "w" ); fwrite( $aFile, $aContents ); fclose( $aFile ); } ?>

Wydruk 16.5. Wykorzystanie funkcji buforujacych


<?php error_reporting( E_ALL & ~E_NOTICE ); include( "./cache.php" ); if ( $aResult = DumpCacheFile( $PATH_TRANSLATED, 60 * 60 ) ) { // aktualny plik w buforze, koniec skryptu exit; } ob_start(); // dane strony $aOldIncludePath = ini_get( 'include_path' ); ini_set( 'include_path', $aOldIncludePath . ":./mweather" ); include( "mweather.php" ); ini_restore( 'include_path' ); SaveCacheFile( $PATH_TRANSLATED, ob_get_contents() ); ?>

Skrypt z wydruku 16.5. korzysta z funkcji buforujacych umieszczonych na wydruku 16.4. w celu zrealizowania cogodzinnego buforowania strony z prognoza pogody. Funkcja DumpCacheFile() realizuje kilka waznych operacji. Po pierwsze, sprawdzana jest data ostatniej modyfikacji pliku w buforze i jest ona porwnywana z biezaca data. Jezeli rznica pomiedzy tymi datami jest wieksza od wartosci expire, funkcja zwraca False. Jezeli tak nie jest, funkcja odczytuje plik z bufora, wyswietla go i zwraca wartosc True. Po powrocie do skryptu sprawdzana jest zwracana wartosc. Jezeli jest ona True, glwny skrypt sie konczy, poniewaz plik z bufora jest aktualny i zostal on juz wyslany do przegladarki. Jezeli wartosc ta wynosi False, skrypt jest wykonywany i za pomoca funkcji buforowania wydruku jego wynik jest zapamietywany. Na koncu skryptu wywolywana jest funkcja SaveCacheFile(), ktra zapisuje zawartosc strony. W przykladzie tym strona jest generowana przez dolaczany skrypt mweather.php. Jedynym zadaniem glwnego skryptu jest modyfikacja zmiennej PHP include_path. Jest to wymagane przez skrypt MWeather i nie ma nic wsplnego z buforowaniem. 209 PHP Kompendium wiedzy

Plik cache.php moze byc uzywany z dowolnym skryptem PHP, w ktrym nalezy zrealizowac funkcje buforowania na zadanie. Bardzo wazne jest jednak, aby zdawac sobie sprawe, jakie skrypty moga dzialac z tym typem buforowania. Metoda ta sprawdza sie jedynie dla stron, ktre nie sa wynikiem zadan HTTP GET lub POST. Inaczej mwiac, buforowanie jest niepraktyczne w przypadku stron zaleznych od wartosci wprowadzonych przez uzytkownika. Poprzedni przyklad pokazuje pogode w Rexburg w stanie Idaho, niezaleznie kto oglada strone. Jezeli skrypt wyswietlalby pogode w miejscu okreslonym przez uzytkownika, buforowanie nie moze byc juz zastosowane. Wyobrazmy sobie, ze strona zostala by umieszczona w buforze przez uzytkownika z Londynu, a kolejne wywolanie pochodzilo by z Cape Town. Otrzymana strona byla by oczywiscie nieprawidlowa dla uzytkownika z Cape Town. Przedstawiony typ buforowania jest uzyteczny, ale nie moze byc uzywany dla wszystkich przypadkw. Jezeli aplikacja zawiera strony z informacjami zmieniajacymi sie co okreslony odcinek czasu i niezalezne od danych uzytkownika, ten typ buforowania jest bardzo uzyteczny i wyraznie poprawia wydajnosc witryny. W przedstawionym przykladzie do pobrania danych o aktualnej pogodzie potrzebny jest czas okolo dwch sekund. Po zbuforowaniu, strona pojawia sie natychmiast.

Podsumowanie
Mimo, ze PHP jest najczesciej uzywany do dynamicznego tworzenia stron WWW, wazne jest, aby odnalezc sytuacje, gdy nie sa potrzebne w pelni dynamiczne strony. Generujac statyczne strony lub buforujac je, mozna wyraznie poprawic wydajnosc witryny. Projektanci witryny powinni w ten sposb zrwnowazyc szybkosc ladowania sie statycznych stron z elastycznoscia stron dynamicznych, aby aplikacja miala dostateczna szybkosc i byla uzyteczna dla uzytkownikw.

Rozdzial 16. Generowanie statycznych stron HTML w oparciu o dynamiczne dane

210

Rozdzial 17. Witryny handlu elektronicznego


Wstep
Handel elektroniczny jest dla wiekszosci firm najwazniejszym zadaniem, jakie ma spelniac firmowa witryna WWW. Z tego powodu niezmiernie wazne jest poznanie sposobu zrealizowania za pomoca PHP wszystkich aspektw tworzenia aplikacji handlu elektronicznego. Duza czesc tego rozdzialu jest poswiecona koncepcjom i zalozeniom projektowania tego typu aplikacji. Samo programowanie i korzystanie z istniejacych narzedzi przeznaczonych dla e-handlu jest trywialne. Prawdziwym wyzwaniem jest stworzenie bezpiecznej, stabilnej i skalowalnej aplikacji handlu elektronicznego.

Bezpieczenstwo
Pierwszorzedna kwestia przy tworzeniu aplikacji przeznaczonych do handlu elektronicznego jest zagadnienie bezpieczenstwa. Juz w czasie projektowania aplikacji nalezy miec na uwadze ochrone danych o klientach. Nalezy wykonac kilka krokw w celu zapewnienia mozliwie najwyzszego poziomu bezpieczenstwa. Nie nalezy tego traktowac jako propozycji, sa to zazwyczaj wymagania wiekszosci centrw rozliczajacych karty kredytowe.

Zastosowanie SSL
Pierwszym krokiem powinno byc wyodrebnienie fragmentw witryny, ktre wymagaja zastosowania bezpiecznego polaczenia za pomoca mechanizmu secure socket layer (SSL). Wiekszosc aplikacji posiada dwa obszary dzialania. Pierwszy jest obszarem zawierajacym opisy dostepnych produktw i uslug oferowanych na witrynie. W czesci tej zawieraja sie zwykle strony zawierajace dane o firmie, regulaminy i inne dane nie zwiazane bezposrednio z handlem. Drugi fragment zawiera aplikacje handlowa. W czesci tej zbierane sa prywatne dane, takie jak dane niezbedne do identyfikacji klienta lub numery kart kredytowych. Wiekszosc tego rozdzialu jest poswiecona temu wlasnie fragmentowi witryny. Uzycie PHP z SSL nie rzni sie niczym do uzywania PHP na serwerze nie obslugujacym SSL. Istnieje kilka dostepnych bezpiecznych serwerw WWW. Jednym z nich jest Stronghold (http://www.c2.net/products/sh3/). W dystrybucji RedHat (http://www.redhat.com/) istnieje rwniez serwer zawierajacy OpenSSL. Mozna go uzyc do skompilowania bezpiecznego serwera Apache. Po zainstalowaniu bezpiecznego serwera WWW opartego o Apache, mozna uzyc jednej z metod opisanych w rozdziale 1. Kompilacja i instalowanie PHP w celu dodania PHP w postaci wspldzielonego modulu. Mozna rwniez przekompilowac bezpieczny serwer Apache ze statycznie dolaczonym modulem PHP.

Certyfikaty
Kolejnym krokiem wymaganym do stworzenia bezpiecznej aplikacji jest zainstalowanie certyfikatu bezpieczenstwa. Certyfikat to plik na serwerze, ktry jest przesylany do przegladarki razem ze stronami WWW. Certyfikaty sa wystawiane przez kilka firm, ktre sa rozpoznawane przez wiekszosc nowoczesnych przegladarek jako bezpieczne. Jedna z takich firm jest Thawte Consulting (http://www.thawte.com/). Witryna firmy Thawte

zawiera wszystkie dane niezbedne do wyprbowania i wykupienia certyfikatu bezpieczenstwa. Aby otrzymac certyfikat nalezy dostarczyc kilka dokumentw: 1. Dokument potwierdzajacy istnienie firmy, na przyklad akt zalozycielski splki. 2. Dokument potwierdzajacy prawo do nazwy domeny. Jezeli nazwa widniejaca na dokumentach przedstawionych w punkcie 1. zgadza sie z danymi uzyskanymi przez zapytanie whois do domeny dla ktrej instalowany jest certyfikat, nie trzeba dostarczac dokumentw wymienionych w punkcie 2. Z witryny firmy Thawte mozna pobrac i zainstalowac certyfikat testowy. Jezeli wykorzystujemy taki certyfikat przegladarka generuje ostrzezenia, ale mozna przetestowac aplikacje bez koniecznosci kupienia certyfikatu. Jezeli uzywanym serwerem jest Apache, aby zaczal on korzystac z certyfikatu nalezy zainstalowac certyfikat i zmodyfikowac plik httpd.conf. Na wydruku 17.1. pokazana jest przykladowa konfiguracja wirtualnego systemu hostingowego. Wydruk 17.1. Plik httpd.conf z dyrektywami dotyczacymi certyfikatw
SSLCertificateFile /apache/conf/ssl.crt/server.crt SSLCertificateKeyFile /apache/conf/ssl.key/server.key NameVirtualHost 19.129.1.1:443 <VirtualHost 129.129.1.1:443> SSLEnable ServerAdmin webmaster@server.com DocumentRoot /home/server/secure ServerName secure.server.com DirectoryIndex index.phtml index.html </VirtualHost>

Na witrynie firmy Thawte dostepne sa wszystkie informacje potrzebne do wygenerowania i zainstalowania certyfikatu. Jezeli potrzebne jest wiecej informacji na temat instalowania certyfikatu w konkretnym serwerze WWW, nalezy ich szukac w dokumentacji serwera. Jezeli korzystasz z dystrybucji RedHat, to informacje te sa bardzo jasno napisane i latwe do odszukania.

Bezpieczenstwo bazy danych


Jednym z odkryc jakie zawdzieczamy ostatnio internetowym zlodziejom numerw kart kredytowych jest to, ze we wielu przypadkach witryny przechowuja dane w niezaszyfrowanej bazie danych dostepnej bezposrednio z Internetu. Nawet witryny uzywajace kodowania SSL do zbierania danych, przechowuja dane prywatne w malo bezpieczny sposb. Ostatnio jednak, niektre umowy pomiedzy sprzedawcami a centrami rozliczeniowymi zawieraja klauzule o przechowywaniu danych w postaci zaszyfrowanej, umieszczeniu bazy danych za firewallem, albo o zastosowaniu obu tych rozwiazan. Zaczyna byc to powszechnie stosowana praktyka. Aplikacja powinna kodowac zarwno transmisje jak rwniez przechowywane dane prywatne. Wiele nowoczesnych systemw baz danych zawiera funkcje szyfrujace dane. Na przyklad SZBD MySQL zawiera funkcje ENCODE() oraz DECODE() jako integralna czesc jezyka. Funkcje te nie sa jednak wystarczajaco dobre do szyfrowania krytycznych danych. Uzycie tych lub podobnych funkcji poprawia jednak poziom ochrony przechowywanych danych. Ostatecznie to ty i twoja firma jestescie odpowiedzialni za dziury w systemie bezpieczenstwa, ktre spowoduja ujawnienie krytycznych danych.

Przetwarzanie platnosci
Po skompilowaniu i przetestowaniu bezpiecznego serwera WWW nalezy wybrac metode obslugi platnosci. PHP zawiera wlasne interfejsy do kilku systemw przetwarzania platnosci, np.: CyberCash, VeriSign i CCVS. Na rysunku 17.1. przedstawiony zostal obieg informacji pomiedzy uzytkownikiem, bezpiecznym serwerem WWW i narzedziami obslugi platnosci.

Rozdzial 17. Witryny handlu elektronicznego

212

Rysunek 17.1. Zaleznosci w aplikacji handlu elektronicznego

Na rysunku 17.1. zostaly pokazane cztery podstawowe jednostki biorace udzial w obsludze platnosci: uzytkownik, serwer, system przetwarzania i instytucja finansowa. Klient i serwer komunikuja sie ze soba za pomoca protokolu SSL, ktry zapewnia dwukierunkowa szyfrowana transmisje. Serwer komunikuje sie z systemem obslugi platnosci za pomoca protokolu narzuconego przez system. Sam system przetwarzania komunikuje sie z instytucja finansowa w celu sprawdzenia czy moze przyjac platnosc za pomoca karty kredytowej (lub innej metody platnosci). Jezeli korzystamy z systemu CCVS mozliwe jest ominiecie systemu przetwarzania i bezposrednia komunikacja z finansowym centrum rozliczeniowym. Jednym z powodw wyboru systemu obslugi platnosci CyberCash jest to, ze protokl komunikacyjny uzywany do przesylania informacji pomiedzy serwerem a systemem obslugi transakcji, jest wbudowany w interfejs programistyczny do CyberCash. Inne systemy transakcji wymagaja uzycia przez aplikacje bezpiecznych gniazd, w celu zrealizowania komunikacji z nimi. Nalezy pamietac, ze mimo uzycia bezpiecznego serwera wykorzystujacego protokl SSL, sam PHP nie posiada implementacji SSL. Inaczej mwiac, jezeli skrypt otworzy port, to nie zostanie automatycznie uzyty protokl SSL, pomimo ze serwer WWW uzywa SSL. Dopki PHP nie bedzie posiadal bezposredniej obslugi gniazd SSL, wykorzystanie niektrych mozliwosci systemw transakcyjnych nie bedzie mozliwe. CyberCash uzywa do zapewnienia bezpiecznej transmisji pomiedzy serwerem WWW a centrum przetwarzania, wlasnego algorytmu Triple DES (potrjny DES). W pozostalej czesci rozdzialu bedziemy wykorzystywac CyberCash jako system przetwarzania platnosci. CyberCash (http://www.cybercash.com/) jest firma oferujaca interfejsy programistyczne (API) dla C i C++ oraz Javy. Wersja API dla C i C++ moze zostac wbudowana w PHP za pomoca opcji konfiguracji --withcybercash. Najpierw nalezy sciagnac z witryny CyberCash pakiet Merchant Connection Kit (MCK). Oprcz tego nalezy upewnic sie, ze twoje konto sprzedawcy moze byc uzywane w systemie CyberCash. Jezeli nie masz jeszcze konta sprzedawcy, nalezy je zarejestrowac u jednego z partnerw firmy CyberCash. Proces ten wymaga podania wielu szczeglowych informacji finansowych, ale moze byc przeprowadzony w ciagu 24 godzin. Glwne kroki wymagane do zainstalowania MCK sa nastepujace: 1. Nawiazanie wsplpracy z przedstawicielem finansowym firmy CyberCash (konto sprzedawcy). 2. Zarejestrowanie sie na witrynie http://amps.cybercash.com/ jako sprzedawca CyberCash. 3. Sciagniecie MCK. 4. Dekompresja i zainstalowanie MCK. 5. Kompilacja PHP z obsluga CyberCash (--with-cybercash). Na witrynie WWW firmy CyberCash znajduje sie dokladny opis instalacji MCK. Pakiet ten moze byc zainstalowany na systemach Unix lub pod Windows. Procedura instalacji dla systemw Unix jest bardzo prosta. Podstawowe kroki sa nastepujace: 1. Dekompresja instalatora: uncompress install-mck-3.2.0.6-<system_operacyjny>.Z. 213 PHP Kompendium wiedzy

2. Zmiana uprawnien do pliku instalatora w taki sposb, aby mozna bylo go uruchomic: chmod +x installmck-3.2.0.6-<system_operacyjny>. 3. Uruchomienie programu instalacyjnego: ./install-mck-3.2.0.6-<system_operacyjny>. 4. Uruchomienie programu konfiguracyjnego: ./configure. W punktach 3. i 4. zostana zadane pytania na temat firmy, sklepu sieciowego i innych informacji tego typu. Po wykonaniu tych krokw mozna przekompilowac PHP podajac opcje konfiguracji --withcybercash=/sciezka/do/MCK. Nalezy podac pelna sciezke do katalogu gdzie zostal zainstalowany MCK. Po utworzeniu PHP z obsluga CyberCash mozna przeprowadzic testowe transakcje. Jedna z milych cech uzycie MCK wraz z PHP jest mozliwosc opuszczenia wiekszosci opcji konfiguracji (jak sugeruje to podrecznik). Uzycie PHP do komunikacji z CyberCash jest bardzo proste i wymaga jedynie dolaczenia jednego skryptu. Skrypt pokazujacy sposb uzycia CyberCash znajduje sie w dystrybucji PHP zawierajacej pelny kod zrdlowy w katalogu <php>/ext/cybercash. Na wydruku 17.2. zamieszczony jest ten wlasnie skrypt testowy. Wydruk 17.2. Test.php (skrypt testowy CyberCash)
<?php require "cyberlib.php"; $merchant=""; /* Tutaj nalezy umiescic idnetyfikator sprzedawcy. */ $merchant_key=""; /* Tutaj nalezy umiescic klucz sprzedawcy. */ $payment_url="http://cr.cybercash.com/cgi-bin/"; $auth_type="mauthonly"; $response=SendCC2_1Server($merchant,$merchant_key,$payment_url, $auth_type,array("Order-ID" => "2342322", "Amount" => "usd 11.50", "Card-Number" => "4111111111111111", "Card-Address" => "1600 Pennsylvania Avenue", "Card-City" => "Washington", "Card-State" => "DC", "Card-Zip" => "20500", "Card-Country" => "USA", "Card-Exp" => "12/99", "Card-Name" => "Bill Clinton")); while(list($key,$val)=each($response)) { echo $key."=".$val."<br>"; } ?>

Jak widac przetwarzanie platnosci przy pomocy PHP i CyberCash jest bardzo proste. Zmienne $merchant oraz $merchant_key musza zawierac identyfikator sprzedawcy oraz jego klucz nadany przez CyberCash. Nastepnie po ustawieniu w tablicy asocjacyjnej danych wymaganych przez CyberCash platnosc jest przekazywana do obslugi przy pomocy wywolania funkcji SendCC2_1Server() zdefiniowanej w dolaczonym pliku cyberlib.php. Nie potrzeba nawet wywolywac zadnej z funkcji cybercash_xxx() dostepnych w PHP. Funkcja SendCC2_1Server() hermetyzuje w sobie wszystkie niezbedne funkcje, jak rwniez obsluguje komunikacje za pomoca gniazd z serwerem CyberCash. Dane niezbedne do dzialania z Cyberash sa przekazywane za pomoca tablicy asocjacyjnej bedacej ostatnim parametrem funkcji SendCC2_1Server(). Zawartosc tej tablicy jest okreslana przez wartosc zmiennej $auth_type. Zmienna ta okresla rodzaj wykonywanej operacji lub typ komunikatu przesylanego do CyberCash. Komunikaty obslugiwane przez CyberCash zawarte sa w tablicy 17.1. Tabela 17.1. Komunikaty dostepne w CyberCash oraz zadania przez nie realizowane Komunikat Realizowane zadanie batch-commit Potwierdza transakcje zebrane w grupe. batch-prep Powoduje wyslanie transakcji oznaczonych jako gotowe do przetworzenia w postaci grupy. batch-query Pytanie o grupe. batch-retry Ponawia prbe przetworzenia oczekujacej grupy. batch-unroll Zapytanie o transakcje wyslana w postaci grupy. card-query Odczytuje dane karty kredytowej dla podanego zamwienia. checkauth Sprawdza i autoryzuje platnosc czekiem Rozdzial 17. Witryny handlu elektronicznego 214

checkreturn mauthcapture

mauthonly

postauth query retry return void merchant-checkpayment check-query check-update-status check-query-orderstatus

zainicjowana przez sprzedawce. Komunikat ten jest obslugiwany jedynie przez procesor Paymentech (wykorzystujac opcje Electronic Check Payment ECP). Zwraca pieniadze na konto czekowe klienta. Autoryzuje i przechwytuje rozpoczeta przez sprzedawce transakcje za pomoca karty kredytowej. Jest uzywany jedynie dla glwnych procesorw przechwytujacych. Autoryzuje rozpoczeta przez sprzedawce sprzedaz za pomoca karty kredytowej. Jest uzywany dla koncowych procesorw przechwytujacych. Przechwytuje platnosc karta kredytowa autoryzowana za pomoca mauthonly lub checkauth. Odpytuje baze transakcji. Ponawia oczekujaca transakcje dla podanego zamwienia. Zwraca pieniadze na karte kredytowa klienta. Uniewaznia transakcje. Sprawdza i autoryzuje zainicjowana przez sprzedawce platnosc w systemie PayNow. Odszukuje w bazie danych PayNow danych na temat okreslonych rachunkw. Uaktualnia serwer rachunkw za pomoca zmian przeprowadzonych w bramce. Sprawdza biezacy status zamwien.

Dokumentacja CyberCash zawiera dokladny opis kazdego z komunikatw oraz jego przeznaczenia. W wiekszosci przypadkw pierwszym obslugiwanym komunikatem (i czesto jedynym) jest komunikat mauthonly. Jest on uzywany do autoryzacji platnosci dokonywanej karta kredytowa. W zaleznosci od rodzaju sprzedawanego produktu lub uslugi, mozna tak skonfigurowac CyberCash, aby automatycznie zaznaczal i realizowal wszystkie poprawnie autoryzowane transakcje. W tabeli 17.2. zebrane sa wszystkie pola uzywane do obslugi komunikatu mauthonly. W tabeli zaznaczone sa wszystkie pola, ktre nalezy obowiazkowo umiescic w komunikacie. Tabela 17.2. Pola komunikatu mauthonly i ich opis Pole Opis Wy magane order Unikalny identyfikator transakcji.
id amount

cardnumber cardexp

Kwota do autoryzacji (to znaczy kwota platnosci) w tej transakcji. Nalezy uzywac notacji waluta zlote.grosze (na przyklad: usd 12.50). Numer karty kredytowej obciazanej ta transakcja. Data waznosci karty kredytowej obciazanej ta transakcja. Nalezy uzyc formatu mm/rr (na przyklad: 02/01 dla lutego 2001). Nazwa wlasciciela karty kredytowej. Adres zamieszkania wlasciciela karty kredytowej. UWAGA: pole jest wymagane w przypadku kart AVS i Discover. Miejscowosc w ktrej mieszka wlasciciel karty. UWAGA: pole jest wymagane w przypadku kart AVS i Discover.

cardname cardaddress

cardcity

215

PHP Kompendium wiedzy

cardzip

cardstate cardcountry

Kod pocztowy miejscowosci, w ktrej mieszka wlasciciel karty. Prawidlowymi zapisami sa 22091, 201911448,, NW3 5RJ i 113 192. UWAGA: pole jest wymagane w przypadku kart AVS i Discover. Stan w ktrym mieszka wlasciciel karty. UWAGA: pole jest wymagane w przypadku kart AVS i Discover. Kraj w ktrym mieszka wlasciciel karty.

Funkcja SendCC2_1Server() zwraca wartosci rwniez w postaci tablicy asocjacyjnej, ktra zawiera dane na temat transakcji przeslane przez CyberCash. W tabeli 17.3. znajduja sie pola znajdujace sie w odpowiedzi na komunikat mauthonly. Tabela 17.3. Pola odpowiedzi na komunikat mauthonly i ich opis Pole Opis MStatus Zwracany kod statusu wykonanej operacji Pole to zawsze istnieje. Moze przyjmowac jedna z nastepujacych wartosci: success transakcja udana. success-duplicate wynik poprzedniej udanej transakcji. partial success grupa zawiera nieudane transakcje. failure-hard nieudana transakcja, jej powtrzenie nie uda sie. failure-q-or-cancel, failure-q-or-discard nieudane transakcje z powodu problemw z transmisja, moga byc powtrzone. failure-swversion transakcja nieudana z powodu uzycia starego lub nieistniejacego (nieistniejacy numer wersji) oprogramowania. failure-bad-money transakcja nieudana z powodu problemu z obciazeniem przez instytucje finansowa. MErrLoc Miejsce wystapienia bledu w transakcji. Pole to pojawia sie jedynie w przypadku nieudanej transakcji (czyli MStatus jest rzny od success). Zwracane sa nastepujace wartosci: smps wystapil blad w CashRegister. ccsp wystapil blad w bramce. financial institution blad wystapil w instytucji finansowej CCMckDirectLib3_2 blad wystapil w MCK MErrMsg Tekst komunikatu bledu zwracanego przez transakcje. Pole to wystepuje jedynie w przypadku nieudanej transakcji. MErrCod Numer bledu odpowiadajacy komunikat bledu przekazanego w e MErrMsg. merchNumer uzywany przez bramke do identyfikacji przeprowadzanej txn transakcji. Pole to wystepuje zawsze. orderIdentyfikator zamwienia do ktrego nalezy przetwarzana transakcja. id Pole to wystepuje zawsze. custNumer transakcji uzywany przez portfel CyberCash do identyfikacji txn transakcji. Dla transakcji nie posiadajacych portfela jest on taki sam jak merch-txn. aux-msg Komunikat bramki sprzedawcy zawierajacy dodatkowy opis z bramki lub serwera platnosci. MSWErrM Komunikat bledu przy uzyciu nieaktualnej wersji portfela lub serwera sg platnosci. Pole to nie zawsze wystepuje. addnlDodatkowe dane transakcji zwracane przez bramke. UWAGA: Jezeli response-data brak jest takich danych pole to jest puste. Na wydruku 17.3. znajduje sie przyklad uzycia CyberCash, pochodzacy z dzialajacej witryny. Przyklad ten zawiera obsluge bledw oraz wysyla informacje zwrotne do klienta. Elementy te nie byly zawarte w przykladowym skrypcie z wydruku 17.2. Rozdzial 17. Witryny handlu elektronicznego 216

Wydruk 17.3. Uzycie CyberCash


<?php include "cyberlib.php"; // Funkcje obslugi CyberCash include "dbclass.php"; // Klasa bazy danych dla tej aplikacji include "class.FastTemplate.php"; // FastTemplate // funkcja zamieniajaca tablice asocjacyjna // w jeden ciag rozdzielany srednikami function ArrayCrunch( $aArray ) { $aResult = ""; foreach( $aArray as $aKey => $aValue ) { $aResult .= "$aKey=$aValue;"; } return $aResult; } $tpl = new FastTemplate( "." ); // pobranie identyfikatora pliku z zaszyfrowanego pola formularza $aCustomerID = UnhideID( $ID ); $merchant $merchant_key $payment_url $auth_type = = = = ""; /* tutaj identyfikator sprzedawcy. */ ""; /* tutaj klucz sprzedawcy. */ "http://cr.cybercash.com/cgi-bin/"; "mauthonly";

$aDB = new dbAccess; $aDB->Init(); // kontrola czy klient ten nie zaplacil wczesniej $aSQL = "select ISPAID from orders where ( ID = $aCustomerID )"; $aDB->SetSQL( $aSQL ); if ( $aDB->RecordCount() == 1 ) { $aRow = $aDB->GetData( 0 ); $aIsPaid = $aRow["ISPAID"]; } else { $aIsPaid = 0; } // Jezeli klient juz zaplacil, pokaz informacje i zakoncz skrypt if ( $aIsPaid == 1 ) { mail( "blake@intechra.net", "Ponowna prba platnosci ($aCustomerID)", "Czy chcesz jeszcze raz zaplacic??", "From: support@intechra.net\r\n" ); $tpl->define( array( base footer body ) ); => "a_base.tpl", => "c_footer.tpl", => "s_paid_already.tpl"

$tpl->assign( array( TITLE URL THEDATE ORDERID HIDDENID ) ); AddSiteVars( $tpl, $aHiddenID ); $tpl->parse( FOOTER, "footer" ); $tpl->parse( BODY, "body" ); $tpl->parse( PAGE, "base" ); $tpl->FastPrint( PAGE ); exit; }

=> => => => =>

"Platnosc Intechra.Net", $aInternalURL, date( "l, j F Y" ), $aOrderID, $ID

// pobierz nowy MCK_ID dla tego klienta $aSQL = "select MAX( MCK_ID ) as MAX_ID from customers_to_mcks where ( ID = $aCustomerID )"; $aDB->SetSQL( $aSQL ); if ( $aDB->RecordCount() == 1 ) { $aRow = $aDB->GetData( 1 );

217

PHP Kompendium wiedzy

$aMaxID } else { $aMaxID } $aCurID $aOrderID

= $aRow["MAX_ID"];

= 0;

= $aMaxID + 1; = "INT-" . date( "Ymd" ) . "-" . sprintf( "%06d", $aFamilyID ) . "-" . sprintf( "%04d", $aCurID ); => => => => => => => => => $aOrderID, "usd 39.00", $CCNum, $CCAddr, $CCCity, $CCState, $CCZip, $CCExpDate, $CCName );

$aOrderDetails = array( "Order-ID" "Amount" "Card-Number" "Card-Address" "Card-City" "Card-State" "Card-Zip" "Card-Exp" "Card-Name"

$response = SendCC2_1Server( $merchant, $merchant_key, $payment_url, $auth_type, $aOrderDetails ); $aRawRequest = ArrayCrunch( $aOrderDetails ); $aRawResponse = ArrayCrunch( $response ); $aSQL = "insert into customers_to_mcks values ( $aCustomerID, $aCurID, 0, NOW(), ENCODE( \"$aRawRequest\", \"good_password\" ), ENCODE( \"$aRawResponse\", \"good_password\" ) )"; $aDB->SetSQL( $aSQL ); if ( $response["MStatus"] == "success" ) { mail( "blake@intechra.net", "Platnosc dla Intechra.net zrealizowana ($aCustomerID)", "Platnosc zakonczona sukcesem", "From: support@intechra.net\r\n" ); $aSQL = "update orders set ISPAID = 1 where ( ID = $aCustomerID )"; $aDB->SetSQL( $aSQL ); $tpl->define( array( base footer body ) ); => "a_base.tpl", => "c_footer.tpl", => "s_paid_ok.tpl"

$tpl->assign( array(

TITLE URL THEDATE ORDERID HIDDENID ) );

=> => => => =>

"Platnosci Intechra.net", $aInternalURL, date( "l, j F Y" ), $aOrderID, $ID

AddSiteVars( $tpl, $aHiddenID ); $tpl->parse( FOOTER, "footer" ); $tpl->parse( BODY, "body" ); $tpl->parse( PAGE, "base" ); $tpl->FastPrint( PAGE ); } else { mail( "blake@intechra.net", "Platnosc dla Intechra.net nieudana ($ ($aCustomerID)", "Platnosc nieudana", "From: support@intechra.net\r\n" ); $tpl->define( array( base footer body ) ); => "a_base.tpl", => "c_footer.tpl", => "s_paid_fail.tpl"

$tpl->assign( array(

TITLE HIDDENID ) );

=> "Platnosci Intechra.net", => $ID

$tpl->parse( FOOTER, "footer" ); $tpl->parse( BODY, "body" ); $tpl->parse( PAGE, "base" ); $tpl->FastPrint( PAGE );

Rozdzial 17. Witryny handlu elektronicznego

218

} ?>

Skrypt z wydruku 17.2. pokazuje w jaki sposb na podstawie skryptu z wydruku 17.1. mozna stworzyc prawdziwy system obslugi platnosci. Skrypt ten jest uzywany do przetwarzania danych formularza, w ktrym uzytkownik podaje dane karty kredytowej. Na poczatku skrypt pobiera identyfikator klienta z pola formularza. Nastepnie inicjuje zmienne CyberCash, w tym ustawiajac typ komunikatu na mauthonly. Nastepnie w bazie danych sprawdzane jest, czy uzytkownik nie zaplacil juz wczesniej. W tej aplikacji kazdy uzytkownik dokonuje jednej platnosci za usluge. Jezeli uzytkownik juz zaplacil skrypt wysyla do administratora poczte zawierajaca komunikat informujacy o tym fakcie, oraz wyswietla strone informujaca uzytkownika, ze dokonal juz wczesniej platnosci. Na tym skrypt sie konczy. Jezeli platnosc nie byla jeszcze dokonana, z bazy danych pobierany jest nowy niepowtarzalny identyfikator. Dokumentacja CyberCash nakazuje, aby identyfikator ten byl co najwyzej 25 znakowy i musi byc unikalny. Mozna uzywac w nim liter, liczb, kropek, daszkw i podkreslen. Skrypt ten generuje identyfikatory w postaci RRRRMMDD-CCCCCC-OOOO, gdzie YYYYMMDD jest biezaca data, CCCCCC to identyfikator klienta a OOOO jest identyfikatorem pobieranym z bazy danych. W tablicy $aOrderDetails umieszczane sa dane platnosci i wywolywana jest funkcja SendCC2_3Server(). Zadanie i odpowiedz sa zapisywane do bazy danych w postaci zaszyfrowanej. Nastepnie sprawdzany jest status odpowiedzi. Jezeli transakcja zakonczyla sie powodzeniem, wyswietlany jest komunikat o prawidlowym przetworzeniu transakcji i uaktualniane sa dane klienta na temat platnosci. Jezeli operacja sie nie powiedzie, klient jest o tym informowany. W kazdym z przypadkw do administratora wysylany jest informujacy e-mail. Przegladajac ten przyklad mozna stwierdzic, ze uzycie API CyberCash w PHP jest proste, ale stworzenie bezpiecznej i stabilnej aplikacji handlu elektronicznego wymaga sporej ilosci przemyslen i planowania. Po systemie obslugujacym prawdziwe pieniadze klienci oczekuja najlepszej jakosci uslug. Jezeli aplikacja pozwoli na przypadkowe wielokrotne platnosci lub nie dostarczy odpowiednich informacji, klienci nie beda zadowoleni. Nalezy poswiecic nieco czasu na przestudiowanie dokumentacji procesora transakcji. Dostepne jest mnstwo informacji i ty jestes odpowiedzialny za ich zrozumienie i wlasciwa implementacje.

Dostarczanie produktw
Innym aspektem aplikacji handlu elektronicznego, ktry wymaga planowania jest kwestia dostarczania towarw do klientw. Jezeli twj towar musi byc wyslany do klienta, wymagane jest kilku dodatkowych krokw oprcz wymienionych poprzednio. Powodem jest to, ze wielu wystawcw kart kredytowych zada, aby karta byla obciazana dopiero po dostarczeniu towaru do klienta. Mozna zadac autoryzacji przed dostarczeniem towaru, ale obciazenie nie bedzie zrealizowane do czasu dostarczenia towaru. Wazne jest rwniez podawanie rzeczywistego kosztu przesylki. Jezeli wysylasz towary, aplikacja przetwarzania platnosci staje sie o wiele bardziej skomplikowana od pokazanej w tym rozdziale. Jednak wiele wymaganych czynnosci moze byc zrealizowane za pomoca PHP. Zalecanym scenariuszem jest stworzenie osobnej aplikacji zapisujacej stan przesylek i po dostarczeniu przesylki konczona jest platnosc karta i do klienta wysylany jest komunikat. Dostepne jest kilka mozliwosci sledzenia na biezaco przesylek i kosztw. Zarwno UPS (http://www.ups.com/) jak i Federal Express (http://www.fedex.com/) dostarczaja narzedzia do integracji modulu przesylek we wlasnej aplikacji WWW. Narzedzia UPS sa bardzo elastyczne i wydajne i latwo moga byc umieszczone w aplikacji PHP korzystajac z niewielkiej ilosci kodu. Niestety nie otrzymalem pozwolenia na dokumentacje zadnego z tych systemw przed zakonczeniem tego rozdzialu. Jezeli otrzymam pozwolenie, umieszcze odpowiednie informacje na witrynie WWW wymienionej w zasobach sieci w dodatkach. Mozna jedynie powiedziec, ze wykorzystujac narzedzia sieciowe UPS mozna skorzystac z mechanizmw obliczajacych dokladne koszta przesylek da dowolnych miejsc na ziemi przy uzyciu dowolnego poziomu uslugi. Dane sa pobierane z witryny UPS aplikacja odpytuje ich serwery pobierajac dane prawidlowe w momencie sprzedazy.

219

PHP Kompendium wiedzy

Podsumowanie
Tworzenie aplikacji handlu elektronicznego nie jest zbytnim wyzwaniem patrzac jedynie od strony kodu. Wyzwaniem staje sie stworzenie aplikacji, ktra jest jednoczesnie bezpieczna i prosta w uzyciu, oraz integruje w sobie wszystkie niezbedne technologie. Tworzac aplikacje handlowe nalezy poswiecic nieco czasu na poznanie wszystkich komponentw oraz na gruntowne testowanie systemu. Nalezy rwniez szyfrowac przechowywane dane oraz cala transmisje pomiedzy klientem i serwerem realizowac za pomoca SSL.

Rozdzial 17. Witryny handlu elektronicznego

220

Dodatek A. Funkcje
function_exists
Szuka w liscie zdefiniowanych funkcji nazwy przekazanej w znaleziono podana nazwe funkcji, w przeciwnym wypadku zwraca False.
int function_exists( string nazwa_funkcji )

$function_name.

Zwraca

True,

jezeli

func_get_arg
Zwraca argument numer $arg_num z listy argumentw funkcji. Argumenty sa numerowane od 0. Func_get_arg() generuje ostrzezenie jezeli jest wywolana poza funkcja. Jezeli wartosc $arg_num jest wieksza niz ilosc przekazanych argumentw, generowane jest ostrzezenie a funkcja func_get_arg() zwraca False.
mixed func_get_arg( int arg_num ) <?php function foo() { $numargs = func_num_args(); echo "Ilosc argumentw: $numargs<br>\n"; if ($numargs >= 2) echo "Drugi argument: " . func_get_arg(1) . "<br>\n"; } foo (1, 2, 3); ?>

Funkcja func_get_arg() moze byc uzywana wraz z func_num_args() i funkcji ze zmienna liczba argumentw. Funkcja zostala dodana w PHP 4.

func_get_args()

do zrealizowania

func_get_args
func_get_args()

Zwraca tablice, w ktrej kazdy element zawiera odpowiedni argument z listy argumentw funkcji. Funkcja generuje ostrzezenie w wypadku wywolania jej spoza definicji funkcji.

array func_get_args( void ) <?php function foo() { $numargs = func_num_args(); echo "Ilosc argumentw: $numargs<br>\n"; if ($numargs >= 2) echo "Drugi argument: " . func_get_arg(1) . "<br>\n"; $arg_list = func_get_args(); for ($i = 0; $i < $numargs; $i++) echo "Argument $i = " . $arg_list[$i] . "<br>\n"; } foo (1, 2, 3); ?>

Funkcja func_get_args() moze byc uzywana wraz z func_num_args() i funkcji ze zmienna liczba argumentw. Funkcja zostala dodana w PHP 4.

func_get_arg()

do zrealizowania

func_num_args
Zwraca liczbe argumentw przekazanych do biezacej funkcji. Funkcja ostrzezenie w przypadku wywolania jej z poza funkcji.
int func_num_args( void )

func_num_args()

generuje

<?php function foo() { $numargs = func_num_args(); echo "Ilosc argumentw: $numargs<br>\n"; } foo (1, 2, 3); ?>

Funkcja func_num_args() moze byc uzywana wraz z func_get_args() i funkcji ze zmienna liczba argumentw. Funkcja zostala dodana w PHP 4.

func_get_arg()

do zrealizowania

fwrite
Zapisuje zawartosc $string do pliku wskazywanym przez $fp. Jezeli podany zostal argument $length, zapisywanie jest przerywane po zapisaniu $length bajtw lub calej zawartosci $string. Jezeli podany zostal argument $length, ignorowana jest opcja konfiguracji magic_quotes_runtime i z $string nie beda usuwane ukosniki. Patrz rwniez fread(), fopen(), fsockopen(), popen() i fputs().
int fwrite( int fp, string [, int length])

getallheaders
Zwraca tablice asocjacyjna z wszystkimi naglwkami HTTP wyslanymi wraz z biezacym zadaniem.
Wskazwka Mozna rwniez odczytac wartosci zmiennych wspldzielonych CGI ze srodowiska. Mozna to zrealizowac gdy PHP pracuje jako modul Apache lub jako CGI. Aby odczytac wszystkie zmienne srodowiska zdefiniowane w ten sposb nalezy uzyc funkcji phpinfo().
array geallheaders( void )

Przyklad: getallheaders()
$headers = getallheaders(); while (list ($header, $value) = each($headers)) { echo "$header: $value<br>\n"; }

Przyklad ten wyswietla wszystkie naglwki biezacego zadania HTTP. Funkcja jedynie, gdy PHP pracuje jako modul Apache.

getallheaders()

dziala

getcwd
Zwraca biezacy katalog.
string getcwd( void )

getdate
Zwraca tablice asocjacyjna zawierajaca informacje o dacie odczytane na podstawie parametru Tablica zawiera nastepujace elementy: seconds sekundy minutes minuty hours godziny mday dzien miesiaca wday dzien tygodnia jako numer mon miesiac jako numer year rok jako numer yday dzien w roku jako numer, na przyklad 299 weekday dzien tygodnia jako tekst, na przyklad Friday month miesiac jako tekst, na przyklad January Dodatek A - Funkcje
$timestamp.

222

array getdate( int timetamp )

getenv
Zwraca wartosc zmiennej srodowiska o nazwie $varname, lub w przypadku wystapienia bledu False.
string getenv( string varname ) $ip = getenv( "REMOTE_ADDR" ); // odczytuje numer IP uzytkownika

Liste zmiennych srodowiska mozna uzyskac za pomoca funkcji phpinfo(). Znaczenie wielu z nich opisane jest w specyfikacji CGI (http://hoohoo.ncsa.uiuc.edu/cgi/) na stronie poswieconej zmiennym srodowiska (http://hoohoo.ncsa.uiuc.edu/cgi/env.html).
Uwaga Funkcja ta nie dziala w trybie ISAPI.

gethostbyaddr
Zwraca nazwe komputera o adresie przekazanym w argumencie bledu funkcja zwraca $ip_address. Patrz rwniez: gethostbyname().
string gethostbyaddr( string ip_address )

$ip_address.

W przypadku wystapienia

gethostbyname
Zwraca adres IP komputera o nazwie przekazanej w $hostname. Patrz rwniez: gethostbyaddr().
string gethostbyname( string hostname )

gethostbynamel
gethostbyaddr(), checkdnserr(), getmxrr()

Zwraca liste adresw IP skojarzonych z nazwa oraz man named(8).

$hostname.

Patrz rwniez:

gethostbyname(),

string gethostbynamel( string hostname )

GetImageSize
Odczytuje wielkosc rysunku GIF, JPG, PNG lub SWF i zwraca wymiary, typ pliku oraz ciag tekstu z szerokoscia i wysokoscia w postaci fragmentu znacznika IMG. Funkcja zwraca tablice z 4 elementami. Pod indeksem 0 znajduje sie szerokosc rysunku w pikselach, pod indeksem 1 znajduje sie wysokosc rysunku. Indeks 2 zawiera znacznik okreslajacy typ rysunku, 1 = GIF, 2 = JPG, 3 = PNG, 4 = SWF. Pod indeksem 3 znajduje sie ciag zawierajacy tekst height=xxx width=xxx, ktry moze byc uzyty bezposrednio w znaczniku IMG.
array GetImageSize( string filename [, array imgeinfo])

Przyklad: GetImageSize()
<?php $size = GetImageSize ("img/flag.jpg"); ?> <IMG SRC="img/flag.jpg" <?php echo $size[3]; ?>

Opcjonalny parametr $imageinfo pozwala na odczytanie dodatkowych danych z pliku rysunku. W chwili obecnej zwracane sa rzne znaczniki APP pliku JPG w postaci tablicy asocjacyjnej. Niektre programy wykorzystuja znaczniki APP do umieszczenia w rysunku informacji tekstowej. Czestym zastosowaniem jest umieszczanie danych IPTC http://www.xe.net/iptc/ w znaczniku APP13. Do zamiany binarnego znacznika APP13 na postac czytelna dla czlowieka mozna uzyc funkcji iptcparse(). Przyklad: GetImageSize() zwracajacy IPTC
<?php $size = GetImageSize ("testimg.jpg", &$info); if (isset(($info["APP13"])) { $iptc = iptcparse( $info["APP13"]); var_dump( $iptc); } ?>

Uwaga

223

PHP Kompendium wiedzy

Funkcja ta nie wymaga biblioteki GD

getlastmod
Zwraca czas ostatniej zmiany biezacej strony. Zwracana wartosc jest znacznikiem czasu Uniksa. W przypadku bledu zwraca False.
int getlastmod( void )

Przyklad: getlastmod()
<?php // zwraca ciag w postaci 'Ostatnia modyfikacja: March 04 1998 20:43:59.' echo "Ostatnia modyfikacja: ". date ("F d Y H:i:s.", getlastmod()); ?>

Patrz rwniez: date(), getmyuid(), get_current_user(), getmyinode() oraz getmypid().

getmxrr
Szuka w DNS rekordu MX skojarzonego z $hostname. Zwraca True, jezeli znalezione zostaly jakies rekordy, w przypadku wystapienia bledu lub braku rekordw zwracana jest wartosc False. Lista znalezionych rekordw MX jest umieszczana w tablicy $mxhosts. Jezeli zostanie podana tablica $weight, zostanie wypelniona wagami odnalezionych rekordw. Patrz rwniez: checkdnsrr(), gethostbyname(), gethostbynamel(), gethostbyaddr() oraz man named(8).
int getxrr( string hostname, array mxhosts [, array weight])

getmyinode
Zwraca biezacy inode pliku ze skryptem lub False w przypadku wystapienia bledu. Patrz rwniez: getmyuid(), get_current_user(), getmypid() i getlastmod().
Uwaga Funkcja ta nie dziala w Windows
int getmyinode( void )

getmypid
Zwraca identyfikator procesu PHP lub False w przypadku wystapienia bledu.
Uwaga Jezeli PHP dziala jako modul serwera, w kolejnych wywolaniach skryptu nie jest gwarantowane, ze identyfikatory procesw beda rzne. Patrz rwniez: getmyuid(), get_current_user(), getmyinode() oraz getlastmod().
int getmypid( void )

getmyuid
Zwraca identyfikator uzytkownika uruchamiajacego biezacy skrypt, lub False w przypadku wystapienia bledu. Patrz rwniez: getmypid(), get_current_user(), getmyinode() oraz getlastmod().
int getmyuid( void )

getprotobyname
Zwraca numer protokolu skojarzonego z protokolem getprotobynumber().
int getprotobyname( string name )

$name

wedlug pliku /etc/protocols. Patrz rwniez:

Dodatek A - Funkcje

224

getprotobynumber
Zwraca nazwe protokolu skojarzonego z protokolem getprotobyname().
int getprotobynumber( string name )

$number

wedlug pliku /etc/protocols. Patrz rwniez:

getrandmax
srand(), mt_rand(), mt_srand()
int getrandmax( void )

Zwraca maksymalna wartosc, jaka moze byc zwrcona przez funkcje oraz mt_getrandmax().

rand().

Patrz rwniez:

rand(),

getrusage
Jest to interfejs do getrusage(2). Zwraca tablice asocjacyjna zawierajaca dane zwrcone przez wywolanie systemowe. Jezeli $who jest rwne 1, getrusage zostanie wywolane z RUSAGE_CHILDREN.
array getrusage( [int who] )

Przyklad: getrusage()
$dat echo echo echo echo = getrusage(); $dat["ru_nswap"]; $dat["ru_majflt"]; $dat["ru_utime.tv_sec"]; $dat["ru_utime.tv_usec"]; # # # # ilosc ilosc uzyty uzyty stronicowan bledw strony czas uzytkownika (sekundy) czas uzytkownika (mikrosekundy)

Wiecej szczeglw na temat getrusage(2).

getrusage

mozna znalezc w podreczniku systemowym pod haslem

getservbyname
Zwraca numer portu uzywanego przez usluge $service dla protokolu $protocol, wedlug definicji w /etc/services. $protocol moze byc TCP lub UDP. Patrz rwniez: getservbyport().
int getservbyname( string service, string protocol)

gettext
Funkcja szuka tlumaczenia ciagu w jednej z tablic tlumaczen. Zwraca przetlumaczony ciag lub oryginalny ciag, jezeli tlumaczenie nie zostanie znalezione. Jako Znakw zastepczych mozna uzywac podkreslenia.
string gettext( string message )

Przyklad: gettext()
<?php // Ustaw jezyk na niemiecki putenv( "LANG=de"); // Okresl polozenie tablic tlumaczen bindtextdomain( "myPHPApp", "./locale"); // wybierz domene textdomain( "myPHPApp"); // wypisz komunikat testowy print (gettext( "Welcome to My PHP Application")); ?>

gettimeofday
Jest to interfejs do gettimeofday(2). Zwraca tablice asocjacyjna zawierajaca dane zwracane przez wywolanie systemowe. sec sekundy usec mikrosekundy minuteswest przesuniecie w minutach na zachd od Greenwich dsttime typ poprawki dst
array gettimeofday( void )

225

PHP Kompendium wiedzy

gettype
Zwraca typ zmiennej PHP $var. Mozliwe zwracane wartosci zamieszczone sa ponizej:
boolean array unknown type integer object double resource string user function

string gettype( mixed var )

Patrz rwniez: settype().

get_browser
Odczytuje mozliwosci przegladarki uzytkownika. Jest to realizowane przez odszukanie danych na temat przegladarki w pliku browscap.ini. Domyslnie uzywana jest wartosc zmiennej $HTTP_USER_AGENT, ale mozna przekazac dowolna dowolny parametr $user_agent (na przyklad, aby odczytac mozliwosci innej przegladarki). Zwracany jest obiekt zawierajacy dane opisujace, na przyklad numer wersji, identyfikator, wartosci True lub False dla takich wlasnosci jak, obsluga ramek, JavaScript, cookie itd. Mimo, ze plik browscap.ini zawiera dane o wielu przegladarkach, to jednak uzytkownik musi dbac o jego aktualnosc. Format pliku jest bardzo prosty. Ponizszy przyklad pokazuje przykladowe dane zwracane dla przegladarki uzytkownika.
object get_browser( [string user_agent])

Przyklad: get_browser()
<?php function list_array ($array) { while (list ($key, $value) = each($array)) $str .= "<b>$key:</b> $value<br>\n"; return $str; } echo "$HTTP_USER_AGENT<hr>\n"; $browser = get_browser(); echo list_array( (array) $browser); ?>

Wynik dzialania tego skryptu moze wygladac nastepujaco


Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)<hr> <b>browser_name_pattern:</b> Mozilla/4\.0 (compatible; MSIE 5\.5; Windows NT 5\.0)<br> <b>parent:</b> IE 5.0<br> <b>version:</b> 5.5<br> <b>minorver:</b> 5<br> <b>platform:</b> Win2000<br> <b>beta:</b> <br> <b>browser:</b> IE<br> <b>majorver:</b> 5<br> <b>frames:</b> 1<br> <b>tables:</b> 1<br> <b>cookies:</b> 1<br> <b>backgroundsounds:</b> 1<br> <b>vbscript:</b> 1<br> <b>javascript:</b> 1<br> <b>javaapplets:</b> 1<br> <b>activexcontrols:</b> 1<br> <b>win16:</b> <br> <b>ak:</b> <br> <b>sk:</b> <br> <b>aol:</b> <br> <b>crawler:</b> <br> <b>msn:</b> <br> <b>cdf:</b> 1<br> <b>dhtml:</b> 1<br> <b>xml:</b> 1<br>

Aby skrypt ten mgl dzialac nalezy tak ustawic zmienna konfiguracji browscap, aby wskazywala na katalog z plikiem browscap.ini. Wiecej informacji (w tym adresy skad mozna sciagnac plik browscap.ini) mozna znalezc w FAQ do PHP pod adresem http://www.php.net/FAQ.php.

get_cfg_var
Zwraca wartosc zmiennej konfiguracji PHP okreslonej przez $varname, lub False w przypadku wystapienia bledu. Funkcja ta nie zwraca danych konfiguracji ustawionych przy kompilacji PHP lub poprzez pliki konfiguracyjne Apache (przy uzyciu dyrektywy php3_configuration_option). Aby sprawdzic, czy system Dodatek A - Funkcje 226

korzysta z pliku konfiguracji, nalezy sprbowac odczytac wartosc zmiennej konfiguracji jest to mozliwe, oznacza to, ze jest uzywany plik konfiguracji.
string get_cfg_var( string varname )

cfg_file_path.

Jezeli

get_class
Zwraca nazwe klasy przekazanego obiektu $obj. Patrz rwniez: get_parent_class(), is_subclass_of().
string get_class( object obj )

get_class_methods
Zwraca tablice z nazwami metod zdefiniowanych w klasie okreslonej przez get_class_vars(), get_object_vars().
array get_class_methods( string class_name )

$class_name.

Patrz rwniez:

get_class_vars
Zwraca tablice z nazwami wlasciwosci zdefiniowanych w klasie okreslonej przez rwniez: get_class_methods(), get_object_vars().
array get_class_vars( string class_name )

$class_name.

Patrz

get_current_user
Zwraca nazwe wlasciciela biezacego skryptu PHP. Patrz rwniez oraz getlastmod().
string get_current_user( void )

getmyuid(), getmypid(), getmyinode()

get_declared_classes
Zwraca tablice nazw klas zadeklarowanych w biezacym skrypcie. W PHP 4.0.1pl2 na poczatku tablicy zwracane byly trzy dodatkowe klasy: stdClass (zdefiniowana w Zend/zend.c), OverloadedTestClass (zdefiniowana w ext/standard/basic_functions.h) oraz Directory (zdefiniowana w ext/standard/dir.c).
array get_declared_classes( void )

get_extension_funcs
Zwraca nazwy wszystkich funkcji zdefiniowanych w module $module_name.
array get_extension_funcs( string module_name )

Przyklad: get_extension_funcs()
print_r (get_extension_funcs( "xml")); print_r (get_extension_funcs( "gd"));

Wykonanie tych linii spowoduje wypisanie listy funkcji umieszczonych w modulach xml i gd. Patrz rwniez: get_loaded_extensions().

get_html_translation_table
Zwraca tablice translacji uzywana wewnetrznie w funkcjach htmlspecialchars() i htmlentities(). Mozliwe jest okreslenie potrzebnej w danym momencie tabeli (HTML_ENTITIES i HTML_SPECIALCHARS). Tak samo jak w przypadku funkcji htmlspecialchars() i htmlentities() mozna opcjonalnie okreslic rodzaj ukosnikw $quote_style. Domyslnym ustawieniem jest tryb ENT_COMPAT. Opis trybw znajduje sie w opisie funkcji htmlspecialchars().
string get_html_translation_table( int table [, int quote_style])

Przyklad: Tablica translacji


$trans = get_html_translation_table( HTML_ENTITIES ); $str = "To firma & <PRO> & splka"; $encoded = strtr( $str, $trans);

227

PHP Kompendium wiedzy

Zmienna $encoded zawiera teraz ciag To firma &amp; &lt;PRO&gt; &amp; sp&oacute;&sup3;ka. Ciekawym zastosowaniem jest uzycie funkcji array_flip() w celu zmiany kierunku translacji.
$trans = array_flip( $trans ); $original = strtr ($str, $trans);

Teraz w zmiennej $original bedzie znajdowal sie ciag: To firma & <PRO> & splka.
Uwaga Funkcja ta zostala dodana w PHP 4.0

Patrz rwniez htmlspecialchars(), htmlentities(), strtr() i array_flip().

get_included_files
Funkcja zwraca tablice asocjacyjna z nazwami wszystkich plikw dolaczonych do skryptu za pomoca funkcji include_once(). Indeksami tej tablicy sa nazwy plikw uzytych w include_once() bez rozszerzenia .php. W PHP 4.0.1pl2 funkcja zakladala, ze pliki dolaczane poprzez include_once() maja rozszerzenia .php i inne rozszerzenia nie dzialaja. Patrz rwniez: require_once(), include_once(), get_required_files().
array get_included_files( void )

get_loaded_extesions
Zwraca nazwy wszystkich modulw wkompilowanych i zaladowanych przez interpreter PHP.
array get_loaded_extensions( void )

Przyklad get_loaded_extensions()
print_r (get_loaded_extensions());

Spowoduje to wypisanie listy podobnej do nastepujacej:


Array ( [0] => standard [1] => bcmath [2] => Calendar [3] => com [4] => variant [5] => ftp [6] => mysql [7] => odbc [8] => pcre [9] => session [10] => xml [11] => wddx [12] => apache )

Patrz rwniez: get_extension_funcs().

get_magic_quotes_gpc
Zwraca stan ustawienia magic_quotes_gpc (0 wylaczone, 1 wlaczone). Patrz rwniez: get_magic_quotes_runtime(), set_magic_quotes_runtime().
long get_magic_quotes_gpc( void )

get_magic_quotes_runtime
Zwraca stan ustawienia
magic_quotes_runtime

(0 wylaczone, 1 wlaczone). Patrz rwniez:

get_magic_quotes_gpc(), set_magic_quotes_runtime().
long get_magic_quotes_runtime( void )

get_meta_tags
Otwiera plik $filename i analizuje go szukajac znacznikw meta.
array get_meta_tags( string filename [, int use_include_path])

Przyklad: Znaczniki <META> Dodatek A - Funkcje 228

<meta name="author" content="name"> <meta name="tags" content="php3 documentation"> </head> <!-- tutaj zatzymuje sie analiza -->

Uwaga Uwaga na konce linii PHP wykorzystuje wlasna funkcje analizujaca plik wejsciowy, wiec pliki z MacIntosha moga nie dzialac na Uniksie.

Nazwa wlasciwosci staje sie kluczem, natomiast zawartosc umieszczana jest w tablicy jako wartosc elementu. Dzieki temu mozna wykorzystac standardowe funkcje przegladajace tablice. Znaki specjalne sa zastepowane znakiem podkreslenia, natomiast pozostaly tekst jest konwertowany do malych liter. Ustawienie use_include_path na 1 spowoduje, ze PHP bedzie prbowal otworzyc plik znajdujacy sie na standardowej sciezce dolaczania.

get_object_vars
Zwraca tablice asocjacyjna wlasciwosci zdefiniowanych w obiekcie okreslonym przez $obj. Jezeli zmienna zdefiniowana w klasie nie ma przypisanej wartosci, nie znajdzie sie ona w tablicy asocjacyjnej.
array get_object_vars( object obj)

Przyklad: uzycie get_object_vars()


<?php class Point2D { var $x, $y; var $label; function Point2D( $x, $y) { $this->x = $x; $this->y = $y; } function setLabel( $label) { $this->label = $label; } function getPoint() { return array( "x" => $this->x, "y" => $this->y, "label" => $this->label); } } $p1 = new Point2D( 1.233, 3.445); print_r(get_object_vars($p1)); // Wlasciwosc $Label jest zdefiniowana, ale nie zainicjowana // Array // ( // [x] => 1.233 // [y] => 3.445 // ) $p1->setLabel("point #1"); print_r(get_object_vars($p1)); // Array // ( // [x] => 1.233 // [y] => 3.445 // [label] => point #1 // ) ?>

Patrz rwniez: get_class_methods(), get_class_vars().

get_parent_class
Zwraca nazwe klasy bazowej dla klasy, ktrej instancja jest obiekt is_subclass_of().
string get_parent_class( object obj )

$obj.

Patrz rwniez:

get_class(),

229

PHP Kompendium wiedzy

get_required_files
Zwraca tablice asocjacyjna z nazwami wszystkich plikw zaladowanych do skryptu poprzez funkcje require_once().
array get_required_files( void )

Przyklad: Wypisywanie plikw dolaczanych za pomoca require i include.


<?php require_once( "local.php" ); require_once( "../inc/global.php" ); for ($i=1; $i<5; $i++) include "util". $i . ".php"; echo "Pliki dolaczane przez require_once\n"; print_r (get_required_files()); echo "Pliki dolaczane przez include_once\n"; print_r (get_included_files()); ?>

Wykonanie tego skryptu spowoduje wygenerowanie nastepnego wyniku:


Pliki dolaczane przez require_once Array ( [0] => C:\helion\php4-devguide\site\doda\local.php [1] => C:\helion\php4-devguide\site\inc\global.php [2] => C:\helion\php4-devguide\site\doda\util1.php [3] => C:\helion\php4-devguide\site\doda\util2.php [4] => C:\helion\php4-devguide\site\doda\util3.php [5] => C:\helion\php4-devguide\site\doda\util4.php ) Pliki dolaczane przez include_once Array ( [0] => C:\helion\php4-devguide\site\doda\local.php [1] => C:\helion\php4-devguide\site\inc\global.php [2] => C:\helion\php4-devguide\site\doda\util1.php [3] => C:\helion\php4-devguide\site\doda\util2.php [4] => C:\helion\php4-devguide\site\doda\util3.php [5] => C:\helion\php4-devguide\site\doda\util4.php )

Uwaga W PHP 4.0.1pl2 funkcja zakladala, ze pliki dolaczane poprzez include_once() maja rozszerzenia .php i inne rozszerzenia nie dzialaja.

Patrz rwniez: require_once(), include_once(), get_included_files().

gmdate
Funkcja ta jest identyczna z date(), poza tym, ze zwracany czas jest czasem Greenwich (GMT). Jezeli przyklad zostanie uruchomiony w Polsce (GMT +0100), pierwsza linia przykladu zwrci Jan 01 1998 00:00:00, natomiast druga Dec 31 1997 23:00:00.
string gmdate( string format, int timestamp )

Przyklad: gmdate()
echo date("M d Y H:i:s", mktime( 0,0,0,1,1,1998)); echo gmdate("M d Y H:i:s", mktime( 0,0,0,1,1,1998));

Patrz rwniez: date(), mktime() i gmmktime().

gmmktime
Funkcja identyczna jak mktime(), poza tym, ze przekazane parametry reprezentuja czas GMT.
int gmmktime( int hour, int minute, int second, int month, int day, int year [, int is_dst])

gmstrftime
Zachowuje sie tak samo jako jak funkcja strftime(), ale zwracany czas jest czasem GMT. Na przyklad, jezeli bedzie uzyta w strefie czasowej GMT -0500, pierwsze wywolanie z przykladu wypisze ciag Dec 31 1998 20:00:00, natomiast drugie: Jan 01 1999 01:00:00. Dodatek A - Funkcje 230

string gmstrftime( string format, int timestamp )

Przyklad: gmstrftime()
setlocale( 'LC_TIME', 'en_US'); echo strftime("%b %d %Y %H:%M:$S", mktime( 20,0,0,12,31,98)); echo gmstrftime("%b %d %Y %H:%M:$S", mktime( 20,0,0,12,31,98));

Patrz rwniez: strftime().

GregorianToJD
Prawidlowy zakres dat kalendarza gregorianskiego to 4714 p.n.e. do 9999 n.e. Chociaz mozna stosowac tak szeroki zakres dat, nie ma to jednak sensu. Kalendarz gregorianski zostal ustanowiony 15 pazdziernika 1582 roku (lub 5 pazdziernika 1582 roku wedlug kalendarza julianskiego). Niektre kraje jeszcze dlugo nie wprowadzily tego kaledarza. Na przyklad Anglia przyjela go w 1752 roku, Rosja w 1918 a Grecja w 1923 roku. Wiekszosc krajw europejskich przed kalendarzem gregorianskim uzywala kalendarza julianskiego.
int GregorianToJD( int month, int day, int year)

Przyklad: Funkcje kalendarza


<?php $jd = GregorianToJD( 10, 11, 1970); echo "$jd\n"; $gregorian = JDToGregorian( $jd ); echo "$gregorian\n"; ?>

gzclose
Funkcja zamyka plik gz wskazywany przez $zp. W przypadku powodzenia zwraca True, a w przypadku bledu, False. Wskaznik pliku gz musi byc prawidlowym wskaznikiem wskazujacym na plik otwarty przez funkcje gzopen().
int gzclose( int zp )

gzcompress
Zwraca dane wejsciowe przekazane w $data skompresowane gzipem, lub False w przypadku wystapienia bledu. Opcjonalny parametr $level moze przyjmowac wartosci od 0 dla braku kompresji, do 9 dla maksymalnej kompresji. Patrz rwniez: gzuncompress().
string gzcompress( string data [, int level])

gzeof
Zwraca True, jezeli wskaznik pliku gz znajduje sie na koncu pliku lub wystapil blad. W przeciwnym przypadku zwraca False. Wskaznik pliku gz musi byc prawidlowym wskaznikiem wskazujacym na plik otwarty przez funkcje gzopen().
int gzeof( int zp )

gzfile
Funkcja identyczna z readgzfile(), poza tym, ze gzfile() zwraca zawartosc pliku w tablicy. Mozna ustawic parametr opcjonalny na 1, co spowoduje szukanie pliku rwniez na sciezce ustawionej w include_path. Patrz rwniez: readgzfile(), gzopen().
array gzfile( string filename [, int use_include_path])

gzgetc
Zwraca ciag zawierajacy jeden znak (nieskompresowany) odczytany z pliku na ktry wskazuje $zp. Zwraca False na koncu pliku (tak samo jak gzeof()).Wskaznik pliku gz musi byc prawidlowym wskaznikiem wskazujacym na plik otwarty przez funkcje gzopen(). Patrz rwniez: gzopen() i gzgets().
string gzgetc( int zp )

231

PHP Kompendium wiedzy

gzgets
Zwraca ciag znakw (nieskompresowany) o maksymalnej dlugosci $length-1 odczytany z pliku na ktry wskazuje $zp. Czytanie konczy sie po odczytaniu $length-1 znakw, znaku nowej linii lub znaku EOF. Zwraca False w przypadku wystapienia bledu. Wskaznik pliku gz musi byc prawidlowym wskaznikiem wskazujacym na plik otwarty przez funkcje gzopen(). Patrz rwniez: gzopen(), gzgetc() i fgets().
string gzgets( int zp, int length )

gzgetss
Funkcja identyczna jak gzgets(), ale dodatkowo gzgetss() usiluje usunac znaczniki HTML i PHP z odczytanego tekstu. Mozna uzyc opcjonalnego trzeciego parametru w celu okreslenia znacznikw, ktre maja pozostac w tekscie. Parametr $allowable_tags zostal dodany w PHP 3.0.13, PHP4B3. Patrz rwniez: gzgets(), gzopen() i strip_tags().
string gzgetss( int zp, int length [, string allowable_tags])

gzopen
Otwiera plik gzip (.gz) do odczytu lub zapisu. Parametr $mode jest taki jak w fopen() ("rb" lub "wb"), ale moze zawierac rwniez poziom kompresji ("wb9") lub strategie: f dla filtrowania danych, na przyklad "wb6f", h dla kompresji tylko metoda Huffmana, np.: "wb1h". Wiecej informacji na temat filtrowania znajduje sie w opisie deflateIni2 w pliku zlib.h. Mozna rwniez wykorzystac gzopen() do odczytania danych, ktre nie sa w formacie gzip. W takim przypadku gzread() odczytuje plik bez jego dekompresji. Funkcja gzopen() zwraca wskaznik do otwartego pliku. Po tej operacji wszystkie dane odczytywane z tego pliku sa dekompresowane, natomiast dane zapisywane do pliku sa kompresowane. Jezeli otwarcie pliku nie uda sie, funkcja zwraca False. Mozna uzyc opcjonalnego trzeciego argumentu i ustawic go na 1 w celu wlaczenia poszukiwania pliku do otwarcia na sciezce include_path.
int gzopen( string filename, string mode [, int use_include_path])

Przyklad gzopen()
$fp = gzopen( "/tmp/file.gz", "r" );

Patrz rwniez: gzclose().

gzpassthru
Odczytuje plik wskazywany przez wskaznik do pliku gz, az do znaku EOF, a jego (nieskompresowana) zawartosc kieruje na wyjscie. Jezeli wystapi blad zwraca False. Wskaznik pliku gz musi byc prawidlowym wskaznikiem wskazujacym na plik otwarty przez funkcje gzopen(). Po zakonczeniu odczytu pliku jest on zamykany.
int gzpassthru( int zp )

gzputs
Identyczna jak funkcja gzwrite().
int gzputs( int zp, string str [, int length])

gzread
Odczytuje maksymalnie $length bajtw z pliku gz wskazywanego przez $zp. Odczyt zostaje przerwany, gdy zostanie odczytane $length znakw (nieskompresowanych), lub napotkany zostanie koniec pliku.
string gzread( int zp, int length )

Przyklad: gzread()
// odzytanie zawartosci pliku gz do ciagu $filename = "/usr/local/somth.txt.gz"; $zd = gzopen( $filename, "r"); $contents = gzread( $dz, 10000 );

Patrz rwniez: gzwrite(), gzopen(), gzgets(), gzgetss(), gzfile(), gzpassthru(). Dodatek A - Funkcje 232

gzrewind
Ustawia znacznik pozycji na poczatku pliku. Jezeli wystapi blad, funkcja zwraca 0. Wskaznik pliku gz musi byc prawidlowym wskaznikiem wskazujacym na plik otwarty przez funkcje gzopen(). Patrz rwniez gzseek(), gztell().
int gzrewind( int zp )

gzseek
Ustawia znacznik pozycji pliku wskazywanego przez $zp na pozycje okreslona przez $offset. Jest to odpowiednik wywolania (w C) gzseek( zp, offset, SEEK_SET). Jezeli plik jest otwarty do odczytu, funkcja jest wykonywana, ale moze byc to niezwykle powolne. Jezeli plik jest otwarty do zapisu, obslugiwane jest jedynie przesuniecie w przd; gzseek() kompresuje wtedy sekwencje zer az do nowej pozycji. W przypadku powodzenia operacji zwraca 0, w przeciwnym wypadku zwraca -1.
Uwaga Przesuniecie poza znacznik EOF nie jest traktowane jako blad.

Patrz rwniez gztell() i gzrewind().


int gzseek( int zp, int offset )

gztell
Zwraca pozycje znacznika pozycji dla pliku wskazywanego przez $zp, to znaczy przesuniecie od poczatku pliku. Jezeli wystapi blad, funkcja zwraca False. Wskaznik pliku gz musi byc prawidlowym wskaznikiem wskazujacym na plik otwarty przez funkcje gzopen(). Patrz rwniez: gzopen(), gzseek() i gzrewind().
int gztell( int zp )

gzuncompress
Na podstawie danych $data, skompresowanych za pomoca funkcji gzcompress() zwraca oryginalne nieskompresowane dane. W przypadku bledu zwraca False. Funkcja zakonczy sie niepowodzeniem, jezeli rozmiar rozkompresowanych danych przekracza 256 krotnosc wielkosci danych wejsciowych $data, lub jest wiekszy od opcjonalnego parametru $length. Patrz rwniez gzcompress().
string gzuncompress( string data [, int length])

gzwrite
Zapisuje zawartosc $string do pliku gz wskazywanego przez $zp. Jezeli podano argument $length, zapis jest przerywany po zapisaniu $length bajtw (nieskompresowanych), lub po osiagnieciu konca danych wejsciowych.
Uwaga Jezeli podany zostal argument $length, ignorowany jest parametr konfiguracji magic_quotes_runtime i z ciagu $string nie beda usuniete ukosniki.

Patrz rwniez: gzread(), gzopen() i gzputs().

header
Funkcja uzywana na poczatku pliku HTML do wyslania surowych naglwkw HTTP. Wiecej informacji na temat surowych naglwkw mozna znalezc w specyfikacji protokolu HTTP 1.1 (http://www.w3.org/Protocols/rfc2616/rfc2616).
Uwaga

233

PHP Kompendium wiedzy

Nalezy pamietac, ze funkcja header() musi byc wywolana przed wyslaniem danych HTML, niezaleznie czy poprzez normalny kod HTML czy poprzez PHP. Bardzo czesto spotykanym bledem jest umieszczanie wolnych linii przed wywolaniem funkcji header().

Istnieja dwa naglwki specjalnego przeznaczenia. Pierwszy to naglwek Location. Oprcz odeslania tego naglwka do przegladarki zwraca on do Apache kod statusu REDIRECT. Dla programistw skryptw moze nie byc to zbyt wazne, ale wazne jest dla programistw zainteresowanych dzialaniem serwera Apache.
int header( string string )

Przyklad: header()
header("Location: http://www.php.net"); /* przekierowuje rzegladarke do witryny PHP */ exit; /* nalezy sie upewnic, ze kod ponizej nie zostanie wykonany. */

Drugim naglwkiem specjalnego przeznaczenia jest naglwek rozpoczynajacy sie ciagiem HTTP/ (wielkosc znakw bez znaczenia). Na przyklad jezeli skonfigurowana zostanie dyrektywa Apache ErrorDocument 404, tak aby wskazywala na skrypt PHP, dobrze jest sie upewnic, ze skrypt PHP generuje blad 404. W tym celu nalezy wyslac nastepujacy naglwek:
header("HTTP/1.0 404 Not Found");

Skrypty PHP czesto generuja dynamiczny kod HTML, ktry nie powinien byc buforowany w przegladarkach i serwerach proxy. Mozna zablokowac wiele serwerw proxy za pomoca naglwkw:
header("Expires: Mon, 26 ul 1997 05:00:00 GMT"); header("LastModified: " .. gmdate("D, d M y H:i:s"); header("Cache-Control: no-cache, must-revalidate"); header("Pragme: no-cache"); //Data w przeszlosci // Czas GMT // zawsze zmodyfikowane HTTP/1.1 // HTTP/1.0

Patrz rwniez: headers_sent().

headers_sent
Zwraca True, jezeli wyslane zostaly naglwki HTTP, w przeciwnym przypadku zwraca rwniez: header().
boolean headers_sent( void )

False.

Patrz

hebrev
Opcjonalny parametr $max_chas_per_line wskazuje na maksymalna ilosc znakw w linii danych wyjsciowych. Funkcja prbuje uniknac lamania wyrazw. Patrz rwniez: hebrevc().
string hebrev(string hebrew_text [, int max_chars_per_line])

hebrevc
Funkcja podobna do hebrev() z ta rznica, ze konwertuje znaki nowej linii (\n) na <br>\n. Opcjonalny parametr $max_chars_per_line wskazuje maksymalna ilosc znakw w wyniku. Funkcja prbuje uniknac lamania wyrazw. Patrz rwniez: hebrev().
string hebrevc( string hebrev_text [, int max_chars_per_line])

hexdec
Zwraca dziesietny odpowiednik liczby szesnastkowej przekazanej w parametrze $hex_string. Funkcja konwertuje ciag szesnastkowy na liczbe dziesietna. Najwieksza liczba, jaka moze byc skonwertowana jest 7fffffff lub 2147483647 dziesietnie. Patrz rwniez: dechex().
hexdec()
int hexdec( string hex_string )

highlight_file
Wynikiem dzialania funkcji jest wersja pliku PHP, o nazwie $filename, z wyrzniona skladnia. Uzywane kolory sa zdefiniowane w wewnetrznym module wyrzniania skladni.
void highlight_file( string filename )

Przyklad: Tworzenie laczy do plikw z wyrzniona skladnia Aby utworzyc lacze umozliwiajace wyrznienie skladni dowolnego pliku, skorzystamy z dyrektywy Apache ForceType. Pozwala to na stworzenie eleganckiego adresu URL, natomiast uzycie funkcji Dodatek A - Funkcje 234

highlight_file()

pozwala na pokazanie ladnie wygladajacego kodu. W pliku httpd.conf nalezy dodac

nastepujace linie:
<Location /source> ForceType application/x-httpd-php </Location>

Nastepnie nalezy utworzyc plik o nazwie source i umiescic go w glwnym katalogu serwera WWW:
<HTML> <HEAD> <TITLE>Wyswietlanie zrdla</TITLE> </HEAD> <BODY COLOR BGCOLOR="white"> <?php $script = getenv( "PATH_TRANSLATED"); if (!$script) { echo "<BR><B>BLAD: wymagana nazwa skryptu</B><BR>"; } else { if ereg("(\.php|\.inc)$", $script)) { echo "<H1>Zrdlo skryptu: $PATH_INFO</H1>\n<hr>\n"; highlight_file( $script ); } else echo "<H1>BLAD: Dopuszczalne sa jedynie rozszerzenia php i inc</H1>"; } echo "Przetworzony: " . date( "Y/M/d H:i:s", time()); </BODY> </HTML> ?>

Teraz mozna uzyc adresw podobnych do przytoczonego ponizej, aby wyswietlic kolorowa wersje skryptu /sciezka/do/skryptu.php.
http://serwer.com/source/sciezka/do/skryptu.php

Patrz rwniez: highlight_string() i show_source().

highlight_string
Wysyla na wyjscie pokolorowana wersje ciagu $str. Uzywane kolory sa zdefiniowane w wewnetrznym module PHP. Patrz rwniez: highlight_file() i show_source().
void highlight_string( string str )

htmlentities
Funkcja jest identyczna z htmlspecialchars(), ale wszystkie znaki posiadajace odpowiadajace im symbole HTML sa zamieniane na te symbole. Tak jak w przypadku funkcji htmlspecialchars() mozna uzyc opcjonalnego argumentu wskazujacego na sposb traktowania cudzysloww i apostrofw. Wartosc ENT_COMPAT (domyslna) konwertuje jedynie cudzyslowy, pozostawiajac bez zmian apostrofy. ENT_QUOTES powoduje konwersje zarwno cudzysloww jak i apostrofw. ENT_NOQUOTES powoduje, ze zarwno cudzyslowy jak i apostrofy pozostaja niezmienione. W chwili obecnej uzywany jest zestaw znakw ISO-8859-1. Nalezy pamietac, ze argument opcjonalny zostal dodany w PHP 3.0.17 i PHP 4.0.3. Patrz rwniez: htmlspecialchars() i nl2br().
string htmlentities( string string [, int quote_style])

htmlspecialchars
Niektre znaki maja specjalne znaczenie w HTML i powinny byc reprezentowane przez symbole HTML. Funkcja ta zwraca ciag z zastosowanymi niektrymi z tych konwersji. Sa to najczesciej uzywane konwersje przy programowaniu dla WWW. Jezeli wymagana jest kompletna konwersja, nalezy uzyc funkcji htmlentities(). Funkcja ta jest uzyteczna do usuwania znacznikw HTML z tekstu wprowadzonego przez uzytkownika, na przyklad w ksiedze gosci lub na tablicy ogloszeniowej. Argument opcjonalny, $quote_style wskazuje sposb konwersji apostrofw i cudzysloww. Domyslny tryb ENT_COMPAT jest dostepny dla zachowania zgodnosci z poprzednimi wersjami i konwertuje jedynie cudzyslowy, pozostawiajac bez zmian apostrofy. ENT_QUOTES PHP Kompendium wiedzy

235

powoduje konwersje zarwno cudzysloww jak i apostrofw. jak i apostrofy pozostaja niezmienione.
Uwaga

ENT_NOQUOTES

powoduje, ze zarwno cudzyslowy

string htmlspecialchars( string string [, int quote_style])

Wykonywane sa nastepujace konwersje: & jest zamieniane na &amp; " jest zamieniany na &quot;, o ile nie jest ustawiona wartosc ENT_NOQUOTES ' jest zmieniany na &#039; jezeli jest ustawiona wartosc ENT_QUOTES < jest zmieniane na &lt; > jest zmieniane na &gt;

Funkcja ta wykonuje jedynie przedstawione translacje. Aby przeprowadzic pelna translacje nalezy uzyc funkcji htmlentities(). Nalezy pamietac, ze argument opcjonalny zostal dodany w PHP 3.0.17 i PHP 4.0.3.

hw_Array2Objrec
Konwertuje $object_array na rekord obiektowy. Wielokrotne atrybuty na przyklad Title w rznych jezykach sa obslugiwane prawidlowo. Patrz rwniez: hw_objrec2array().
string hw_Array2Objrec( array object_array )

hw_Children
Zwraca tablice identyfikatorw obiektw. Kazdy identyfikator nalezy do elementu kolekcji o identyfikatorze $objectID. Tablica zawiera wszystkie elementy potomne, zarwno dokumenty jak i kolekcje.
array hw_Children( int connection, int objectID )

hw_ChildrenObj
Zwraca tablice rekordw obiektw. Kazdy z obiektw nalezy do elementu potomnego o identyfikatorze $objectID. Tablica zawiera wszystkie elementy potomne, zarwno dokumenty jak i kolekcje.
array hw_ChildrenObj( int connection, int objectID )

hw_Close
Zwraca False, jezeli $connection nie jest prawidlowym indeksem polaczenia, a w przeciwnym przypadku True. Zamyka polaczenie o podanym indeksie do serwera Hyperwave.
int hw_Close( int connection )

hw_Connect
zwraca Otwiera polaczenie do serwera Hyperwave i zwraca indeks polaczenia, jezeli operacja sie uda. Jezeli nie, False. Kazdy z argumentw powinien byc ciagiem poza numerem portu. Argumenty $username i $password sa opcjonalne i moga byc opuszczone. W takim przypadku nie bedzie przeprowadzana identyfikacja uzytkownika. Jest to zblizone do identyfikacji uzytkownika anonimowego. Funkcja zwraca indeks polaczenia, ktry jest potrzebny w innych funkcjach Hyperwave. Mozna utrzymywac kilka polaczen do serwera, Nalezy jedynie pamietac, ze przesylane haslo nie jest zaszyfrowane. Patrz rwniez: hw_pConnect().
int hw_Connect( string host, int port, string username, string password )

hw_Cp
Kopiuje obiekt o identyfikatorze podanym w drugim parametrze do kolekcji o identyfikatorze $destination_id. Zwracana wartoscia jest ilosc skopiowanych obiektw. Patrz rwniez: hw_mv().
int hw_Cp( int conection, array object_id_array, int destination_id

Dodatek A - Funkcje

236

hw_Deleteobject
Usuwa obiekt o identyfikatorze przekazanym w drugim argumencie funkcji. Usuwa wszystkie kopie obiektu. Zwraca True, jezeli nie wystapily zadne bledy, lub False gdy bledy wystapily. Patrz rwniez hw_mv().
int hw_Deleteobject( int connection, int object_to_delete )

hw_DocByAnchor
Zwraca identyfikator obiektu, do ktrego nalezy $anchorID.
int hw_DocByAnchor( int connection, int anchorID )

hw_DocByAnchorObj
Zwraca rekord obiektu dokumentu, do ktrego nalezy $anchorID.
int hw_DocByAnchorObj( int connection, int anchorID )

hw_Document_Attributes
Zwraca rekord obiektu dokumentu. Dla zachowania zgodnosci z poprzednimi wersjami akceptowane jest rwniez hw_DocumentAttributes(). Jednak nie zaleca sie stosowania tej nazwy. Patrz rwniez: hw_Document_BodyTag() i hw_Document_Size().

hw_Document_BodyTag
Zwraca znacznik BODY dokumentu. Jezeli jest to dokument HTML, znacznik BODY powinien byc wydrukowany przez dokumentem. Patrz rwniez: hw_Document_Attributes(), hw_Document_Size(). Dla zapewnienia zgodnosci akceptowana jest rwniez nazwa hw_DocumentBodyTag(). Nie zaleca sie jej stosowania.
string hw_Document_BodyTag( int hw_document )

hw_Document_Content
Zwraca tresc dokumentu. Jezeli jest to dokument HTML, zawartoscia jest wszystko po znaczniku BODY. ze znacznikw BODY i HEAD sa zapamietywane w rekordzie obiektu. Parz rwniez: hw_Document_Attributes(), hw_Document_Size() i hw_DocumentSetContent(). Dane
string hw_Document_Content( int hw_document )

hw_Document_SetContent
Zapisuje lub zmienia zawartosc dokumentu. Jezeli dokument jest w formacie HTML, zawartosc stanowi wszystko po znaczniku BODY. Dane ze znacznikw HEAD i BODY sa przechowywane w rekordzie obiektu. Jezeli informacje te zostana umieszczone w zawartosci dokumentu, po wstawieniu dokumentu serwer Hyperwave zmieni odpowiednio rekord obiektu; nie jest to najlepsze rozwiazanie. Jezeli funkcja sie nie powiedzie, dokument bedzie zawieral poprzednia zawartosc. Patrz rwniez: hw_Document_Attributes(), hw_Document_Size() i hw_Document_Content().
string hw_DocumentSetContent( int hw_document, string content )

hw_Document_Size
dokumentu w bajtach. Patrz rwniez: hw_Document_BodyTag() i W celu zachowania zgodnosci akceptowana jest rwniez nazwa hw_DocumentSize, ale jej stosowanie nie jest zalecane.
hw_Document_Attributes().
int hw_Document_Size( int hw_document )

Zwraca

wielkosc

237

PHP Kompendium wiedzy

hw_EditText
Przesyla test dokumentu na serwer. Rekord obiektu dokumentu nie moze byc modyfikowany do czasu zakonczenia edycji. Funkcja ta dziala jedynie dla dokumentw czysto tekstowych. Nie otwiera specjalnego polaczenia i przez to na czas przesylania blokuje polaczenie sterujace. Patrz rwniez: hw_PipeDocument(), hw_FreeDocument(), hw_Document_BodyTag(), hw_Document_Size(), hw_Output_Document() i hw_GetText().
int hw_EditText( int connection, int hw_document )

hw_Error
Zwraca kod ostatniego bledu. Jezeli nie wystepowaly zadne bledy, zwraca 0. Blad odnosi sie do ostatnio wykonanej komendy.
int hw_Error( int connection )

hw_ErrorMsg
False.

Zwraca ciag zawierajacy ostatni komunikat bledu lub ciag No Error. Jezeli funkcja sie nie udala, zwraca Komunikat bledu odnosi sie do ostatnio wykonanej komendy.

string hw_ErrorMsg( int connection )

hw_Free_Document
Zwalnia pamiec zajmowana przez dokument Hyperwave.
int hw_Free_Document( int hw_document )

hw_GetAnchors
Zwraca tablice identyfikatorw obiektw z laczami dokumentw z identyfikatorem obiektu $objectID.
array hw_GetAnchors( int connection, int objectID )

hw_GetAnchorsObj
Zwraca tablice rekordw obiektw z laczami dokumentw z identyfikatorem obiektu $objectID.
array hw_GetAnchorsObj( int connection, int objectID )

hw_GetAndLock
Zwraca rekord obiektu dla obiektu o identyfikatorze $objectID. Dodatkowo naklada blokade na obiekt, dzieki czemu inni uzytkownicy nie maja do niego dostepu do czasu zwolnienia blokady. Patrz rwniez: hw_Unlock() i hw_GetObject().
string hw_GetAndLock( int connection, int objectID )

hw_GetChildColl
Zwraca tablice identyfikatorw obiektw. Kazdy z identyfikatorw nalezy do kolekcji potomnej w kolekcji o identyfikatorze $objectID. Funkcja nie zwraca dokumentw potomnych. Patrz rwniez: hw_GetChildren() i hw_GetChildDocColl().
array hw_GetChildColl( int connection, int objectID )

hw_GetChildCollObj
Zwraca tablice rekordw obiektw. Kazdy z rekordw obiektw nalezy do kolekcji potomnej w kolekcji o identyfikatorze $objectID. Funkcja nie zwraca dokumentw potomnych. Patrz rwniez: hw_ChildrenObj() i hw_GetChildDocCollObj().
array hw_GetChildCollObj( int connection, int objectID )

Dodatek A - Funkcje

238

hw_GetChildDocColl
Zwraca tablice identyfikatorw obiektw dokumentw potomnych w kolekcji. Patrz rwniez: hw_GetChildren() i hw_GetChildColl().
array hw_GetChldDocColl( int connection, int objectID )

hw_GetChildDocCollObj
hw_ChildrenObj()

Zwraca tablice rekordw obiektw dla dokumentw potomnych w kolekcji. Patrz rwniez: i hw_GetChildCollObj().

array hw_GetChildDocCollObj( int connection, int objectID )

hw_GetObject
Jezeli drugi parametr jest licza calkowita, zwraca rekord obiektu dla obiektu o identyfikatorze $objectID. Jezeli drugi parametr jest tablica liczb calkowitych, funkcja zwrci tablice rekordw obiektw. W tym przypadku analizowany jest rwniez trzeci parametr ciag zapytania.
array hw_GetObject( int connection, {int,array} objectID, string query )

Ciag zapytania posiada nastepujaca skladnie:


<expr> ::= "(" <expr> ")" | "!" <expr> | /* Negacja */ <expr> "||" <expr> | /* OR */ <expr> "&&" <expr> | /* AND */ <attribute> <operator> <value> <attribute> ::= /* dowolna nazwa atrybutu (Tytul, Autor, TypDokumentu ...) */ <operator> ::= "=" | /* rwny */ "<" | /* mniejszy od (porwnanie ciagw) */ ">" | /* wiekszy od (porwnanie ciagw) */ "~" /* porwnywanie wyrazen regularnych */

Zapytanie pozwala na dalszy wybr odpowiednich obiektw z listy zwracanych obiektw. W przeciwienstwie do pozostalych funkcji zapytan, to zapytanie moze dzialac na atrybutach bez indeksw. Ilosc zwracanych rekordw obiektw zalezy od zapytania i od tego, czy mozliwy jest dostep do dokumentu. Patrz rwniez: hw_GetAndLock() i hw_GetObjectByQuery().

hw_GetObjectByQuery
Przeszukuje wszystkie obiekty na serwerze i zwraca tablice identyfikatorw obiektw. Maksymalna ilosc identyfikatorw jest ograniczona do $max_hits. Jezeli $max_hits ma wartosc -1, maksymalna ilosc zwracanych identyfikatorw nie jest ograniczona. Zapytanie dziala jedynie na atrybutach posiadajacych indeksy. Patrz rwniez: hw_GetObjectByQueryObj().
array hw_GetObjectByQuery( int connection, string query, int max_hits )

hw_GetObjectByQueryColl
Przeszukuje obiekty w kolekcji o identyfikatorze $objectID i zwraca tablice identyfikatorw obiektw. Maksymalna ilosc identyfikatorw jest ograniczona do $max_hits. Jezeli $max_hits ma wartosc -1, maksymalna ilosc zwracanych identyfikatorw nie jest ograniczona. Zapytanie dziala jedynie na atrybutach posiadajacych indeksy. Patrz rwniez: hw_GetObjectByQueryCollObj().
array hw_GetObjectByQueryColl( int connection, int objectID, string query, int max_hits )

hw_GetObjectByQueryCollObj
Przeszukuje obiekty w kolekcji o identyfikatorze $objectID i zwraca tablice rekordw obiektw. Maksymalna ilosc obiektw jest ograniczona do $max_hits. Jezeli $max_hits ma wartosc -1, maksymalna ilosc zwracanych obiektw nie jest ograniczona. Zapytanie dziala jedynie na atrybutach posiadajacych indeksy. Patrz rwniez: hw_GetObjectByQueryColl().
array hw_GetObjectByQueryCollObj( int connection, int objectID, string query, int max_hits )

239

PHP Kompendium wiedzy

hw_GetObjectByQueryObj
Przeszukuje wszystkie obiekty na serwerze i zwraca tablice rekordw obiektw. Maksymalna ilosc identyfikatorw jest ograniczona do $max_hits. Jezeli $max_hits ma wartosc -1, maksymalna ilosc zwracanych identyfikatorw nie jest ograniczona. Zapytanie dziala jedynie na atrybutach posiadajacych indeksy. Patrz rwniez: hw_GetObjectByQuery().
array hw_GetObjectByQueryObj( int connection, string query, int max_hits )

hw_GetParents
Zwraca indeksowana tablice identyfikatorw obiektw. Kazdy identyfikator obiektu jest obiektem podrzednym do obiektu o identyfikatorze $objectID.
array hw_GetParents( int connection, int objectID )

hw_GetParentsObj
Zwraca indeksowana tablice rekordw obiektw oraz dodatkowo skorelowana tablice z danymi statystycznymi o rekordach obiektw. Dodatkowa tablica jest umieszczona w ostatnim elemencie zwracanej tablicy. Kazdy z rekordw obiektw jest obiektem podrzednym do obiektu o identyfikatorze $objectID.
array hw_GetParentsObj( int connection, int objectID )

hw_GetRemote
Zwraca zdalny dokument. Dokumenty zdalne w sensie Hyperwave sa dokumentami pobieranymi z zewnetrznych zrdel. Najczesciej dokumentami zdalnymi sa strony WWW lub zapytania do baz danych. Aby byl mozliwy dostep do zewnetrznych zrdel dokumentw, Hyperwave wprowadza protokl Hyperwave Gateway Interface (HGI), ktry jest podobny do CGI. W chwili obecnej poprzez HGI mozna uzyskac dostep do serwerw http, ftp i niektrych baz danych. Wywolanie hw_GetRemote() zwraca dokument pochodzacy ze zdalnego zrdla danych. Jezeli chcesz uzyc tej funkcji, powinienes dobrze znac HGI. Powinienes rwniez rozwazyc uzycie PHP zamiast Hyperwave do komunikacji z zdalnym zrdlem danych. Dodanie obslugi baz danych poprzez Hyperwave bedzie bardziej skomplikowane, niz wykonanie tego samego w PHP. Patrz rwniez: hw_GetRemoteChildren().
int hw_GetRemote( int connection, int objectID )

hw_GetRemoteChilden
Zwraca obiekty pochodne do zdalnego dokumentu. Obiektami pochodnymi zdalnego dokumentu sa rwniez zdalne dokumenty. Funkcja ta moze byc wykorzystana, jezeli mozna ograniczyc zapytanie bazy danych. Jest to opisane w podreczniku Hyperwave Programmers Guide. Jezeli istnieje tylko jeden obiekt pochodny, funkcja zwraca ten obiekt sformatowany przez HGI. Jezeli istneije wiecej niz jeden element pochodny, funkcja zwraca tablice rekordw obiektw, z ktrych kazdy byc moze moze byc wartoscia wejsciowa w kolejnym wywolaniu funkcji hw_GetRemoteChildren(). Obiekty te sa obiektami wirtualnymi i nie istnieja w serwerze Hyperwave, i dlatego nie posiadaja wlasnych identyfikatorw. Jezeli zamierzasz wykorzystac ta funkcje powinienes dobrze znac HGI. Powinienes rwniez rozwazyc uzycie PHP zamiast Hyperwave do komunikacji z zdalnym zrdlem danych. Dodanie obslugi baz danych poprzez Hyperwave bedzie bardziej skomplikowane, niz wykonanie tego samego w PHP. Patrz rwniez: hw_GetRemote().

hw_GetSrcByDestObj
Zwraca rekordy obiektw wskazujacych na obiekt o identyfikatorze dokumentem lub zakotwiczeniem. Patrz rwniez: hw_GetAnchors().
array hw_GetSrcByDestObj( int connection, int objectID )

$objectID.

Obiekt ten moze byc

Dodatek A - Funkcje

240

hw_GetText
Zwraca dokument z identyfikatorem $objectID. Jezeli dokument posiada zakotwiczenia, ktre mozna do niego wstawic, zostana one wstawione. Opcjonalny parametr $rootID/$prefix moze byc ciagiem lub liczba calkowita. Jezeli jest to liczba, okresla w jaki sposb wstawiane sa do dokumentu lacza. Wartoscia domyslna jest 0 i powoduje to utworzenie laczy z nazwy i obiektu docelowego lacza. Jest to uzyteczne przy tworzeniu aplikacji WWW. Jezeli lacze wskazuje na nazwe internet_movie, lacze HTML bedzie mialo postac <A HREF="/internet_movie">. Polozenie zrdla i celu lacza jest ignorowane. Bedziesz musial tak ustawic swj serwer WWW, aby zamienial takie lacza na, na przyklad /my_script.php3/internet_movie. Skrypt my_script.php3 musi sprawdzic zawartosc $PATH_INFO i odczytac dokument. Wszystkie lacza powinny zaczynac sie od /my_script.php3/. Jezeli nie chcesz tego robic, mozesz ustawic odpowiednio parametr opcjonalny $rootID/$prefix na dowolny prefiks. W tym przypadku musi byc to ciag.
int hw_GetText( int connection, int objectID [, mixed rootID/prefix])

Jezeli $rootID/$prefix jest liczba rzna od 0, lacze jest tworzone z wszystkich nazw wzgledem biezacego obiektu, zaczynajac od $rootID/$prefix oddzielanych ukosnikami. Jezeli na przyklad poprzedni dokument internet_movie jest umieszczony w a-b-c-internet_movie, gdzie znak - jest separatorem hierarchii w serwerze Hyperwave, a dokument zrdlowy znajduje sie w a-b-d-source, wynikowe lacze HTML bedzie mialo postac <A HREF="../c/internet_movie">. Jest to korzystne, jezeli chcesz zapisac cala zawartosc serwera na dysk i odwzorowac hierarchie dokumentw w systemie plikw. Funkcja ta dziala jedynie dla dokumentw tekstowych. Nie otwiera ona specjalnego polaczenia, wiec blokuje na czas przesylu polaczenie sterujace. Patrz rwniez: hw_PipeDocument(), hw_FreeDocument(), hw_Document_BodyTag(), hw_Document_Size() i hw_Open_Document().

hw_getusername
Zwraca nazwe uzytkownika polaczenia.
string hw_getusername( int connection )

hw_Identify
Autoryzuje uzytkownika za pomoca ciagw $username i $password. Autoryzacja jest wazna jedynie w biezacej sesji. Funkcja nie jest potrzebna zbyt czesto. W wiekszosci przypadkw latwiejsza metoda autoryzacji jest otwarcie polaczenia. Patrz rwniez: hw_Connect().

hw_InCollections
Sprawdza, czy zbir obiektw (dokumentw lub kolekcji) przekazanych w $object_id_array jest czescia kolekcji przekazanych w $collection_id_array. Jezeli czwarty parametr, $return_collections jest rwny 0, podzbir identyfikatorw bedacych czescia kolekcji (na przyklad dokumenty lub kolekcje podrzedne do jednej, lub wiecej kolekcji) jest zwracany w postaci tablicy. Jednak gdy czwarty argument jest rwny 1, zbir kolekcji posiadajacych co najmniej jeden obiekt w znalezionym podzbiorze obiektw podrzednych jest zwracany w postaci tablicy. Opcja ta pozwala na przyklad, na wyrznienie czesci hierarchii dokumentw, w ktrej zawarte sa wyniki przekazanego zapytania.
array hw_InCollections( int connection, array object_id_array, array collection_id_array, int return_collections)

hw_Info
Zwraca dane na temat biezacego polaczenia. Zwracany ciag posiada nastepujaca postac: <Serwer>, <Host>, <Port>, <Uzytkownik>, <Port na kliencie>, <Zamiana bajtw>.
string hw_Info( int connection )

241

PHP Kompendium wiedzy

hw_InsColl
Wstawia nowa kolekcje z atrybutami zawartymi w tablicy $objectID.
$object_array,

do kolekcji o identyfikatorze

int hw_InsColl( int connection, int objectID, array object_array )

hw_InsDoc
$parentID.

Wstawia nowy dokument z atrybutami zawartymi w $object_record, do kolekcji o identyfikatorze Funkcja wstawia rekord obiektu lub rekord obiektu oraz tekst przekazany w $text, o ile zostal podany. Jezeli chcesz wstawic dokument dowolnego typy, nalezy uzyc funkcji hw_insertdocument(). Patrz rwniez: hw_InsertDocument() i hw_InsColl().
int hw_InsDoc( int connection, int parentID, string object_record, string 3text )

hw_InsertDocument
Przesyla dokument do kolekcji o identyfikatorze $parentID. Dokument musi byc wczesniej utworzony za pomoca funkcji hw_NewDocument(). Nalezy sie upewnic, ze rekord obiektu posiada co najmniej nastepujace atrybuty: Type, DocumentType, Title i Name. Przydatne jest ustawienie atrybutu MimeType. Funkcja zwraca identyfikator obiektu nowego dokumentu, lub False. Patrz rwniez: hw_PipeDocument().
int hw_InsertDocument( int connection, int parent_id, int hw_document )

hw_InsertObject
Umieszcza obiekt na serwerze. Obiekt musi byc prawidlowym obiektem Hyperwave. Wiecej danych na ten temat znajduje sie w dokumentacji HG-CSP.
Uwaga Jezeli chcesz wstawic zakotwiczenie atrybut position musi byc zawsze ustawiony na wartosc poczatkowa, koncowa lub invisible. Pozycje niewidoczne sa wymagane, jezeli opis ni ma odpowiedniego lacza do tekstu opisu.

Patrz rwniez: hw_PipeDocument(), hw_InsertDocument(), hw_InsDoc() i hw_InsColl().


int hw_InsertObject( int connection, string object_rec, string parameter )

hw_mapid
Mapuje identyfikator globalnego obiektu na dowolnym serwerze Hyperwave, nawet jezeli nie wykonano podlaczenia do niego za pomoca hw_connect(), do identyfikatora obiektu wirtualnego. Ten obiekt wirtualny moze byc uzywany identycznie, jak kazdy inny identyfikator obiektu, na przyklad do pobrania rekordu obiektu za pomoca hw_getobject(). Identyfikator serwera jest pierwsza czescia globalnego identyfikatora obiektu (GOid) i w chwili obecnej jest to numer IP w postaci liczby.
Uwaga Aby uzyc tej funkcji nalezy ustawic znacznik F_DISTRIBUTED, co obecnie mozna wykonac jedynie w czasie kompilacji pliku hg_comm.c. Nie jest to wykonywane domyslnie. Nalezy zapoznac sie z komentarzami na poczatku pliku hg_comm.c.
int hw_mapid( int connection, int server_id, int object_id )

hw_Modifyobject
Polecenie to pozwala na usuniecie, dodanie lub zmiane poszczeglnych atrybutw rekordu obiektu. Obiekt jest okreslony za pomoca identyfikatora $object_to_change. Pierwsza tablica, $remove, jest lista atrybutw do usuniecia. Druga tablica, $add, jest lista atrybutw ktre nalezy dodac do obiektu. W celu zmiany atrybutu, nalezy usunac stary atrybut i dodac nowy. Funkcja hw_Modifyobject() zawsze najpierw usuwa stare atrybuty a potem dodaje nowe chyba, ze wartosci atrybutw do usuniecia nie sa tablica ciagw. Ostatni parametr wskazuje, czy Dodatek A - Funkcje 242

operacja ma byc wykonana w sposb rekurencyjny. Wartosc 1 oznacza rekurencyjne wywolanie. Jezeli nie jest mozliwa modyfikacja niektrych obiektw, zostana pominiete bez zadnej informacji o tym fakcie. Funkcja hw_error() moze nie wskazac zadnego bledu, choc nie wszystkie obiekty beda zmienione.
int hw_Modifyobject( int connecion, int object_to_change, array remove, array add, int mode )

Kluczami w obu tablicach sa nazwy atrybutw. Wartoscia kazdego z elementw tablicy moze byc tablica ciagw, ciag, badz cokolwiek innego. Jezeli bedzie to tablica, wartosc atrybutu jest tworzona z klucza, srednika i wartosci. Wstawienie pustego ciagu spowoduje calkowite usuniecie atrybutu. Jezeli wartosc nie jest ani ciagiem ani tablica, ale na przyklad liczba, nie beda podejmowane zadne operacje na atrybucie. Jest to niezbedne, jezeli chcesz dodac calkowicie nowy atrybut a nie wartosc istniejacego atrybutu. Jezeli tablica z elementami do usuniecia bedzie zawierala pusty ciag dla atrybutu, usuniecie sie nie uda. Ustawienie wartosci tego atrybutu na, na przyklad 0, spowoduje, ze nie bedzie podjeta prba jego usuniecia, natomiast dodanie atrybutu powiedzie sie. Jezeli chcesz zmienic atrybut Name z biezaca wartoscia ksiazki na artykuly, powinienes utworzyc dwie tablice i wywolac funkcje hw_modifyobject(). Przyklad: zmiana atrybutu
// $connect jest istniejacym polaczeniem do serwera Hyperwave // $objid jest identyfikatorem obiektu do zmiany $remarr = array("Name" => "ksiazki"); $addarr = array("Name" => "artykuly"); $hw_modifyobject($connect, $objid, $remarr, $addarr);

Aby usunac lub dodac pare nazwawartosc, nalezy przekazac tablice zawierajace dodawane i usuwane atrybuty przekazujac w trzecim parametrze pusta tablice. Jezeli atrybut jest pierwszym atrybutem o tej nazwie, nalezy ustawic wartosci w tablicy atrybutw do usuniecia na liczby calkowite. Przyklad: dodanie calkowicie nowego atrybutu
// $connect jest istniejacym polaczeniem do serwera Hyperwave // $objid jest identyfikatorem obiektu do zmiany $remarr = array("Name" => 0); $addarr = array("Name" => "artykuly"); $hw_modifyobject($connect, $objid, $remarr, $addarr);

Uwaga Atrybuty w wielu jezykach, na przyklad Title moga byc zmieniane na dwa sposoby. Pierwszym sposobem jest wpisywanie wartosci atrybutw w postaci jezyk:tytul, lub przekazywanie tablicy z elementami dla kazdego jezyka zapisanymi w identyczny sposb jak poprzednio. Poprzedni przyklad moze byc zapisany w nastepujacy sposb:

Przyklad: zmiana atrybutu Title


$remarr = array("Title" => "en:Books"); $addarr = array("Title" => "en:Articles"); $hw_modifyobject($connect, $objid, $remarr, $addarr);

lub Przyklad: zmiana atrybutu Title


$remarr = array("Title" => array("en" => "Books")); $addarr = array("Title" => array("en" => "Articles", "ge"=>"Artikel"); $hw_modifyobject($connect, $objid, $remarr, $addarr);

W przykladzie tym zostanie usuniety angielski tytul Books i dodany tytul angielski Articles i niemiecki Artikel. Przyklad: usuwanie atrybutu
$remarr = array("Title" => ""); $addarr = array("Title" => "en:Articles"); $hw_modifyobject($connect, $objid, $remarr, $addarr);

Uwaga Wykonanie poprzedniego przykladu spowoduje usuniecie wszystkich atrybutw o nazwie Title i dodanie nowego atrybutu Title. Jest to wygodne, jezeli chcesz usuwac atrybuty w sposb rekurencyjny. Jezeli chcesz usunac wszystkie atrybuty o zadanej nazwie, musisz przekazac pusty ciag jako wartosc atrybutu. Jedynie atrybuty Title, Description i Keyword prawidlowo obsluguja prefiksy jezykw. Jezeli atrybut nie posiada prefiksu jezyka, uzyty zostanie prefiks xx. Atrybut Name ma specjalne znaczenie; w niektrych przypadkach nie jest mozliwe jego calkowite usuniecie. Otrzymasz wtedy komunikat bledu Change of base attribute (nie jest jasna przyczyna tego bledu). Dlatego zawsze musisz dodawac nowy atrybut Name przed usunieciem starego. Uwaga Nie musisz otaczac wywolania tej funkcji wywolaniami hw_getandlock() i hw_unlock(). Funkcja hw_modifyobject() robi to samodzielnie. Zwraca True w przypadku pomyslnego wykonania i False w przypadku bledu.

243

PHP Kompendium wiedzy

hw_Mv
Przenosi obiekt o identyfikatorze podanym w drugim parametrze z kolekcji i identyfikatorze $source do kolekcji o identyfikatorze $destination. Jezeli identyfikator kolekcji docelowej wynosi 0, obiekt jest usuwany ze zrdlowej kolekcji. Jezeli jest to ostatni egzemplarz obiektu, zostanie on usuniety. Jezeli chcesz usunac wszystkie wystapienia za pomoca jednego wywolania, nalezy uzyc funkcji hw_deleteobject(). Zwracana wartosc jest iloscia przeniesionych obiektw. Patrz rwniez: hw_cp() i hw_deleteobject().
int hw_Mv( int connection, array object_id_array, int souce_id, int destination_id )

hw_New_Document
Zwraca nowy dokument Hyperwave. Zawartosc dokumentu jest przekazana w parametrze $document_data, natomiast rekord obiektu w $object_record. Wielkosc danych musi byc przekazana w parametrze $document_size. Funkcja ta nie wstawia dokumentu do serwera Hyperwave. Patrz rwniez: hw_FreeDocument(), hw_Document_Size(), hw_Document_BodyTag(), hw_Output_Document() i hw_InsertDocument().
int hw_new_document (string object_record, string document_data, int document_size)

hw_Objrec2Array
Konwertuje $object_record na tablice obiektw. Kluczami wynikowej tablicy sa nazwy atrybutw. Atrybuty wielowartosciowe, takie jak Title, w rznych jezykach tworza wlasne tablice. Kluczami w tych tablicach czesci stojace z lewej strony dwukropka. Czesc ta musi miec dwa znaki. Inne wartosci wielowartosciowe nie posiadajace prefiksw tworza indeksowana tablice. Jezeli nie podany zostal parametr opcjonalny, atrybuty Title, Description i Keyword sa traktowane jako atrybuty jezyka,, natomiast atrybuty Group, Parent i HtmlAttr sa traktowane jako wartosci wielowartosciowe bez prefiksu. Przekazujac tablice zawierajaca typy kazdego z argumentw mozna zmienic to zachowanie. Tablica jest tablica asocjacyjna z nazwa atrybutu jako klucze i wartosciami bedacymi jedna z wartosci HW_ATTR_LANG lub HW_ATTR_NONE. Patrz rwniez: hw_array2objrec().
array hw_objrec2array (string object_record [, array format])

hw_Output_Document
hw_OutputDocument(),

Drukuje dokument bez znacznika BODY. Dla zgodnosci z poprzednimi wersjami mozna uzyc nazwy ale jest to postac przestarzala.

int hw_output_document (int hw_document)

hw_pConnect
W przypadku powodzenia zwraca numer polaczenia, lub False w przypadku, gdy polaczenie nie moze byc wykonane. Otwiera trwale polaczenie do serwera Hyperwave. Kazdy z argumentw oprcz numeru portu, powinien byc ciagiem znakw. Argumenty $username i $password sa opcjonalne. W takim przypadku nie jest wykonywana autoryzacja na serwerze. Jest to zblizone do korzystania z konta goscia. Funkcja zwraca numer polaczenia, ktry jest przekazywany do wszystkich funkcji Hyperwave. Mozna miec kilka jednoczesnie otwartych trwalych polaczen. Patrz rwniez: hw_Connect().
int hw_pconnect (string host, int port, string username, string password)

hw_PipeDocument
Zwraca dokument Hyperwave o identyfikatorze obiektu $objectID. Jezeli dokument posiada mozliwe do wstawienia zakotwiczenia, zostana one wstawione. Dokument zostanie przeslany poprzez polaczenie specjalne, ktre nie blokuje polaczenia sterujacego. Patrz rwniez: hw_GetText(). Wiecej informacji na temat wstawiania laczy znajduje sie w opisie funkcji hw_FreeDocument(), hw_Document_Size(), hw_Document_BodyTag() i hw_Output_Document().
int hw_pipedocument (int connection, int objectID)

Dodatek A - Funkcje

244

hw_Root
Zwraca identyfikator obiektu kolekcji korzenia; w chwili obecnej posiada ona wartosc 0. Kolekcja potomna tej kolekcji jest glwna kolekcja serwera.
int hw_root ()

hw_Unlock
Odblokowuje dokument, wiec uzytkownicy maja nw do niego dostep. Patrz rwniez: hw_GetAndLock().
int hw_unlock (int connection, int objectID)

hw_Who
Zwraca tablice z uzytkownikami obecnie zalogowanymi na serwerze Hyperwave. Kazda pozycja jest kolejna tablica, zawierajaca atrybuty: identyfikator elementu, nazwa, system, pola onSinceDate, onSinceTime, TotalTime, oraz self. Wartoscia self jest 1 jezeli pozycja nalezy do uzytkownika inicjujacego zadanie.
int hw_who (int connection)

ibase_close
Zamyka polaczenie z baza danych InterBase identyfikowane przez identyfikator polaczenia zwracany przez funkcje ibase_connect(). Jezeli identyfikator polaczenia jest pominiety, funkcja dziala na ostatnio otwartym polaczeniu. Domyslna transakcja w tym polaczeniu jest zatwierdzana, natomiast pozostale transakcje sa wycofywane.
int ibase_close ([int connection_id])

ibase_connect
Nawiazuje polaczenie z serwerem InterBase. Argument $database musi byc sciezka do pliku bazy danych na serwerze. Jezeli serwer nie jest serwerem lokalnym, musi byc poprzedzony albo ciagiem hostname: (TCP/IP), //hostname (NetBEUI) lub hostname@ (IPX/SPX) w zaleznosci od protokolu uzywanego w tym polaczeniu. Parametry $username i $password moga byc pobierane w dyrektywach konfiguracji ibase.default_user i ibase.default_password. Parametr $charset jest domyslnym zestawem znakw dla bazy danych. Parametr $buffers okresla ilosc buforw bazy danych zakladanych na serwerze. Jezeli podane zostanie 0 lub parametr zostanie opuszczony, serwer zaklada domyslna dla siebie ilosc buforw. Parametr $dialect wybiera domyslny dialekt SQL obowiazujacy dla wszystkich wyrazen wykonywanych poprzez biezace polaczenie. Wartoscia domyslna jest najwyzszy dialekt obslugiwany przez biblioteki klienta. Jezeli ibase_connect() jest wywolywany po raz drugi z tymi samymi parametrami, nie jest tworzone nowe polaczenie. Zamiast tego zwracany jest identyfikator istniejacego polaczenia. Polaczenie z serwerem jest zamykane natychmiast po zakonczeniu wykonywania skryptu, chyba, ze wczesniej zostala wywolana funkcja ibase_close().
int ibase_connect(string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role]]]]]])

Przyklad: ibase_connect()
<?php $dbh = ibase_connect ($host, $username, $password); $stmt = 'SELECT * FROM tblname'; $sth = ibase_query ($dbh, $stmt); while ($row = ibase_fetch_object ($sth)) { print $row->email . "\n"; } ibase_close ($dbh); ?>

Uwaga Parametry $buffers i $dialect zostaly dodane w PHP4-RC2. Dzialaja one jedynie z serwerem InterBase 6 i nowszymi od niego. Parametr $role dziala jedynie z InterBase 5 i wyzszymi.

Patrz rwniez: ibase_pconnect(). 245 PHP Kompendium wiedzy

ibase_execute
Wykonuje zapytanie przygotowane za pomoca ibase_prepare(). W przypadku, gdy to samo zapytanie jest powtarzane dla rznych parametrw, jest to o wiele bardziej efektywne niz wykorzystanie ibase_query().
int ibase_execute (int query [, int bind_args])

Przyklad: ibase_execute()
<?php $updates 1 => 5 => 7 => ); = array( 'Eric', 'Filip', 'Larry'

$query = ibase_prepare("UPDATE FOO SET BAR = ? WHERE BAZ = ?"); while (list($baz, $bar) = each($updates)) { ibase_execute($query, $bar, $baz); } ?>

ibase_fetch_object
Pobiera wiersz w postaci pseudoobiektu korzystajac z
ibase_execute().
object ibase_fetch_object (int result_id)

$result_id

zwrconego przez

ibase_query()

lub

Przyklad: ibase_fetch_object()
<php $dbh = ibase_connect ($host, $username, $password); $stmt = 'SELECT * FROM tblname'; $sth = ibase_query ($dbh, $stmt); while ($row = ibase_fetch_object ($sth)) { print $row->email . "\n"; } ibase_close ($dbh); ?>

Patrz rwniez: ibase_fetch_row().

ibase_fetch_row
Zwraca kolejny wiersz korzystajac z identyfikatora wyniku zwracanego przez funkcje ibase_query().
array ibase_fetch_row (int result_identifier)

ibase_free_query
Zwalnia zapytanie przygotowane przez ibase_prepare().
int ibase_free_query (int query)

ibase_free_result
Zwalania wynik tworzony przez ibase_query().
int ibase_free_result (int result_identifier)

ibase_num_fields
Zwraca liczbe okreslajaca ilosc pl w wyniku zapytania. Patrz rwniez ibase_field_info().
Uwaga Funkcja ibase_num_fields() nie dziala jeszcze w PHP 4.

Przyklad: ibase_num_fields() Dodatek A - Funkcje 246

<?php $dbh = ibase_connect ($host, $username, $password); $stmt = 'SELECT * FROM tblname'; $sth = ibase_query ($dbh, $stmt); if (ibase_num_fields($sth) > 0) { while ($row = ibase_fetch_object ($sth)) { print $row->email . "\n"; } } else { die ("No Results were found for your query"); } ibase_close ($dbh); ?>

ibase_pconnect
Dziala bardzo podobnie do ibase_connect() z dwiema powaznymi rznicami. Po pierwsze, w czasie dolaczania do serwera funkcja prbuje odszukac istniejace (trwale) polaczenie otwarte z tym samym zestawem argumentw. Jezeli zostanie znalezione takie polaczenie, jego identyfikator jest zwracany i nie jest tworzone nowe polaczenie. Po drugie, Polaczenie do serwera InterBase nie jest zamykane po zakonczeniu wykonywania skryptu. Polaczenie pozostaje otwarte do wykorzystania w przyszlosci (ibase_close() nie zamyka polaczen utworzonych przez ibase_pconnect()). Polaczenie takie nazywane jest z tego powodu polaczeniem trwalym. Opis parametrw przekazywanych do funkcji jest zamieszczony przy opisie funkcji ibase_connect(); sa one identyczne.
int ibase_pconnect(string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role]]]]]])

ibase_prepare
Przygotowuje zapytanie dodajac obsluge parametrw dolaczanych pzniej za pomoca funkcji ibase_execute().
int ibase_prepare ([int link_identifier, string query])

ibase_query
Wykonuje zapytanie na basie danych InterBase i zwraca identyfikator wyniku wykorzystywany w funkcjach ibase_fetch_row(), ibase_fetch_object(), ibase_free_result() i ibase_free_query(). Mimo, ze funkcja ta obsluguje dolaczanie zmiennych do parametrw, uzywanie tego udogodnienia w tej wlasnie funkcji nie ma wielkiego sensu. Przyklad uzycia funkcji jest umieszczony przy opisie funkcji ibase_prepare() i ibase_execute().
int ibase_query ([int link_identifier, string query [, int bind_args]])

ibase_timefmt
Ustala format znacznika czasu, daty i czasu dla kolumn tych typw zwracanych zapytaniach. Wewnetrznie kolumny sa formatowane przez funkcje C strftime(), wiec wszelkie szczegly na temat ciagu formatujacego znajduja sie w jej dokumentacji. Parametr $columntype jest jedna ze stalych IBASE_TIMESTAMP, IBASE_DATE i IBASE_TIME. Jezeli zostanie ion opuszczony, przyjmowana jest wartosc IBASE_TIMESTAMP w celu zapewnienia zgodnosci z poprzednimi wersjami.
int ibase_timefmt (string format [, int columntype])

Przyklad: ibase_timefmt()
<?php // kolumny InterBase 6 typu TIME beda zwracane w postaci // '05 godzin 37 minut'. ibase_timefmt("%H godzin %M minut", IBASE_TIME); ?>

Mozna rwniez ustawic domyslny format za pomoca dyrektyw konfiguracji PHP ibase.timestampformat, i ibase.timeformat. Parametr $columntype zostal dodany w PHP 4.0. Ma on znaczenie jedynie w wersjach InterBase 6 i wyzszych.
ibase.dateformat

247

PHP Kompendium wiedzy

Uwaga W PHP 4.0 wprowadzono zmiane, ktra powodowala niezgodnosc z poprzednimi wersjami, zmieniajac nazwe dyrektywy konfiguracji ibase.timeformat na ibase.timestampformat oraz dodane zostaly dyrektywy ibase.dateformat i ibase.timeformat w celu ulepszenia dzialania funkcji.

icap_close
Zamyka podany strumien icap.
int icap_close (int icap_stream [, int flags])

icap_delete_event
Usuwa zdarzenie z kalendarza o identyfikatorze podanym w $uid. Zwraca True.
string icap_delete_event (int sream_id, int uid)

icap_fetch_event
Pobiera zdarzenie okreslone przez $event_id ze strumienia kalendarza.
int icap_fetch_event (int stream_id, int event_id [, int options])

Zwraca obiekt zdarzenia zawierajacy nastepujace atrybuty: int id Identyfikator zdarzenia. int public True jezeli zdarzenie jest publiczne lub False, gdy jest prywatne. string category Ciag zawierajacy kategorie zdarzenia. string title Ciag zawierajacy tytul zdarzenia. string description Ciag z opisem zdarzenia . int alarm Ilosc minut przed zdarzeniem gdy wysylane jest powiadomienie lub alarm. object start Obiekt zawierajacy date i czas. object end Obiekt zawierajacy date i czas. Wszystkie pozycje daty i czasu zawieraja nastepujace atrybuty: int year rok int month miesiac int mday dzien miesiaca int hour godzina int min minuty int sec sekundy

icap_list_alarms
icap_list_alarms()

Zwraca tablice z identyfikatorami zdarzen ktre wysla alarm o podanej godzinie. Funkcja wymaga podania daty i czasu oraz strumienia kalendarza. Zwracana jest tablica identyfikatorw zdarzen z aktywnym alarmem o podanej godzinie.
int icap_list_alarms (int stream_id, array date, array time)

Wszystkie pozycje z data i czasem zawieraja nastepujace atrybuty: int year rok int month miesiac int mday dzien miesiaca int hour godzina int min minuty int sec sekundy

Dodatek A - Funkcje

248

icap_list_events
Zwraca tablice identyfikatorw zdarzen pomiedzy dwiema datami. Funkcja icap_list_events() pobiera ze strumienia identyfikatory zdarzen pomiedzy data poczatkowa i koncowa. Zwracana jest tablica identyfikatorw zdarzen pomiedzy podanymi datami.
array icap_list_events (int stream_id, int begin_date [, int end_date])

Wszystkie pozycje z data i czasem zawieraja nastepujace atrybuty: int year rok int month miesiac int mday dzien miesiaca int hour godzina int min minuty int sec sekundy

icap_open
W przypadku powodzenia zwraca strumien ICAP, natomiast w przypadku wystapienia bledu, False. Funkcja icap_open() otwiera polaczenie ICAP do podanego w $calendar magazynu. Jezeli podany jest parametr opcjonalny $options, jest on rwniez przekazany do otwieranej skrzynki pocztowej.
stream icap_open (string calendar, string username, string password, string options)

icap_snooze
Wlacza alarm dla zdarzenia kalendarza okreslonego przez $uid. Zwraca True.
string icap_snooze (int stream_id, int uid)

icap_store_event
Zapisuje zdarzenie w kalendarzu ICAP.
string icap_store_event (int stream_id, object event)

Obiekt zdarzenia zawiera nastepujace atrybuty: int id Identyfikator zdarzenia. int public 1 jezeli zdarzenie jest publiczne lub 0, gdy jest prywatne. string category Ciag zawierajacy kategorie zdarzenia. string title Ciag zawierajacy tytul zdarzenia. string description Ciag z opisem zdarzenia . int alarm Ilosc minut przed zdarzeniem gdy wysylane jest powiadomienie lub alarm. object start Obiekt zawierajacy date i czas. object end Obiekt zawierajacy date i czas. Wszystkie pozycje daty i czasu zawieraja nastepujace atrybuty: int year rok int month miesiac int mday dzien miesiaca int hour godzina int min minuty int sec sekundy Zwraca True w przypadku powodzenia operacji lub False w przypadku bledu.

ifxus_close_slob
Usuwa obiekt slob dla podanego w $bid identyfikatora obiektu slob. Zwraca wystapienia bledu, True w przypadku powodzenia operacji.
int ifxus_close_slob (int bid)

False

w przypadku

249

PHP Kompendium wiedzy

ifxus_create_slob
Tworzy obiekt slob i otwiera go. Tryby: 1 = LO_RDONLY, 2 = LO_WRONLY, 4 = LO_APPEND, 8 = LO_RDWR, 16 = LO_BUFFER, 32 = LO_NOBUFFER. Mozna rwniez uzyc stalych o nazwach IFX_LO_RDONLY, IFX_LO_WRONLY itd. Zwraca False w przypadku wystapienia bledu a w przypadku powodzenia, identyfikator obiektu slob.

ifxus_free_slob
Usuwa obiekt slob. Parametr $bid jest identyfikatorem obiektu slob. Zwraca wystapienia bledu i True w przeciwnym wypadku.
int ifxus_free_slob (int bid)

False

w przypadku

ifxus_open_slob
powinien byc identyfikatorem istniejacego obiektu. Tryby: 1 = Zwraca False w przypadku wystapienia bledu a w przeciwnym wypadku identyfikator nowego obiektu slob.
$bid LO_RDONLY, 2 = LO_WRONLY, 4 = LO_APPEND, 8 = LO_RDWR, 16 = LO_BUFFER, 32 = LO_NOBUFFER.
int ifxus_open_slob (long bid, int mode)

Otwiera obiekt slob. Parametr

ifxus_read_slob
Czyta n bajtw z obiektu slob. Parametr $bid jest identyfikatorem istniejacego obiektu slob, natomiast $nbytes jest iloscia bajtw do przeczytania. Zwraca False w przypadku wystapienia bledu a w przeciwnym wypadku zwraca ciag.
int ifxus_read_slob (long bid, long nbytes)

ifxus_seek_slob
Ustawia biezacy plik lub wyszukuje pozycje w otwartym obiekcie slob. Parametr $bid powinien byc identyfikatorem istniejacego obiektu slob. Tryby: 0 = LO_SEEK_SET, 1 = LO_SEEK_CUR, 2 = LO_SEEK_END natomiast $offset jest przesunieciem w bajtach. Zwraca False w przypadku wystapienia bledu a w przeciwnym wypadku pozycje w pliku.
int ifxus_seek_slob (long bid, int mode, long offset)

ifxus_tell_slob
Zwraca biezaca pozycje w pliku lub przesuniecie w otwartym obiekcie slob. Parametr $bid powinien byc identyfikatorem istniejacego obiektu slob. Zwraca False w przypadku wystapienia bledu a w przeciwnym wypadku pozycje w pliku.
int ifxus_tell_slob (long bid)

ifxus_write_slob
Zapisuje zawartosc ciagu do obiektu slob. Parametr $bid musi byc identyfikatorem obiektu slob, natomiast $content zawiera dane do zapisania. Zwraca False w przypadku wystapienia bledu, w przeciwnym przypadku ilosc zapisanych bajtw.
int ifxus_write_slob (long bid, string content)

ifx_affected_rows
Parametr $result_id powinien byc identyfikatorem wyniku zwracanym przez funkcje ifx_query() lub Zwraca ilosc wierszy zmienionych przez zapytanie zwiazane z $result_id. W przypadku operacji wstawienia, zamiany lub usuniecia, ilosc ta jest prawdziwa liczba operacji (sqlerrd[2]). W przypadku operacji SELECT nie jest dokladna liczba zwracanych wierszy, a jedynie oszacowaniem (sqlerrd[0]). Serwer bazy danych moze nigdy nie zwrcic ilosci wierszy zwracanych przez operacje SELECT w tej fazie operacji (zaraz po operacji
ifx_prepare().

Dodatek A - Funkcje

250

PREPARE,

po ustaleniu planu wykonania przez optymalizator), poniewaz nie rozpoczal on odczytywania zwracanych wierszy. Jest to uzyteczna funkcja do ograniczania zapytan do takich, ktre zwracaja rozsadna ilosc wierszy po przygotowaniu zapytania przez ifx_prepare(). Patrz rwniez: ifx_num_rows().
int ifx_affected_rows (int result_id)

Przyklad: wykorzystanie funkcji serwera Informix ifx_affected_rows()


$rid = ifx_prepare ("select * from emp where name like " . $name, $connid); if (! $rid) { ... blad ... } $rowcount = ifx_affected_rows ($rid); if ($rowcount > 1000) { printf ("Zapytanie zwraca zbyt duzo wierszy: (%d)\n<br>", $rowcount); die ("Prosze ograniczyc zapytanie<br>\n"); }

ifx_blobinfile_mode
Ustawia domyslny tryb przechowywania obiektw blob w zapytaniach przechowywanie blobw w pamieci, natomiast 1, przechowywanie ich w pliku.
void ifx_blobinfile_mode (int mode)

SELECT.

Tryb

oznacza

ifx_byteasvarchar
Ustawia domyslny tryb zapytaniach SELECT. Tryb zwracanie pola varchar z danymi tekstowymi.
void ifx_byteasvarchar (int mode)

powoduje zwracanie identyfikatora blob, natomiast 1,

ifx_close
Zawsze zwraca True. Funkcja ifx_close() powoduje zamkniecie polaczenia z baza danych Informix, skojarzona z podanym identyfikatorem polaczenia. Jezeli nie zostal podany identyfikator polaczenia, zamykane jest ostatnio otwarte polaczenie.
Uwaga nie jest to operacja niezbedna, poniewaz nietrwale polaczenia sa zamykane automatycznie po zakonczeniu wykonywania skryptu. Funkcja ifx_close() nie zamyka polaczen trwalych generowanych przez ifx_pconnect().

Patrz rwniez: ifx_connect() i ifx_pconnect().


int ifx_close ([int link_identifier])

Przyklad: Zamykanie polaczenia z baza danych Informix


$conn_id = ifx_connect ("mydb@ol_srv", "itsme", "mypassword"); ... potrzebne zapytania ... ifx_close($conn_id);

ifx_connect
Zwraca identyfikator polaczenia lub false w przypadku wystapienia bledu. Funkcja ifx_connect() nawiazuje polaczenie z serwerem Informix. Wszystkie argumenty sa opcjonalne i w przypadku opuszczenia ktregos z nich, z pliku konfiguracyjnego pobierane sa wartosci domyslne, ifx.default_host zawiera nazwe serwera biblioteki Informixa korzystaja ze zmiennej srodowiskowej INFORMIXSERVER), ifx.default_user zawiera nazwe uzytkownika a ifx.default_password zawiera domyslne haslo (jezeli nie jest zdefiniowana to bez hasla). Jezeli drugi raz wywolano funkcje ifx_connect() z tymi samymi argumentami, nie jest nawiazywane nowe polaczenie. Zamiast tego zwracany jest identyfikator istniejacego polaczenia. Polaczenie nie jest zamykane po zakonczeniu wykonywania skryptu lub po wywolaniu funkcji ifx_close(). Patrz rwniez: ifx_pconnect() i ifx_close().
int ifx_connect (string [database], string [userid], string [password])

Przyklad: Podlaczenie do bazy Informix


$conn_id = ifx_connect ("mydb@ol_srv", "itsme", "mypassword");

251

PHP Kompendium wiedzy

ifx_copy_blob
Tworzy kopie podanego obiektu blob. Parametr $bid jest identyfikatorem obiektu blob. Zwraca przypadku bledu, a w przeciwnym wypadku identyfikator nowego obiektu blob.
int ifx_copy_blob (int bid)

False

ifx_create_blob
Tworzy obiekt blob. Zwraca obiektu blob.
False

w przypadku bledu, a w przeciwnym wypadku identyfikator nowego

int ifx_create_blob (int type, int mode, string param)

Parametr $type: 1 = TEXT, 0 = BYTE Parametr $mode: 0 = obiekt blob jest przechowywany w pamieci, 1 = obiekt blob jest przechowywany w pliku. Parametr $param: Jezeli tryb=0 jest to wskaznik na zawartosc, jezeli tryb=1, wskaznik na strumien pliku.

ifx_create_char
Tworzy obiekt znakowy. Parametr $param powinien zawierac zawartosc obiektu.
int ifx_create_char (string param)

ifx_do
Zwraca True gdy operacja sie powiodla i False w przypadku bledu. Wykonuje uprzednio przygotowane zapytanie i otwiera dla niego kursor. W przypadku wystapienia bledu nie zwalnia $result_id. Dla zapytan innych od SELECT ustawia rwniez wlasciwa liczbe zmienionych wierszy, ktra mozna odczytac za pomoca ifx_affected_rows(). Patrz rwniez ifx_prepare().
int ifx_do (int result_id)

ifx_error
Kody bledw serwera Informix (SQLSTATE i SQLCODE) sa formatowane nastepujaco: x [SQLSTATE = aa bbb SQLCODE=cccc] Gdy x jest spacja, oznacza to brak bledu. E blad N koniec danych W ostrzezenie ? niezdefiniowany
string ifx_error (void)

Jezeli znak x jest czymkolwiek poza spacja, SQLSTATE i SQLCODE dokladniej opisuja blad. Opis SQLSTATE i SQLCODE mozna znalezc w podreczniku do serwera Informix. Zwraca jeden znak okreslajacy wynik wyrazenia oraz zarwno wartosc SQLSTATE jak i SQLCODE zwiazane z ostatnio wykonywanym wyrazeniem SQL. Format tego ciagu jest nastepujacy: (znak) [SQLSTATE=(dwa znaki) (trzy znaki) SQLCODE=(jeden znak)]. Pierwszym znakiem moze byc spacja (sukces), W (wyrazenie wygenerowalo ostrzezenia), E (zdarzyl sie blad w czasie wykonywania wyrazenia) lub N (wyrazenie nie zwrcilo zadnych danych). Patrz rwniez: ifx_errormsg().

ifx_erormsg
Zwraca komunikat serwera Informix opisujacy ostatni blad w serwerze lub gdy podano wartosc opcjonalnego parametru $errorcode, komunikat zwiazany z podanym numerem bledu. Patrz rwniez: idx_error().
string ifx_errormsg ([int errorcode])

Przyklad: ifx_errormsg()
printf("%s\n<br>", ifx_errormsg(-201));

Dodatek A - Funkcje

252

ifx_fetch_row
Zwraca tablice asocjacyjna zawierajaca odczytany wiersz, lub False jezeli nie ma nastepnego wiersza. Kolumny blob sa zwracane w postaci numerycznych identyfikatorw blob, ktre mozna uzyc w funkcji ifx_get_blob(), lub jezeli zostaly wywolane funkcje ifx_textasvarchar(1) lub ifx_byteasvarchar(1), pola blob sa zwracane w postaci ciagw znakw. W przypadku wystapienia bledu zwraca False. Parametr $result_id musi byc prawidlowym identyfikatorem wyniku zwracanym przez ifx_query() lub ifx_prepare() (tylko dla zapytan SELECT). Opcjonalny parametr $position wskazuje na rodzaj operacji na kursorze. Moze byc to NEXT, PREVIOUS, CURRENT, FIRST, LAST lub liczba. Jezeli podana zostanie liczba, odczytywany jest wiersz o podanym numerze. Jest to parametr opcjonalny stosowany tylko dla kursorw typu SCROLL.
array ifx_fetch_row (int result_id [, mixed position])

Funkcja ifx_fetch_row() odczytuje jeden wiersz danych z wyniku zwiazanego z podanym identyfikatorem wyniku. Wiersz jest zwracany w postaci tablicy. Kazda kolumna wyniku jest przechowywana w osobnej komrce tablicy, ktrej kluczem jest nazwa kolumny. Kolejne wywolania ifx_fetch_row() zwracaja kolejne wiersze wyniku lub False, gdy nie ma juz kolejnych wierszy. Przyklad: Odczyt wierszy wyniku
$rid = ifx_prepare ("select * from emp where name like " . $name, $connid, IFX_SCROLL); if (! $rid) { ... error ... } $rowcount = ifx_affected_rows($rid); if ($rowcount > 1000) { printf ("Zapytanie zwraca zbyt duzo wierszy: (%d)\n<br>", $rowcount); die ("Prosze ograniczyc zapytanie<br>\n"); }} if (! ifx_do ($rid)) { ... error ... } $row = ifx_fetch_row ($rid, "NEXT"); while (is_array($row)) { for(reset($row); $fieldname=key($row); next($row)) { $fieldvalue = $row[$fieldname]; printf ("%s = %s,", $fieldname, $fieldvalue); } printf("\n<br>"); $row = ifx_fetch_row ($rid, "NEXT"); } ifx_free_result ($rid);

ifx_fieldproperties
Zwraca tablice asocjacyjna z nazwami pl jako kluczami i wlasciwosciami pl SQL dla wyniku zapytania okreslonego przez $result_id, jako danymi. W przypadku wystapienia bledu zwraca False. Zwraca wlasciwosci SQL serwera Informix w postaci tablicy asocjacyjnej, dla kazdego pola zwracanego przez zapytanie. Wlasciwosci te sa zapisywane jako SQLTYPE:dlugosc:dokladnosc:skala:ISNULLABLE, gdzie SQLTYPE jest typem Informixa, np.: SQLVCHAR, natomiast ISNULLABLE moze miec wartosc Y lub N.
array ifx_fieldproperties (int result_id)

Przyklad: wlasciwosci pl SQL serwera Informix


$properties = ifx_fieldproperties ($resultid); if (! isset($properties)) { ... blad ... } for ($i = 0; $i < count($properties); $i++) { $fname = key ($properties); printf ("%s:\t typ = %s\n", $fname, $properties[$fname]); next ($properties); }

ifx_fieldtypes
Dla wyniku zapytania o identyfikatorze $result_id zwraca tablice asocjacyjna z nazwami pl jako kluczami i typami pl SQL jako danymi. W przypadku wystapienia bledu zwraca False.
array ifx_fieldtypes (int result_id)

Przyklad: Nazwy i typy pl SQL


types = ifx_fieldtypes ($resultid);

253

PHP Kompendium wiedzy

if (! isset ($types)) { ... blad ... } for ($i = 0; $i < count($types); $i++) { $fname = key($types); printf("%s :\t typ = %s\n", $fname, $types[$fname]); next($types); }

ifx_free_blob
Usuwa obiekt blob o podanym identyfikatorze przeciwnym wypadku True.
int ifx_free_blob (int bid)

$bid.

W przypadku wystapienia bledu zwraca

False,

ifx_free_char
Usuwa obiekt znakowy o podanym identyfikatorze $bid. W przypadku wystapienia bledu zwraca False, w przeciwnym wypadku True.
int ifx_free_char (int bid)

ifx_free_result
Dla identyfikatora wyniku $result_id zwalnia zasoby przydzielone dla zapytania.

przypadku wystapienia bledu zwraca False.


int ifx_free_result (int bid)

ifx_getsqlca
Zwraca pseudo-wiersz (tablice asocjacyjna) z wartosciami sqlca.sqlerrd[0] ... sqlca.sqlerrd[5] po skojarzeniu zapytania z $result_id. Parametr $result_id musi byc prawidlowym identyfikatorem wyniku zwracanym przez ifx_query() lub ifx_prepare().
array ifx_getsqlca (int result_id)

Dla zapytan INSERT, UPDATE i DELETE zwracane wartosci sa ustawiane przez serwer po wykonaniu zapytania. Pozwala to odczytac ilosc wierszy zmienionych przez zapytanie oraz numer kolejny wstawionego wiersza. W przypadku wyrazen SELECT, wartosci te sa ustawiane po wykonaniu operacji PREPARE. Pozwala to na odczytanie przewidywanej ilosci wierszy wyniku. Wykorzystanie tej funkcji pozwala na zmniejszenei narzutu czasowego na wykonanie zapytania select dbinfo('sqlca.sqlerrdx') i odczytanie wartosci zapisanych w odpowiednim momencie przez sterownik bazy Informix. Przyklad: Odczytywanie wartosci sqlca.sqlerrd[x]
/* zakladamy, ze pierwsza kolumna 'sometable' jest numerem seryjnym rekordu */ $qid = ifx_query("insert into sometable values (0, '2nd column', 'another column') ", $connid); if (! $qid) { ... blad ... } $sqlca = ifx_getsqlca ($qid); $serial_value = $sqlca["sqlerrd1"]; echo "Numer seryjny wstawionego wiersza wynosi: " . $serial_value<br>\n";

ifx_get_blob
Zwraca zawartosc obiektu blob o podanym identyfikatorze obiektu $bid.
int ifx_get_blob (int bid)

ifx_get_char
Zwraca zawartosc obiektu znakowego o podanym identyfikatorze obiektu $bid.
int ifx_get_char (int bid)

Dodatek A - Funkcje

254

ifx_htmltbl_result
Zwraca ilosc odczytanych wierszy, lub False w przypadku wystapienia bledu. Formatuje wiersze wyniku o identyfikatorze $result_id do postaci tabeli HTML. Drugim opcjonalnym parametrem funkcji jest ciag atrybutw znacznika <TABLE>.
int ifx_htmltbl_result (int result_id [, string html_table_options])

ifx_nullformat
Ustawia domyslna wartosc wartosci NULL po odczytaniu wiersza. Tryb 0 powoduje zwracanie "" a tryb 1 zwracanie "NULL".
void ifx_nullformat (int mode)

ifx_num_fields
Zwraca ilosc kolumn zapytania o identyfikatorze $result_id lub False w przypadku wystapienia bledu. Po przygotowaniu lub wykonaniu zapytania wywolanie to pozwala na odczytanie ilosci kolumn w zapytaniu.
int ifx_num_fields (int result_id)

ifx_num_rows
Zwraca ilosc wierszy odczytanych do tej pory z wyniku zapytania $result_id, po wykonaniu ifx_query() lub ifx_do().
int ifx_num_rows (int result_id)

ifx_pconnect
Zwraca dodatni identyfikator trwalego polaczenia do serwera Informix lub False w przypadku wystapienia bledu. Funkcja ifx_pconnect() dziala bardzo podobnie do ifx_connect() z dwoma wyjatkami. Funkcja dziala identycznie jak ifx_connect(), jezeli PHP nie dziala jako modul Apache. Po pierwsze, w czasie polaczenia funkcja prbuje znalezc lacze (trwale) otwarte do tego samego serwera z identycznym uzytkownikiem i haslem. Jezeli zostanie znalezione takie polaczenie, zamiast otwierania nowego polaczenia, zwracany jest identyfikator istniejacego polaczenia. Po drugie, polaczenie z serwerem SQL nie jest zamykane po zakonczeniu wykonywania skryptu. Zamiast tego lacze pozostanie otwarte do wykorzystania w przyszlosci (ifx_close() nie zamyka laczy zestawionych za pomoca ifx_pconnect()). Z tego powodu ten typ lacza nazywany jest trwalym. Patrz rwniez: ifx_connect().
int ifx_pconnect ([string database [, string userid [, string password]]])

ifx_query
Zwraca identyfikator wyniku lub w przypadku wystapienia bledu wartosc False. Identyfikator ten jest uzywany przez inne funkcje do pobrania wynikw dzialania zapytania. Ustawia jest wartosc okreslajaca ilosc wierszy zwracanych przez zapytanie, ktra mozna odczytac przez wywolanie ifx_affected_rows(). Funkcja ifx_query() wysyla zapytanie do bazy danych okreslanej przez podany identyfikator polaczenia. Jezeli nie zostanie podany identyfikator polaczenia, operacja jest wykonywana na ostatnio otwartym polaczeniu. Jezeli nie istnieje otwarte polaczenie, funkcja prbuje je ustanowic, identycznie jak funkcja ifx_connect() i nastepnie wykorzystuje to polaczenie. Wykonuje zapytanie $query na polaczeniu $conn_id. W przypadku zapytan SELECT deklarowany i otwierany jest kursor. Opcjonalny parametr $cursor_type pozwala na utworzenie kursora typu SCROLL lub (oraz) HOLD. Jest to maska bitowa, ktra moze przyjmowac wartosci IFX_SCROLL, IFX_HOLD lub jednoczesnie obie wartosci. Zapytania inne niz SELECT wykonywane sa w trybie natychmiastowym. IFX_SCROLL i IFX_HOLD sa stalymi symbolicznymi i nie nalezy ich zapisywac w apostrofach. Jezeli nie podasz tego parametru, otwierany jest zwykly kursor sekwencyjny. Dla dowolnego typu zapytania zapamietywana jest ilosc wierszy bedacych wynikiem zapytania (rzeczywista lub szacowana), ktra mozna odczytac za pomoca funkcji ifx_affected_rows().
int ifx_query (string query [, int link_identifier [, int cursor_type,

255

PHP Kompendium wiedzy

mixed [blobidarray]]])

Jezeli w zapytaniu UPDATE wystepuje kolumna BLOB (BYTE lub TEXT), mozna dodac parametr $blobidarray, zawierajacy odpowiednie identyfikatory blob, i powinienes zamienic te kolumny znakiem ? w tekscie zapytania. Jezeli zawartosc kolumny TEXT (lub BYTE) pozwala na to, mozna wywolac funkcje ifx_textasvarchar(1) i ifx_byteasvarchar(1). Pozwoli to na traktowanie kolumn TEXT (lub BYTE) w zapytaniach SELECT, tak, jakby byla to zwykla (choc dluga) kolumna VARCHAR, i nie przejmowac sie identyfikatorami obiektw blob. Wywolujac ifx_textasvarchar(0) i ifx_byteasvarchar(0) (domyslna sytuacja) zapytania SELECT kolumny BLOB beda zwracane jako identyfikatory obiektw blob (wartosci numeryczne). Majac taki identyfikator mozna pobrac zawartosc kolumny BLOB za pomoca funkcji obslugujacych bloby. Patrz rwniez: ifx_connect(). Przyklad: Wyswietlenie wszystkich wierszy tabeli orders jako tabeli html
ifx_textasvarchar(1); // uzycie "trybu tekstowego" do blobw $res_id = ifx_query("select * from orders", $conn_id); if (! $res_id) { printf("Nie mozna wykonac zapytania : %s\n<br>%s<br>\n", ifx_error()); ifx_errormsg(); die; } ifx_htmltbl_result($res_id, "border=\"1\""); ifx_free_result($res_id);

Przyklad: Wstawienie kilku wierszy do tabeli catalog


// utworzenie identyfikatorw blobw dla kolunm byte i text $textid = ifx_create_blob(0, 0, "Kolumna Text w pamieci!"); $byteid = ifx_create_blob(1, 0, "Kolumna Byte w pamieci"); // zapamietanie identyfikatorw blob w tablicy blobid $blobidarray[] = $textid; $blobidarray[] = $byteid; // wykonanie zapytania $query = "insert into catalog (stock_num, manu_code, " . "cat_descr,cat_picture) values(1,'HRO',?,?)"; $res_id = ifx_query($query, $conn_id, $blobidarray); if (! $res_id) { ... blad ... } // zwonienie identyfikatora wyniku ifx_free_result($res_id);

ifx_textasvarchar
Ustawia domyslny tryb tekstowy dla zapytan SELECT. Tryb natomiast tryb 1 powoduje zwracanie zawartosci jako tekstu.
void ifx_textasvarchar (int mode)

powoduje zwracanie identyfikatorw blob,

ifx_update_blob
Uaktualnia zawartosc obiektu blob dla podanego identyfikatora $bid. Parametr $content jest ciagiem zawierajacym nowe dane. Zwraca False w przypadku bledu a w przeciwnym przypadku True.
ifx_update_blob (int bid, string content)

ifx_update_char
Uaktualnia zawartosc obiektu znakowego dla podanego identyfikatora $bid. Parametr $content jest ciagiem zawierajacym nowe dane. Zwraca False w przypadku bledu a w przeciwnym przypadku True.
ifx_update_char (int bid, string content)

ignore_user_abort
Funkcja ta ustawia znacznik, czy klient moze spowodowac przerwanie wykonywania skryptu. Zwraca wczesniejsze ustawienie i moze byc wywolana bez argumentw w celu sprawdzenia biezacego ustawienia, bez jego zmiany.
int ignore_user_abort ([int setting])

Dodatek A - Funkcje

256

ImageArc
Rysuje fragment elipsy o srodku o wsplrzednych $cx, $cy (lewy grny rg to 0,0) na rysunku reprezentowanym przez $im. Parametry $w i $h okreslaja szerokosc i wysokosc elipsy, natomiast punkty poczatkowe i koncowe sa okreslane w stopniach podawanych w argumentach $s i $e.
int ImageArc (int im, int cx, int cy, int w, int h, int s, int e, int col)

ImageChar
Rysuje pierwszy znak w $c na rysunku okreslonym przez $id. Lewy grny rg litery znajduje sie na wsplrzednych $x, $y (lewy grny rg to 0,0), kolor to $col. Jezeli $font jest 1, 2, 3, 4 lub 5, uzywane sa wbudowane czcionki (najwieksza liczba reprezentuje najwieksza czcionke). Patrz rwniez imageloadfont().
int ImageChar (int im, int font, int x, int y, string c, int col)

ImageCharUp
Rysuje pionowo pierwszy znak w $c na rysunku okreslonym przez $id. Lewy grny rg litery znajduje sie na wsplrzednych $x, $y (lewy grny rg to 0,0), kolor to $col. Jezeli $font jest 1, 2, 3, 4 lub 5, uzywane sa wbudowane czcionki (najwieksza liczba reprezentuje najwieksza czcionke). Patrz rwniez imageloadfont().
int ImageCharUp (int im, int font, int x, int y, string c, int col)

ImageColorAllocate
Zwraca identyfikator koloru reprezentujacy kolor stworzony z podanych skladnikw RGB. Argument $im jest wynikiem funkcji imagecreate(). Funkcja ImageColorAllocate() musi byc wywolana do stworzenia kazdego koloru, ktry bedzie uzywany na rysunku $im.
int imagecolorallocate (int im, int red, int green, int blue)

Przyklad
$white = ImageColorAllocate ($im, 255, 255, 255); $black = ImageColorAllocate ($im, 0, 0, 0);

ImageColorAt
Zwraca indeks koloru piksela o podanych wsplrzednych. Patrz rwniez: ImageColorsForIndex().
int imagecolorat (int im, int x, int y)

ImageColorSet()

ImageColorClosest
Zwraca indeks koloru, w palecie kolorw rysunku, ktry jest najblizszy podanej wartosci RGB. Odleglosc od zadanego koloru i kolorw istniejacych w palecie jest obliczana tak, jakby wartosci RGB reprezentowaly punkty w przestrzeni trjwymiarowej. Patrz rwniez: ImageColorExact().
int imagecolorclosest (int im, int red, int green, int blue)

ImageColorDeAllocate
Usuwa kolor poprzednio utworzony za pomoca funkcji ImageColorAllocate().
int imagecolordeallocate (int im, int index)

Przyklad:
$white = ImageColorAllocate($im, 255, 255, 255); ImageColorDeAllocate($im, $white);

ImageColorExact
Zwraca indeks podanego koloru w palecie kolorw rysunku. Jezeli kolor nie wystepuje w palecie, zwracana jest wartosc -1. Patrz rwniez: ImageColorClosest().
int imagecolorexact (int im, int red, int green, int blue)

257

PHP Kompendium wiedzy

ImageColorResolve
Funkcja gwarantuje zwrcenie indeksu dla podanego koloru. Bedzie to dokladnie identyczny kolor lub najblizszy mu podobny. Patrz rwniez: ImageColorClosest().
int imagecolorresolve (int im, int red, int green, int blue)

ImageColorSet
Ustawia indeks w palecie kolorw na podany kolor. Jest to przydatne do tworzenia efektw wypelniania za pomoca palety, bez potrzeby wykonywania wypelniania. Patrz rwniez: ImageColorAt().
bool imagecolorset (int im, int index, int red, int green, int blue)

ImageColorsForIndex
Zwraca tablice asocjacyjna z kluczami red, green i blue, ktre zawieraja odpowiednie wartosci dla podanego indeksu koloru. Patrz rwniez: ImageColorAt() i ImageColorExact().
array imagecolorsforindex (int im, int index)

ImageColorsTransparent
Ustawia kolor przezroczysty w rysunku $im na $col. Parametr $im jest identyfikatorem zwracanym przez ImageCreate(), natomiast $col jest identyfikatorem koloru zwracanym przez ImageColorAllocate(). Zwracany jest identyfikator nowego (lub biezacego, jezeli nie podano nowego koloru) koloru przezroczystego.
int imagecolortransparent (int im [, int col])

ImageCopy
Kopiuje fragment rysunku $src_im do $dst_im, rozpoczynajac od wsplrzednych $src_x, $src_y o szerokosci $src_w i wysokosci $src_h. Zdefiniowany fragment jest kopiowany do docelowego rysunku na wsplrzedne $dst_x i $dst_y.
int ImageCopy (resource dst_im, resource src_im, int dst_x, int dst_y, int src_x, int src_y, int src_w, int src_h)

ImageCopyResized
Kopiuje prostokatny fragment rysunku do innego rysunku. Parametr $dst_im jest docelowym rysunkiem, natomiast $src_im to identyfikator rysunku zrdlowego. Jezeli wsplrzedne zrdla i celu oraz szerokosc i wysokosc rznia sie, stosowane jest odpowiednie przeskalowanie kopiowanego fragmentu. Wsplrzedne wskazuja na lewy grny rg. Funkcja moze byc uzywana do kopiowania obszarw tego samego rysunku (jezeli $dst_im jest taki sam jak $src_im), ale gdy obszary te nachodza na siebie, wyniki sa nieprzewidywalne.
int ImageCopyResized (resource dst_im, resource src_im, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH)

ImageCreate
Zwraca identyfikator rysunku wskazujacy na pusty rysunek o rozmiarze $x_size na $y_size.
int imagecreate (int x_size, int y_size)

Przyklad: Tworzenie nowego strumienia rysunku GD i tworzenie rysunku.


<?php header ("Content-type: image/png"); $im = @ImageCreate (50, 100) or die ("Nie mozna zainicjowac nowego strumienia rysunku GD"); $background_color = ImageColorAllocate ($im, 255, 255, 255); $text_color = ImageColorAllocate ($im, 233, 14, 91); ImageString ($im, 1, 5, 5, "Prosty tekst przykladowy", $text_color); ImagePng ($im); ?>

Dodatek A - Funkcje

258

ImageCreateFromGif
Zwraca identyfikator rysunku reprezentujacy rysunek pobrany z pliku o podanej nazwie. Funkcja ImageCreateFromGif() w przypadku wystapienia bledu zwraca pusty ciag. Wyswietla rwniez komunikat bledu, ale niestety jest on wyswietlany w przegladarce jako nieprawidlowe lacze. Aby ulatwic uruchamianie mozna zastosowac ponizszy przyklad, ktry tworzy rysunek GIF z komunikatem bledu.
int ImageCreateFromGif (string filename)

Przyklad: Obsluga bledu w czasie tworzenia rysunku (podziekowania dla vic@zymsys.com)


function LoadGif ($imgname) { $im = @ImageCreateFromGIF ($imgname); /* Prba otwarcia */ if (!$im) { /* Jezeli sie nie udalo */ $im = ImageCreate (150, 30); /* Tworzenie pustego rysunku */ $bgc = ImageColorAllocate ($im, 255, 255, 255); $tc = ImageColorAllocate ($im, 0, 0, 0); ImageFilledRectangle ($im, 0, 0, 150, 30, $bgc); /* Wyswietlenie komunikatu bledu */ ImageString($im, 1, 5, 5, "Blad przy ladowaniu $imgname", $tc); } return $im; }

Uwaga Poniewaz obsluga GIF zostala usunieta z biblioteki GD od wersji 1.6 funkcja ta nie jest juz dostepna.

ImageCreateFromJPEG
Zwraca identyfikator rysunku reprezentujacy rysunek pobrany z pliku o podanej nazwie. Funkcja w przypadku wystapienia bledu zwraca pusty ciag. Wyswietla rwniez komunikat bledu, ale niestety jest on wyswietlany w przegladarce jako nieprawidlowe lacze. Aby ulatwic uruchamianie mozna zastosowac ponizszy przyklad, ktry tworzy rysunek JPEG z komunikatem bledu.
ImageCreateFromJPEG()
int ImageCreateFromJPEG (string filename)

Przyklad: Obsluga bledu w czasie tworzenia rysunku (podziekowania dla vic@zymsys.com)


function LoadJPEG ($imgname) { $im = @ImageCreateFromJPEG ($imgname); /* Prba otwarcia */ if (!$im) { /* Jezeli sie nie udalo */ $im = ImageCreate (150, 30); /* Tworzenie pustego rysunku */ $bgc = ImageColorAllocate ($im, 255, 255, 255); $tc = ImageColorAllocate ($im, 0, 0, 0); ImageFilledRectangle ($im, 0, 0, 150, 30, $bgc); /* Wyswietlenie komunikatu bledu */ ImageString($im, 1, 5, 5, "Blad przy ladowaniu $imgname", $tc); } return $im; }

ImageCreateFromPNG
Zwraca identyfikator rysunku reprezentujacy rysunek pobrany z pliku o podanej nazwie. Funkcja w przypadku wystapienia bledu zwraca pusty ciag. Wyswietla rwniez komunikat bledu, ale niestety jest on wyswietlany w przegladarce jako nieprawidlowe lacze. Aby ulatwic uruchamianie mozna zastosowac ponizszy przyklad, ktry tworzy rysunek PNG z komunikatem bledu. Przyklad: Obsluga bledu w czasie tworzenia rysunku (podziekowania dla vic@zymsys.com)
ImageCreateFromPNG()
function LoadPNG ($imgname) { $im = @ImageCreateFromPNG ($imgname); /* Prba otwarcia */ if (!$im) { /* Jezeli sie nie udalo */ $im = ImageCreate (150, 30); /* Tworzenie pustego rysunku */ $bgc = ImageColorAllocate ($im, 255, 255, 255); $tc = ImageColorAllocate ($im, 0, 0, 0); ImageFilledRectangle ($im, 0, 0, 150, 30, $bgc); /* Wyswietlenie komunikatu bledu */ ImageString($im, 1, 5, 5, "Blad przy ladowaniu $imgname", $tc); } return $im; }

259

PHP Kompendium wiedzy

ImageDashedLine
Rysuje na rysunku $im linie przerywana z Patrz rwniez: ImageLine().
$x1, $y1

do

$x2, $y2

(lewy grny rg to 0,0) o kolorze

$col.

int imagedashedline (int im, int x1, int y1, int x2, int y2, int col)

ImageDestroy
Zwalnia pamiec zajeta przez rysunek $im. Parametr $im jest identyfikatorem rysunku zwracanym przez funkcje ImageCreate().
int imagedestroy (int im)

ImageFill
Wykonuje wypelnianie metoda zalewania (flood fill) rysunku (lewy grny rg to 0,0) kolorem $col.
int imagefill (int im, int x, int y, int col)

$im

rozpoczynajac od wsplrzednych

$x, $y

ImageFilledPolygon
Tworzy wypelniony wielobok na rysunku $im. Parametr $points jest tablica PHP zawierajaca wierzcholki wieloboku, to znaczy $points[0] = x0, $points[1] = y0, $points[2] = x1, $points[3] = y1 i tak dalej. Parametr $num_points zawiera calkowita ilosc wierzcholkw.
int imagefilledpolygon (int im, array points, int num_points, int col)

ImageFilledRectangle
Na rysunku $im tworzy wypelniony prostokat o kolorze $col, rozpoczynajac od grnego lewego rogu o wsplrzednych $x1, $y1, konczac na prawym dolnym rogu o wsplrzednych $x2, $y2. Lewy grny rg rysunku ma wsplrzedne 0,0.
int imagefilledrectangle (int im, int x1, int y1, int x2, int y2, int col)

ImageFillToBorder
Wypelnia na rysunku obszar ograniczony kolorem zdefiniowanym w parametrze rozpoczecia wypelniania to $x, $y (lewy grny rg to 0,0), kolor wypelnienia to $col.
int imagefilltoborder (int im, int x, int y, int border, int col)

$border.

Punkt

ImageFontHeight
Zwraca wysokosc znaku w pikselach dla okreslonej czcionki. Patrz rwniez:
ImageLoadFont().
int imagefontheight (int font)

ImageFontWidth()

ImageFontWidth
Zwraca szerokosc znaku w pikselach dla okreslonej czcionki. Patrz rwniez:
ImageLoadFont().
int ImageFontWidth (int font)

ImageFontHeiht()

ImageGammaCorrect
Stosuje korekcje gamma na rysunku $im na podstawie wartosci gamma wejsciowej wyjsciowej $outputgamma.
int imagegammacorrect (int im, float inputgamma, float outputgamma)

$inputgamma

Dodatek A - Funkcje

260

ImageGIF
Tworzy plik GIF na podstawie rysunku $im. Parametr $im jest identyfikatorem zwracanym przez funkcje ImageCreate(). Rysunek zostanie zapisany w formacie GIF87a chyba, ze rysunek bedzie zawieral kolor przezroczysty stworzony za pomoca funkcji ImageColorTransparent(). W takim przypadku formatem pliku bedzie GIF89a. Nazwa pliku jest opcjonalna, jezeli zostanie pominieta, utworzony zostanie bezposredni surowy strumien rysunku. Wysylajac za pomoca funkcji header() typ zawartosci image/gif, mozna stworzyc skrypt PHP, ktry bezposrednio wysyla do przegladarki rysunki GIF.
Uwaga Poniewaz obsluga GIF zostala usunieta z biblioteki GD od wersji 1.6 funkcja ta nie jest juz dostepna.
int imagegif (int im [, string filename])

ImageInterlace
$interlace

Ustawia i kasuje bit przeplotu. Jezeli $interlace jest rwny 1, rysunek bedzie z przeplotem. Jezeli jest 0, przeplot nie zostanie zastosowany. Funkcja zwraca biezaca wartosc bitu przeplotu dla rysunku.

int imageinterlace (int im [, int interlace])

ImageJPEG
Tworzy plik JPEG na podstawie rysunku $im. Parametr $im jest identyfikatorem zwracanym przez funkcje Nazwa pliku jest opcjonalna, jezeli zostanie pominieta, utworzony zostanie bezposredni surowy strumien rysunku. Aby opuscic nazwe pliku i jednoczesnie podac wartosc parametru $quality nalezy uzyc pustego ciagu (""). Wysylajac za pomoca funkcji header() typ zawartosci image/jpeg, mozna stworzyc skrypt PHP, ktry bezposrednio wysyla do przegladarki rysunki JPEG.
ImageCreate(). Uwaga Obsluga formatu JPEG jest dostepna jedynie, jezeli biblioteka GD jest w wersji 1.8 lub nowszej.
int imagejpeg (int im [, string filename [, int quality]])

ImageLine
Na rysunku $im rysuje linie od $x1, $y1 do $x2, $y2 (lewy grny rg to 0,0) o kolorze ImageCreate() i ImageColorAllocate().
int imageline (int im, int x1, int y1, int x2, int y2, int col)

$col.

Patrz rwniez:

ImageLoadFont
Laduje czcionke bitmapowa zdefiniowana przez uzytkownika i zwraca identyfikator czcionki (zawsze wiekszy od 5, wiec nie koliduje z wbudowanymi czcionkami). Format pliku jest obecnie binarny, zalezny od architektury. Oznacza to, ze nalezy generowac pliki czcionek na komputerze z takim samym procesorem, co komputer na ktrym jest uruchomione PHP. Format pliku jest nastepujacy: Pozycja Typ Opis w bajtach danych C 0 3 int Ilosc znakw w pliku czcionek 4 7 int Wartosc pierwszego znaku czcionki (czesto 32 dla spacji) 8 11 int Szerokosc kazdego znaku w pikselach 12 15 int Wysokosc kazdego znaku w pikselach 16 char Tablica danych znakowych, jeden bajt na piksel w kazdym xxx znaku, razem (znaki*szerokosc*wyskokosc) bajtw Patrz rwniez: ImageFontWidth() i ImageFontHeight(). 261 PHP Kompendium wiedzy

int imageloadfont (string file)

ImagePNG
Otwiera strumien GD ($im) w formacie PNG i przesyla dane do standardowego wyjscia (zwykle jest to przegladarka), lub jezeli podana jest nazwa pliku $filename, zapisuje rysunek do pliku.
int imagepng (int im [, string filename])

Przyklad:
<?php $im = ImageCreateFromPng("test.png"); ImagePng($im); ?>

ImagePolygon
Tworzy wielobok na rysunku $im. Parametr $points jest tablica PHP zawierajaca wierzcholki wieloboku to znaczy $points[0] = x0, $points[1] = y0, $points[2] = x1, $points[3] = y1 i tak dalej. Parametr $num_points zawiera calkowita ilosc wierzcholkw. Patrz rwniez: ImageCreate().
int imagepolygon (int im, array points, int num_points, int col)

ImagePSBBox
Parametr $size jest wyrazony w pikselach, $space pozwala zmienic domyslna wartosc odstepu w czcionkach. Wartosc ta jest dodawana do standardowej wartosci odstepu i moze byc ujemna. Parametr $tightness pozwala kontrolowac ilosc swiatla pomiedzy literami. Wartosc ta jest dodawana do normalnej szerokosci znaku i moze rwniez byc ujemna. Parametr $angle jest wyrazony w stopniach. Parametry $space i $tightness sa podawane w jednostkach odstepu znaku, gdzie 1 jednostka odstepu jest 1/1000 pica do kwadratu. Parametry $space, $tightness i $angle sa opcjonalne. Ramka ograniczajaca jest wyliczana z wykorzystaniem dostepnych danych z metryki czcionki i niestety nieco rzni sie od wynikw otrzymywanych przez rasteryzacje tekstu. Jezeli kat wynosi 0, nalezy sie spodziewac, ze tekst bedzie potrzebowal o 1 piksel wiecej w kazdym kierunku. Funkcja zwraca tablice zawierajaca nastepujace elementy: 0 lewa dolna wsplrzedna x, 1 lewa dolna wsplrzedna y, 2 prawa grna wsplrzedna x i 3 prawa grna wsplrzedna y. Patrz rwniez: ImagePSText().
array ImagePSBBox (string text, int font, int size [, int space [, int tightness [, float angle]]])

ImagePSEncodeFont
Laduje z pliku wektor kodowania znakw i zmienia na niego istniejacy wektor kodowania czcionki. Poniewaz w czcionkach PostScript wektor kodowania nie zawiera wielu znakw na pozycjach powyzej 127, prawie na pewno musisz zmienic wektor kodowania w przypadku wykorzystywania jezykw innych niz angielski. Dokladny format pliku jest opisany w dokumentacji T1lib. T1lib zawiera dwa gotowe do uzycia pliki, IsoLatin1.enc i IsoLatin2.enc. Jezeli chcesz caly czas wykorzystywac ta funkcje, lepszym sposobem na zdefiniowanie kodowania jest ustawienie w pliku konfiguracyjnym zmiennej ps.default_encoding na odpowiedni plik kodowania. Wszystkie zaladowane przez uzytkownika czcionki beda mialy odpowiednio zdefiniowane kodowanie.
int imagepsencodefont (int font_index, string encodingfile)

ImagePsExtendfont
Powieksza lub zmniejsza czcionke funkcja zmniejsza czcionke.
$font_index.

Jezeli wartosc parametru

$extend

jest mniejsza od jeden,

bool imagepsextendfont (int font_index, float extend)

ImagePSFreeFont
Patrz rwniez: ImagePSLoadFont().
void imagepsfreefont (int fontindex)

Dodatek A - Funkcje

262

ImagePSLoadFont
Jezeli wszystko odbedzie sie bez bledw, funkcja zwraca prawidlowy indeks czcionki, ktry moze byc uzyty do innych celw. Jezeli cos sie nie powiedzie, funkcja zwraca False i drukuje komunikat opisujacy blad. Patrz rwniez: ImagePSFreeFont().
int ImagePSLoadFont (string filename)

ImagePsSlantFont
Pochyla czcionke wskazywana przez parametr $font_index o wartosc przekazana w parametrze $slant.
bool imagepsslantfont (int font_index, float slant)

ImagePSText
Parametr $size jest wyrazony w pikselach. Parametr $foreground jest kolorem jakim zostanie namalowany tekst, natomiast $background to kolor na ktry tekst bedzie sie zmienial przy zastosowaniu wygladzania (antialiasing). Nie sa rysowane zadne punkty w kolorze $background, wiec tlo nie bedzie zamalowane. Wsplrzedne przekazane w $x, $y definiuja poczatek (punkt odniesienia) pierwszego znaku (mniej wiecej lewy dolny rg znaku). Funkcja rzni sie tym od ImageString(), gdzie $x, $y okreslaja lewy grny rg pierwszego znaku. Jezeli potrzebujesz blizszych informacji na temat czcionek i systemu miar, znajduja sie w dokumentacji PostScript.
array imagepstext (int image, string text, int font, int size, int foreground, int background, int x, int y [, int space [, int tightness [, float angle [, int antialias_steps]]]])

Parametr $space pozwala na zmiane domyslnego odstepu w czcionce. Wartosc ta jest dodawana do normalnej wartosci, wiec moze byc ujemna. Parametr $tightness powala na kontrolowanie ilosci swiatla pomiedzy literami. Wartosc ta jest dodawana do normalnej szerokosci znaki i rwniez moze byc ujemna. Wartosc $angle podawana jest w stopniach. Parametr $antialiasing_steps pozwala na okreslanie ilosci kolorw uzytych do wygladzania tekstu. Dopuszczalnymi wartosciami sa 4 i 16. Wyzsza wartosc jest polecana dla tekstw o rozmiarze mniejszych od 20, gdzie wygladzanie mocno wplywa na jakosc tekstu. W przypadku wiekszych czcionek mozna uzyc wartosci 4, poniewaz potrzeba wtedy mniej obliczen. Parametry $space i $tightness sa wyrazane w jednostkach odstepu znaku, gdzie 1 jednostka odstepu jest 1/1000 pica do kwadratu. Parametry $space, $tightness, $angle i $antialias sa opcjonalne. Funkcja zwraca tablice zawierajaca nastepujace elementy: 0 lewa dolna wsplrzedna x, 1 lewa dolna wsplrzedna y, 2 prawa grna wsplrzedna x i 3 prawa grna wsplrzedna y. Patrz rwniez: ImagePSBBox().

ImageRectangle
Na rysunku $im tworzy prostokat w kolorze $col o wsplrzednych lewego grnego rogu prawego dolnego $x2, $y2. Lewy grny rg rysunku ma wsplrzedne 0,0.
int ImageRectangle (int im, int x1, int y1, int x2, int y2, int col)

$x1, $y1

ImageSetPixel
Rysuje na rysunku $im piksel w kolorze rwniez: ImageCreate() i ImageColorAllocate().
$col

na wsplrzednych

$x, $y

(lewy grny rg to 0,0). Patrz

int ImageSetPixel (int im, int x, int y, int col)

ImageString
Na rysunku $im rysuje ciag $s rozpoczynajac od wsplrzednych $x, $y (lewy grny rg to 0,0) w kolorze $col. Jezeli $font wynosi 1, 2, 3, 4 lub 5, uzywane sa wbudowane czcionki. Patrz rwniez: ImageLoadFont().
int ImageString (int im, int font, int x, int y, string s, int col)

263

PHP Kompendium wiedzy

ImageStringUp
Na rysunku $im rysuje pionowo ciag $s rozpoczynajac od wsplrzednych $x, $y (lewy grny rg to 0,0) w kolorze $col. Jezeli $font wynosi 1, 2, 3, 4 lub 5, uzywane sa wbudowane czcionki. Patrz rwniez: ImageLoadFont().
int ImageStringUp (int im, int font, int x, int y, string s, int col)

ImageSX
Zwraca szerokosc rysunku identyfikowanego przez $im. Patrz rwniez: ImageCreate() i ImageSY().
int ImageSX (int im)

ImageSY
Zwraca wysokosc rysunku identyfikowanego przez $im. Patrz rwniez: ImageCreate() i ImageSX().
int ImageSY (int im)

ImageTTFBBox
Funkcja oblicza i zwraca ramke otaczajaca tekst TrueType (w pikselach). Parametr $text jest ciagiem do zmierzenia. Parametr $size jest wielkoscia czcionki, $fontfile jest nazwa pliku z czcionka TrueType (moze byc w postaci URL). $angle jest katem pochylenia tekstu $text w stopniach. Funkcja ImageTTFBBox() zwraca tablice skladajaca sie z osmiu elementw reprezentujacych cztery punkty tworzace ramke otaczajaca tekst: 0 wsplrzedna X lewego dolnego rogu, 1 wsplrzedna Y lewego dolnego rogu, 2 wsplrzedna X prawego dolnego rogu, 3 wsplrzedna Y prawego dolnego rogu, 4 wsplrzedna X prawego grnego rogu, 5 wsplrzedna Y prawego grnego rogu, 6 wsplrzedna X lewego grnego rogu, 7 wsplrzedna Y lewego grnego rogu. Punkty te sa niezalezne od pochylenia tekstu, wiec lewy grny oznacza grny wierzcholek po lewej stronie, patrzac na tekst poziomo. Funkcja wymaga bibliotek GD i FreeType. Patrz rwniez: ImageTTFText().
array imagettfbbox (int size, int angle, string fontfile, string text)

ImageTTFText
Na rysunku $im rysuje ciag $text, rozpoczynajac od wsplrzednych $x, $y (lewy grny rg to 0,0), pod katem $angle w kolorze $col, za pomoca czcionki TrueType umieszczonej w pliku $fontfile. Wsplrzedne podane w $x, $y okreslaja punkt bazowy pierwszego znaku (mniej wiecej lewy dolny rg znaku). Rzni sie to od funkcji ImageString(), gdzie x, y okreslaja prawy grny rg pierwszego znaku. Parametr $angle jest wyrazony w stopniach, gdzie 0 stopni okresla tekst czytany z lewej do prawej (kierunek na godzine trzecia), natomiast wyzsze wartosci reprezentuja pochylenie w kierunku przeciwnym do ruchu wskazwek zegara. (wartosc 90 powoduje narysowanie tekstu od gry do dolu). Parametr $fontflile jest sciezka do pliku TrueType z uzywana czcionka. Parametr $text jest ciagiem tekstowym, ktry moze zawierac sekwencje znakw UTF-8 (w postaci :{) uzywane do stosowania znakw o kodach powyzej 255. $col jest indeksem koloru. Uzycie ujemnego indeksu koloru powoduje wylaczenie wygladzania tekstu. Funkcja ImageTTFText() zwraca tablice osmioelementowa reprezentujaca cztery punkty stanowiace ramke ograniczajaca tekst. Punkty te sa umieszczone w tablicy w kolejnosci lewy grny, prawy grny, prawy dolny i lewy dolny. Punkty te sa niezalezne od pochylenia tekstu, wiec lewy grny oznacza grny wierzcholek po lewej stronie, patrzac na tekst poziomo.
array imagettftext (int im, int size, int angle, int x, int y, int col, string fontfile, string text)

Przyklad: ImageTTFText
<?php Header ("Content-type: image/gif"); $im = imagecreate (400, 30); $black = ImageColorAllocate ($im, 0, 0, 0); $white = ImageColorAllocate ($im, 255, 255, 255); ImageTTFText ($im, 20, 0, 10, 20, $white, "/path/arial.ttf", "Testowanie... Omega: &#937;"); ImageGif ($im); ImageDestroy ($im);

Dodatek A - Funkcje

264

?>

Funkcja wymaga bibliotek GD i FreeType. Patrz rwniez: ImageTTFBox().

ImageTypes
Funkcja zwraca maske bitowa zwiazana z formatami rysunkw obslugiwanych przez biblioteke GD dolaczona do PHP. Zwracane sa nastepujace bity: IMG_GIF | IMG_JPG | IMG_PNG | IMG_WBMP.
int imagetypes (void)

Przyklad: ImageTypes
<?php if (ImageTypes() & IMG_PNG) { echo "Obsluga PNG jest aktywna"; } ?>

imap_8bit
Konwertuje ciag 8-bitowy na ciag quoted-printable (zgodnie z RFC2045, sekcja 6.7). Zwraca ciag quotedprintable. Patrz rwniez imap_qprint().
string imap_8bit (string string)

imap_alerts
imap_alerts(),

Zwraca tablice wszystkich komunikatw ostrzezen IMAP wygenerowanych od ostatniego wywolania lub od poczatku strony. Gdy zostanie wywolana funkcja imap_alerts(), stos ostrzezen jest czyszczony. Specyfikacja IMAP wymaga, aby komunikaty te byly pokazywane uzytkownikowi.
array imap_alerts (void)

imap_append
Zwraca True w przypadku powodzenia i False w przypadku bledu. Funkcja dolacza ciag komunikatu do skrzynki pocztowej $mbox. Jezeli podane zostaly opcjonalne znaczniki $flags, funkcja dolacza rwniez do skrzynki te znaczniki. Dzialajac na serwerze Cyrus IMAP, trzeba uzyc terminatorw linii \r\n zamiast \n, lub operacja sie nie powiedzie.
int imap_append (int imap_stream, string mbox, string message [, string flags])

Przyklad: imap_append()
$stream = imap_open("{your.imap.host}INBOX.Drafts","username", "password"); $check = imap_check($stream); print "Ilosc komunikatw przed dolaczeniem: ". $check->Nmsgs."\n"; imap_append($stream,"{your.imap.host}INBOX.Drafts" ,"From: me@my.host\r\n" ."To: you@your.host\r\n" ."Subject: test\r\n" ."\r\n" ."przesylka testowa, prosze zignorowac\r\n" ); $check = imap_check($stream); print "Ilosc komunikatw po dolaczeniu : ". $check->Nmsgs."\n"; imap_close($stream);

imap_base64
Dekoduje tekst zakodowany metoda BASE-64 (patrz RFC2045, sekcja 6.8). Zdekodowany komunikat jest zwracany w postaci ciagu. Patrz rwniez: imap_binary().
string imap_base64 (string text)

265

PHP Kompendium wiedzy

imap_binary
Konwertuje 8-bitowy ciag na ciag zakodowany metoda BASE-64 (zgodnie z RFC2045, sekcja 6.8). Zwraca ciag base64. Patrz rwniez: imap_base64().
string imap_binary (string string)

imap_body
$flags

Zwraca tresc przesylki o numerze $msg_number z biezacej skrzynki pocztowej. Opcjonalny parametr jest maska bitowa zawierajaca jedna lub wiecej wartosci: FT_UID Wartosc $msgno jest idnetyfikatorem UID FT_PEEK Nie ustawia znacznika \Seen, jezeli jest juz ustawiony FT_INTERNAL Zwracany ciag jest w formacie wewnetrznym Funkcja imap_body() zwraca doslowna kopie tresci przesylki. Aby odczytac jeden fragment wieloczesciowej przesylki kodowanej za pomoca MIME nalezy uzyc funkcji imap_fetch_structure() do zanalizowania struktury i imap_fetch_body() do skopiowania pojedynczego komponentu przesylki.
string imap_body (int imap_stream, int msg_number [, int flags])

imap_check
Zwraca dane na temat biezacej skrzynki pocztowej. W przypadku bledu zwraca False. Funkcja imap_check() sprawdza status biezacej skrzynki na serwerze i zwraca dane w postaci obiektu o nastepujacych wlasciwosciach: Date ostatnia zmiana zawartosci skrzynki Driver protokl uzywany do komunikacji ze skrzynka: POP3, IMAP, NNTP Mailbox nazwa skrzynki pocztowej Nmsgs ilosc przesylek w skrzynce Recent ilosc nowych przesylek w skrzynce
object imap_check (int imap_stream)

imap_clearflag_full
Funkcja powoduje usuniecie okreslonego znacznika ze zbioru znacznikw przesylki w okreslonej sekwencji. Znacznikami do usuwania sa: \\Seen, \\Answered, \\Flagged, \\Deleted, \\Draft i \\Recent (wedlug RFC2060). Parametr $options jest maska bitowa skladajaca sie z nastepujacych znacznikw: ST_UID, sekwencja argumentw zawierajaca UID zamiast numerw sekwencji.
string imap_clearflag_full (int stream, string sequence, string flag, string options)

imap_close
Zamyka strumien imap. Posiada opcjonalny parametr $flag CL_EXPUNGE, ktry powoduje wyczyszczenie skrzynki przed zamknieciem poprzez usuniecie przesylek zaznaczonych jako usuniete.
int imap_close (int imap_stream [, int flags])

imap_createmailbox
Tworzy nowa skrzynke pocztowa o nazwie $mbox. Nazwy zawierajace znaki narodowe powinny byc zakodowane przy pomocy funkcji imap_utf7_encode(). Zwraca True w przypadku powodzenia lub False w przypadku wystapienia bledu. Patrz rwniez: imap_renamemailbox(), imap_deletemailbox() i imap_open() gdzie znajduje sie opis formatw nazw $mbox.
int imap_createmailbox (int imap_stream, string mbox)

Przyklad: imap_createmailbox()
$mbox = imap_open("{your.imap.host}","username","password",OP_HALFOPEN) or die("nie mozna polaczyc: ".imap_last_error()); $name1 = "phpnewbox";

Dodatek A - Funkcje

266

$name2 = imap_utf7_encode("phpnewbx"); $newname = $name1; echo "Nowa nazwa bedzie '$name1'<br>\n"; # tworzymy nowa skrzynke o nazwie "phptestbox" w skrzynce poczty przychozacej # sprawdzamy status po utworzeniu i na koniec usuwamy, przywracajac skrzynke # do stanu poczatkowego if(@imap_createmailbox($mbox,imap_utf7_encode("{your.imap.host}INBOX.$newname"))) { $status = @imap_status($mbox,"{your.imap.host}INBOX.$newname",SA_ALL); if($status) { print("nowa skrzynka '$name1' ma nastepujacy status:<br>\n"); print("Komunikatw: ". $status->messages )."<br>\n"; print("Ostatnich: ". $status->recent )."<br>\n"; print("Nieprzeczytanych:". $status->unseen )."<br>\n"; print("Nastepny UID: ". $status->uidnext )."<br>\n"; print("Poprawnosc UID: ". $status->uidvalidity)."<br>\n"; if(imap_renamemailbox($mbox,"{your.imap.host}INBOX.$newname", "{your.imap.host}INBOX.$name2")) { echo "zmieniono nazwe srzyni z '$name1' na '$name2'<br>\n"; $newname=$name2; } else { print "Nieudane wywolanie imap_renamemailbox na nowej skrzynce: " .imap_last_error()."<br>\n"; } } else { print "Nieudane wywolanie imap_status na nowej skrzynce: " .imap_last_error()."<br>\n"; } if(@imap_deletemailbox($mbox,"{your.imap.host}INBOX.$newname")) { print "nowa skrzynka usunieta, przywracajac stan poczatkowy<br>\n"; } else { print "Nieudane wywolanie imap_deletemailbox na nowej skrzynce: " .implode("<br>\n",imap_errors())."<br>\n"; } } else { print "nie mozna utworzyc nowej skrzyki: ".implode("<br>\n",imap_errors()) ."<br>\n"; } imap_close($mbox);

imap_delete
Zwraca True. Funkcja imap_delete() oznacza do usuniecia przesylke wskazywana przez $msg_number. Opcjonalny parametr $flags posiada tylko jedna opcje, FT_UID, ktra wskazuje funkcji, ze argumenty $msg_number nalezy traktowac jako identyfikatory UID. Przesylki zaznaczone do usuniecia pozostaja w skrzynce do czasu wywolania funkcji imap_expunge() lub imap_close() z ustawionym parametrem opcjonalnym CL_EXPUNGE.
int imap_delete (int imap_stream, int msg_number [, int flags])

Przyklad: imap_delete()
$mbox = imap_open ("{your.imap.host}INBOX", "username", "password") or die ("nie mozna polaczyc: " . imap_last_error()); $check = imap_mailboxmsginfo ($mbox); print "Przesylki przed usunieciem: " . $check->Nmsgs . "<br>\n" ; imap_delete ($mbox, 1); $check = imap_mailboxmsginfo ($mbox); print "Przesylki po usunieciu: " . $check->Nmsgs . "<br>\n" ; imap_expunge ($mbox); $check = imap_mailboxmsginfo ($mbox); print "Przesylki po wyczyszczeni: " . $check->Nmsgs . "<br>\n" ; imap_close ($mbox);

imap_deletemailbox
suwa podana skrzynke pocztowa (format nazw $mbox mozna znalezc przy opisie imap_open()). Zwraca True w przypadku powodzenia i False w przypadku bledu. Patrz rwniez: imap_createmailbox(), imap_renamemailbox() i imap_open(). 267 PHP Kompendium wiedzy

int imap_deletemailbox (int imap_stream, string mbox)

imap_errors
imap_errors()

Zwraca tablice wszystkich komunikatw bledw IMAP wygenerowanych od ostatniego wywolania lub od poczatku skryptu. Po wywolaniu imap_errors() stos bledw jest czyszczony.

array imap_errors (void)

imap_expunge
Usuwa
imap_setflag_full().

przesylki zaznaczone Zwraca True.

jako

usuniete

przez

imap_delete(),

imap_mail_move()

lub

int imap_expunge (int imap_stream)

imap_fetchbody
Funkcja powoduje pobranie sekcji z tresci podanego komunikatu w postaci tekstu i zwrcenie tego tekstu. Specyfikacja sekcji jest ciagiem liczb rozdzielonych kropkami, ktre sa indeksami w liscie czesci, w sposb okreslony przez specyfikacje IMAP4. Czesci z trescia nie sa dekodowane przez ta funkcje. Parametrem imap_fetchbody() jest maska bitowa z jedna lub wiecej stalych: FT_UID Parametr $msg_number jest UID FT_PEEK Nie ustawia znacznika \Seen, jezeli nie byl wczesniej ustawiony FT_INTERNAL Zwracany ciag jest w postaci wewnetrznej bez konwersji koncw linii.
string imap_fetchbody (int imap_stream, int msg_number, string part_number [, flags flags])

imap_fetchheader
Powoduje odczytanie calego, nieprzefiltrowanego RFC822 naglwka formatu podanego komunikatu i zwrcenie go ciagu znakw. Opcje sa nastepujace: FT_UID Parametr $msg_number jest UID FT_INTERNAL Zwracany ciag jest w postaci wewnetrznej bez konwersji koncw linii. FT_PREFETCH TEXT.RFC822 powinien byc w tym samym czasie wstepnie pobrany. Pozwala to uniknac dodatkowego RTT na polaczeniu IMAP, jezeli wymagany jest pelny tekst przesylki (na przyklad, operacja zapis do pliku)
string imap_fetchheader (int imap_stream, int msgno, int flags)

imap_fetchstructure
Funkcja pobiera wszystkie informacje o strukturze podanej przesylki. Opcjonalny parametr $flags posiada tylko jedna opcje, FT_UID, ktra wskazuje funkcji, ze argumenty $msg_number nalezy traktowac jako identyfikatory UID. Zwracany obiekt zawiera koperte, date wewnetrzna, rozmiar, znaczniki i strukture tresci, oraz podobne obiekty dla kazdego zalacznika MIME.
object imap_fetchstructure (int imap_stream, int msg_number [, int flags])

Tabela 1. Zwracany obiekt z imap_fetchstructure() Typ Typ tresci encoding Kodowanie do przeslania tresci ifsubtype TRUE jezeli wystepuje ciag podtypu subtype Podtyp MIME ifdescription TRUE jezeli jest to ciag opisu description Ciag opisu tresci ifid TRUE jezeli jest to ciag identyfikacyjny id Ciag identyfikacyjny lines Ilosc linii Dodatek A - Funkcje 268

bytes ifdisposition disposition ifdparameters dparameters ifparameters parameters parts Uwaga

Ilosc bajtw TRUE jezeli jest to ciag rozmieszczenia Ciag rozmieszczenia TRUE jezeli istnieje tablica dparameters Tablica parametrw rozmieszczenia TRUE jezeli istnieje tablica parametrw Tablica parametrw MIME Tablica obiektw opisujacych kazda czesc przesylki

Dparameters jest tablica obiektw posiadajacych atrybuty $attribute i $value. Parameters jest tablica obiektw posiadajacych atrybuty $attribute i $value. Parts jest tablica obietw o identycznej strukturze jak nadrzedny obiekt, z ograniczeniem, ze nie moga posiadac nastepnych obiektw parts.

Podstawowe typy tresci 0:text, 1: multipart, 2:message, 3:application, 4:audio, 5:image, 6-video, 7-other Rodzaje kodowania 0:7BIT, 1:8BIT, 2:BINARY, 3:BASE64, 4:QUOTED-PRINTABLE, 5:OTHER

imap_fetch_overview
Pobiera naglwki dla podanej sekwencji $sequence i zwraca skrt ich zawartosci. Parametr $sequence moze zawierac sekwencje indeksw wiadomosci lub identyfikatorw UID, gdy parametr $flag zawiera FT_UID. Funkcja zwraca tablice obiektw opisujacych nastepujace naglwki kolejnych wiadomosci: subject temat wiadomosci from nadawca wiadomosci date data wyslania message_id identyfikator wiadomosci references odwolania do tego identyfikatora wiadomosci size rozmiar w bajtach uid identyfikator UID wiadomosci w skrzynce msgno numer kolejny komunikatu w skrzynce recent wiadomosc oznaczona jako niedawna flagged wiadomosc zaznaczona answered wiadomosc na ktra zostala udzielona odpowiedz deleted wiadomosc zaznaczona do usuniecia seen wiadomosc przeczytana draft wiadomosc oznaczona jako szkic
array imap_fetch_overview (int imap_stream, string sequence [, int flags])

Przyklad: imap_fetch_overview()
$mbox = imap_open("{your.imap.host:143}","username","password") or die("blad polaczenia: ".imap_last_error()); $overview = imap_fetch_overview($mbox,"2,4:6",0); if(is_array($overview)) { reset($overview); while( list($key,$val) = each($overview)) { print $val->msgno . " - " . $val->date . " - " . $val->subject . "\n"; } } imap_close($mbox);

269

PHP Kompendium wiedzy

imap_getmailboxes
Zwraca tablice obiektw zawierajacych dane na temat skrzynek pocztowych. Kazdy obiekt posiada nastepujace atrybuty: $name zawiera pelna nazwe skrzynki, $delimiter znak podzialu w tej czesci hierarchii, w ktrej znajduje sie skrzynka, $attributes maska bitowa, ktra moze byc testowana za pomoca nastepujacych stalych: LATT_NOINFERIORS skrzynka nie posiada dzieci (skrzynek w niej zalozonych) LATT_NOSELECT jest to kontener a nie skrzynka i nie moze byc otwierany LATT_MARKED skrzynka jest zaznaczona i uzywana jedynie przez UW-IMAPD LATT_UNMARKED skrzynka nie jest zaznaczona i uzywana jedynie przez UW-IMAPD
array imap_getmailboxes (int imap_stream, string ref, string pattern)

Nazwy skrzynek zawierajace znaki narodowe z poza drukowalnego zakresu kodw ASCII sa zakodowane i moga byc rozkodowane za pomoca funkcji imap_utf7_decode(). Normalnie $ref powinien byc okreslany przez specyfikacje serwera, tak jak jest to opisane przy funkcji imap_open(), natomiast $pattern okresla poczatek przeszukiwania w hierarchii skrzynek pocztowych. Jezeli chcesz uzyskac wszystkie skrzynki, nalezy przekazac do parametru $pattern ciag "*". Moga byc tu uzywane dwa znaki specjalne: * i %. Jezeli uzyjemy znaku * w wyniku otrzymamy wszystkie skrzynki w hierarchii. Znak % powoduje otrzymanie jedynie skrzynek z biezacego poziomu hierarchii. Jezeli podamy jedynie "%", otrzymamy skrzynki z glwnego poziomu hierarchii, "~/mail/%" na UW-IMAPD zwrci wszystkie skrzynki z katalogu ~/mail, ale bez podkatalogw. Przyklad: imap_getmailboxes()
$mbox = imap_open("{your.imap.host}","username","password",OP_HALFOPEN) or die("blad polaczenia: ".imap_last_error()); $list = imap_getmailboxes($mbox,"{your.imap.host}","*"); if(is_array($list)) { reset($list); while (list($key, $val) = each($list)) { print "($key) "; print imap_utf7_decode($val->name).","; print "'".$val->delimiter."',"; print $val->attributes."<br>\n"; } } else print "nieudane wywolanie funkcji imap_getmailboxes: ".imap_last_error()."\n"; imap_close($mbox);

imap_getsubscribed
Identyczna z subskrypcje.
imap_getmailboxes(),

ale zwraca jedynie skrzynki, do ktrych uzytkownik posiada

array imap_getsubscribed (int imap_stream, string ref, string pattern)

imap_header
Alias funkcji imap_headerinfo(), dziala dokladnie tak samo.
imap_header( void )

imap_headerinfo
Zwraca obiekt do rznych fragmentw naglwka: message_id, newsgroups, followup_to, references.
imap_header( void )

remail, date, Date, subject, Subject, in_reply_to,

Dostepne sa nastepujace znaczniki wiadomosci: Recent 'R' jezeli wiadomosc jest przeczytana i niedawna, 'N' jezeli jest niedawna i nieprzeczytana, ' ' jezeli nie jest niedawna Unseen 'U' jezeli nie jest przeczytana i nie jest niedawna, ' ' jezeli przeczytana lub niedawna Answered 'A' jezeli udzielono odpowiedzi, ' ' jezeli nie udzielono odpowiedzi Deleted 'D' gdy usunieta, ' ' jezeli nie usunieta Dodatek A - Funkcje 270

Draft

Flagged Uwaga

'X' jezeli jest szkicem, ' ' 'F' jezeli jest zaznaczona, ' ' jezeli jest oznaczona

gdy

nim

nie

jest

Dzialanie znacznikw Recent i Unseen jest nieco dziwne. Jezeli chcesz sprawdzic, czy wiadomosc nie jest przeczytana, sprawdz Unseen == 'U' || Recent == 'N'.

(kompletna linia to:, do 1024 znakw) to[] (zwraca tablice obiektw z linii to: zawierajaca: personal, adl, mailbox, host) fromaddress (kompletna linia from:, do 1024 znakw) from[] (zwraca tablice obiektw z linii from: zawierajaca: personal, adl, mailbox, host) ccaddress (kompletna linia cc:, do 1024 znakw) cc[] (zwraca tablice obiektw z linii cc: zawierajaca: personal, adl, mailbox, host) bccaddress (kompletna linia bcc:, do 1024 znakw) bcc[] (zwraca tablice obiektw z linii bcc: zawierajaca: personal, adl, mailbox, host) reply_toaddress (kompletna linia reply_to:, do 1024 znakw) reply_to[] (zwraca tablice obiektw z linii reply_to: zawierajaca: personal, adl, mailbox, host) senderaddress (kompletna linia sender:, do 1024 znakw) sender[] (zwraca tablice obiektw z linii sender: zawierajaca: personal, adl, mailbox, host) return_path (kompletna linia return_path:, do 1024 znakw) return_path[] (zwraca tablice obiektw z linii return_path: zawierajaca: personal, adl, mailbox, host) udate (mail, message, date, in, unix, time) fetchfrom (linia from: sformatowana tak, aby zmiescila sie w $fromlength znakach) fetchsubject (linia subject: sformatowana tak, aby zmiescila sie w $fromlength znakach)
toaddress

imap_headers
Zwraca tablice ciagw sformatowanych z danymi naglwkw. Pozwala na jeden element na przesylke.
array imap_headers (int imap_stream)

imap_last_error
Zwraca pelny tekst ostatniego komunikatu bledu IMAP, ktry wystapil na biezacej stronie. Stos bledw pozostaje niezmieniony. Kolejne wywolania imap_last_error() zwrca ten sam blad, jezeli nie wystapia w miedzyczasie inne bledy.

imap_listmailbox
Zwraca tablice zawierajaca nazwy skrzynek pocztowych. Opis parametrw przy opisie imap_getmailboxes().
array imap_listmailbox (int imap_stream, string ref, string pattern)

$ref

$pattern

znajduje sie

Przyklad: imap_listmailbox()
$mbox = imap_open("{your.imap.host}","username","password",OP_HALFOPEN) or die("blad polaczenia: ".imap_last_error()); $list = imap_listmailbox($mbox,"{your.imap.host}","*"); if(is_array($list)) { reset($list); while (list($key, $val) = each($list)) print imap_utf7_decode($val)."<br>\n"; } else print "Nieudane wywolanie funkcji imap_listmailbox: ".imap_last_error()."\n"; imap_close($mbox);

271

PHP Kompendium wiedzy

imap_listsubscribed
Zwraca tablice z wszystkimi skrzynkami pocztowymi, do ktrych posiadasz subskrypcje. Jest ona niemal identyczna jak imap_listmailbox(), ale zwraca jedynie te skrzynki, do ktrych zalogowany uzytkownik posiada subskrypcje.
array imap_listsubscribed (int imap_stream, string ref, string pattern)

imap_mail
Funkcja ta jest obecnie dostepna tylko w PHP 3.
string imap_mail (string to, string subject, string message [, string additional_headers [, string cc [, string bcc [, string rpath]]]])

imap_mailboxmsginfo
Zwraca informacje na temat biezacej skrzynki pocztowej. Zwraca False w przypadku wystapienia bledu. Funkcja imap_mailboxmsginfo() sprawdza status skrzynki na serwerze. Jest podobna do imap_status(), ale dodatkowo sumuje rozmiary wszystkich wiadomosci w skrzynce, co jednak powoduje wydluzenie czasu wykonywania funkcji. Zwraca dane w postaci obiektu z nastepujacymi wlasciwosciami.
object imap_mailboxmsginfo (int imap_stream)

Wlasciwosci skrzynki pocztowej Date data ostatniej zmiany Driver sterownik Mailbox nazwa skrzynki Nmsgs ilosc wiadomosci Recent ilosc ostatnich wiadomosci Unread ilosc wiadomosci nie przeczytanych Deleted ilosc usunietych wiadomosci Size rozmiar skrzynki Przyklad: imap_mailboxmsginfo()
<?php $mbox = imap_open("{your.imap.host}INBOX","username", "password") or die("blad polaczenia: ".imap_last_error()); $check = imap_mailboxmsginfo($mbox); if($check) { print "Date: " . print "Driver: " . print "Mailbox: " . print "Messages: ". print "Recent: " . print "Unread: " . print "Deleted: " . print "Size: " . } else { print "imap_check() } imap_close($mbox); ?>

$check->Date $check->Driver $check->Mailbox $check->Nmsgs $check->Recent $check->Unread $check->Deleted $check->Size

."<br>\n" ."<br>\n" ."<br>\n" ."<br>\n" ."<br>\n" ."<br>\n" ."<br>\n" ."<br>\n"

; ; ; ; ; ; ; ;

failed: ".imap_last_error(). "<br>\n";

imap_mail_compose
string imap_mail_compose (array envelope, array body)

Przyklad: imap_mail_compose()
<?php $envelope["from"]="musone@afterfive.com"; $envelope["to"]="musone@darkstar"; $envelope["cc"]="musone@edgeglobal.com"; $part1["type"]=TYPEMULTIPART;

Dodatek A - Funkcje

272

$part1["subtype"]="mixed"; $filename="/tmp/imap.c.gz"; $fp=fopen($filename,"r"); $contents=fread($fp,filesize($filename)); fclose($fp); $part2["type"]=TYPEAPPLICATION; $part2["encoding"]=ENCBINARY; $part2["subtype"]="octet-stream"; $part2["description"]=basename($filename); $part2["contents.data"]=$contents; $part3["type"]=TYPETEXT; $part3["subtype"]="plain"; $part3["description"]="description3"; $part3["contents.data"]="contents.data3\n\n\n\t"; $body[1]=$part1; $body[2]=$part2; $body[3]=$part3; echo nl2br(imap_mail_compose($envelope,$body)); ?>

imap_mail_copy
Zwraca True w przypadku sukcesu lub False w przypadku wystapienia bledu. Kopiuje wiadomosc okreslona przez $msglist do okreslonej skrzynki pocztowej. Parametr $msglist moze zawierac zakres a nie tylko numery komunikatw, jak to zostalo opisane w RFC2060 (http://www.faqs.org/rfcs/rfc2060.html). Parametr $flags jest maska bitowa zawierajaca CP_UID sekwencja liczb zawiera UID i CP_MOVE usuwa komunikaty ze skrzynki po ich skopiowaniu.
int imap_mail_copy (int imap_stream, string msglist, string mbox [, int flags])

imap_mail_move
Przenosi przesylke pocztowa okreslona przez $msglist to podanej skrzynki pocztowej. Parametr $msglist moze zawierac zakres a nie tylko numery komunikatw, jak to zostalo opisane w RFC2060 (http://www.faqs.org/rfcs/rfc2060.html). Parametr $flags jest maska bitowa i moze zawierac jedna wartosc CP_UID. Zwraca True w przypadku sukcesu lub False w przypadku wystapienia bledu.
int imap_mail_move (int imap_stream, string msglist, string mbox [, int flags])

imap_mime_header_decode
Dekoduje rozszerzenia naglwkw komunikatw MIME, ktre zawieraja tekst z poza ASCII (RFC2047 http://www.faqs.org/rfcs/rfc2047.html). Zdekodowane elementy sa zwracane w postaci tablicy obiektw, z ktry posiada dwie wlasciwosci: charset i text. Jezeli element nie moze byc zdekodowany a inne slowa sa w USASCII, wlasciwosc charset jest ustawiona na wartosc domyslna.
array imap_mime_header_decode (string text)

Przyklad: imap_mime_header_decode()
$text="=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>"; $elements=imap_mime_header_decode($text); for($i=0;$i<count($elements);$i++) { echo "Charset: {$elements[$i]->charset}\n"; echo "Text: {$elements[$i]->text}\n\n"; }

W przedstawionym przykladzie otrzymamy dwa elementy, gdzie pierwszy element jest zakodowany za pomoca ISO-8859-1 a drugi bedzie US-ASCII.

imap_msgno
Zwraca numer sekwencji wiadomosci dla podanego UID. Jest to odwrotnosc imap_uid().
int imap_msgno (int imap_stream, int uid)

273

PHP Kompendium wiedzy

imap_num_msg
Zwraca ilosc przesylek w biezacej skrzynce pocztowej.
int imap_num_msg (int imap_stream)

imap_num_recent
Zwraca ilosc ostatnich przesylek w biezacej skrzynki pocztowej.
int imap_num_recent (int imap_stream)

imap_open
W przypadku powodzenia zwraca strumien IMAP, a w przypadku bledu False. Funkcja moze byc uzywana do otwarcia strumienia do serwerw POP3 i NNTP i nie wszystkie funkcje i wlasnosci sa dostepne na serwerach IMAP. Nazwa skrzynki sklada sie z dwch czesci: nazwy serwera i sciezki do skrzynki na tym serwerze. Nazwa specjalna INBOX okresla biezaca skrzynke pocztowa uzytkownika. Fragment nazwy okreslajacy serwer jest otoczony nawiasami klamrowymi {} i zawiera nazwe serwera, lub jego numer IP, okreslenie protokolu komunikacji (rozpoczynajace sie od /), oraz opcjonalnie numer portu rozpoczynajacy sie od znaku :. Podawanie nazwy serwera jest obowiazkowe we wszystkich parametrach skrzynki pocztowej. Nazwy skrzynek zawierajace znaki narodowe spoza drukowalnego podzbioru kodw ASCII sa zakodowane za pomoca funkcji imap_utf7_encode().
int imap_open (string mailbox, string username, string password [, int flags])

Opcje stanowia maske bitowa zawierajaca jedna, lub wiecej z ponizszych wartosci: OP_READONLY otwiera skrzynke tylko do odczytu, OP_ANONYMOUS nie uzywa ani nie zmienia pliku .newsrc (tylko NNTP), OP_HALFOPEN dla polaczen IMAP i NNTP, otwiera polaczenie, ale nie otwiera skrzynki, CL_EXPUNGE automatycznie czysci skrzynke po jej zamknieciu. Aby podlaczyc sie z serwerem IMAP dzialajacym na porcie 143 na komputerze lokalnym, nalezy wywolac funkcje w nastepujacy sposb:
$mbox = imap_open ("{localhost:143}INBOX", "user_id", "password");

Aby podlaczyc sie z serwerem POP3 dzialajacym na porcie 110 na komputerze lokalnym, nalezy wywolac funkcje w nastepujacy sposb:
$mbox = imap_open ("{localhost:110/pop3}INBOX", "user_id", "password");

Aby podlaczyc sie z serwerem NNTP dzialajacym na porcie 119 na komputerze lokalnym, nalezy wywolac funkcje w nastepujacy sposb:
$mbox = imap_open ("{localhost:993/imap/ssl}INBOX", "user_id", "password");

Aby polaczyc sie ze zdalnym serwerem nalezy zastapic localhost nazwa lub numerem IP serwera, z ktrym ma byc nawiazane polaczenie. Przyklad: imap_open()
$mbox = imap_open ("{your.imap.host:143}", "username", "password"); echo "<p><h1>Skrzynki pocztowe</h1>\n"; $folders = imap_listmailbox ($mbox, "{your.imap.host:143}", "*"); if ($folders == false) { echo "wywolanie nieudane<br>\n"; } else { while (list ($key, $val) = each ($folders)) { echo $val."<br>\n"; } } echo "<p><h1>naglwki w INBOX</h1>\n"; $headers = imap_headers ($mbox); if ($headers == false) { echo "wywolanie nieudane<br>\n"; } else { while (list ($key,$val) = each ($headers)) { echo $val."<br>\n"; } } imap_close($mbox);

Dodatek A - Funkcje

274

imap_ping
Zwraca True, jezeli strumien jest aktywny, False w przypadku nieaktywnego strumienia. Funkcja imap_ping() sprawdza za pomoca operacji ping, czy strumien jest nadal aktywny. Moze sprawdzac nowa poczte. Jest to zalecana metoda okresowego sprawdzania nowej poczty oraz podtrzymywania polaczenia do serwerw rozlaczajacych nieaktywne polaczenia (poniewaz skrypty PHP nie dzialaja zbyt dlugo, funkcja ta prawdopodobnie nie bedzie zbyt uzyteczna).
int imap_ping (int imap_stream)

imap_qprint
Konwertuje ciag zakodowany w postaci quoted-printable na ciag 8-bitowy zgodnie z RFC2045 (http://www/faqs.org/rfcs/rfc2045.html, sekcja 6.7). Zwraca ciag 8-bitowy (binarny). Patrz rwniez: imap_8bit().
string imap_qprint (string string)

imap_renamemailbox
Zmienia nazwe skrzynki pocztowej na nowa (format nazw skrzynek opisany jest przy funkcji Zwraca True gdy operacja sie powiodla i False w przypadku bledu. Patrz rwniez: imap_createmailbox(), imap_deletemailbox() i imap_open().
imap_open()).
int imap_renamemailbox (int imap_stream, string old_mbox, string new_mbox)

imap_reopen
Ponownie otwiera strumien do nowej skrzynki na serwerze IMAP lub NNTP. Opcje sa maska bitowa zawierajaca jedna lub wiecej nastepujacych wartosci: OP_READONLY otwiera skrzynke tylko do odczytu, OP_ANONYMOUS nie uzywa ani nie zmienia pliku .newsrc (tylko NNTP), OP_HALFOPEN dla polaczen IMAP i NNTP, otwiera polaczenie, ale nie otwiera skrzynki, CL_EXPUNGE automatycznie czysci skrzynke po jej zamknieciu. Zwraca True w przypadku powodzenia i False w przypadku bledu.
int imap_reopen (int imap_stream, string mailbox [, string flags])

imap_rfc822_parse_adrlist
Analizuje adresy w sposb zdefiniowany w RFC822 (http://www/faqs.org/rfcs/rfc2045.html). Dla kazdego adresu zwraca tablice obiektw. Wlasciwosciami obiektw sa: mailbox nazwa skrzynki (nazwa uzytkownika), host nazwa hosta, personal nazwa opisowa uzytkownika, adl sciezka do domeny zrdlowej.
array imap_rfc822_parse_adrlist (string address, string default_host)

Przyklad: imap_rfc822_parse_adrlist()
$address_string = "Hartmut Holzgraefe <hartmut@cvs.php.net>, postmaster@somedomain.net, root"; $address_array = imap_rfc822_parse_adrlist($address_string,"somedomain.net"); if(! is_array($address_array)) die("cos poszlo zle\n"); reset($address_array); while(list($key,$val)=each($address_array)){ print "mailbox : ".$val->mailbox."<br>\n"; print "host : ".$val->host."<br>\n"; print "personal: ".$val->personal."<br>\n"; print "adl : ".$val->adl."<p>\n"; }

275

PHP Kompendium wiedzy

imap_rfc822_parse_headers
Zwraca obiekt z rznymi elementami naglwka, podobnie do elementw pochodzacych z serwera IMAP.
imap_header(),

ale bez znacznikw i innych

object imap_rfc822_parse_headers (string headers [, string defaulthost])

imap_rfc822_write_address
Zwraca prawidlowo sformatowany adres e-mail wedlug definicji w (http://www/faqs.org/rfcs/rfc2045.html), na podstawie skrzynki pocztowej, hosta i danych osobistych.
string imap_rfc822_write_address (string mailbox, string host, string personal)

RFC822

Przyklad: imap_rfc822_write_address()
print imap_rfc822_write_address("hartmut","cvs.php.net","Hartmut Holzgraefe")."\n";

imap_scanmailbox
Zwraca tablice zawierajaca nazwy skrzynek, ktre zawieraja tekst przekazany w $string. Funkcja ta jest podobna do imap_listmailbox(), ale dodatkowo sprawdza czy w danych skrzynki zawarty tekst $content. Opis parametrw $ref i $pattern mozna znalezc przy funkcji imap_getmailboxes().
array imap_scanmailbox (int imap_stream, string ref, string pattern, string content)

imap_search
Przeszukuje skrzynke pocztowa otwarta za poca podanego strumienia IMAP. Parametr $criteria zawiera ciag, w ktrym dozwolone sa zamieszczone ponizej slowa kluczowe rozdzielone spacjami. Wszystkie elementy wielowyrazowe musza byc otoczone apostrofami, na przyklad FROM "jan kowalski".
array imap_search (int imap_stream, string criteria, int flags)

ALL

ANSWERED

zwraca wszystkie wiadomosci spelniajace pozostale warunki szuka wiadomosci z ustawionym znacznikiem \\ANSWERED BCC "string" szuka wiadomosci z ciagiem "string" w polu Bcc: BEFORE "date" szuka wiadomosci sprzed podanej daty BODY "string" szuka wiadomosci z ciagiem "string" w temacie wiadomosci CC "string" szuka wiadomosci z ciagiem "string" w polu Cc: DELETED szuka usunietych wiadomosci FLAGGED szuka wiadomosci z ustawionym znacznikiem \\FLAGGED (czasami nazywanymi wiadomosciami waznymi) FROM "string" szuka wiadomosci z ciagiem "string" w polu From: KEYWORD "string" szuka wiadomosci ze slowem kluczowym "string" NEW szuka nowych wiadomosci OLD szuka starych wiadomosci ON "date" szuka wiadomosci z polem Date: ustawionym na "date" RECENT szuka wiadomosci z ustawionym znacznikiem \\RECENT SEEN szuka przeczytanych wiadomosci (z ustawionym znacznikiem \\SEEN) SINCE "date" szuka wiadomosci z polem Date: ustawionym na date wczesniejsza od "date" SUBJECT "string" szuka wiadomosci z ciagiem "string" w polu Subject: TEXT "string" szuka wiadomosci z ciagiem "string" w tekscie TO "string" szuka wiadomosci z ciagiem "string" w polu To: UNANSWERED szuka wiadomosci, a ktre nie byla udzielona odpowiedz UNDELETED szuka wiadomosci, ktre nie sa usuniete UNFLAGGED szuka wiadomosci, ktre nie sa oznaczone UNKEYWORD "string" szuka wiadomosci nie posiadajacych slowa kluczowego "string" UNSEEN szuka wiadomosci nie przeczytanych 276

Dodatek A - Funkcje

Na przyklad, aby odnalezc wszystkie wiadomosci wyslanych przez Mama, na ktre nie byla udzielona odpowiedz, nalezy uzyc ciagu "UNANSWERED FROM Mama". Przy przeszukiwaniu duze i male litery nie sa rozrzniane. Podana lista warunkw jest odczytana ze zrdel UW c-client i moze byc niekompletna lub nieprecyzyjna (patrz RFC2060 sekcja 6.4.4). Prawidlowa wartoscia parametru $flags jest SE_UID, ktry powoduje zwracanie tablicy zawierajacej identyfikatory UID zamiast numerw kolejnych wiadomosci.

imap_setflag_full
Powoduje dodanie okreslonych znacznikw do wiadomosci z podanej sekwencji. Znaczniki jakie mozna ustawic to: \\Seen, \\Answered, \\Flagged, \\Deleted, \\Draft i \\Recent (wedlug RFC2060). Prawidlowa wartoscia parametru $flags jest ST_UID, ktry powoduje zwracanie tablicy zawierajacej identyfikatory UID zamiast numerw kolejnych wiadomosci.
string imap_setflag_full (int stream, string sequence, string flag, string options)

Przyklad: imap_setflag_full()
$mbox = imap_open("{your.imap.host:143}","username","password") or die("blad polaczenia: ".imap_last_error()); $status = imap_setflag_full($mbox,"2,5","\\Seen \\Flagged"); print gettype($status)."\n"; print $status."\n"; imap_close($mbox);

imap_sort
Zwraca tablice numerw wiadomosci posortowana wedlug podanego parametru. Jezeli sortowanie jest odwrotne.
array imap_sort (int stream, int criteria, int reverse, int options)

$reverse

jest 1,

Sortowanie moze sie odbywac wedlug jednego (tylko jednego) z ponizszych warunkw: SORTDATE data wiadomosci SORTARRIVAL data otrzymania wiadomosci SORTFROM adresu nadawcy (From:) SORTSUBJECT tematu wiadomosci SORTTO adresu z pola To: SORTCC adresu z pola Cc: SORTSIZE wielkosci przesylki liczonej w oktetach Opcje sa maska bitowa z nastepujacymi wartosciami: SE_UID Funkcja zwraca identyfikatory UID zamiast numerw kolejnych SE_NOPREFETCH nie odczytuje wstepnie szukanych wiadomosci

imap_status
Zwraca obiekt zawierajacy dane statusu.
object imap_status (int imap_stream, string mailbox, int options)

Dozwolonymi znacznikami sa: SA_MESSAGES ustawia status->messages na ilosc wiadomosci w skrzynce SA_RECENT ustawia status->recent na ilosc niedawnych wiadomosci w skrzynce SA_UNSEEN ustawia status->unseen na ilosc nierzeczytanych (nowych) wiadomosci w skrzynce SA_UIDNEXT ustawia status->uidnext na nastepny UID jaki zostanie uzyty w skrzynce SA_UIDVALIDITY ustawia status->uidvalidity na stala, ktra zmienia sie, gdy UID skrzynki przestaje byc prawidlowy SA_ALL ustawia wszystkie powyzsze wlasciwosci Dodatkowo ustawiany jest status->flags zawierajacy maske bitowa, ktra moze byc porwnywana z przedstawionymi powyzej stalymi. Przyklad: imap_status()
$mbox = imap_open("{your.imap.host}","username","password",OP_HALFOPEN) or die("blad polaczenia: ".imap_last_error());

277

PHP Kompendium wiedzy

$status = imap_status($mbox,"{your.imap.host}INBOX",SA_ALL); if($status) { print("Wiadomosci: ". $status->messages )."<br>\n"; print("Niedawnych: ". $status->recent )."<br>\n"; print("Nieprzeczytanych:". $status->unseen )."<br>\n"; print("Nastepny UID: ". $status->uidnext )."<br>\n"; print("Poprawnosc UID: ". $status->uidvalidity)."<br>\n"; } else print "nieudane wywolanie imap_status: ".imap_last_error()."\n"; imap_close($mbox);

imap_subscribe
Subskrybuje nowa skrzynke. Zwraca bledu.
int imap_subscribe (int imap_stream, string mbox)

True

po poprawnym wykonaniu operacji lub

False

w przypadku

imap_uid
Zwraca identyfikator UID wiadomosci na podstawie jej numeru kolejnego. UID to jednoznaczny identyfikator nie zmieniajacy sie w czasie w przeciwienstwie do numerw kolejnych, ktre moga sie zmienic po zmianie zawartosci skrzynki. Funkcja jest odwrotna do imap_msgno().
int imap_uid (int imap_stream, int msgno)

imap_undelete
imap_move().

Usuwa znacznik usuniecia dla podanej wiadomosci ustawiony przez funkcje Zwraca True w przypadku powodzenia i False w przypadku bledu.

imap_delete()

lub

int imap_undelete (int imap_stream, int msg_number)

imap_unsubscribe
Usuwa subskrypcje do podanej skrzynki. Zwraca bledu.
int imap_unsubscribe (int imap_stream, string mbox)

True

w przypadku powodzenia i

False

w przypadku

imap_utf7_decode
Dekoduje $text w postaci UTF-7 do danych 8-bitowych. Zwraca zdekodowane dane 8-bitowe, lub False, gdy ciag wejsciowy nie jest prawidlowym ciagiem UTF-7. Funkcja ta jest niezbedna do dekodowania nazw skrzynek zwierajacych znaki narodowe spoza drukowalnego zakresu kodw ASCII. Zmodyfikowane kodowanie UTF-7 jest zdefiniowane w RFC2060 (http://www/faqs.org/rfcs/rfc2060.html sekcja 5.1.3), natomiast oryginalne kodowanie UTF-7 jest zdefiniowane w RFC1642 (http://www/faqs.org/rfcs/rfc1642.html).
string imap_utf7_decode (string text)

imap_utf7_encode
Konwertuje 8-bitowe dane do tekstu UTF-7. Jest to niezbedne do zakodowania nazw skrzynek zawierajacych znaki narodowe spoza drukowalnego zakresu kodw ASCII. Zmodyfikowane kodowanie UTF-7 jest zdefiniowane w RFC2060 (http://www/faqs.org/rfcs/rfc2060.html sekcja 5.1.3), natomiast oryginalne kodowanie UTF-7 jest zdefiniowane w RFC1642 (http://www/faqs.org/rfcs/rfc1642.html). Zwraca ciag zakodowany zmodyfikowana metoda UTF-7.
string imap_utf7_encode (string data)

imap_utf8
Konwertuje podany ciag na postac UTF8 w sposb zdefiniowany w RFC2044.
string imap_utf8 (string text)

Dodatek A - Funkcje

278

implode
Zwraca ciag zawierajacy wszystkie elementy tablicy w tej samej kolejnosci z ciagiem sklejajacym pomiedzy elementami.
Uwaga Funkcja implode() moze, z powodw historycznych, pobierac swoje argumenty w dowolnym porzadku. Jednak z powodu spjnosci z explode() powinno sie korzystac z kolejnosci przedstawionej w dokumentacji.

Patrz rwniez: explode(), join() i split().


string implode (string glue, array pieces)

Przyklad: implode()
$colon_separated = implode(":", $array);

ini_alter
Zmienia wartosc podanej opcji konfiguracji. Zwraca przypadku sukcesu, poprzednia wartosc opcji.
Uwaga Jest to alias do ini_set(). False

w przypadku niepowodzenia, natomiast w

Patrz rwniez: ini_get(), ini_restore() i ini_set().


string ini_alter (string varname, string newvalue)

ini_get
ini_restore()

Zwraca wartosc opcji konfiguracji lub i ini_set().

False

w przypadku wystapienia bledu. Patrz rwniez:

ini_alter(),

string ini_get (string varname)

ini_restore
Przywraca oryginalna wartosc podanej opcji konfiguracji. Patrz rwniez
ini_set().
string ini_restore (string varname)

ini_alter(), ini_get()

ini_set
Ustawia wartosc podanej opcji konfiguracji. Zwraca False w przypadku niepowodzenia, natomiast w przypadku sukcesu, poprzednia wartosc opcji. Patrz rwniez: ini_alter(), ini_get() i ini_restore().
string ini_set (string varname, string newvalue)

intval
Zwraca wartosc calkowita zmiennej $var przy uzyciu konwersji o podanej podstawie (wartoscia domyslna jest 10). Parametr $var moze byc dowolnym typem skalarnym. Nie mozna uzywac funkcji intval() na tablicach i obiektach. Patrz rwniez doubleval(), strval() i settype().
int intval (mixed var [, int base])

in_array
Szuka $needle w zostanie znaleziony. 279
$haystack.

Zwraca

True,

jezeli ciag zostanie znaleziony w tablicy i

False,

jezeli nie

bool in_array (mixed needle, array haystack)

PHP Kompendium wiedzy

Przyklad: in_array()
$os = array ("Mac", "NT", "Irix", "Linux"); if (in_array ("Irix", $os)) { print "Znaleziono Irix"; }

ip2long
Generuje adres IPv4 na podstawie standardowego formatu (ciag z kropkami).
int ip2long (string ip_address)

Przyklad: ip2long()
<?php $ip = gethostbyname("www.php.net"); $out = "Nastepujace adresy sa swoimi odpowiednikami:<br>\n"; $out .= "http://www.php.net/, http://".$ip."/ i http://".ip2long($ip)."/<br>\n"; echo $out; ?>

Patrz rwniez: long2ip().

iptcparse
Dzieli pojedynczy blok IPTC na pojedyncze znaczniki. Zwraca tablice uzywajac jako indeksw oznaczen znacznikw a jako wartosci, wartosci znacznikw. W przypadku bledu lub braku danych IPTC zwraca False. Patrz rwniez: GetImageSize().
array iptcparse (string iptcblock)

isset
Jezeli istnieje $var zwraca True, a unset(), funkcja isset() zwraca False.
boolean isset (mixed var)

False

gdy nie istnieje. Jezeli zmienna zostala usunieta za pomoca

Przyklad: isset()
$a = "test"; echo isset ($a); // TRUE unset ($a); echo isset ($a); // FALSE $foo = NULL; print isset ($foo); // FALSE

Patrz rwniez: empty() i unset().

is_array
is_integer(), is_string()

Zwraca True, jezeli $var jest tablica i i is_object().

False,

gdy nia nie jest. Patrz rwniez:

is_float(), is_int(),

bool is_array (mixed var)

is_bool
Zwraca True, jezeli parametr $var jest wartoscia boolean. Parz rwniez: is_array(), is_float(), is_int(), is_integer(), is_string() i is_object().
bool is_bool (mixed var)

is_dir
Zwraca True, jezeli istnieje katalog o podanej nazwie. Wynik funkcji jest przechowywany w pamieci podrecznej. Wiecej szczeglw na ten temat znajduje sie w opisie funkcji clearstatchache(). Patrz rwniez: is_file() i is_link().
bool is_dir (string filename)

Dodatek A - Funkcje

280

is_double
Zwraca True, jezeli parametr $var jest liczba double, w przeciwnym wypadku zwraca rwniez: is_bool(), is_int(), is_integer(), is_string(), is_array() i is_object().
int is_double( mixed var)

False.

Patrz

is_executable
Zwraca True, jezeli istnieje plik o podanej nazwie pliku i jest on plikiem wykonywalnym. Wyniki dzialania funkcji sa przechowywane w pamieci podrecznej. Wiecej szczeglw na ten temat znajduje sie w opisie funkcji clearstatchache(). Patrz rwniez: is_file() i is_link().
bool is_executable (string filename)

is_file
Zwraca True, jezeli istnieje plik o podanej nazwie pliku i jest on zwyklym plikiem. Wyniki dzialania funkcji sa przechowywane w pamieci podrecznej. Wiecej szczeglw na ten temat znajduje sie w opisie funkcji clearstatchache(). Patrz rwniez: is_dir() i is_link().
bool is_file (string filename)

is_float
Alias do funkcji is_double(). Patrz rwniez: is_bool(), is_int(), is_integer(), is_string(), is_array() i is_object().
bool is_float (mixed var)

is_int
Alias do is_object().
is_long().

Patrz rwniez:

is_bool(), is_float(), is_integer(), is_string(), is_array()

bool is_int (mixed var)

is_integer
Alias do is_object().
is_long().

Patrz rwniez:

is_bool(), is_float(), is_integer(), is_string(), is_array()

bool is_integer (mixed var)

is_link
Zwraca True, jezeli istnieje plik o podanej nazwie pliku i jest on laczem symbolicznym. Wyniki dzialania funkcji sa przechowywane w pamieci podrecznej. Wiecej szczeglw na ten temat znajduje sie w opisie funkcji clearstatchache(). Patrz rwniez: is_dir() i is_file(). Funkcja ta nie dziala w systemie Windows.
bool is_link (string filename)

is_long
Zwraca True, jezeli $var jest liczba calkowita (long), w przeciwnym wypadku zwraca rwniez: is_bool(), is_float(), is_integer(), is_string(), is_array() i is_object().
is_long( mixed var)

False.

Patrz

is_numeric
Zwraca True, jezeli $var jest liczba lub ciagiem zawierajacym liczbe, w przeciwnym wypadku zwraca False. Patrz rwniez: is_bool(), is_float(), is_int(), is_string(), is_object(), is_array() i is_integer().
bool is_numeric (mixed var)

281

PHP Kompendium wiedzy

is_object
Zwraca True, jezeli $var jest obiektem, w przeciwnym wypadku zwraca is_int(), is_integer(), is_float(), is_string() i is_array().
bool is_object (mixed var)

False.

Patrz rwniez:

is_bool(),

is_readable
Zwraca True, jezeli plik o podanej nazwie istnieje i mozna go odczytac. Nalezy pamietac, ze PHP moze czytac ten plik jako uzytkownik na rzecz ktrego jest uruchomiony serwer WWW (czesto jest to nobody). Nie sa brane pod uwage ograniczenia trybu bezpiecznego. Wiecej szczeglw na ten temat znajduje sie w opisie funkcji clearstatchache(). Patrz rwniez: is_writable().
bool is_readable (string filename)

is_real
Alias do funkcji is_double(). Patrz rwniez: is_bool(), is_int(), is_integer(), is_string(), is_array() i is_object().
int is_real( mixed var )

is_resource
Zwraca True, jezeli zmienna przekazana przez parametr $var jest zasobem, w przeciwnym przypadku zwraca False. Zasobami sa identyfikatory plikw lub wynikw zapytan do bazy danych, ktre sa tworzone i usuwane poprzez wewnetrzne funkcje PHP. Jezeli nie sa one uzywane mozna zastosowac ich porzadkowanie, ale nie powinny byc one zwalniane przez kod uzytkownika.
bool is_resource (mixed var)

is_string
Zwraca True, jezeli $var jest ciagiem, w przeciwnym wypadku zwraca False. Patrz rwniez: is_bool(), is_int(), is_integer(), is_float(), is_real(), is_object() i is_array().
bool is_string (mixed var)

is_subclass_of
Zwraca True, jezeli $obj jest obiektem klasy, ktra jest klasa pochodna po wypadku zwraca False. Patrz rwniez: get_class(), get_parent_class().
bool is_subclass_of (object obj, string superclass)

$superclass,

w przeciwnym

is_uploaded_file
Funkcja ta jest dostepna w PHP3 poczawszy od wersji PHP 3.0.16 i w PHP od wersji 4.0.2. Zwraca True, jezeli plik o podanej nazwie zostal przeslany poprzez HTTP POST. Jest ona uzyteczna do sprawdzenia, czy zlosliwy uzytkownik nie prbuje oszukac skryptu tak, aby pracowal on na pliku, na ktrym nie powinien, na przyklad /etc/passwd. Jest to uzyteczne, gdy istnieje jakakolwiek szansa, ze zawartosc przesylanego pliku moze byc pokazana uzytkownikowi, lub innym uzytkownikom na tym samym systemie. Patrz rwniez: move_uploaded_file().
bool is_uploaded_file (string filename)

is_writeable
Zwraca True, jezeli plik o podanej nazwie istnieje i mozna do niego pisac. Parametr moze byc rwniez nazwa katalogu, co pozwala sprawdzic, czy mozna zapisywac do tego katalogu. Nalezy pamietac, ze PHP moze czytac ten plik jako uzytkownik na rzecz ktrego jest uruchomiony serwer WWW (czesto jest to nobody). Nie sa Dodatek A - Funkcje 282

brane pod uwage ograniczenia trybu bezpiecznego. Wiecej szczeglw na ten temat znajduje sie w opisie funkcji clearstatchache(). Patrz rwniez: is_readable().
bool is_writeable (string filename)

JDDayOfWeek
Zwraca dzien tygodnia. W zaleznosci od trybu moze zwracac ciag lub liczbe.
mixed jddayofweek (int julianday, int mode)

Tabela 2. Tryby tygodni w kalendarzu Tryb Znaczenie 0 Zwraca numer dnia jako liczbe (0=niedziela, 1=poniedzialek, itd.) 1 Zwraca ciag zawierajacy dzien tygodnia (angielskigregorianski) 2 Zwraca ciag zawierajacy skrt dnia tygodnia (angielski-gregorianski)

JDMonthName
Zwraca ciag zawierajacy nazwe miesiace. Parametr $mode wskazuje funkcji do ktrego kalendarza skonwertowac liczbe dni julianskich i jaki typ nazwy miesiaca nalezy zwrcic.
string jdmonthname (int julianday, int mode)

Tabela 3. Tryby kalendarza Tryb Znaczenie 0 Gregorianski skrcony 1 Gregorianski 2 Julianski skrcony 3 Julianski 4 Zydowski 5 Republiki francuskiej

JDToFrench
Konwertuje liczbe dni julianskich do kalendarza Rewolucji Francuskiej.
string jdtofrench (int juliandaycount)

JDToGregorian
Konwertuje liczbe dni julianskich na ciag zawierajacy date gregorianska w formacie miesiac/dzien/rok.
string jdtogregorian (int julianday)

JDToJewish
Konwertuje liczbe dni julianskich na kalendarz zydowski.
string jdtojewish (int julianday)

JDToJulian
Konwertuje liczbe dni julianskich na ciag zawierajacy date w kalendarzu julianskim w formacie miesiac/dzien/rok.
string jdtojulian (int julian3day)

283

PHP Kompendium wiedzy

jdtounix
Zwraca znacznik czasu Uniksa odpowiadajacy dacie julianskiej przekazanej w $jday, lub False jezeli $jday wykracza poza ere Uniksa (lata gregorianskie pomiedzy 1970 i 2037 lub 2440588 <= $jday <= 2465342). Patrz rwniez: jdtounix().
Uwaga Funkcja ta jest dostepna od wersji PHP4RC1.
int jdtounix (int jday)

JewishToJD
Mimo, ze oprogramowanie moze obslugiwac daty az do roku 1 (3761 p.n.e.), jednak moze byc to mylace. Kalendarz zydowski jest w uzyciu od kilku tysiecy lat, ale w poczatkowym okresie nie bylo wzoru na wyliczenie poczatku miesiaca. Miesiac byl rozpoczynany po zaobserwowaniu nowiu ksiezyca.
int jewishtojd (int month, int day, int year)

join
Jest to alias do funkcji implode() i dziala identycznie. Patrz rwniez: explode(), implode() i split().
string join (string glue, array pieces)

JulianToJD
Zakres dat kalendarza julianskiego to 4713 p.n.e. do 9999 n.e. Mimo, ze oprogramowanie moze obslugiwac daty od 413 p.n.e., jednak moze byc to mylace. Kalendarz zostal utworzony w roku 46 p.n.e., ale jego szczegly nie ustabilizowaly sie do roku 8 n.e. a nawet prawdopodobnie do 4 wieku. Rwniez poczatek roku rznil sie w rznych kulturach nie wszyscy zaakceptowali styczen jako pierwszy miesiac.
int juliantojd (int month, int day, int year)

key
Zwraca klucz biezacej pozycji tablicy. Patrz rwniez: current() i next().
mixed key (array array)

krsort
Sortuje tablice w odwrotnej kolejnosci utrzymujac korelacje miedzy kluczami i danymi. Jest to przydatne w przypadku tablic asocjacyjnych.
int krsort (array array [, int sort_flags])

Przyklad: krsort()
<? $fruits = array ("d"=>"cytryna", "a"=>"pomarancza", "b"=>"banan", "c"=>"jablko"); krsort ($fruits); reset ($fruits); while (list ($key, $val) = each ($fruits)) { echo "$key = $val\n"; } ?>

Wykonanie przykladu spowoduje wyswietlenie:


d c b a = = = = cytryna jablko banan pomarancza

Mozna zmienic dzialanie funkcji uzywajac opcjonalnego parametru $sort_flags. Szczeglowy opis znajduje sie przy funkcji sort(). Patrz rwniez: asort(), arsort(), ksort(), sort(), natsort() i rsort().

Dodatek A - Funkcje

284

ksort
Sortuje tablice utrzymujac korelacje miedzy kluczami i danymi. Jest to przydatne w przypadku tablic asocjacyjnych.
int ksort (array array [, int sort_flags])

Przyklad: ksort()
<? $fruits = array ("d"=>"cytryna", "a"=>"pomarancza", "b"=>"banan", "c"=>"jablko"); ksort ($fruits); reset ($fruits); while (list ($key, $val) = each ($fruits)) { echo "$key = $val\n"; } ?>

Wykonanie przykladu spowoduje wyswietlenie:


a b c d = = = = pomarancza banan jablko cytryna

Mozna zmienic dzialanie funkcji uzywajac opcjonalnego parametru $sort_flags. Szczeglowy opis znajduje sie przy funkcji sort(). Patrz rwniez: asort(), arsort(), krsort(), sort(), natsort() i rsort().

lcg_value
Zwraca liczbe pseudolosowa z zakresu (0, 1). Funkcja laczy dwie wartosci CG z okresem 2^31 - 85 i 2^31 - 249. Okres tej funkcji jest rwny iloczynowi obu liczb pierwszych.
double lcg_value( void )

ldap_add
Zwraca True w przypadku powodzenia operacji i False w przypadku bledu. Funkcja ldap_add() jest uzywana do dodawania wpisw do katalogu LDAP. DN dodawanego wpisu jest okreslane w parametrze $dn. Tablica $entry zawiera informacje na temat wpisw. Wartosci wpisw sa indeksowane kolejnymi atrybutami. W przypadku wielu wartosci atrybutu sa one indeksowane liczbami rozpoczynajac od 0:
entry["atrybut1"] = wartosc entry["atrybut2"][0] = wartosc1 entry["atrybut2"][1] = wartosc 2 int ldap_add (int link_identifier, string dn, array entry)

Przyklad: Kompletny przyklad autoryzowanego wiazania


<?php $ds=ldap_connect("localhost"); // zakladajac,ze serwer LDAP // dziala na tym komputerze if ($ds) { // wiazanie z odpowiednim dn, aby uzyskac mozliwosc wprowadzania zmian $r=ldap_bind($ds,"cn=root, o=My Company, c=US", "secret"); // przygotowanie danych $info["cn"]="John Jones"; $info["sn"]="Jones"; $info["mail"]="jonj@here.and.now"; $info["objectclass"]="person"; // dodanie danych do katalogu $r=ldap_add($ds, "cn=John Jones, o=My Company, c=US", $info); ldap_close($ds); } else { echo "Blad wiazania z serwerem LDAP"; } ?>

285

PHP Kompendium wiedzy

ldap_bind
Wiaze z katalogiem LDAP z odpowiednim RDN i haslem. Zwraca True w przypadku powodzenia i False w przypadku bledu. Funkcja ldap_bind() wykonuje operacje wiazania. Parametry $bind_rdn i $bind_password sa opcjonalne. Jezeli nie zostana podane, wykonane zostanie wiazanie anonimowe.
int ldap_bind (int link_identifier [, string bind_rdn [, string bind_password]])

ldap_close
Zwraca True w przypadku powodzenia i False w przypadku bledu. Funkcja ldap_close() zamyka polaczenie z serwerem LDAP, skojarzone z podanym identyfikatorem $link_identifier. Wywolanie to jest wewnetrznie identyczne z ldap_unbind(). API LDAP korzysta z funkcji ldap_unbind(), wiec prawdopodobnie nalezy uzywac tej funkcji zamiast ldap_close().
int ldap_close (int link_identifier)

ldap_compare
Zwraca True, jezeli zostanie dopasowana wartosc $value, w przeciwnym przypadku zwraca False. Zwraca -1 w przypadku bledu. Funkcja ldap_compare() jest uzywana do porwnywania wartosci $value atrybutu $attribute z wartoscia tego samego atrybutu w pozycji katalogu LDAP okreslonej przez $dn. Zamieszczony przyklad pokazuje, w jaki sposb mozna sprawdzic czy podane haslo odpowiada zdefiniowanemu w pozycji DN.
int ldap_compare (int link_identifier, string dn, string attribute, string value)

Przyklad: Przyklad kontroli hasla


<?php $ds=ldap_connect("localhost"); // zakladajac,ze serwer LDAP // dziala na tym komputerze if ($ds) { // wiazanie if(ldap_bind($ds)) { // przygotowanie danych $dn = "cn=Matti Meikku, ou=My Unit, o=My Company, c=FI"; $value = "secretpassword"; $attr = "password"; // porwnanie wartosci $r=ldap_compare($ds, $dn, $attr, $value); if ($r === -1) { echo "Blad: ".ldap_error($ds); } elseif ($r === TRUE) { echo "Haslo prawdlowe."; } elseif ($r === FALSE) { echo "Haslo nieprawidlowe!"; } } else { echo "Blad przy laczeniu z serwerem LDAP."; } ldap_close($ds); } else { echo "Nie mozna przylaczyc do serwera LDAP."; } ?>

Uwaga Funkcja ldap_compare() nie moze porwnywac wartosci binarnych! Funkcja zostala dodana w PHP 4.0.2.

ldap_connect
False.

W przypadku powodzenia operacji zwraca dodatni identyfikator lacza LDAP, w przypadku bledu zwraca Funkcja ldap_connect() zestawia polaczenie z serwerem LDAP na komputerze $hostname i porcie $port. Oba argumenty sa opcjonalne. Jezeli nie podane zostana argumenty, zwracany jest identyfikator istniejacego polaczenia. Jezeli zostanie podana jedynie nazwa komputera, domyslnym portem jest 389.
int ldap_connect ([string hostname [, int port]])

Dodatek A - Funkcje

286

ldap_count_entries
Zwraca ilosc pozycji w wyniku lub False w przypadku wystapienia bledu. Funkcja ldap_count_entries() zwraca ilosc pozycji zapamietanych w wyniku ostatniej operacji szukania. Parametr $result_identifier okresla wewnetrzny wynik LDAP.
int ldap_count_entries (int link_identifier, int result_identifier)

ldap_delete
Zwraca True w przypadku powodzenia operacji lub usuwa pozycje z katalogu LDAP okreslona przez $dn.
int ldap_delete (int link_identifier, string dn)

False

w przypadku bledu. Funkcja

ldap_delete()

ldap_dn2ufn
Uzywana do przeksztalcania DN na postac bardziej czytelna dla czlowieka poprzez usuniecie nazw typw.
string ldap_dn2ufn (string dn)

ldap_err2str
Zwraca ciag z komunikatem bledu. Funkcja ta zwraca komunikat bledu opisujacy blad numer $errno. Choc numery bledw LDAP sa zestandaryzowane, rzne biblioteki zwracaja rzne, nawet przetlumaczone, tekstowe opisy bledw. Nigdy nie nalezy porwnywac tekstu komunikatw bledw, zamiast tego zawsze nalezy uzywac do porwnania numerw bledw. Patrz rwniez: ldap_errno() i ldap_error().
string ldap_err2str (int errno)

Przyklad: Wyliczanie wszystkich komunikatw bledw LDAP


<?php for($i=0; $i<100; $i++) { printf("Blad $i: %s<br>\n", ldap_err2str($i)); } ?>

ldap_errno
Zwraca numer bledu LDAP dla ostatniego polecenia LDAP na podanym polaczeniu. Funkcja ta zwraca standardowy numer bledu zwracany przez ostatnie polecenie LDAP. Numer ten moze zostac zamieniony na komunikat tekstowy za pomoca funkcji ldap_err2str(). Jezeli nie zmniejszysz wystarczajaco poziomu ostrzezen w pliku php.ini lub nie bedziesz poprzedzal funkcji LDAP znakiem @, generowane bledy beda pokazywaly sie rwniez w wynikowym HTML.
int ldap_errno (int link_id)

Przyklad: Generowanie i przechwytywanie bledw


<?php // przyklad ten zawiera blad, ktry zostanie przechwycony $ld = ldap_connect("localhost"); $bind = ldap_bind($ld); // blad skladni w wyrazeniu filtrujacym (nr: 87), // aby dzialalo musi byc "objectclass=*" $res = @ldap_search($ld, "o=Myorg, c=DE", "objectclass"); if (!$res) { printf("LDAP-Errno: %s<br>\n", ldap_errno($ld)); printf("LDAP-Error: %s<br>\n", ldap_error($ld)); die("Aaaaaa!<br>\n"); } $info = ldap_get_entries($ld, $res); printf("%d pasujacych wpisw.<br>\n", $info["count"]); ?>

Patrz rwniez: ldap_err2str() i ldap_error().

ldap_error
Zwraca ciag z komunikatem bledu. Funkcja zwraca komunikat bledu objasniajacy blad wygenerowany przez ostatnie polecenie LDAP wykonane na podanym polaczeniu. Choc numery bledw LDAP sa PHP Kompendium wiedzy 287

zestandaryzowane, rzne biblioteki zwracaja rzne, nawet przetlumaczone, tekstowe opisy bledw. Nigdy nie nalezy porwnywac tekstu komunikatw bledw, zamiast tego zawsze nalezy uzywac do porwnania numerw bledw. Jezeli nie zmniejszysz wystarczajaco poziomu ostrzezen w pliku php.ini lub nie bedziesz poprzedzal funkcji LDAP znakiem @, generowane bledy beda pokazywaly sie rwniez w wynikowym HTML. Patrz rwniez: ldap_err2str() i ldap_errno().
string ldap_error (int link_id)

ldap_explode_dn
Funkcja uzywana do podzialu ciagu DN zwracanego przez funkcje ldap_get_dn(), na pojedyncze komponenty. Kazda z czesci nazywana jest Relative Distinguished Name (RDN). Funkcja ldap_explode_dn() zwraca tablice zawierajaca wszystkie te czesci. Za pomoca parametru $with_attrib mozna zdecydowac, czy RDN sa zwracane ze swoimi wartosciami, czy bez. Aby otrzymac RDN z wartoscia (to znaczy w postaci atrybut=wartosc) nalezy ustawic $with_attrib na 0. Aby otrzymac tylko wartosci, nalezy ustawic go na 1.
array ldap_explode_dn (string dn, int with_attrib)

ldap_first_attribute
Zwraca pierwszy atrybut pozycji lub False w przypadku bledu. Podobnie do odnosnych pozycji, atrybuty rwniez moga byc czytane po kolei z okreslonej pozycji. Funkcja ldap_first_attribute() zwraca pierwszy atrybut pozycji wskazywanej przez identyfikator pozycji. Pozostale atrybuty moga byc odczytane za pomoca kolejnych wywolan ldap_next_attribute(). Parametr $ber_identifier jest identyfikatorem wewnetrznego wskaznika pamieci. Jest on przekazywany przez referencje. Ten sam $ber_identifier jest przekazywany do ldap_next_attribute(), ktra modyfikuje wskaznik. Patrz rwniez: ldap_get_attributes().
string ldap_first_attribute (int link_identifier, int result_entry_identifier, int ber_identifier)

ldap_first_entry
Zwraca identyfikator pierwszej pozycji wyniku lub False w przypadku bledu. Pozycje w wyniku LDAP moga byc czytane sekwencyjnie przy uzyciu funkcji ldap_first_entry() i ldap_next_entry(). Funkcja ldap_first_entry() zwraca identyfikator pierwszej pozycji wyniku. Identyfikator ten przekazywany jest do funkcji ldap_next_entry() w celu odczytania kolejnych pozycji wyniku. Patrz rwniez: ldap_get_entries().
int ldap_first_entry (int link_identifier, int result_identifier)

ldap_free_result
w przypadku powodzenia operacji lub False w przypadku bledu. Funkcja ldap_free_result() zwalnia pamiec zajmowana przez wynik, na ktry wskazuje $result_identifier. Cala pamiec zajmowana przez wynik jest automatycznie zwalniana po zakonczeniu skryptu. W przypadku, gdy skrypt wykonuje kolejne wyszukiwania, ktre powoduja powstanie duzych wynikw mozna wywolac funkcje ldap_free_result(), aby zmniejszyc ilosc pamieci zuzywana przez skrypt.
True
int ldap_free_result (int result_identifier)

Zwraca

ldap_get_attributes
Zwraca wszystkie dane pozycji w postaci wielowymiarowej tablicy lub w przypadku wystapienia bledu, False. Funkcja ldap_get_attribues() uzywana jest w celu uproszczenia odczytywania atrybutw i wartosci z pozycji znajdujacej sie w wyniku. Zwracana wartoscia jest wielowymiarowa tablica atrybutw i wartosci. Po odszukaniu odpowiedniej pozycji w katalogu mozesz za pomoca takiego wywolania odczytac wszystkie informacje przechowywane w tej pozycji. Mozna wykorzystac ta funkcje do napisania aplikacji za pomoca ktrej mozna przegladac pozycje katalogu nawet, gdy nie znamy struktury okreslonych atrybutw. We wielu aplikacjach szuka sie okreslonego atrybutu, na przyklad adresu e-mail lub nazwiska i nie ma potrzeby przejmowac sie zawartoscia innych pozycji. Struktura tabeli jest nastepujaca: Dodatek A - Funkcje 288

return_value["count"] = ilosc atrybutw w pozycji return_value[0] = pierwszy atrybut return_value[n] = n-ty atrybut return_value["atrybut"]["count"] = ilosc wartosci atrybutu return_value["atrybut"][0] = pierwsza wartosc atrybutu return_value["atrybut"][i] = i-ta wartosc atrybutu array ldap_get_attributes (int link_identifier, int result_entry_identifier)

Przyklad: Wyswietlenie listy atrybutw przechowywanych w pozycji katalogu


// $ds jest identyfikatorem polaczenia z katalogiem // $sr jest prawidlowym wynikiem pochodzacym z // wywolania jednej z funkcji przeszukujacych $entry = ldap_first_entry($ds, $sr); $attrs = ldap_get_attributes($ds, $entry); echo $attrs["count"]." atrybutw w tej pozycji:<p>"; for ($i=0; $i<$attrs["count"]; $i++) echo $attrs[$i]."<br>";

Patrz rwniez: ldap_first_attribute() i ldap_next_attribute().

ldap_get_dn
Zwraca DN pozycji wyniku lub sprawdzenia DN pozycji wyniku.
False

w przypadku bledu. Funkcja

ldap_get_dn()

jest uzywana do

string ldap_get_dn (int link_identifier, int result_entry_identifier)

ldap_get_entries
False.

Zwraca wszystkie dane pozycji w postaci wielowymiarowej tablicy lub w przypadku wystapienia bledu, Funkcja ldap_get_entries() uzywana jest w celu uproszczenia odczytywania wielu pozycji z wyniku i nastepnie odczytywanie atrybutw i wielokrotnych wartosci. Wszystkie dane sa zwracane za pomoca jednego wywolania funkcji we wielowymiarowej tablicy. Struktura tablicy jest nastepujaca. Indeksy atrybutw sa konwertowane do malych liter (wielkosc liter w atrybutach ma znaczenie dla serwerw katalogw, ale nie gdy sa uzywane jako indeksy tablicy).
return_value["count"] = ilosc pozycji w wyniku return_value[0] : szczegly pierwszej pozycji return_value[i]["dn"] = DN i-tej pozycji w wyniku return_value[i]["count"] = ilosc atrybutw w i-tej pozycji return_value[i][j] = j-ty atrybut i-tej pozycji w wyniku return_value[i]["atrybut"]["count"] = ilosc wartosci dla atrybutw i-tej pozycji return_value[i]["atrybut"][j] = j-ta wartosc atrybutu na i-tej pozycji array ldap_get_entries (int link_identifier, int result_identifier)

ldap_get_values
Zwraca tablice wartosci atrybutu lub False w przypadku wystapienia bledu. Funkcja ldap_get_values() jest uzywana do odczytania wszystkich wartosci atrybutw z pozycji wyniku. Pozycja jest okreslona przez $result_entry_identifier. Ilosc wartosci mozna odczytac z wynikowej tablicy, spod indeksu count. Poszczeglne wartosci moga byc odczytane poprzez numeryczne indeksy tablicy. Pierwszy indeks ma wartosc 0. Funkcja wymaga identyfikatora pozycji wyniku, wiec musi byc poprzedzona przez jedna z funkcji wyszukujacych i jedno z wywolan pobierajacych poszczeglne pozycje. W aplikacji mozna na stale zapisac nazwy interesujacych nas atrybutw (na przyklad surname lub mail), mozna rwniez uzyc funkcji ldap_get_attributes() do sprawdzenia jakie atrybuty istnieja dla danej pozycji. LDAP pozwala na przechowywanie wiecej niz jednej pozycji dla atrybuty, wiec mozna na przyklad zapamietywac kilka adresw e-mail w pozycji katalogu zawierajacej okreslona osobe.
return_value["count"] = ilosc wartosci atrybutu return_value[0] = pierwsza wartosc atrybutu return_value[i] = i-ta wartosc atrybutu array ldap_get_values (int link_identifier, int result_entry_identifier, string attribute)

Przyklad: Lista wszystkich wartosci atrybutu mail dla pozycji katalogu


// $ds jest identyfikatorem polaczenia z katalogiem // $sr jest prawidlowym wynikiem pochodzacym z

289

PHP Kompendium wiedzy

// wywolania jednej z funkcji przeszukujacych // $entry jest idnetyfikatorem pozycji pochodzacym z // jednego z wywolan zwracajacych pozycje katalogu $values = ldap_get_values($ds, $entry,"mail"); echo $values["count"]." adresw email dla tej pozycji.<p>"; for ($i=0; $i < $values["count"]; $i++) echo $values[$i]."<br>";

ldap_get_values_len
wartosci atrybutu lub False w przypadku wystapienia bledu. Funkcja ldap_get_values_len() uzywana jest do odczytania wszystkich wartosci atrybutu dla pozycji wyniku. Pozycja jest okreslona przez $result_entry_identifier. Ilosc wartosci mozna odczytac z indeksu count wynikowej tablicy. Poszczeglne wartosci sa dostepne w tablicy pod indeksami calkowitymi. Indeksy zaczynaja sie od 0. Funkcji tej uzywa sie identycznie jak ldap_get_values(), ale obsluguje dane binarne a nie ciagi.
Uwaga Funkcja zostala dodana w PHP 4.0.
array ldap_get_values_len (int link_identifier, int result_entry_identifier, string attribute)

Zwraca

tablice

ldap_list
Zwraca identyfikator wyniku poszukiwania, lub False w przypadku wystapienia bledu. Funkcja ldap_list() przeszukuje katalog w poszukiwaniu wartosci pasujacych do podanego filtra z zastosowaniem zasiegu LDAP_SCOPE_ONELEVEL. Zasieg LDAP_SCOPE_ONELEVEL oznacza, ze przeszukiwany zostanie tylko poziom bezposrednio po podanym bazowym DN podanym w wywolaniu funkcji (ekwiwalent wpisania ls i pobrania naw plikw i folderw w biezacym katalogu). Funkcja posiada 5 parametrw opcjonalnych. Opis znajduje sie przy omawianiu funkcji ldap_search().
Uwaga Parametry opcjonalne $attrsonly, $sizelimit, $timelimit i $deref zostaly dodane w PHP 4.0.2.
int ldap_list (int link_identifier, string base_dn, string filter [, array attributes [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]])

Przyklad: Utworzenie listy wszystkich jednostek organizacyjnych w organizacji


// $ds jest identyfikatorem polaczenia do serwera katalogu $basedn = "o=My Company, c=US"; $justthese = array("ou"); $sr=ldap_list($ds, $basedn, "ou=*", $justthese); $info = ldap_get_entries($ds, $sr); for ($i=0; $i<$info["count"]; $i++) echo $info[$i]["ou"][0] ;

ldap_modify
Zwraca True w przypadku powodzenia operacji lub False w przypadku bledu. Funkcja ldap_modify() uzywana jest do zmiany istniejacych pozycji w katalogu LDAP. Struktura pozycji jest identyczna jak ldap_add().
int ldap_modify (int link_identifier, string dn, array entry)

ldap_mod_add
Zwraca True w przypadku powodzenia operacji lub False w przypadku bledu. Funkcja dodaje atrybut do podanego $dn. Wykonuje zmiane na poziomie atrybutu a nie na poziomie obiektu. Dodawanie na poziomie obiektu wykonywane jest za pomoca funkcji ldap_add().
int ldap_mod_add (int link_identifier, string dn, array entry)

Dodatek A - Funkcje

290

ldap_mod_del
Zwraca True w przypadku powodzenia operacji lub False w przypadku bledu. Funkcja usuwa atrybut do podanego $dn. Wykonuje zmiane na poziomie atrybutu a nie na poziomie obiektu. Usuwanie na poziomie obiektu wykonywane jest za pomoca funkcji ldap_del().
int ldap_mod_del (int link_identifier, string dn, array entry)

ldap_mod_replace
Zwraca True w przypadku powodzenia operacji lub False w przypadku bledu. Funkcja zamienia atrybut(y) z podanego $dn. Wykonuje zmiane na poziomie atrybutu a nie na poziomie obiektu. Modyfikacje na poziomie obiektu wykonywane jest za pomoca funkcji ldap_modify().
int ldap_mod_replace (int link_identifier, string dn, array entry)

ldap_next_attribute
kolejny atrybut w pozycji lub False w przypadku wystapienia bledu. Funkcja jest wywolywana w celu odczytania atrybutw pozycji. Stan wewnetrznego wskaznika jest utrzymywany przez $ber_identifier. Jest on przekazywany do funkcji przez referencje. Pierwsze wywolanie ldap_next_identifier() jest wykonywane z $result_entry_identifier zwracanym przez ldap_first_identifier(). Patrz rwniez: ldap_get_atributes().
ldap_next_attribute()
string ldap_next_attribute (int link_identifier, int result_entry_identifier, int ber_identifier)

Zwraca

ldap_next_entry
Zwraca identyfikator pozycji dla nastepnej pozycji w wyniku, ktrego pierwsza pozycja zostala odczytana za pomoca ldap_first_entry(). Jezeli nie ma juz kolejnych pozycji w wyniku, funkcja zwraca False. Funkcja ldap_next_entry() uzywana jest do odczytania pozycji znajdujacych sie w wyniku. Kolejne wywolania ldap_next_entry() powoduje zwracanie kolejnych pozycji az do ich wyczerpania. Pierwsze wywolanie ldap_next_entry() jest wykonywane z identyfikatorem wyniku zwrconym przez ldap_first_entry(). Patrz rwniez: ldap_get_entries().
int ldap_next_entry (int link_identifier, int result_entry_identifier)

ldap_read
Zwraca identyfikator wyniku przeszukiwania lub False w przypadku wystapienia bledu. Funkcja szuka filtra w katalogu z zakresie LDAP_SCOPE_BASE, wiec jest odpowiednikiem odczytania pozycji z katalogu. Nie jest dozwolone uzywanie pustego filtra. Jezeli chcesz odczytac wszystkie dane z tej pozycji nalezy uzyc filtra objectClass=*. Jezeli wiesz, jaki typ pozycji jest uzyty w serwerze katalogu, mozna wykorzystac odpowiedni filtr, na przyklad objectClass=inetOrgPerson. Funkcja posiada piec parametrw opcjonalnych. Opis znajduje sie przy omawianiu funkcji ldap_search().
ldap_read() Uwaga Parametry opcjonalne $attrsonly, $sizelimit, $timelimit i $deref zostaly dodane w PHP 4.0.2.
int ldap_read (int link_identifier, string base_dn, string filter [, array attributes [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]])

ldap_search
Zwraca identyfikator wyniku przeszukiwania lub False w przypadku bledu. Funkcja ldap_search() szuka podanego filtra w katalogu, z zastosowaniem zasiegu LDAP_SCOPE_SUBTREE. Jest to ekwiwalent przeszukania zawartosci katalogu. Parametr $base_dn okresla bazowy DN w katalogu. Dostepny jest czwarty parametr opcjonalny, ktry pozwala ograniczyc ilosc zwracanych atrybutw i wartosci. Uzycie tego parametru powinno 291 PHP Kompendium wiedzy

byc traktowane jako dobra praktyke programistyczna. Czwarty parametr jest zwykla tablica ciagw zawierajacych wymagane atrybuty, na przyklad: array( "mail", "cn").
Uwaga DN jest zawsze zwracany niezaleznie od typw zadanych typw atrybutw. Nalezy pamietac, ze niektre serwery katalogw sa tak skonfigurowane, aby zwracac nie wiecej, niz skonfigurowana ilosc pozycji. Jezeli wystapi taka sytuacja, serwer wskazuje, ze zwraca jedynie czesciowy wynik. Wystepuje to rwniez, gdy ustawiony zostanie szsty parametr $sizelimit ograniczajacy ilosc pobieranych pozycji.
int ldap_search (int link_identifier, string base_dn, string filter [, array attributes [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]])

Piaty parametr $attrsonly powinien byc ustawiony na 1, jezeli potrzebujemy jedynie atrybutu. Jezeli ustawiony jest na 0, pobierane sa zarwno atrybuty jak i ich wartosci. Jest to ustawienie domyslne. Za pomoca szstego parametru, $sizelimit, mozna ograniczyc ilosc pobieranych pozycji.
Uwaga Parametr ten nie moze zwiekszyc limitu ustawionego na serwerze, ale moze go zmniejszyc.

Sidmy parametr, $timelimit, ogranicza czas przeszukiwania katalogu do podanej liczby sekund. Ustawienie tego parametru na 0 powoduje zniesienie limitu.
Uwaga Parametr ten nie moze zwiekszyc limitu ustawionego na serwerze, ale moze go zmniejszyc.

smy parametr, $deref, wskazuje na sposb obslugi aliasw w czasie szukania. Moze przyjmowac nastepujace wartosci: LDAP_DEREF_NEVER (domyslny) aliasy nie sa rozwijane LDAP_DEREF_SEARCHING aliasy sa rozwijane w czasie szukania, ale nie w czasie okreslania podstawowych obiektw przeszukiwania LDAP_DEREF_FINDING aliasy sa rozwijane w czasie okreslania podstawowych obiektw przeszukiwania, ale nie w czasie szukania LDAP_DEREF_ALWAYS aliasy sa zawsze rozwijane Parametry opcjonalne $atrsonly, $sizelimit, $timelimit i $deref zostaly dodane w PHP 4.0.2. Filtry przeszukiwania moga byc proste lub zaawansowane z wykorzystaniem operatorw logicznych w formacie opisanym w dokumentacji LDAP (np.: Netscape Directory SDK pod adresem http://developer.netscape.com/docs/manuals/directory/41/ag/find.htm). Ponizszy przyklad odczytuje jednostke organizacyjna, nazwisko, imie i e-mail wszystkich osb w firmie Firma, ktrych nazwiska zawieraja ciag okreslony przez zmienna $person. Przyklad ten wykorzystuje filtry logiczne nakazujace serwerowi poszukiwanie danych we wiekszej ilosci atrybutw. Przyklad: Przeszukiwanie LDAP
// $ds jest identyfikatorem polaczenia z katalogiem // $person jest kompletna nazwa lub jej czescia np: "Jo" $dn = "o=Firma, c=US"; $filter="(|(sn=$person*)(givenname=$person*))"; $justthese = array( "ou", "sn", "givenname", "mail"); $sr=ldap_search($ds, $dn, $filter, $justthese); $info = ldap_get_entries($ds, $sr); print $info["count"]." pozycji w wyniku<p>";

ldap_unbind
Zwraca True w przypadku powodzenia operacji lub odlacza od katalogu LDAP.
int ldap_unbind (int link_identifier)

False

w przypadku bledu. Funkcja

ldap_unbind()

Dodatek A - Funkcje

292

leak
Powoduje wyciek okreslonej ilosci pamieci. Jest to przydatne przy testowaniu zarzadcy pamieci, ktry automatycznie odzyskuje pamiec utracona po wycieku, po zakonczeniu kazdego zadania.
void leak (int bytes)

levenshtein
Zwraca odleglosc Levenshtein pomiedzy dwoma ciagami przekazanymi jako argumenty lub -1 gdy jeden z ciagw jest dluzszy niz 255 znakw (255 powinno wystarczyc do porwnywania nazwisk lub katalogw a nikt rozsadny nie bedzie wykonywal analizy genetycznej za pomoca PHP). Odleglosc Levenshtein jest definiowana jako minimalna ilosc znakw jakie trzeba zamienic, wstawic lub usunac, aby zamienic $str1 na $str2. Algorytm ten ma zlozonosc O(m*n), gdzie m i n sa dlugoscia ciagw $str1 i $str2 (calkiem niezle w porwnaniu do similar_text(), ktra ma zlozonosc O(max(n,m)**3), ale i tak jest to kosztowny algorytm)
int levenshtein (string str1, string str2) int levenshtein (string str1, string str2, int cost_ins, int cost_rep, int cost_del) int levenshtein (string str1, string str2, function cost)

W swojej najprostszej postaci funkcja wymaga jedynie dwch ciagw jako parametry i oblicza ilosc operacji wstawienia, zamiany lub usuniecia potrzebnych do zamiany $str1 na $str2. Drugi wariant potrzebuje trzech dodatkowych paramterw definiujacych koszt operacji wstawienia, zamiany i usuniecia. Jest to bardziej oglny i adaptowalny wariant funkcji, ale nie jest on tak wydajny. Trzeci wariant, ktry jeszcze nie zostal zaimplementowany, bedzie najbardziej oglny, ale rwniez najwolniejszy. Bedzie wywolywal funkcje napisana przez uztkownika, ktra bedzie zwracala koszt kazdej operacji. Funkcja uzytkownika posiadac musi nastepujace parametry: operacja do wykonania: I, R lub D biezacy znak w ciagu 1 biezacy znak w ciagu 2 pozycja w ciagu 1 pozycja w ciagu 2 pozostale znaki w ciagu 1 pozostale znaki w ciagu 2 Funkcja napisana przez uzytkownika musi zwracac liczbe dodatnia oznaczajaca koszt biezacej operacji, ale do tego celu moze uzywac tylko niektrych z przekazanych argumentw. Uzycie funkcji uzytkownika pozwala na mozliwosc wziecia pod uwage rznicy pomiedzy znakami lub nawet kontekstu, w jakim wystepuja w ciagu. Jednak wywolywanie tej funkcji do obliczenia kosztu kazdej operacji, powoduje utrate wszystkich optymalizacji uzycia rejestrw procesora i pamieci podrecznej, ktre sa zastosowane w poprzednich dwch wariantach. Patrz rwniez: soundex(), similar_text() i metaphone().

link
Tworzy trwale lacze. Patrz rwniez: linkinfo().
Uwaga Funkcja ta nie dziala w systemie Windows
int link (string target, string link)

symlink()

do tworzenia lacz symbolicznych oraz

readlink()

linkinfo
Zwraca pole st_dev ze struktury stat zwracanej przez funkcje systemowa lstat w systemie UNIX. Funkcja ta uzywana jest do sprawdzania, czy lacze (wskazywane przez $path) istnieje (wykorzystujac metode 293 PHP Kompendium wiedzy

zdefiniowana w makro S_ISLNK z pliku stat.h). Zwraca 0 lub False w przypadku bledu. Patrz rwniez: link() i readlink().
Uwaga Funkcja ta nie dziala w systemie Windows
int linkinfo (string path)

symlink(),

list
Podobnie jak array() nie jest prawdziwa funkcja, ale konstrukcja jezyka. przypisywania wartosci do listy zmiennych przy pomocy jednej operacji.
void list (...)

list()

jest uzywane do

Przyklad: list()
<table> <tr> <th>Nazwisko pracownika</th> <th>Pensja</th> </tr> <?php $result = mysql_query ($conn, "SELECT id, name, salary FROM employees"); while (list ($id, $name, $salary) = mysql_fetch_row ($result)) { print (" <tr>\n". " <td><a href=\"info.php3?id=$id\">$name</a></td>\n". " <td>$salary</td>\n". " </tr>\n"); } ?> </table>

Patrz rwniez: each() i array().

listen
Po utworzeniu gniazda $socket za pomoca funkcji socket() i przylaczeniu go za pomoca bind(), mozna za pomoca funkcji listen() nakazac nasluchiwanie przychodzacych polaczen. Kolejkowane i przetwarzane bedzie $backlog polaczen. Funkcja listen() dziala jedynie na gniazdach o typie SOCK_STREAM lub SOCK_SEQPACKET. Zwraca 0 w przypadku powodzenia lub ujemny kod bledu w przypadku niepowodzenia. Kod ten moze byc przekazany do strerror() w celu otrzymania tekstu opisujacego blad. Patrz rwniez: socket_connect(), bind(), connect(), socket(), socket_get_status() i strerror().
int listen (resource socket, int backlog)

localtime
Zwraca tablice identyczna ze struktura zwracana przez ta sama funkcje w C. Pierwszym argumentem localtime() jest znacznik czasu. Jezeli nie zostanie podany, uzyty zostanie biezacy czas. Drugi argument to $is_associative. Jezeli jest ustawiony na 0 lub nie zostanie podany, zwracana tablica jest zwykla tablica z indeksami numerycznymi. Jezeli argument ten zostanie ustawiony na 1, localtime() zwrci tablice asocjacyjna zawierajaca wszystkie elementy struktury zwracanej przez wywolanie funkcji localtime() w C.
array localtime ([int timestamp [, bool is_associative]])

Nazwy kluczy w tablicy asocjacyjnej sa: tm_sec sekundy tm_min minuty tm_hour godziny tm_mday dzien miesiaca tm_mon miesiac w roku tm_year rok, nie jest zgodny z rokiem 2000 tm_wday dzien tygodnia tm_yday dzien kolejny w roku tm_isdst czy zastosowano czas zimowy Dodatek A - Funkcje

294

log
Zwraca logarytm naturalny z $arg.
float log (float arg)

log10
Zwraca logarytm o podstawie 10 z $arg.
float log10 (float arg)

long2ip
Generuje adres internetowy w postaci z kropkami (aaa.bbb.ccc.ddd) na podstawie wlasciwej reprezentacji adresu.
string long2ip (int proper_address)

lstat
Zbiera statystyki pliku lub lacza symbolicznego o podanej nazwie. Funkcja jest podobna do stat() poza tym, ze gdy parametr $filename jest laczem symbolicznym, zwracany jest stan lacza a nie status pliku, na ktry wskazuje lacze.
array lstat (string filename)

Zwraca tablice ze statystykami nastepujacych parametrw pliku: urzadzenie liczba dowiazan i-node node identyfikator wlasciciela typ urzadzenia, jezeli rozmiar w bajtach jest to urzadzenie z i-node * czas ostatniej czas ostatniej zmiany modyfikacji identyfikator grupy czas ostatniego dostepu rozmiar bloku dla operacji wejscia-wyjscia systemu plikw * tryb zabezpieczenia i-

ilosc przydzielonych blokw * dostepne tylko na systemach obslugujacych typ st_blksize inne systemy (na przyklad Windows) zwracaja -1. Wyniki tej funkcji sa przechowywane w buforze. Szczegly zostaly opisane przy funkcji clearstatcache().

ltrim
Usuwa znaki odstepu z poczatku ciagu i zwraca obciety ciag. Obslugiwanymi znakami odstepu sa: \n, \r, \t, \v, \0 oraz spacja. Patrz rwniez: chop() i trim().
string ltrim (string str [, string charlist])

mail
Wysyla wiadomosc pocztowa o tresci przekazanej w $message do odbiorcy w odbiorcw umieszczajac srednik pomiedzy adresami przekazanymi w parametrze $to.
bool mail (string to, string subject, string message [, string additional_headers [, string additional_parameters]])

$to.

Mozna podac wielu

Przyklad: wysylanie poczty


mail("rasmus@lerdorf.on.ca", "Temat", "Linia 1\nLinia 2\nLinia 3");

Jezeli zostanie przekazany czwarty argument ciag ten jest wstawiany na koncu naglwka. Jest on zwykle uzywany do wstawiania do wiadomosci dodatkowych naglwkw. Kolejne wiersze naglwka musza byc rozdzielone znakiem nowego wiersza. PHP Kompendium wiedzy 295

Przyklad: Wysylanie wiadomosci z dodatkowymi naglwkami


mail("nobody@aol.com", "Temat", $message, "From: webmaster@$SERVER_NAME\nReply-To: webmaster@$SERVER_NAME\nX-Mailer: PHP/" . phpversion());

Mozna rwniez stosowac proste techniki budowania ciagw do tworzenia calkiem skomplikowanych wiadomosci e-mail. Przyklad: Wysylanie skomplikowanych przesylek e-mail
/* odbiorcy */ $recipient .= "Mary <mary@u.college.edu>" . ", " ; //zwrc uwage na przecinek $recipient .= "Kelly <kelly@u.college.edu>" . ", "; $recipient .= "ronabop@php.net"; /* temat */ $subject = "Przypomnienie o urodzinach w sierpniu"; /* wiadomosc */ $message .= "Wiadomosc zawiera tabele sformatowana za pomoca znakw ASCII\n"; $message .= "Dzien \t\tMiesiac \t\tRok\n"; $message .= "3 \t\tSierpien \t\t1970\n"; $message .= "17\t\tSierpien \t\t1973\n"; /* mozna dodac sygnaturke */ $message .= "--\r\n"; //Separator sygnaturki $message .= "Przypominacz urodzin oddany do publicznego uzywania"; /* dodatkowe fragmenty naglwka, From cc, bcc, itp. */ $headers .= "From: Pzrypominacz urodzin <birthday@php.net>\n"; $headers .= "X-Sender: <birthday@php.net>\n"; $headers .= "X-Mailer: PHP\n"; // klient poczty $headers .= "X-Priority: 1\n"; // wiadomosc wazna! $headers .= "Return-Path: <birthday@php.net>\n"; // sciezka zwrotna dla bledw /* jezeli chcez wyslac poczte HTML, usun komentarz z ponizszej linii */ // $headers .= "Content-Type: text/html; charset=iso-8859-1\n"; // Typ mime $headers .= "cc: birthdayarchive@php.net\n"; // CC $headers .= "bcc: birthdaycheck@php.net, birthdaygifts@php.net"; // BCC /* wyslij wiadomosc */ mail($recipient, $subject, $message, $headers);

max
Zwraca parametr o najwiekszej wartosci numerycznej. Jezeli pierwszy parametr jest tablica, max() zwraca najwieksza wartosc w tablicy. Jezeli pierwszy parametr jest liczba calkowita, ciagiem lub liczba double, funkcja wymaga co najmniej dwch parametrw i zwraca najwiekszy z nich. Mozna porwnywac nieograniczona ilosc wartosci. Jezeli jedna lub wiecej wartosci jest liczba double, wszystkie wartosci sa traktowane jako double i zwracana jest liczba typu double. Jezeli zadna z wartosci nie jest liczba double, wszystkie sa traktowane jako liczby calkowite i rwniez zwracana jest liczba calkowita.
mixed max (mixed arg1, mixed arg2, mixed argn)

mcal_append_event
Zapamietuje globalne zdarzenie w kalendarzu MCAL, dla podanego strumienia. Zwraca identyfikator wstawionego zdarzenia.
int mcal_append_event (int mcal_stream)

mcal_close
Zamyka podany strumien MCAL.
int mcal_close (int mcal_stream, int flags)

mcal_create_calendar
Tworzy nowy kalendarz o nazwie $calendar.
string mcal_create_calendar (int stream, string calendar)

mcal_date_compare
Porwnuje dwie podane daty. Zwraca <0, 0, >0 gdy a<b, a==b, a>b.
int mcal_date_compare (int a_year, int a_month, int a_day, int b_year, int b_month, int b_day)

Dodatek A - Funkcje

296

mcal_date_valid
Zwraca prawidlowa.
True,

jezeli podany rok, miesiac i dzien jest prawidlowa data lub

False,

gdy nie jest to data

int mcal_date_valid (int year, int month, int day)

mcal_days_in_month
Zwraca ilosc dni w podanym miesiacu biorac pod uwage, czy rok jest przestepny czy nie.
int mcal_days_in_month (int month, int leap year)

mcal_day_of_week
Zwraca dzien tygodnia dla podanej daty.
int mcal_day_of_week (int year, int month, int day)

mcal_day_of_year
Zwraca dzien w roku dla podanej daty.
int mcal_ (int year, int month, int day)

mcal_delete_calendar
Usuwa kalendarz o nazwie $calendar.
string mcal_delete_calendar (int stream, string calendar)

mcal_delete_event
Usuwa zdarzenie kalendarza wskazywane przez $event_id. Zwraca True.
int mcal_delete_event (int mcal_stream [, int event_id])

mcal_event_add_attribute
Dodaje do globalnej struktury zdarzen strumienia atrybut o wartosci przekazanej w parametrze $value.
void mcal_event_add_attribute (int stream, string attribute, string value)

mcal_event_init
Inicjuje globalna strukture strumienia. Powoduje to ustawienie wszystkich elementw struktury na 0 lub na wartosc domyslna. Zwraca True.
int mcal_event_init (int stream)

mcal_event_set_alarm
Ustawia alarm w globalnej strukturze strumienia na podana liczbe minut przed zdarzeniem. Zwraca True.
int mcal_event_set_alarm (int stream, int alarm)

mcal_event_set_category
Ustawia kategorie globalnej struktury zdarzenia na podany ciag. Zwraca True.
int mcal_event_set_category (int stream, string category)

mcal_event_set_class
Ustawia klase globalnej struktury zdarzenia na podana wartosc. Klasa moze miec wartosc lub 0 prywatna. Zwraca True. 297
1

publiczna

PHP Kompendium wiedzy

int mcal_event_set_class (int stream, int class)

mcal_event_set_description
Ustawia opis globalnej struktury zdarzenia na podana wartosc. Zwraca True.
int mcal_event_set_description (int stream, string description)

mcal_event_set_end
Ustawia date i czas zakonczenia w globalnej strukturze zdarzenia na podana wartosc. Zwraca True.
int mcal_event_set_end (int stream, int year, int month [, int day [, int hour [, int min [, int sec]]]])

mcal_event_set_recur_daily
Ustawia wartosc powtarzania w globalnej strukturze zdarzenia na podana codzienne powtarzanie konczace sie na podanej dacie.
int mcal_event_set_recur_daily (int stream, int year, int month, int day, int interval)

mcal_event_set_recur_monthly_mday
Ustawia wartosc powtarzania w globalnej strukturze zdarzenia na podana comiesieczne powtarzanie opierajac sie na dniu miesiaca, konczace sie na podanej dacie.
int mcal_event_set_recur_monthly_mday (int stream, int year, int month, int day, int interval)

mcal_event_set_recur_monthly_wday
Ustawia wartosc powtarzania w globalnej strukturze zdarzenia na podana comiesieczne powtarzanie opierajac sie na tygodniu, konczace sie na podanej dacie.
int mcal_event_set_recur_monthly_wday (int stream, int year, int month, int day, int interval)

mcal_event_set_recur_none
Wylacza powtarzanie w globalnej strukturze zdarzenia (event->recur_type jest ustawiane na
MCAL_RECUR_NONE).
int mcal_event_set_recur_none (int stream)

mcal_event_set_recur_weekly
Ustawia wartosc powtarzania w globalnej strukturze zdarzenia na podana cotygodniowe powtarzanie, konczace sie na podanej dacie.
int mcal_event_set_recur_weekly (int stream, int year, int month, int day, int interval, int weekdays)

mcal_event_set_recur_yearly
Ustawia wartosc powtarzania w globalnej strukturze zdarzenia na podana coroczne powtarzanie, konczace sie na podanej dacie.
int mcal_event_set_recur_yearly (int stream, int year, int month, int day, int interval)

mcal_event_set_start
Ustawia date i czas rozpoczecia w globalnej strukturze zdarzenia na podana wartosc. Zwraca True.
int mcal_event_set_start (int stream, int year, int month [, int day [, int hour

Dodatek A - Funkcje

298

[, int min [, int sec]]]])

mcal_event_set_title
Ustawia tytul w globalnej strukturze zdarzenia na podany ciag. Zwraca True.
int mcal_event_set_title (int stream, string title)

mcal_expunge
Usuwa wszystkie zdarzenia oznaczone jako usuniete.
int mcal_expunge (int stream)

mcal_fetch_current_stream_event
object mcal_fetch_current_stream_event (int stream)

Zwraca biezaca strukture zdarzenia ze strumienia w postaci obiektu zawierajacy nastepujace atrybuty: int id Identyfikator zdarzenia. int public TRUE jezeli zdarzenie jest publiczne, FALSE jezeli jest prywatne. string category Ciag z kategoria zdarzenia. string title Ciag z tytulem zdarzenia. string description Ciag z opisem zdarzenia. int alarm Ilosc minut przed zdarzeniem do wyslania alarmu lub przypomnienia. object start Obiekt zawierajacy poczatkowa date i czas. object end Obiekt zawierajacy koncowa date i czas. int recur_type Typ powtarzania. int recur_interval Okres powtarzania. datetime recur_enddate Data zakonczenia powtarzania. int recur_data Dane powtarzania. Wszystkie pozycje zawierajace date i czas sa obiektem zawierajacym: int year rok int month miesiac int mday dzien miesiaca int hour godzina int min minuty int sec sekundy int alarm ilosc minut przed zdarzeniem kiedy nalezy wyslac przypomnienie

mcal_fetch_event
Pobiera zdarzenie ze strumienia kalendarza okreslonego przez $id.
object mcal_fetch_event (int mcal_stream, int event_id [, int options])

299

Zwraca obiekt zdarzenia zawierajacy nastepujace atrybuty: int id Identyfikator zdarzenia. int public TRUE jezeli zdarzenie jest publiczne, FALSE jezeli jest prywatne. string category Ciag z kategoria zdarzenia. string title Ciag z tytulem zdarzenia. string description Ciag z opisem zdarzenia. int alarm Ilosc minut przed zdarzeniem do wyslania alarmu lub przypomnienia. object start Obiekt zawierajacy poczatkowa date i czas. object end Obiekt zawierajacy koncowa date i czas. int recur_type Typ powtarzania. int recur_interval Okres powtarzania. PHP Kompendium wiedzy

Data zakonczenia powtarzania. int recur_data Dane powtarzania. Wszystkie pozycje zawierajace date i czas sa obiektem zawierajacym: int year rok int month miesiac int mday dzien miesiaca int hour godzina int min minuty int sec sekundy int alarm ilosc minut przed zdarzeniem kiedy nalezy wyslac przypomnienie
datetime recur_enddate

mcal_is_leap_year
Zwraca 1 gdy podany rok jest przestepny, 0 gdy nie jest.
int mcal_is_leap_year (int year)

mcal_list_alarms
Zwraca tablice identyfikatorw zdarzen, ktre posiadaja ustawiony alarm pomiedzy data poczatkowa i koncowa, lub jezeli podano tylko strumien, uzywane sa daty z globalnej struktury zdarzen. Funkcja mcal_list_alarms() posiada opcjonalne parametry: date poczatkowa koncowa dla strumienia kalendarza. Zwracana jest tablica identyfikatorw zdarzen, ktre maja alarm pomiedzy podanymi datami lub datami z wewnetrznej struktury zdarzen.
array mcal_list_alarms (int mcal_stream [, int begin_year [, int begin_month [, int begin_day [, int end_year [, int end_month [, int end_day]]]]]])

mcal_list_events
Zwraca tablice identyfikatorw zdarzen wystepujacych pomiedzy data poczatkowa i koncowa, lub jezeli podano tylko strumien, uzywane sa daty z globalnej struktury zdarzen. Funkcja mcal_list_events() posiada opcjonalne parametry: date poczatkowa koncowa dla strumienia kalendarza. Zwracana jest tablica identyfikatorw zdarzen, ktre sa pomiedzy podanymi datami lub datami z wewnetrznej struktury zdarzen.
array mcal_list_events (int mcal_stream, objectbegin_date [, object end_date])

mcal_next_recurrence
Zwraca obiekt z kolejna data wystapienia zdarzenia po podanej dacie. Zwraca puste pole daty, jezeli zdarzenie nie wystapi lub wystapil blad. Uzywa parametru $weekstart do okreslenia dnia rozpoczynajacego tydzien.
int mcal_next_recurrence (int stream, int weekstart, array next)

mcal_open
Zwraca strumien MCAL lub False w przypadku bledu. Funkcja mcal_open() otwiera polaczenie MCAL do okreslonego kalendarza. Jezeli podany zostanie opcjonalny parametr $options, funkcja przekazuje rwniez ten parametr do skrzynki. Po zestawieniu polaczenia inicjowana jest rwniez wewnetrzna struktura strumienia.
int mcal_open (string calendar, string username, string password [, int options])

mcal_popen
Zwraca strumien MCAL lub False w przypadku bledu. Funkcja mcal_open() otwiera polaczenie MCAL do okreslonego kalendarza. Jezeli podany zostanie opcjonalny parametr $options, funkcja przekazuje rwniez ten parametr do skrzynki. Po zestawieniu polaczenia inicjowana jest rwniez wewnetrzna struktura strumienia.
int mcal_popen (string calendar, string username, string password [, int options])

Dodatek A - Funkcje

300

mcal_rename_calendar
Zmienia nazwe kalendarza z $old_name na $new_name.
string mcal_rename_calendar (int stream, string old_name, string new_name)

mcal_reopen
Funkcja mcal_reopen() ponownie otwiera polaczenie MCAL do okreslonego kalendarza. Jezeli podany zostanie opcjonalny parametr $options, funkcja przekazuje rwniez ten parametr do skrzynki.
int mcal_reopen (string calendar [, int options])

mcal_snooze
Wylacza alarm dla kalendarza o podanym identyfikatorze. Zwraca True.
int mcal_snooze (int id)

mcal_store_event
Zapamietuje zmiany w biezacym globalnym zdarzeniu dla podanego strumienia. Zwraca przypadku powodzenia a False w przypadku bledu.
int mcal_store_event (int mcal_stream)

True

mcal_time_valid
Zwraca True, jezeli podana godzina, minuta i sekunda tworza prawidlowy czas, nieprawidlowy.
int mcal_time_valid (int hour, int minutes, int seconds)

False

gdy jest to czas

mcrypt_cbc
Pierwszy prototyp jest dla przypadku, gdy dolaczona jest biblioteka libmcrypt 2.2.x, drugi gdy libmcrypt 2.4.x. Funkcja mcrypt_cbc() szyfruje i deszyfruje (w zaleznosci od trybu) dane $data za pomoca $cipher i $key w trybie szyfrowania CBC i zwraca wynikowy ciag. Patrz rwniez: mcrypt_cfb(), mcrypt_ecb() i mcrypt_ofb().
string mcrypt_cbc (int cipher, string key, string data, int mode [, string iv]) string mcrypt_cbc (string cipher, string key, string data, int mode [, string iv])

jest jedna ze stalych MCRYPT_ciphername. $Key jest kluczem przekazywanym do algorytmu. Musi byc tajny. $Data to dane do zaszyfrowania lub odszyfrowania. $Mode to MCRYPT_ENCRYPT lub MCRYPT_DECRYPT. $IV jest opcjonalnym wektorem inicjalizacji.
$Cipher

mcrypt_cfb
Pierwszy prototyp jest dla przypadku, gdy dolaczona jest biblioteka libmcrypt 2.2.x, drugi gdy libmcrypt 2.4.x. Funkcja mcrypt_cfb() szyfruje i deszyfruje (w zaleznosci od trybu) dane $data za pomoca $cipher i $key w trybie szyfrowania CFB i zwraca wynikowy ciag. Patrz rwniez: mcrypt_cbc(), mcrypt_ecb() i mcrypt_ofb().
string mcrypt_cfb (int cipher, string key, string data, int mode, string iv) string mcrypt_cfb (string cipher, string key, string data, int mode [, string iv])

jest jedna ze stalych MCRYPT_ciphername. $Key jest kluczem przekazywanym do algorytmu. Musi byc tajny. $Data to dane do zaszyfrowania lub odszyfrowania. $Mode to MCRYPT_ENCRYPT lub MCRYPT_DECRYPT. $IV jest opcjonalnym wektorem inicjalizacji.
$Cipher

301

PHP Kompendium wiedzy

mcrypt_create_iv
Funkcja uzywana do tworzenia wektora IV. Posiada dwa argumenty, $size okresla rozmiar IV, natomiast $source okresla zrdlo IV. Zrdlem moze byc MCRYPT_RAND (systemowy generator liczb losowych), MCRYPT_DEV_RANDOM (odczytanie danych z /dev/random) lub MCRYPT_DEV_URANDOM (odczytanie danych z /dev/urandom). Jezeli uzywasz MCRYPT_RAND, upewnij sie, ze wywolales srand() przed inicjalizacja generatora liczb losowych.
string mcrypt_create_iv (int size, int source)

Przyklad: mcrypt_create_iv()
<?php $cipher = MCRYPT_TripleDES; $block_size = mcrypt_get_block_size ($cipher); $iv = mcrypt_create_iv ($block_size, MCRYPT_DEV_RANDOM); ?>

mcrypt_decrypt
Pobiera dane zaszyfrowane i zwraca je w postaci odszyfrowanej.
string mcrypt_decrypt (string cipher, string key, string data, string mode [, string iv])

jest jedna ze stalych MCRYPT_ciphername. $Key jest kluczem przekazywanym do algorytmu. Jezeli jest mniejszy od wymaganej wielkosci klucza, jest dopelniany znakami \0. $Data to dane do odszyfrowania za pomoca podanego szyfru i trybu. $Mode to jedna ze stalych MCRYPT_MODE_modename ktra moze byc: ecb, cbc, cfb, ofb, nofb lub stream. $IV jest parametrem uzywanym do inicjalizacji dla trybw: CBC, CFB, OFB oraz w niektrych algorytmach dla trybu STREAM. Jezeli nie podasz IV, gdy jest on wymagany przez algorytm, funkcja wypisze ostrzezenie i uzyje IV z wszystkimi bajtami ustawionymi na \0.
$Cipher

mcrypt_ecb
Pierwszy prototyp jest dla przypadku, gdy dolaczona jest biblioteka libmcrypt 2.2.x, drugi gdy libmcrypt 2.4.x. Funkcja mcrypt_ecb() szyfruje i deszyfruje (w zaleznosci od trybu) dane $data za pomoca $cipher i $key w trybie szyfrowania CFB i zwraca wynikowy ciag. Patrz rwniez: mcrypt_cbc(), mcrypt_ecb() i mcrypt_ofb().
string mcrypt_ecb (int cipher, string key, string data, int mode) string mcrypt_ecb (string cipher, string key, string data, int mode [, string iv])

jest jedna ze stalych MCRYPT_ciphername. jest kluczem przekazywanym do algorytmu. Musi byc tajny. $Data to dane do zaszyfrowania lub odszyfrowania. $Mode to MCRYPT_ENCRYPT lub MCRYPT_DECRYPT. $IV jest opcjonalnym wektorem inicjalizacji. Patrz rwniez mcrypt_cbc(), mcrypt_cfb() i mcrypt_ofb().
$Cipher $Key

mcrypt_encrypt
Szyfruje dane i zwraca ich zaszyfrowana postac.
string mcrypt_encrypt (string cipher, string key, string data, string mode [, string iv])

jest jedna ze stalych MCRYPT_ciphername. $Key jest kluczem przekazywanym do algorytmu. Jezeli jest mniejszy od wymaganej wielkosci klucza, jest dopelniany znakami \0. $Data to dane do zaszyfrowania za pomoca podanego szyfru i trybu. Jezeli rozmiar danych nie jest n * blocksize, dane beda dopelnione znakami \0. Zwracany zaszyfrowany ciag moze byc dluzszy od danych przekazanych w parametrze $data. $Mode to jedna ze stalych MCRYPT_MODE_modename ktra moze byc: ecb, cbc, cfb, ofb, nofb lub stream.
$Cipher

Dodatek A - Funkcje

302

jest parametrem uzywanym do inicjalizacji dla trybw: CBC, CFB, OFB oraz w niektrych algorytmach dla trybu STREAM. Jezeli nie podasz IV, gdy jest on wymagany przez algorytm, funkcja wypisze ostrzezenie i uzyje IV z wszystkimi bajtami ustawionymi na \0. Przyklad: mcrypt_encrypt()
$IV
<?php $iv = mcrypt_create_iv ( mcrypt_get_iv_size (MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND); $key = "To jest sekretny klucz"; $text = "Spotkajmy sie o 11:00 za pomnikiem."; echo strlen ($text)."\n"; $crypttext = mcrypt_encrypt (MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv); echo strlen ($crypttext)."\n"; ?>

Przyklad ten powinien wypisac:


35 64

mcrypt_enc_get_algorithms_name
Zwraca nazwe algorytmu.
string mcrypt_enc_get_algorithms_name (resource td)

mcrypt_enc_get_block_size
Zwraca wielkosc bloku dla algorytmu okreslonego przez deskryptor $td w bajtach.
int mcrypt_enc_get_block_size (resource td)

mcrypt_enc_get_iv_size
Zwraca wielkosc iv dla algorytmu okreslonego przez deskryptor szyfrowania w bajtach. Jezeli zwraca 0, IV jest ignorowany przez algorytm. Parametru IV uzywaja tryby cbc, cfb o ofb, oraz niektre algorytmy w trybie stream.
int mcrypt_enc_get_iv_size (resource td)

mcrypt_enc_get_key_size
Zwraca maksymalna wielkosc klucza obslugiwana przez algorytm okreslony przez deskryptor bajtach.
int mcrypt_enc_get_key_size (resource td)

$td,

mcrypt_enc_get_modes_name
Zwraca nazwe trybu.
string mcrypt_enc_get_modes_name (resource td)

mcrypt_enc_get_supported_key_sizes
Zwraca tablice z wielkosciami kluczy obslugiwanymi przez algorytm okreslony przez deskryptor szyfrowania. Jezeli zwrci pusta tablice to oznacza, ze wszystkie wielkosci kluczy pomiedzy 1 i mcrypt_enc_get_key_size() sa obslugiwane przez algorytm.
array mcrypt_enc_get_supported_key_sizes (resource td)

mcrypt_enc_is_block_algorithm
Zwraca 1, jezeli algorytm jest blokowy, 0 jezeli jest to algorytm strumieniowy.
int mcrypt_enc_is_block_algorithm (resource td)

303

PHP Kompendium wiedzy

mcrypt_enc_is_block_algorithm_mode
Zwraca 1, gdy tryb jest uzywany przez algorytm blokowy, w przeciwnym przypadku zwraca przyklad, 0 dla stream a 1 dla cbc, cfb, ofb).
int mcrypt_enc_is_block_algorithm_mode (resource td)

(na

mcrypt_enc_is_block_mode
Zwraca 1, gdy tryb zwraca bloki bajtw lub 0, gdy zwraca bajty (na przyklad
stream).
int mcrypt_enc_is_block_mode (resource td)

dla

cbc

ecb

a 0 dla

cfb

mcrypt_enc_self_test
Uruchamia samotestowanie algorytmu okreslonego przez deskryptor przypadku bledu zwraca 1.
int mcrypt_enc_self_test (resource td)

$td.

Jezeli test sie uda, zwraca 0. W

mcrypt_generic
Szyfruje dane. Dane sa dopelniane znakami \0 do wielkosci n dane. Uwaga Wielkosc zwracanego ciagu moze byc wieksza od danych wejsciowych z powodu dopelniania danych.
string mcrypt_generic (resource td, string data)

* blocksize.

Funkcja zwraca zaszyfrowane

mcrypt_generic_end
Konczy szyfrowanie okreslone przez deskryptor szyfrowania ($td). Czysci wszystkie bufory i zamyka uzyte moduly. Zwraca False w przypadku wystapienia bledu a True w przypadku powodzenia operacji.
bool mcrypt_generic_end (resource td)

mcrypt_generic_init
Maksymalna dlugosc klucza powinna byc pobrana poprzez wywolane funkcji mcrypt_enc_get_key_size() i wszystkie wartosci mniejsze od uzyskanej sa dopuszczalne. Parametr $iv powinien miec normalnie wielkosc bloku uzywanego przez algorytm, ale nalezy odczytac ta wielkosc przy pomocy funkcji mcrypt_enc_get_iv_size(). W trybie ECB IV jest ignorowany. IV jest wymagany w trybach CFB, CBC, STREAM, nOFB i OFB. Musi byc on losowy i niepowtarzalny, ale nie musi byc tajny. Ten sam wektor IV musi byc uzyty do kodowania i rozkodowywania. Jezeli nie chcesz go uzywac, mozna zainicjowac go zerami, ale nie jest to zalecane. W przypadku wystapienia bledu funkcja zwraca -1. Funkcja ta musi zostac wywolana przed kazdym wywolaniem mcrypt_generic() lub mdecrypt_generic().
int mcrypt_generic_init (resource td, string key, string iv)

mcrypt_get_block_size
Pierwszy prototyp jest dla przypadku, gdy dolaczona jest biblioteka libmcrypt 2.2.x, drugi gdy libmcrypt 2.4.x. Funkcja mcrypt_get_block_size() jest uzywana do pobierania wielkosci bloku dla podanego szyfrowania, $cipher. Funkcja wymaga dwch argumentw, $cipher oraz $module i zwraca wielkosc w bajtach. Patrz rwniez: mcrypt_get_key_size().
int mcrypt_get_block_size (int cipher) int mcrypt_get_block_size (string cipher, string module)

Dodatek A - Funkcje

304

mcrypt_get_cipher_name
Funkcja uzywana do pobierania nazwy podanego szyfrowania. Wymaga podania szyfrowania w postaci liczby (libmcrypt 2.2.x) lub pobiera nazwe szyfrowania jako argument i zwraca nazwe szyfrowania lub False, jezeli nie istnieje ten sposb szyfrowania.
string mcrypt_get_cipher_name (int cipher) string mcrypt_get_cipher_name (string cipher)

Przyklad: mcrypt_get_cipher_name()
<?php $cipher = MCRYPT_TripleDES; print mcrypt_get_cipher_name ($cipher); ?>

Przyklad ten zwrci nastepujacy napis:


TripleDES

mcrypt_get_iv_size
Pierwszy prototyp jest dla przypadku, gdy dolaczona jest biblioteka libmcrypt 2.2.x, drugi gdy libmcrypt 2.4.x. Funkcja mcrypt_get_iv_size() zwraca wielkosc wektora inicjalizacji (IV) w bajtach. W przypadku bledu zwraca FALSE. Jezeli w podanym trybie IV jest ignorowany, funkcja zwraca 0.
int mcrypt_get_iv_size (string cipher, string mode) int mcrypt_get_iv_size (resource td)

jest jedna ze stalych MCRYPT_ciphername. $Mode to jedna ze stalych MCRYPT_MODE_modename ktra moze byc: ecb, cbc, cfb, ofb, nofb lub stream.
$Cipher $Td jest podanym algorytmem.

mcrypt_get_key_size
Pierwszy prototyp jest dla przypadku, gdy dolaczona jest biblioteka libmcrypt 2.2.x, drugi gdy libmcrypt 2.4.x. Funkcja uzywana do pobierania wielkosci klucza dla podanego szyfrowania, $cipher. Funkcja mcrypt_get_key_size() wymaga podania jednego lub dwch parametrw, $cipher oraz $module i zwraca wielkosc w bajtach. Patrz rwniez: mcrypt_get_block_size().
int mcrypt_get_key_size (int cipher) int mcrypt_get_key_size (string cipher, string module)

mcrypt_list_algorithms
Funkcja uzywana do pobrania tablicy wszystkich obslugiwanych algorytmw w $lib_dir. Posiada parametr opcjonalny, okreslajacy katalog w ktrym znajduja sie wszystkie algorytmy. Jezeli nie zostanie on podany, uzyta zostanie wartosc mcrypt.algorithms_dir z pliku php.ini.
array mcrypt_list_algorithms ([string lib_dir])

Przyklad: mcrypt_algorithms()
<?php $algorithms = mcrypt_list_algorithms ("/usr/local/lib/libmcrypt"); foreach ($algorithms as $cipher) { echo $cipher."/n"; } ?>

Przyklad ten utworzy liste wszystkich obslugiwanych algorytmw z katalogu /usr/local/lib/mcrypt.

mcrypt_list_modes
Funkcja uzywana do pobrania tablicy z wszystkimi obslugiwanymi trybami w $lib_dir. Posiada parametr opcjonalny, okreslajacy katalog w ktrym znajduja sie wszystkie tryby. Jezeli nie zostanie on podany, uzyta zostanie wartosc mcrypt.modes_dir z pliku php.ini.
array mcrypt_list_modes ([string lib_dir])

Przyklad: mcrypt_list_modes()
<?php $modes = mcrypt_list_modes (); foreach ($modes as $mode) { echo "$mode </br>";

305

PHP Kompendium wiedzy

} ?>

Przyklad ten tworzy liste wszystkich obslugiwanych algorytmw w domyslnym katalogu trybw. Jezeli nie jest ustawiony w pliku php.ini jako dyrektywa mcrypt.modes_dir, uzyty zostanie domyslny katalog dla biblioteki mcrypt (/usr/local/lib/libmcrypt)

mcrypt_module_get_algo_block_size
Zwraca wielkosc bloku w bajtach dla podanego algorytmu. W opcjonalnym parametrze podac miejsce, gdzie sa zapisane moduly trybw.
int mcrypt_module_get_algo_block_size (string algorithm [, string lib_dir])

$lib_dir

mozna

mcrypt_module_get_algo_key_size
Zwraca najwieksza obslugiwana wielkosc klucza w bajtach. W opcjonalnym parametrze podac miejsce, gdzie sa zapisane moduly trybw.
int mcrypt_module_get_algo_key_size (string algorithm [, string lib_dir])

$lib_dir

mozna

mcrypt_module_get_algo_supported_key_sizes
Zwraca tablice z wielkosciami kluczy obslugiwanych przez podany algorytm. Jezeli funkcja zwrci pusta tablice, dopuszczalne sa wszystkie rozmiary klucza pomiedzy 1 i mcrypt_get_algo_key_size().W opcjonalnym parametrze $lib_dir mozna podac miejsce, gdzie sa zapisane moduly trybw.
array mcrypt_module_get_algo_supported_key_sizes (string algorithm [, string lib_dir])

mcrypt_module_is_block_algorithm
Zwraca True, jezeli podany algorytm jest algorytmem blokowym i False, jezeli jest algorytmem strumieniowym. W opcjonalnym parametrze $lib_dir mozna podac miejsce, gdzie sa zapisane moduly trybw.
bool mcrypt_module_is_block_algorithm (string mode [, string lib_dir])

mcrypt_module_is_block_algorithm_mode
Zwraca True, jezeli tryb uzywany jest z algorytmem blokowym, w przeciwnym wypadku zwraca 0 (na przyklad 0 dla stream i 1 dla cbc, cfb, cfb). W opcjonalnym parametrze $lib_dir mozna podac miejsce, gdzie sa zapisane moduly trybw.
bool mcrypt_module_is_block_algorithm_mode (string mode [, string lib_dir])

mcrypt_module_is_block_mode
Zwraca True, jezeli tryb powoduje wysylanie blokw bajtw lub False, gdy pojedynczych bajtw (na przyklad: 1 dla cbc i ecb a 0 dla cfb i stream). W opcjonalnym parametrze $lib_dir mozna podac miejsce, gdzie sa zapisane moduly trybw.
bool mcrypt_module_is_block_mode (string mode [, string lib_dir])

mcrypt_module_open
Otwiera modul uzywanego algorytmu i trybu. Nazwa algorytmu jest podana w parametrze $algorithm, na przyklad: twofish jest jedna ze stalych MCRYPT_ciphername. Biblioteka jest zamykana przez mcrypt_module_close() ale wywolanie tej funkcji jest niepotrzebne, jezeli zostala wywolana funkcja mcrypt_generic_end(). Normalnie zwraca deskryptor szyfrowania lub False w przypadku wystapienia bledu. Parametry $algorithm_directory i $mode_directory uzywane sa do odnalezienia modulw szyfrowania. Jezeli jeden z tych parametrw zostanie ustawiony na "", uzyte zostana wartosci znajdujace sie w dyrektywach mcrypt.algorithms_dir lub mcrypt.modes_dir. Jezeli parametry nie zostana ustawione, uzyte zostana wartosci wkompilowane w biblioteke libmcrypt (zwykle /usr/local/lib/libmcrypt).
resource mcrypt_module_open (string algorithm, string algorithm_directory,

Dodatek A - Funkcje

306

string mode, string mode_directory)

Przyklad: mcrypt_module_open()
<?php $td = mcrypt_module_open (MCRYPT_DES, "", MCRYPT_MODE_ECB, "/usr/lib/mcrypt-modes"); ?>

Przyklad ten bedzie prbowal otworzyc szyfrowanie DES z biezacego katalogu i tryb ECB z katalogu /usr/lib/mcrypt-modes.

mcrypt_module_self_test
Uruchamia samotestowanie szyfrowania podanego szyfrowania. W opcjonalnym parametrze $lib_dir mozna podac miejsce, gdzie sa zapisane moduly trybw. Funkcja zwraca True, jezeli test sie powiedzie i False, jezeli sie nie uda.
bool mcrypt_module_self_test (string algorithm [, string lib_dir])

mcrypt_ofb
Pierwszy prototyp jest dla przypadku, gdy dolaczona jest biblioteka libmcrypt 2.2.x, drugi gdy libmcrypt 2.4.x. Funkcja mcrypt_ofb() szyfruje i deszyfruje (w zaleznosci od trybu) dane $data za pomoca $cipher i $key w trybie szyfrowania OFB i zwraca wynikowy ciag.
string mcrypt_ofb (int cipher, string key, string data, int mode, string iv) string mcrypt_ofb (string cipher, string key, string data, int mode [, string iv])

jest jedna ze stalych MCRYPT_ciphername. $Key jest kluczem przekazywanym do algorytmu. Musi byc tajny. $Data to dane do zaszyfrowania lub odszyfrownania. $Mode to jedna ze stalych MCRYPT_ENCRYPT lub MCRYPT_DECRYPT. $IV jest wektorem inicjalizacji. Patrz rwniez: mcrypt_cbc(), mcrypt_cfb() i mcrypt_ecb().
$Cipher

md5
Wykonuje mieszanie ciagu
crc32().
string md5 (string str)

$str

metoda MD5 uzywana przez RSA Data Cecurity Inc. Patrz rwniez:

mdecrypt_generic
Odszyfrowuje dane.
Uwaga Dlugosc zwracanego ciagu moze byc wieksza niz ciag niezaszyfrowany z powodu wyrwnywania danych.
string mdecrypt_generic (resource td, string data)

Przyklad: mdecrypt_generic()
<?php $iv_size = mcrypt_enc_get_iv_size ($td)); $iv = @mcrypt_create_iv ($iv_size, MCRYPT_RAND); if (@mcrypt_generic_init ($td, $key, $iv) != -1) { $c_t = mcrypt_generic ($td, $plain_text); @mcrypt_generic_init ($td, $key, $iv); $p_t = mdecrypt_generic ($td, $c_t); } if (strncmp ($p_t, $plain_text, strlen($plain_text)) == 0) echo "ok"; else echo "blad"; ?>

Przyklad pokazuje w jaki sposb sprawdzic, czy dane przed szyfrowaniem sa takie same jak po odszyfrowaniu. 307 PHP Kompendium wiedzy

metaphone
Oblicza klucz metaphone dla $str. Podobnie jak soundex(), funkcja ta zwraca ten sam klucz dla podobnie brzmiacych slw. Jest ona dokladniejsza od soundex(), poniewaz stosuje podstawowe zasady wymowy angielskiej. Klucze wygenerowane przez funkcje sa zmiennej dlugosci. Autorem algorytmu jest Lawrence Philips <lphilips@verity.com>. Zostal on opisany w ksiazce Practical Algorithms for Programmers, Binstock & Rex, Addison Wesley, 1995.
string metaphone (string str)

method_exists
Funkcja zwraca True jezeli dla obiektu przypadku zwraca False.
$object

zdefiniowana jest metoda

$method_name.

W przeciwnym

bool method_exists (object object, string method_name)

mhash
Uruchamia funkcje mieszajaca okreslona w $hash na danych $data i zwraca wynik mieszania.
string mhash (int hash, string data, string [ key ])

mhash_count
Zwraca najwiekszy dostepny identyfikator funkcji mieszajacej. Sa one numerowane od 0.
int mhash_count (void)

Przyklad: Przegladanie funkcji mieszajacych


<?php $nr = mhash_count(); for ($i = 0; $i <= $nr; $i++) { echo sprintf ("Wielkosc bloku dla %s wynosi %d\n", mhash_get_hash_name ($i), mhash_get_block_size ($i)); } ?>

mhash_get_block_size
Funkcja uzywana do pobrania wielkosci bloku dla podanej funkcji mieszajacej. Wymaga podania jednego parametru, identyfikatora funkcji mieszajacej i zwraca wielkosc bloku w bajtach lub False jezeli nie istnieje podana funkcja.
int mhash_get_block_size (int hash)

mhash_get_hash_name
Funkcja uzywana do pobrania nazwy podanej funkcji mieszajacej. Wymaga podania jednego parametru, identyfikatora funkcji mieszajacej i zwraca jej nazwe lub False jezeli podana funkcja nie istnieje.
string mhash_get_hash_name (int hash)

Przyklad: mhash_get_hash_name()
<?php $hash = MHASH_MD5; print mhash_get_hash_name ($hash); ?>

Uruchomienie przykladu spowoduje wypisanie nastepujacego wyniku:


MD5

microtime
Zwraca ciag mikrosekundy sekundy gdzie sekundy sa biezacym czasem wyrazonym w sekundach od poczatku epoki Uniksa (1 stycznia 1970, 0:00:00). Funkcja jest dostepna w systemach obslugujacych funkcje systemowa gettimeofday(). Parz rwniez: time().
string microtime (void)

Dodatek A - Funkcje

308

min
Zwraca wartosc najmniejszego numerycznie parametru. Jezeli pierwszy parametr jest tablica, min() zwraca najmniejsza wartosc w tablicy. Jezeli pierwszy parametr jest liczba calkowita, ciagiem lub liczba double, funkcja wymaga co najmniej dwch parametrw i zwraca najmniejszy z nich. Mozna porwnywac nieograniczona ilosc wartosci. Jezeli jedna lub wiecej wartosci jest liczba double, wszystkie wartosci sa traktowane jako double i zwracana jest liczba typu double. Jezeli zadna z wartosci nie jest liczba double, wszystkie sa traktowane jako liczby calkowite i rwniez zwracana jest liczba calkowita.
number min (number arg1, number arg2 [, ...])

mkdir
Tworzy katalog okreslony o podanej nazwie.
Uwaga Prawdopodobnie bedziesz chcial podac typ jako liczbe semkowa, musisz wiec dodac na jej poczatku zero.
int mkdir (string pathname, int mode)

Zwraca True w przypadku powodzenia operacji lub False w przypadku wystapienia bledu. Patrz rwniez:
rmdir().
mkdir ("/sciezka/do/nowego/katalogu", 0700);

mktime
Ostrzezenie Zwrc uwage na dziwna kolejnosc argumentw, ktra rzni sie od kolejnosci stosowanej w wywolaniu funkcji Uniksa mktime() ktra nie pomaga w opuszczaniu parametrw od prawej do lewej strony. Czestym bledem jest pomieszanie tych parametrw w skrypcie.

Zwraca znacznik czasu Uniksa odpowiadajacy podanym argumentom. Znacznik ten to liczba calkowita zawierajaca ilosc sekund od poczatku ery Uniksa (1 stycznia 1970) do podanego czasu. Argumenty moga byc opuszczane od prawej do lewej strony a opuszczone wartosci beda zastepowane biezacym czasem lokalnym.
int mktime (int hour, int minute, int second, int month, int day, int year [, int is_dst])

Parametr $is_dst moze byc ustawiony na 1 w przypadku, gdy obowiazuje czas zimowy, na obowiazuje czas letni lub na -1 (domyslnie) gdy nie wiadomo jaki czas obowiazuje.
Uwaga Parametr $is_dst zostal dodany w PHP 3.0.10.

gdy

Funkcja mktime() jest pozyteczna do obliczen na datach oraz kontroli ich poprawnosci, poniewaz automatycznie oblicza wlasciwe wartosci dla parametrw spoza zakresu. Na przyklad: kazdy z ponizszych wierszy powoduje wypisanie ciagu Jan-01-1998. Przyklad: mktime()
echo echo echo echo date date date date ("M-d-Y", ("M-d-Y", ("M-d-Y", ("M-d-Y", mktime mktime mktime mktime (0,0,0,12,32,1997)); (0,0,0,13,1,1997)); (0,0,0,1,1,1998)); (0,0,0,1,1,98));

Parametr $year moze byc liczba dwu badz czterocyfrowa o wartosciach 069 odpowiadajacych 2000 2069 oraz 7099 odpowiadajacych 19701999 (w systemach w ktrych time_t jest 32-bitowa licza ze znakiem, czyli wiekszosci wsplczesnych, prawidlowym zakresem dla $year jest 19022037). Ostatni dzien dowolnego miesiaca moze byc podany jako dzien 0 miesiaca nastepnego. Ponizszy przyklad wypisze dwukrotnie Ostatnim dniem lutego 2000 jest: 29. Przyklad: Ostatni dzien miesiaca:
$lastday = mktime (0,0,0,3,0,2000); echo strftime ("Ostatnim dniam lutego 2000 jest: %d", $lastday); $lastday = mktime (0,0,0,4,-31,2000);

309

PHP Kompendium wiedzy

echo strftime ("Ostatnim dniam lutego 2000 jest: %d", $lastday);

Jezeli jako rok, miesiac i dzien podane zostana wartosci 0, data taka uznana zostanie za bledna. Jezeli by tak nie bylo, odpowiadalo by to dacie 30.11.1999, co wydawac by sie moglo dziwnym dzialaniem. Patrz rwniez: date() i time().

move_uploaded_file
Funkcja dostepna w PHP 3 powyzej wersji 3.0.16 i w PHP 4 powyzej 4.0.2. Funkcja sprawdza, czy plik okreslony przez $filename jest plikiem przeslanym na serwer (za pomoca mechanizmu przesylania HTTP POST). Jezeli plik jest prawidlowy zostaje on przeniesiony na sciezke okreslona przez $destination. Jezeli $filename nie jest prawidlowym plikiem zaladowanym na serwer, nie jest wykonywana zadna operacja i funkcja move_upload_file() zwraca False. Jezeli $filename jest prawidlowym plikiem zaladowanym na serwer, ale z jakichkolwiek przyczyn nie moze byc on przeniesiony, nie jest wykonywana zadna operacja a funkcja move_upload_file() zwraca False. Dodatkowo wyswietlane jest ostrzezenie. Sprawdzenie to jest szczeglnie istotne w przypadkach, gdy istnieje jakakolwiek szansa, ze zawartosc przesylanego pliku moze byc pokazana uzytkownikowi, lub innym uzytkownikom na tym samym systemie. Patrz rwniez: is_uploaded_file() oraz czesc podrecznika sieciowego zatytulowana: Handling file uploads.
bool move_uploaded_file (string filename, string destination)

msql
Zwraca dodatni identyfikator wyniku zapytania mSQL, lub False w przypadku wystapienia bledu. Funkcja mSQL wybiera baze danych i wykonuje na niej zapytanie. Jezeli nie zostanie podany opcjonalny identyfikator polaczenia, funkcja prbuje znalezc otwarte polaczenie do serwera mSQL. Jezeli nie zostanie znalezione takie polaczenie, funkcja sprbuje nawiazac je wywolujac funkcje msql_connect() bez parametrw. Patrz rwniez: msql_connect().
int msql (string database, string query, int link_identifier)

msql_affected_rows
Zwraca ilosc wierszy bioracych udzial w zapytaniu (to znaczy ilosc wierszy zwrconych przez SELECT, ilosc wierszy zmienionych przez UPDATE lub ilosc wierszy usunietych przez DELETE). Patrz rwniez: msql_query().
int msql_affected_rows (int query_identifier)

msql_close
Zwraca True w przypadku powodzenia operacji a False w przypadku bledu. Funkcja zamyka polaczenie z baza mSQL skojarzona z podanym identyfikatorem polaczenia. Jezeli nie zostanie podany identyfikator polaczenia, zostanie uzyty ostatnio otwarte polaczenie.
Uwaga Zwykle nie jest konieczne uzywanie tej funkcji, poniewaz polaczenia nie otwarte jako trwale sa zamykane automatycznie po zakonczeniu skryptu.

Funkja msql_close() nie zamyka polaczen trwalych wygenerowanych przez rwniez: msql_connect() i msql_pconnect().
int msql_close (int link_identifier)

msql_pconnect().

Patrz

msql_connect
Zwraca dodatni identyfikator polaczenia do mSQL, lub False w przypadku bledu. Funkcja msql_connect() nawiazuje polaczenie z serwerem mSQL. Nawa komputera jest opcjonalna i jezeli jest opuszczona, przyjmowana jest nazwa localhost. Drugie wywolanie msql_connect() z takimi samymi argumentami nie spowoduje zestawienia nastepnego polaczenia. Zamiast tego zwrcony zostanie identyfikator istniejacego juz polaczenia. Dodatek A - Funkcje 310

Polaczenie z serwerem zostanie zamkniete po zakonczeniu wykonywania skryptu chyba, ze wczesniej zostanie zamkniete za pomoca msql_close(). Patrz rwniez: msql_pconnect() i msql_close().
int msql_connect ([string hostname [, string hostname[:port] [, string username [, string password]]]])

msql_createdb
Taka sama jak msql_create_db().
int msql_createdb (string database name [, int link_identifier])

msql_create_db
Tworzy baze danych na serwerze skojarzonym z podanym identyfikatorem polaczenia. Patrz rwniez: msql_drop_db().
int msql_create_db (string database name [, int link_identifier])

msql_data_seek
Zwraca True w przypadku powodzenia operacji a False w przypadku bledu. Przesuwa wewnetrzny znacznik wiersza w wyniku mSQL skojarzonym z podanym identyfikatorem wyniku zapytania do wiersza o podanym numerze. Kolejne wywolanie funkcji msql_fetch_row() zwrci ten wiersz. Patrz rwniez: msql_fetch_row().
int msql_data_seek (int query_identifier, int row_number)

msql_dbname
Zwraca nazwe bazy danych zapisana na pozycji $i wskaznika zwracanego przez funkcje Funkcja moze byc wykorzystana do sprawdzenia ilosci dostepnych baz danych.
string msql_dbname (int query_identifier, int i)

msql_listdbs().

msql_dropdb
Patrz msql_drop_db().
int msql_dropdb (void)

msql_drop_db
Zwraca True w przypadku powodzenia operacji a False w przypadku bledu. Funkcja msql_drop_db() prbuje usunac z serwera cala baze danych skojarzona z podanym identyfikatorem polaczenia. Patrz rwniez: msql_create_db().
int msql_drop_db (string database_name, int link_identifier)

msql_error
Bledy przychodzace z serwera mSQL nie sa traktowane jako ostrzezenia PHP. Zamiast tego nalezy uzywac tej funkcji do pobierania ciagu z opisem bledu.
string msql_error ()

msql_fetch_array
Zwraca tablice odpowiadajaca pobranemu wierszowi, lub False jezeli nie ma juz wierszy do pobrania. Funkcja msql_fetch_array() jest rozszerzeniem funkcji msql_fetch_row(). Oprcz zapamietywania danych pod indeksami numerycznymi, dodatkowo dane sa zapisywane pod indeksami asocjacyjnymi, uzywajac nazw pl jako kluczy. Drugi argument, $result_type w funkcji msql_fetch_array() jest jedna z nastepujacych stalych: MSQL_ASSOC, MSQL_NUM i MSQL_BOTH. Nalezy byc uwazym przy odczytywaniu wynikw zapytania, ktre moze zwrcic tylko jedno pole, ktre ma wartosc 0 (pusty ciag albo NULL). PHP Kompendium wiedzy 311

Uwaga Funkcja msql_fetch_array() NIE jest wyraznie wolniejsza od funkcji msql_fetch_row(), jedynie dostarcza wiecej wynikw. Bardziej szczeglowo jest to opisane przy funkcji msql_fetch_row().
int msql_fetch_array (int query_identifier [, int result_type])

msql_fetch_field
Zwraca obiekt zawierajacy informacje o polu. Funkcja msql_fetch_field() moze byc uzyta do pobrania danych na temat pl w wyniku. Jezeli nie zostanie podane przesuniecie, odczytywane jest nastepne pole, ktre nie bylo jeszcze odczytane.
object msql_fetch_field (int query_identifier, int field_offset)

Wlasciwosci zwracanego obiektu sa nastepujace: name nazwa kolumny table nazwa tabeli do ktrej nalezy kolumna not_null 1 jezeli kolumna nie moze byc pusta primary_key 1 jezeli kolumna jest kluczem glwnym unique 1 jezeli kolumna jest kluczem unikalnym type typ kolumny

msql_fetch_object
Zwraca obiekt z wlasciwosciami odpowiadajacymi polom pobieranego wiersza lub False, jezeli nie ma wiecej wierszy do pobrania. Funkcja msql_fetch_object() jest podobna do msql_fetch_array() z jedna rznica zwracany jest obiekt a nie tablica. Oznacza to, ze mozesz odwolywac sie do pl poprzez nazwy a nie poprzez indeks( liczby nie sa prawidlowymi nazwami wlasciwosci). Drugi argument, $result_type w funkcji msql_fetch_array() jest jedna z nastepujacych stalych: MSQL_ASSOC, MSQL_NUM i MSQL_BOTH. Funkcja jest identyczna wydajnosciowo z msql_fetch_array() i prawie tak samo szybka jak msql_fetch_row() rznica jest nieznaczna. Patrz rwniez: msql_fetch_array() i msql_fetch_row().
int msql_fetch_object (int query_identifier [, int result_type])

msql_fetch_row
Zwraca tablice odpowiadajaca pobranemu wierszowi, lub False jezeli nie ma juz wierszy do pobrania. Funkcja msql_fetch_row() pobiera jeden wiersz z wyniku okreslonego przez identyfikator zapytania. Wiersz jest zwracany w postaci tablicy. Kazda kolumna jest zapisywana w osobnym indeksie tablicy, rozpoczynajac od 0. Kolejne wywolanie msql_fetch_row() powoduje zwracanie kolejnych wierszy z wyniku lub False jezeli nie ma juz wiecej wierszy. Patrz rwniez: msql_fetch_array(), msql_fetch_object(), msql_data_seek() i msql_result().
array msql_fetch_row (int query_identifier)

msql_fieldflags
Zwraca atrybuty podanego pola. Atrybutami sa not null, primary key, kombinacja obu oraz pusty ciag.
string msql_fieldflags (int query_identifier, int i)

msql_fieldlen
Zwraca dlugosc podanego pola.
int msql_fieldlen (int query_identifier, int i)

Dodatek A - Funkcje

312

msql_fieldname
Zwraca nazwe podanego pola. Parametr $query_identifier jest identyfikatorem zapytania, a $field jest numerem kolejnym pola. Funkcja msql_fieldname($result, 2) zwrci nazwe drugiego pola z wyniku zwiazanego z podanym identyfikatorem wyniku.
string msql_fieldname (int query_identifier, int field)

msql_fieldtable
Zwraca nazwe tabel do ktrej nalezy pole $field.
int msql_fieldtable (int query_identifier, int field)

msql_fieldtype
Podobna do funkcji int, char lub real.
msql_fieldname().

Argumenty sa takie same, ale zwracany jest typ pola. Moze byc to

string msql_fieldtype (int query_identifier, int i)

msql_field_seek
Przesuwa wskaznik do podanego numeru pola. Jezeli nastepne wywolanie msql_fetch_field() nie bedzie zawieralo numeru pola, zostanie zwrcone to wlasnie pole. Patrz rwniez: msql_fetch_field().
int msql_field_seek (int query_identifier, int field_offset)

msql_freeresult
Patrz msql_free_result().
msql_freeresult( void )

msql_free_result
Zwalnia pamiec przydzielona dla $query_identifier. Po zakonczeniu wykonywania zadania pamiec jest zwalniana automatycznie. Funkcja ta jest potrzebna tylko wtedy, gdy nie chcemy zuzywac zbyt wiele pamieci w czasie dzialania skryptu.
int msql_free_result (int query_identifier)

msql_listdbs
Patrz msql_list_dbs().
msql_listdbs( void )

msql_listfields
Patrz msql_list_fields().
msql_listfields( void )

msql_listtables
Patrz msql_list_tables().
msql_listtables( void )

msql_list_dbs
msql_dbname()

Zwraca znacznik wyniku zawierajacego bazy danych dostepne dla demona msql. Nalezy uzyc funkcji do odczytania tego znacznika wyniku. PHP Kompendium wiedzy

int msql_list_dbs (void)

313

msql_list_fields
Pobiera dane na temat podanej tabeli. Parametrami sa nazwa bazy danych i nazwa tabeli. Zwracany jest znacznik wyniku, ktry moze byc uzyty w funkcjach msql_fieldflags(), msql_fieldlen(), msql_fieldname() i msql_fieldtype(). Identyfikator zapytania jest dodatnia liczba calkowita. W przypadku bledu funkcja zwraca -1. Ciag opisujacy blad umieszczany jest w $phperrmsg i jezeli funkcja nie zostala wywolana jako @msql_list_fields(), ciag ten jest wypisywany na wyjscie. Patrz rwniez: msql_error().
int msql_list_fields (string database, string tablename)

msql_list_tables
Pobiera jako argument nazwe bazy danych i zwraca znacznik wyniku podobnie do funkcji pobrania wyniku na podstawie znacznika powinna zostac uzyta funkcja msql_table_name().
int msql_list_tables (string database)

msql().

Do

msql_numfields
Identyczna z msql_num_fields().
int msql_numfields (int query_identifier)

msql_numrows
Identyczna z msql_num_rows().
int msql_numrows (void)

msql_num_fields
Zwraca ilosc pl w wyniku. Patrz rwniez: msql(), msql_query(), msql_fetch_field() i msql_num_rows().
int msql_num_fields (int query_identifier)

msql_num_rows
Zwraca ilosc wierszy w wyniku. Patrz rwniez: msql(), msql_query() i
int msql_num_rows (int query_identifier)

msql_fetch_row().

msql_pconnect
msql_pconnect()

Zwraca dodatni identyfikator lacza trwalego lub False w przypadku wystapienia bledu. Funkcja dziala bardzo podobnie do msql_connect() z dwiema rznicami. Po pierwsze, w czasie polaczenia zamiast otwierac nowe polaczenie funkcja prbuje znalezc istniejace lacze (trwale). Jezeli zostanie ono znalezione, zostaje zwrcone zamiast nowego polaczenia. Po drugie, polaczenie do serwera mSQL nie jest zamykane po zakonczeniu pracy skryptu. Lacze takie pozostaje otwarte do wykorzystania w przyszlosci (msql_close() nie zamyka polaczen utworzonych przez msql_pconnect()).
int msql_pconnect ([string hostname [, string hostname[:port] [, string username [, string password]]]])

msql_query
Wysyla zapytanie do aktywnej bazy danych skojarzonej z podanym identyfikatorem lacza. Jezeli identyfikator ten nie zostanie podany, uzyte zostanie ostatnio otwarte lacze. Jezeli nie ma otwartego lacza, funkcja prbuje utworzyc polaczenie identycznie jak robi to funkcja msql_connect() a nastepnie uzywa lacza do wykonania zapytania. Zwraca dodatni identyfikator zapytania mSQL lub False w przypadku wystapienia bledu. Patrz rwniez: msql(), msql_select_db() i msql_connect().
int msql_query (string query, int link_identifier)

Dodatek A - Funkcje

314

msql_regcase
Patrz sql_regcase().
msql_regcase( void )

msql_result
Zwraca zawartosc komrki w podanym wierszu, numerze i wyniku mSQL. Funkcja msql_result() zwraca zawartosc jednej komrki z wyniku mSQL. Argument $field moze byc numerem pola, nazwa pola lub nazwa w postaci tabela kropka pole (pole.tabela). Jezeli kolumna otrzymala w zapytaniu alias (select foo as bar from ...), nalezy uzyc aliasu a nie oryginalnej nazwy kolumny. Pracujac na duzych wynikach nalezy rozwazyc uzycie jednej funkcji do wczytania calego wiersza. Poniewaz funkcje te zwracaja zawartosc wielu pl za pomoca jednego wywolania, sa one duzo szybsze od msql_result(). Podawanie numerw pl zamiast ich nazw powoduje szybsze dzialanie funkcji. Zalecanymi szybszymi funkcjami sa: msql_fetch_row(), msql_fetch_array() i msql_fetch_object().
int msql_result (int query_identifier, int i, mixed field)

msql_selectdb
Patrz msql_select_db().
msql_selectdb( void )

msql_select_db
Zwraca True w przypadku powodzenia a False w przypadku bledu. Funkcja msql_select_db() ustawia na serwerze biezaca aktywna baze danych o podanym identyfikatorze lacza. Jezeli identyfikator ten nie zostanie podany, uzyte zostanie ostatnio otwarte lacze. Jezeli nie ma otwartego lacza, funkcja prbuje utworzyc polaczenie identycznie jak robi to funkcja msql_connect() a nastepnie uzywa lacza do wybrania bazy danych. Kolejne wywolania msql_query() wykonywane sa na aktywnej bazie danych. Patrz rwniez: msql_connect(), msql_pconnect() i msql_query().
int msql_select_db (string database_name, int link_identifier)

msql_tablename
Na podstawie identyfikatora wyniku zwracanego przez msql_list_tables() oraz numeru kolejnego pobiera i zwraca nazwe tabeli. Funkcja msql_numrows() moze byc uzyta do okreslenia ilosci tabel w wyniku.
string msql_tablename (int query_identifier, int field)

Przyklad: msql_tablename()
<?php msql_connect ("localhost"); $result = msql_list_tables ("wisconsin"); $i = 0; while ($i < msql_numrows ($result)) { $tb_names[$i] = msql_tablename ($result, $i); echo $tb_names[$i] . "<BR>"; $i++; } ?>

mssql_close
Zwraca True w przypadku powodzenia a False w przypadku bledu. Zamyka polaczenie z baza danych MS SQL Server, ktra jest skojarzona z podanym identyfikatorem polaczenia. Jezeli identyfikator polaczenia nie zostanie podany, uzywane jest ostatnio otwarte polaczenie.
Uwaga Nie jest to zwykle konieczne, poniewaz polaczenia nietrwale sa automatycznie zamykane po zakonczeniu wykonywania skryptu. Funkcja mssql_close() nie zamyka polaczen trwalych otwartych za pomoca mssql_pconnect().

315

PHP Kompendium wiedzy

Patrz rwniez: mssql_connect() i mssql_pconnect().


int mssql_close ([int link_identifier])

mssql_connect
Zwraca dodatni identyfikator polaczenia do MS SQL, lub False w przypadku bledu. Funkcja mssql_connect() nawiazuje polaczenie z serwerem MS SQL. Argument $servername musi byc prawidlowa nazwa serwera zdefiniowana w pliku interfejsw. Drugie wywolanie mssql_connect() z takimi samymi argumentami nie spowoduje zestawienia nastepnego polaczenia. Zamiast tego zwrcony zostanie identyfikator istniejacego juz polaczenia. Polaczenie z serwerem zostanie zamkniete po zakonczeniu wykonywania skryptu chyba, ze wczesniej zostanie zamkniete za pomoca mssql_close(). Patrz rwniez: mssql_pconnect() i mssql_close().
int mssql_connect ([string servername [, string username [, string password]]])

mssql_data_seek
Zwraca True w przypadku powodzenia a False w przypadku bledu. Funkcja mssql_data_seek() przesuwa wewnetrzny wskaznik wiersza w wyniku MS SQL, skojarzonym z podanym identyfikatorem wyniku, do wiersza o podanym numerze. Nastepne wywolanie funkcji mssql_fetch_row() zwrci ten wiersz. Patrz rwniez: mssql_data_seek().
int mssql_data_seek (int result_identifier, int row_number)

mssql_fetch_array
Zwraca tablice odpowiadajaca pobranemu wierszowi, lub False jezeli nie ma juz wierszy do pobrania. Funkcja mssql_fetch_array() jest rozszerzeniem funkcji mssql_fetch_row(). Oprcz zapamietywania danych pod indeksami numerycznymi, dodatkowo dane sa zapisywane pod indeksami asocjacyjnymi, uzywajac nazw pl jako kluczy.
Uwaga Funkcja mssql_fetch_array() NIE jest wyraznie wolniejsza od funkcji mssql_fetch_row(), jedynie dostarcza wiecej wynikw. Bardziej szczeglowo jest to opisane przy funkcji mssql_fetch_row().
int mssql_fetch_array (int result)

mssql_fetch_field
Zwraca obiekt zawierajacy informacje o polu. Funkcja mssql_fetch_field() moze byc uzyta do pobrania danych na temat pl w wyniku. Jezeli nie zostanie podane przesuniecie, odczytywane jest nastepne pole, ktre nie bylo jeszcze odczytane.
object mssql_fetch_field (int result [, int field_offset])

Nazwa kolumny. Jezeli kolumna jest wynikiem dzialania funkcji, wlasciwosc ta ma wartosc computed#N, gdzie #N jest numerem seryjnym. column_source Tabela z ktrej pochodzi kolumna. max_length Maksymalna dlugosc kolumny. numeric 1 gdy kolumna jest numeryczna.
name

mssql_fetch_object
Zwraca obiekt z wlasciwosciami odpowiadajacymi polom pobieranego wiersza lub False, jezeli nie ma wiecej wierszy do pobrania. Funkcja mssql_fetch_object() jest podobna do mssql_fetch_array() z jedna rznica zwracany jest obiekt a nie tablica. Oznacza to, ze mozesz odwolywac sie do pl poprzez nazwy a nie poprzez indeks( liczby nie sa prawidlowymi nazwami wlasciwosci). Funkcja jest identyczna wydajnosciowo z Dodatek A - Funkcje 316

mssql_fetch_array() mssql_fetch_array()

i prawie tak samo szybka jak i mssql_fetch_row().

mssql_fetch_row()

rznica jest nieznaczna. Patrz rwniez:

int mssql_fetch_object (int result)

mssql_fetch_row
Zwraca tablice odpowiadajaca pobranemu wierszowi, lub False jezeli nie ma juz wierszy do pobrania. Funkcja mssql_fetch_row() pobiera jeden wiersz z wyniku okreslonego przez identyfikator zapytania. Wiersz jest zwracany w postaci tablicy. Kazda kolumna jest zapisywana w osobnym indeksie tablicy, rozpoczynajac od 0. Kolejne wywolanie mssql_fetch_row() powoduje zwracanie kolejnych wierszy z wyniku lub False jezeli nie ma juz wiecej wierszy. Patrz rwniez: mssql_fetch_array(), mssql_fetch_object(), mssql_data_seek(), mssql_fetch_lengths() i mssql_result().
array mssql_fetch_row (int result)

mssql_field_length
int mssql_field_length (int result [, int offset])

mssql_field_name
int mssql_field_name (int result [, int offset])

mssql_field_seek
Przesuwa wskaznik do okreslonego numeru pola. Jezeli nastepne wywolanie mssql_fetch_field() nie bedzie zawieralo numeru pola, zostanie zwrcone to wlasnie pole. Patrz rwniez: mssql_fetch_field().
int mssql_field_seek (int result, int field_offset)

mssql_field_type
string mssql_field_type (int result [, int offset])

mssql_free_result
Zwalnia pamiec przydzielona dla $result. Po zakonczeniu wykonywania zadania pamiec jest zwalniana automatycznie. Funkcja ta jest potrzebna tylko wtedy, gdy nie chcemy zuzywac zbyt wiele pamieci w czasie dzialania skryptu.
int mssql_free_result (int result)

mssql_get_last_message
string mssql_get_last_message (void)

mssql_min_error_severity
void mssql_min_error_severity (int severity)

mssql_min_message_severity
void mssql_min_message_severity (int severity)

mssql_num_fields
Zwraca ilosc pl w wyniku. Patrz rwniez:
mssql_num_rows().
int mssql_num_fields (int result)

mssql_db_query(), mssql_query(), mssql_fetch_field()

317

PHP Kompendium wiedzy

mssql_num_rows
Zwraca ilosc wierszy w wyniku. Patrz rwniez: mssql_db_query(), mssql_query() i
int mssql_num_rows (string result)

mssql_fetch_row().

mssql_pconnect
Zwraca dodatni identyfikator lacza trwalego lub False w przypadku wystapienia bledu. Funkcja mssql_pconnect() dziala bardzo podobnie do mssql_connect() z dwiema rznicami. Po pierwsze, w czasie polaczenia zamiast otwierac nowe polaczenie funkcja prbuje znalezc istniejace lacze (trwale). Jezeli zostanie ono znalezione, zostaje zwrcone zamiast nowego polaczenia. Po drugie, polaczenie do serwera MS SQL nie jest zamykane po zakonczeniu pracy skryptu. Lacze takie pozostaje otwarte do wykorzystania w przyszlosci (mssql_close() nie zamyka polaczen utworzonych przez mssql_pconnect()).
int mssql_pconnect ([string servername [, string username [, string password]]])

mssql_query
Zwraca dodatni identyfikator zapytania MS SQL lub False w przypadku wystapienia bledu. Wysyla do aktywnej bazy danych zapytanie skojarzone z podanym identyfikatorem lacza. Jezeli identyfikator ten nie zostanie podany, uzyte zostanie ostatnio otwarte lacze. Jezeli nie ma otwartego lacza, funkcja prbuje utworzyc polaczenie identycznie jak robi to funkcja mssql_connect() a nastepnie uzywa lacza do wykonania zapytania. Patrz rwniez: mssql_db_query(), mssql_select_db() i mssql_connect().
int mssql_query (string query [, int link_identifier])

mssql_result
Funkcja mssql_result() zwraca zawartosc jednej komrki z wyniku MS SQL. Argument $field moze byc numerem pola, nazwa pola lub nazwa w postaci tabela kropka pole (pole.tabela). Jezeli kolumna otrzymala w zapytaniu alias (select foo as bar from ...), nalezy uzyc aliasu a nie oryginalnej nazwy kolumny. Pracujac na duzych wynikach nalezy rozwazyc uzycie jednej funkcji do wczytania calego wiersza. Poniewaz funkcje te zwracaja zawartosc wielu pl za pomoca jednego wywolania, sa one duzo szybsze od mssql_result(). Podawanie numerw pl zamiast ich nazw powoduje szybsze dzialanie funkcji. Zalecanymi szybszymi funkcjami sa: mssql_fetch_row(), mssql_fetch_array() i mssql_fetch_object().
int mssql_result (int result, int i, mixed field)

mssql_select_db
Zwraca True w przypadku powodzenia a False w przypadku bledu. Funkcja mssql_select_db() ustawia na serwerze biezaca aktywna baze danych o podanym identyfikatorze lacza. Jezeli identyfikator ten nie zostanie podany, uzyte zostanie ostatnio otwarte lacze. Jezeli nie ma otwartego lacza, funkcja prbuje utworzyc polaczenie identycznie jak robi to funkcja mssql_connect() a nastepnie uzywa lacza do wybrania bazy danych. Kolejne wywolania mssql_query() wykonywane sa na aktywnej bazie danych. Patrz rwniez: mssql_connect(), mssql_pconnect() i mssql_query().
int mssql_select_db (string database_name [, int link_identifier])

mt_getrandmax
Zwraca maksymalna wartosc, jaka moze byc zwrcona przez funkcje mt_rand(), mt_srand(), rand(), srand() i getrandmax().
int mt_getrandmax (void)

mt_rand().

Patrz rwniez:

mt_rand
Wiele generatorw liczb losowych ze starszych bibliotek libc mialo problematyczna lub nieznana charakterystyke i byly powolne. Domyslnie PHP korzysta z generatora liczb losowych z libc dostepnego za Dodatek A - Funkcje 318

pomoca funkcji rand(). Funkcja mt_rand() jest jej zamiennikiem. Korzysta ona z generatora liczb losowych Mersenne Twister o znanej charakterystyce, ktry generuje liczby losowe wystarczajace do inicjowania niektrych rodzajw funkcji kryptograficznych (wiecej informacji na stronie domowej) i jest srednio cztery razy szybszy od generatora dostarczanego w libc. Strona domowa generatora Mersenne Twister znajduje sie pod adresem http://www.math.keio.ac.jp/~matumoto/emt.html, a zoptymalizowane zrdla MT znajduja sie pod adresem http://www.scp.syr.edu/~marc/hawk/twister.html.
int mt_rand (void) int mt_rand (int min, int max)

Jezeli funkcja zostanie wywolana bez opcjonalnych parametrw $min i $max, mt_rand() zwraca liczbe pseudolosowa z przedzialu 0 do RAND_MAX. Jezeli chcesz otrzymac liczby pomiedzy, na przyklad, 5 a 15 (wlacznie) uzyj mt_rand(5, 15). Nalezy pamietac, ze trzeba zainicjowac generator liczb losowych przed uzyciem funkcji mt_srand().
Uwaga W wersjach wczesniejszych od 3.0.7, drugi parametr oznaczal wielkosc przedzialu. Aby otrzymac te same wyniki, co w naszym krtkim przykladzie trzeba bylo wywolac funkcje mt_rand(5, 11).

Patrz rwniez: mt_srand(), mt_getrandmax(), srand(), rand() i getrandmax().

mt_srand
Inicjuje generator liczb losowych wartoscia $seed.
void mt_srand (int seed)

Przyklad:
//inicjowanie mikrosekundami od ostatniej pelnej sekundy mt_srand((double) microtime() * 1000000); $randval = mt_rand();

Patrz rwniez: mt_rand(), mt_getrandmax(), srand(), rand() i getrandmax().

mysql_affected_rows
Zwraca ilosc wierszy zmienionych przez ostatnie wyrazenie INSERT, UPDATE lub DELETE na serwerze skojarzonym z podanym identyfikatorem lacza. Jezeli nie zostanie podany identyfikator lacza, uzywany jest ostatnio otwarte polaczenie. Jezeli ostatnim zapytaniem bylo zapytanie DELETE bez klauzuli WHERE, usuniete zostana wszystkie wiersze z tabeli, ale funkcja zwrci zero. Funkcja nie dziala dla wyrazen typu SELECT, jedynie dla wyrazen zmieniajacych rekordy. Aby pobrac ilosc wierszy zwracanych przez zapytanie SELECT, nalezy uzyc mysql_num_rows().
int mysql_affected_rows ([resource link_identifier])

mysql_change_user
Zmienia uzytkownika na biezacym polaczeniu lub polaczeniu podanym przez identyfikator polaczenia $link_identifier. Jezeli zostanie podana baza danych, bedzie ona ustawiona jako biezaca baza danych. Jezeli nie uda sie autoryzacja nowego uzytkownika, aktywne pozostanie polaczenie wczesniej podlaczonego uzytkownika.
Uwaga Funkcja zostala wprowadzona w PHP 3.0.13 i wymaga MySQL w wersji co najmniej 3.23.3.
int mysql_change_user (string user, string password [, string database [, resource link_identifier]])

mysql_close
Zwraca True w przypadku powodzenia a False w przypadku bledu. Funkcja mysql_close() zamyka polaczenie do bazy danych MySQL, ktra jest skojarzona z podanym identyfikatorem polaczenia. Jezeli 319 PHP Kompendium wiedzy

identyfikator polaczenia nie zostanie podany, uzywane jest ostatnio otwarte polaczenie. Uzycie tej funkcji nie jest zwykle konieczne, poniewaz polaczenia nietrwale sa automatycznie zamykane po zakonczeniu wykonywania skryptu.
Uwaga Funkcja mysql_close() nie zamyka polaczen trwalych otwartych za pomoca mysql_pconnect().
bool mysql_close ([resource link_identifier])

Przyklad: MySQL_close()
<?php $link = mysql_connect ("kraemer", "marliesle", "secret") or die ("Nie mozna podlaczyc"); print ("Podlaczenie udane"); mysql_close ($link); ?>

Patrz rwniez: mysql_connect() i mysql_pconnect().

mysql_connect
Zwraca dodatni identyfikator polaczenia do MySQL, lub False w przypadku bledu. Funkcja mysql_connect() nawiazuje polaczenie z serwerem MySQL. Jezeli nie zostana podane parametry domyslne, przyjmowane sa nastepujace wartosci domyslne: $host:port = 'localhost:3306', $username nazwa uzytkownika, ktry jest wlascicielem procesu i $password pusty ciag. Ciag z nazwa komputera moze zawierac numer portu lub sciezke do gniazda, np.: ":/sciezka/do/gniazda" dla komputera lokalnego.
Uwaga Obsluga ":port" zostala dodana w PHP 3.0B4. Obsluga ":/sciezka/do/gniazda" zostala dodana w PHP 3.0.10. Mozna zapobiec generowaniu komunikatw bledu umieszczajac znak @ przed nazwa funkcji.

Drugie wywolanie mysql_connect() z takimi samymi argumentami nie spowoduje zestawienia nastepnego polaczenia. Zamiast tego zwrcony zostanie identyfikator istniejacego juz polaczenia. Polaczenie z serwerem zostanie zamkniete po zakonczeniu wykonywania skryptu chyba, ze wczesniej zostanie zamkniete za pomoca mysql_close().
resource mysql_connect ([string hostname [:port] [:/path/to/socket] [, string username [, string password]]])

Przyklad: MySQL_connect()
<?php $link = mysql_connect ("kraemer", "marliesle", "secret") or die ("Nie mozna podlaczyc"); print ("Podlaczenie udane"); mysql_close ($link); ?>

Patrz rwniez: mysql_pconnect() i mysql_close().

mysql_create_db
Tworzy nowa baze danych na serwerze wskazywanym przez podany identyfikator lacza.
int mysql_create_db (string database name [, resource link_identifier])

Przyklad: Tworzenie bazy danych MySQL


<?php $link = mysql_pconnect ("kron", "jutta", "geheim") or die ("Nie mozna podlaczyc"); if (mysql_create_db ("my_db")) { print ("Udane utworzenie bazy danych\n"); } else { printf ("Blad tworzenia bazy danych: %s\n", mysql_error ()); } ?>

Aby zachowac zgodnosc z poprzednimi wersjami mozna rwniez uzywac funkcji mysql_createdb(). Patrz rwniez: mysql_drop_db(). Dodatek A - Funkcje

320

mysql_data_seek
Zwraca True w przypadku powodzenia a False w przypadku bledu. Przesuwa wewnetrzny znacznik wiersza w wyniku MySQL skojarzonym z podanym identyfikatorem wyniku zapytania do wiersza o podanym numerze. Kolejne wywolanie funkcji mysql_fetch_row() zwrci ten wiersz. Parametr $row_number przyjmuje wartosci rozpoczynajace sie od 0.
bool mysql_data_seek (resource result_identifier, int row_number)

Przyklad: Przesuwanie wskaznika w wyniku


<?php $link = mysql_pconnect ("kron", "jutta", "geheim") or die ("Nie mozna podlaczyc"); mysql_select_db ("samp_db") or die ("Nie mozna wybrac bazy danych"); $query = "SELECT last_name, first_name FROM friends"; $result = mysql_query ($query) or die ("Zapytanie nieudane"); # Pobieranie wierszy w odwrotnej kolejnosci for ($i = mysql_num_rows ($result) - 1; $i >=0; $i--) { if (!mysql_data_seek ($result, $i)) { echo "Nie moge przejsc do wersza $i\n"; continue; } if(!($row = mysql_fetch_object ($result))) continue; echo ("$row->last_name $row->first_name<BR>\n"; } mysql_free_result ($result); ?>

mysql_db_name
Jako pierwszego parametru wymaga wskaznika wyniku zwracanego przez funkcje mysql_list_dbs(). Parametr $row jest indeksem w wyniku. Jezeli wystapi blad, zwracana jest wartosc False. Aby okreslic rodzaj bledu nalezy uzyc funkcji mysql_errno() i mysql_error().
string mysql_db_name (resource result, int row [, mixed field])

Przyklad: mysql_db_name()
<?php error_reporting(E_ALL); mysql_connect('dbhost', 'username', 'password'); $db_list = mysql_list_dbs(); $i = 0; $cnt = mysql_num_rows($db_list); while ($i < $cnt) { echo mysql_db_name($db_list, $i) . "\n"; $i++; } ?>

Dla zachowania zgodnosci z poprzednimi wersjami mozna rwniez uzywac nazwy jest to jednak zalecane.

mysql_dbname().

Nie

mysql_db_query
Zwraca dodatni identyfikator zapytania MySQL lub False w przypadku wystapienia bledu. Wybiera baze danych i wykonuje na niej zapytanie. Jezeli opcjonalny identyfikator lacza nie zostanie podany, uzyte zostanie ostatnio otwarte lacze. Jezeli nie ma otwartego lacza, funkcja prbuje utworzyc polaczenie identycznie jak robi to funkcja mysql_connect() wywolana bez argumentw. Patrz rwniez: mysql_connect(). Dla zachowania zgodnosci mozna rwniez uzywac nazwy mysql().
resource mysql_db_query (string database, string query [, resource link_identifier])

mysql_drop_db
Zwraca True w przypadku powodzenia operacji a False w przypadku bledu. Funkcja mysql_drop_db() prbuje usunac z serwera cala baze danych skojarzona z podanym identyfikatorem polaczenia. Patrz rwniez: mysql_create_db(). Dla zachowania zgodnosci mozna rwnie uzywac funkcji mysql_dropdb().
bool mysql_drop_db (string database_name [, resource link_identifier])

321

PHP Kompendium wiedzy

mysql_errno
Zwraca numer bledu dla ostatnio wykonanej funkcji MySQL lub 0, jezeli nie wystapil zaden blad. Bledy wysylane przez serwer MySQL nie moga byc traktowane jako ostrzezenia, zamiast tego nalezy pobierac numery bledw za pomoca funkcji mysql_errno().
Uwaga Funkcja zwraca kod bledu dla ostatnio wykonanej funkcji MySQL (opcz mysql_error() i mysql_errno()). Jezeli chcesz jej uzyc, nalezy sprawdzac kod bledu przed wywolaniem kolejnej funkcji MySQL.
int mysql_errno ([resource link_identifier])

Przyklad: mysql_errno()
<?php mysql_connect("marliesle"); echo mysql_errno().": ".mysql_error()."<BR>"; mysql_select_db("nonexistentdb"); echo mysql_errno().": ".mysql_error()."<BR>"; $conn = mysql_query("SELECT * FROM nonexistenttable"); echo mysql_errno().": ".mysql_error()."<BR>"; ?>

Patrz rwniez: mysql_error().

mysql_error
Zwraca komunikat bledu dla ostatnio wykonanej funkcji MySQL lub 0, jezeli nie wystapil zaden blad. Bledy wysylane przez serwer MySQL nie moga byc traktowane jako ostrzezenia, zamiast tego nalezy pobierac komunikaty bledw za pomoca funkcji mysql_error().
Uwaga

Funkcja zwraca kod bledu dla ostatnio wykonanej funkcji MySQL (opcz mysql_error() i mysql_errno()). Jezeli chcesz jej uzyc, nalezy sprawdzac kod bledu przed wywolaniem kolejnej funkcji MySQL.
string mysql_error ([resource link_identifier])

Przyklad: mysql_errno()
<?php mysql_connect("marliesle"); echo mysql_errno().": ".mysql_error()."<BR>"; mysql_select_db("nonexistentdb"); echo mysql_errno().": ".mysql_error()."<BR>"; $conn = mysql_query("SELECT * FROM nonexistenttable"); echo mysql_errno().": ".mysql_error()."<BR>"; ?>

Patrz rwniez: mysql_errno().

mysql_fetch_array
Zwraca tablice odpowiadajaca pobranemu wierszowi, lub False jezeli nie ma juz wierszy do pobrania. Funkcja mysql_fetch_array() jest rozszerzeniem funkcji mysql_fetch_row(). Oprcz zapamietywania danych pod indeksami numerycznymi, dodatkowo dane sa zapisywane pod indeksami asocjacyjnymi, uzywajac nazw pl jako kluczy. Jezeli dwie lub wiecej pl w wyniku ma takie same nazwy, zwrcona zostanie wartosc ostatniego z nich. Aby odczytac wartosci kolumn o tych samych nazwach nalezy korzystac z indeksw numerycznych lub stworzyc aliasy dla kolumn.
array mysql_fetch_array (resource result [, int result_type])

Nalezy przypomniec, ze funkcja mysql_fetch_array() NIE jest wyraznie wolniejsza od funkcji mysql_fetch_row(), jedynie dostarcza wiecej wynikw. Opcjonalny drugi argument, $result_type moze byc jedna ze stalych: MYSQL_ASSOC, MYSQL_NUM i MYSQL_BOTH (parametr ostal dodany w PHP 3.0.7). Patrz rwniez: mysql_fetch_row() i mysql_fetch_assoc(). Przyklad: mysql_fetch_array()
<?php mysql_connect ($host, $user, $password); $result = mysql_db_query ("database","select user_id, fullname from table"); while ($row = mysql_fetch_array ($result)) {

Dodatek A - Funkcje

322

echo echo echo echo

"ID uzytkownika: "ID uzytkownika: "Pelna nazwa : "Pelna nazwa :

".$row["user_id"]."<br>\n"; ".$row[0]."<br>\n"; ".$row["fullname"]."<br>\n"; ".$row[1]."<br>\n";

} mysql_free_result ($result); ?>

mysql_fetch_assoc
Zwraca tablice asocjacyjna odpowiadajaca biezacemu wierszowi lub False, jezeli nie ma juz wiecej wierszy w wyniku. Funkcja mysql_fetch_assoc() jest odpowiednikiem wywolania funkcji mysql_fetch_array() z parametrem MYSQL_ASSOC. Powoduje to zwrcenie tylko tablicy asocjacyjnej. Jest to sposb w jaki wczesniej dzialala funkcja mysql_fetch_array(). Jezeli dwie lub wiecej pl w wyniku ma takie same nazwy, zwrcona zostanie wartosc ostatniego z nich. Aby odczytac wartosci kolumn o tych samych nazwach nalezy uzyc funkcji mysql_fetch_array() i skorzystac z indeksw numerycznych. Nalezy przypomniec, ze funkcja mysql_fetch_assoc() NIE jest wyraznie wolniejsza od funkcji mysql_fetch_row(), jedynie dostarcza wiecej wynikw. Patrz rwniez: mysql_fetch_row() i mysql_fetch_array().
array mysql_fetch_assoc (resource result)

Przyklad: mysql_fetch_assoc()
<?php mysql_connect ($host, $user, $password); $result = mysql_db_query ("database","select * from table"); while ($row = mysql_fetch_assoc ($result)) { echo $row["user_id"]; echo $row["fullname"]; } mysql_free_result ($result); ?>

mysql_fetch_field
Zwraca obiekt zawierajacy informacje o polu. Funkcja mysql_fetch_field() moze byc uzyta do pobrania danych na temat pl w wyniku. Jezeli nie zostanie podane przesuniecie, odczytywane jest nastepne pole, ktre nie bylo jeszcze odczytane.
object mysql_fetch_field (resource result [, int field_offset])

Wlasciwosci zwracanego obiektu sa nastepujace: name nazwa kolumny table nazwa tabeli do ktrej nalezy kolumna max_length maksymalna dlugosc pola not_null 1 jezeli kolumna nie moze byc pusta primary_key 1 jezeli kolumna jest kluczem glwnym unique_key 1 jezeli kolumna jest kluczem unikalnym multiple_key 1 jezeli kolumna nie jest kluczem unikalnym numeric 1 jezeli kolumna jest numeryczna blob 1 jezeli kolumna jest typu BLOB type typ kolumny unsigned 1 jezeli kolumna jest bez znaku zerofill 1 jezeli kolumna jest wypelniana zerami Przyklad: mysql_fetch_field()
<?php mysql_connect ($host, $user, $password) or die ("Nie mozna podlaczyc"); $result = mysql_db_query ("database", "select * from table") or die ("Zapytanie nieudane"); # pobranie metadanych kolumny $i = 0; while ($i < mysql_num_fields ($result)) { echo "Informacje na temat kolumny: $i:<BR>\n"; $meta = mysql_fetch_field ($result); if (!$meta) { echo "Brak dostepnych danych<BR>\n"; }

323

PHP Kompendium wiedzy

echo "<PRE> blob: $meta->blob max_length: $meta->max_length multiple_key: $meta->multiple_key name: $meta->name not_null: $meta->not_null numeric: $meta->numeric primary_key: $meta->primary_key table: $meta->table type: $meta->type unique_key: $meta->unique_key unsigned: $meta->unsigned zerofill: $meta->zerofill </PRE>"; $i++; } mysql_free_result ($result); ?>

mysql_fetch_lengths
Zwraca tablice zawierajaca dlugosci pl z ostatniego wiersza odczytanego przez funkcje mysql_fetch_row() lub False w przypadku bledu. Funkcja mysql_fetch_lengths() przechowuje dlugosci kazdej kolumny wyniku w ostatnim wierszu zwracanym przez mysql_fetch_row(), mysql_fetch_array() i mysql_fetch_object() w tablicy rozpoczynajacej sie od indeksu 0. Patrz rwniez: mysql_fetch_row().
array mysql_fetch_lengths (resource result)

mysql_fetch_object
Zwraca obiekt z wlasciwosciami odpowiadajacymi polom pobieranego wiersza lub False, jezeli nie ma wiecej wierszy do pobrania. Funkcja mysql_fetch_object() jest podobna do mysql_fetch_array() z jedna rznica zwracany jest obiekt a nie tablica. Oznacza to, ze mozesz odwolywac sie do pl poprzez nazwy a nie poprzez indeks( liczby nie sa prawidlowymi nazwami wlasciwosci). Drugi argument, $result_type w funkcji mysql_fetch_array() jest jedna z nastepujacych stalych: MYSQL_ASSOC, MYSQL_NUM i MYSQL_BOTH. Funkcja jest identyczna wydajnosciowo z mysql_fetch_array() i prawie tak samo szybka jak mysql_fetch_row() rznica jest nieznaczna.
object mysql_fetch_object (resource result [, int result_type])

Przyklad: mysql_fetch_object()
<?php mysql_connect ($host, $user, $password); $result = mysql_db_query ("database", "select * from table"); while ($row = mysql_fetch_object ($result)) { echo $row->user_id; echo $row->fullname; } mysql_free_result ($result); ?>

Patrz rwniez: mysql_fetch_array() i mysql_fetch_row().

mysql_fetch_row
Zwraca tablice odpowiadajaca pobranemu wierszowi, lub False jezeli nie ma juz wierszy do pobrania. Funkcja mysql_fetch_row() pobiera jeden wiersz z wyniku okreslonego przez identyfikator zapytania. Wiersz jest zwracany w postaci tablicy. Kazda kolumna jest zapisywana w osobnym indeksie tablicy, rozpoczynajac od 0. Kolejne wywolanie mysql_fetch_row() powoduje zwracanie kolejnych wierszy z wyniku lub False jezeli nie ma juz wiecej wierszy. Patrz rwniez: mysql_fetch_array(), mysql_fetch_object(), mysql_data_seek() i mysql_result().
array mysql_fetch_row (resource result)

mysql_field_flags
Zwraca atrybuty podanego pola. Atrybuty sa zwracane w jednym ciagu rozdzielone spacjami, wiec mozna je latwo rozdzielic za pomoca funkcji explode(). Zwracane sa nastepujace atrybuty o ile twoja wersja MySQL je Dodatek A - Funkcje 324

wszystkie obsluguje: not_null, primary_key, unique_key, multiple_key, blob, unsigned, zerofill, binary, enum, auto_increment i timestamp. Dla zachowania zgodnosci wstecz mozna uzywac rwniez nazwy mysql_fieldflags().
string mysql_field_flags (resource result, int field_offset)

mysql_field_len
Zwraca dlugosc podanego pola. Dla zachowania zgodnosci wstecz mozna uzywac rwniez nazwy mysql_fieldlen().
int mysql_field_len (resource result, int field_offset)

mysql_field_name
Zwraca nazwe podanego pola. Parametr numerem kolejnym pola.
Uwaga Wartosci $field_index rozpoczynaja sie od 0. Na przyklad, indeks trzeciego pola bedzie 2, czwartego 3 itd.
string mysql_field_name (resource result, int field_index)

$result

jest identyfikatorem zapytania, a

$field_index

jest

Przyklad: mysql_field_name()
// Tabela users sklada sie z trzech pl: // user_id // username // password. $res = mysql_db_query("users", "select * from users", $link); echo mysql_field_name($res, 0) . "\n"; echo mysql_field_name($res, 2);

Wykonanie tego przykladu spowoduje wypisanie nastepujacego wyniku:


user_id password

Dla zachowania zgodnosci wstecz mozna uzywac rwniez nazwy mysql_fieldname().

mysql_field_seek
Przesuwa wskaznik do podanego numeru pola. Jezeli nastepne wywolanie mysql_fetch_field() nie bedzie zawieralo numeru pola, zostanie zwrcone to wlasnie pole. Patrz rwniez: mysql_fetch_field(). Patrz rwniez: mysql_fetch_field().
int mysql_field_seek (resource result, int field_offset)

mysql_field_table
Zwraca nazwe tabeli, z ktrej pochodzi podane pole. Dla zachowania zgodnosci wstecz mozna uzywac rwniez nazwy mysql_fieldtable().
string mysql_field_table (resource result, int field_offset)

mysql_field_type
Funkcja podobna do mysql_field_name(). Argumenty sa identyczne, ale zwracane sa typy pl. Typami tymi moga byc int, real, string, blob i inne opisane w dokumentacji MySQL.
string mysql_field_type (iresource result, int field_offset)

Przyklad: Typy pl MySQL


<?php mysql_connect ("localhost:3306"); mysql_select_db ("wisconsin"); $result = mysql_query ("SELECT * FROM onek"); $fields = mysql_num_fields ($result); $rows = mysql_num_rows ($result); $i = 0;

325

PHP Kompendium wiedzy

$table = mysql_field_table ($result, $i); echo "Tabela '".$table."' ma ".$fields." pl i ".$rows." rekordw <BR>"; echo "Tabela sklada sie z nastepujacych pl: <BR>"; while ($i < $fields) { $type = mysql_field_type ($result, $i); $name = mysql_field_name ($result, $i); $len = mysql_field_len ($result, $i); $flags = mysql_field_flags ($result, $i); echo $type." ".$name." ".$len." ".$flags."<BR>"; $i++; } mysql_close(); ?>

Dla zachowania zgodnosci wstecz mozna uzywac rwniez nazwy mysql_fieldtype().

mysql_free_result
Zwalnia pamiec przydzielona dla $result. Po zakonczeniu wykonywania zadania pamiec jest zwalniana automatycznie. Funkcja ta jest potrzebna tylko wtedy, gdy nie chcemy zuzywac zbyt wiele pamieci w czasie dzialania skryptu. Dla zachowania zgodnosci wstecz mozna uzywac rwniez nazwy mysql_freeresult().
int mysql_free_result (resource result)

mysql_insert_id
Zwraca identyfikator generowany dla kolumn AUTO_INCREMENT przez ostatnie wyrazenie INSERT wykonane na podanym identyfikatorze lacza. Jezeli nie zostanie podany identyfikator lacza, przyjmowane jest ostatnio otwarte lacze. Funkcja mysql_insert_id() zwraca 0 jezeli poprzednie zapytanie nie generowalo wartosci AUTO_INCREMENT. Jezeli chcesz zachowac ta wartosc do pzniejszego uzycia trzeba pamietac, aby wywolac funkcje natychmiast po zapytaniu generujacym wartosc.
Uwaga Wartosc funkcji MySQL LAST_INSERT_ID() zawsze zawiera ostatnio wygenerowana wartosc AUTO_INCREMENT i nie jest ona kasowana pomiedzy zapytaniami.

Funkcja mysql_insert_id() konwertuje typ wartosci zwracanej przez funkcje MySQL API na typ long. Jezeli kolumna AUTO_INCREMENT bedzie miala typ BIGINT, wartosci zwracane przez mysql_insert_id() beda nieprawidlowe. Zamiast tego mozna uzywac wewnetrznej funkcji MySQL LAST_INSERT_ID().
int mysql_insert_id ([resource link_identifier])

mysql_list_dbs
Zwraca znacznik wyniku zawierajacego bazy danych dostepne dla demona mysql. Nalezy uzyc funkcji mysql_tablename() do odczytania tego znacznika wyniku.
Uwaga Funkcja dziala rwniez z funkcjami mysql_fetch_row() lub podobnymi.

Dla zachowania zgodnosci wstecz mozna uzywac rwniez nazwy mysql_listdbs().


resource mysql_list_dbs ([resource link_identifier])

Przyklad: mysql_list_dbs()
$link = mysql_connect('localhost', 'myname', 'secret'); $db_list = mysql_list_dbs($link); while ($row = mysql_fetch_object($db_list)) { echo $row->Database . "\n"; }

Przyklad ten moze dac nastepujace wyniki:


database1 database2 database3 ...

Dodatek A - Funkcje

326

mysql_list_fields
Pobiera dane na temat podanej tabeli. Parametrami sa nazwa bazy danych i nazwa tabeli. Zwracany jest znacznik wyniku, ktry moze byc uzyty w funkcjach mysql_fieldflags(), mysql_fieldlen(), mysql_fieldname() i mysql_fieldtype(). Identyfikator wyniku jest dodatnia liczba calkowita. W przypadku bledu funkcja zwraca -1. Ciag opisujacy blad umieszczany jest w $phperrmsg i jezeli funkcja nie zostala wywolana jako @mysql_list_fields(), ciag ten jest wypisywany na wyjscie. Dla zachowania zgodnosci wstecz mozna uzywac rwniez nazwy mysql_listfields().
resource mysql_list_fields (string database_name, string table_name [, resource link_identifier])

Przyklad: mysql_list_fields()
$link = mysql_connect('localhost', 'myname', 'secret'); $fields = mysql_list_fields("database1", "table1", $link); $columns = mysql_num_fields($fields); for ($i = 0; $i < $columns; $i++) { echo mysql_field_name($fields, $i) . "\n";; }

Przyklad ten moze dac nastepujace wyniki:


field1 fiels2 field3 ...

mysql_list_tables
mysql_db_query().

Pobiera jako argument nazwe bazy danych i zwraca znacznik wyniku podobnie do funkcji Do pobrania wyniku na podstawie znacznika powinna zostac uzyta funkcja mysql_tablename(). Dla zachowania zgodnosci wstecz mozna uzywac rwniez nazwy mysql_listtables().
resource mysql_list_tables (string database [, resource link_identifier])

mysql_num_fields
Zwraca ilosc pl w wyniku. Patrz rwniez: mysql_db_query(), mysql_query(), mysql_fetch_field() i mysql_num_rows(). Dla zachowania zgodnosci wstecz mozna uzywac rwniez nazwy mysql_numfields().
int mysql_num_fields (resource result)

mysql_num_rows
Zwraca ilosc wierszy w wyniku. Funkcja dziala jedynie dla wyrazen SELECT. Aby odczytac ilosc wierszy zwracanych z wyrazen INSERT, UPDATE lub DELETE nalezy uzywac funkcji mysql_affected_rows(). Patrz rwniez: mysql_db_query(), mysql_query() i mysql_fetch_row().Dla zachowania zgodnosci wstecz mozna uzywac rwniez nazwy mysql_numrows().
int mysql_num_rows (resource result)

mysql_pconnect
Zwraca dodatni identyfikator trwalego polaczenia do MySQL, lub False w przypadku bledu. Funkcja nawiazuje polaczenie z serwerem MySQL. Jezeli nie zostana podane parametry domyslne, przyjmowane sa nastepujace wartosci domyslne: $host:port = 'localhost:3306', $username nazwa uzytkownika, ktry jest wlascicielem procesu i $password pusty ciag. Ciag z nazwa komputera moze zawierac numer portu lub sciezke do gniazda, np.: ":/sciezka/do/gniazda" dla komputera lokalnego.
mysql_pconnect() Uwaga Obsluga ":port" zostala dodana w PHP 3.0B4. Obsluga ":/sciezka/do/gniazda" zostala dodana w PHP 3.0.10. Mozna zapobiec generowaniu komunikatw bledu umieszczajac znak @ przed nazwa funkcji.
resource mysql_pconnect ([string hostname [:port] [:/path/to/socket] [, string username [, string password]]])

327

PHP Kompendium wiedzy

Funkcja mysql_pconnect() dziala bardzo podobnie do mysql_connect() z dwiema rznicami. Po pierwsze, w czasie polaczenia zamiast otwierac nowe polaczenie funkcja prbuje znalezc istniejace lacze (trwale). Jezeli zostanie ono znalezione, zostaje zwrcone zamiast nowego polaczenia. Po drugie, polaczenie do serwera MySQL nie jest zamykane po zakonczeniu pracy skryptu. Lacze takie pozostaje otwarte do wykorzystania w przyszlosci (mysql_close() nie zamyka polaczen utworzonych przez mysql_pconnect()). Dlatego ten typ polaczenia nazywany jest trwalym.

mysql_query
Wysyla zapytanie do aktywnej bazy danych skojarzonej z podanym identyfikatorem lacza. Jezeli identyfikator ten nie zostanie podany, uzyte zostanie ostatnio otwarte lacze. Jezeli nie ma otwartego lacza, funkcja prbuje utworzyc polaczenie identycznie jak robi to funkcja mysql_connect() wywolana bez parametrw a nastepnie uzywa lacza do wykonania zapytania.
Uwaga Ciag z zapytaniem nie moze konczyc sie srednikiem.

Funkcja mysql_query() zwraca True (wartosc rzna od zera) jezeli zapytanie udalo sie lub False gdy nie udalo sie. Zwrcenie wartosci True wskazuje tylko, ze zapytanie moze byc wykonane przez serwer. Nie mwi to nic na temat ilosci zmienionych lub zwrconych wierszy. Jest mozliwe wykonanie poprawnego zapytania, ktre nie zwrci zadnych wierszy.
resource mysql_query (string query [, resource link_identifier])

Ponizsze zapytanie jest niepoprawne skladniowo, wiec funkcja mysql_query() zwrci False. Przyklad: mysql_query()
<?php $result = mysql_query ("SELECT * WHERE 1=1") or die ("Nieprawidlowe zapytanie"); ?>

Kolejne zapytanie moze byc niepoprawne, jezeli kolumna my_col nie bedzie istniala w tabeli my_tbl i w takim przypadku mysql_query() zwrci False. Przyklad: mysql_query()
<?php $result = mysql_query ("SELECT my_col FROM my_tbl") or die ("Nieprawidlowe zapytanie"); ?>

Funkcja mysql_query() moze sie rwniez nie udac i zwrcic False, jezeli nie masz wystarczajacych uprawnien do tabel na ktrych operuje zapytanie. Zakladajac, ze zapytanie sie uda, mozna wywolac funkcje mysql_num_rows() aby sprawdzic ile wierszy zwrcilo zapytanie SELECT lub mysql_affected_rows() aby sprawdzic ile wierszy zostalo zmienionych przez wyrazenie DELETE, INSERT, REPLACE lub UPDATE. Dla wyrazen SELECT funkcja mysql_query() zwraca nowy identyfikator wyniku, ktry moze byc przekazany do funkcji mysql_result(). Po zakonczeniu pracy na wyniku mozna zwolnic zasoby z nim zwiazane wywolujac mysql_free_result(). Przydzielona pamiec jest jednak automatycznie zwalniana po zakonczeniu skryptu. Patrz rwniez: mysql_affected_rows(), mysql_db_query(), mysql_free_result(), mysql_result(), mysql_select_db() i mysql_connect().

mysql_result
Zwraca zawartosc komrki w podanym wierszu, numerze i wyniku MySQL. Argument $field moze byc numerem pola, nazwa pola lub nazwa w postaci tabela kropka pole (pole.tabela). Jezeli kolumna otrzymala w zapytaniu alias (select foo as bar from ...), nalezy uzyc aliasu a nie oryginalnej nazwy kolumny. Pracujac na duzych wynikach nalezy rozwazyc uzycie jednej funkcji do wczytania calego wiersza. Poniewaz funkcje te zwracaja zawartosc wielu pl za pomoca jednego wywolania, sa one duzo szybsze od mysql_result(). Podawanie numerw pl zamiast ich nazw powoduje szybsze dzialanie funkcji. Wywolania funkcji mysql_result() nie powinny byc mieszane z wywolaniami innych funkcji operujacych na wyniku. Zalecanymi szybszymi funkcjami sa: mysql_fetch_row(), mysql_fetch_array() i mysql_fetch_object().
mixed mysql_result (resource result, int row [, mixed field])

Dodatek A - Funkcje

328

mysql_select_db
Zwraca True w przypadku powodzenia a False w przypadku bledu. Funkcja mysql_select_db() ustawia na serwerze biezaca aktywna baze danych o podanym identyfikatorze lacza. Jezeli identyfikator ten nie zostanie podany, uzyte zostanie ostatnio otwarte lacze. Jezeli nie ma otwartego lacza, funkcja prbuje utworzyc polaczenie identycznie jak robi to funkcja mysql_connect() a nastepnie uzywa lacza do wybrania bazy danych. Kolejne wywolania mysql_query() wykonywane sa na aktywnej bazie danych. Patrz rwniez: mysql_connect(), mysql_pconnect() i mysql_query(). Dla zgodnosci z poprzednimi wersjami mozna korzystac z nazwy mysql_selectdb().
bool mysql_select_db (string database_name [, resource link_identifier])

mysql_tablename
Na podstawie identyfikatora wyniku zwracanego przez mysql_list_tables() oraz numeru kolejnego pobiera i zwraca nazwe tabeli. Funkcja mysql_numrows() moze byc uzyta do okreslenia ilosci tabel w wyniku.
string mysql_tablename (resource result, int i)

Przyklad: mysql_tablename()
<?php mysql_connect ("localhost:3306"); $result = mysql_list_tables ("wisconsin"); $i = 0; while ($i < mysql_num_rows ($result)) { $tb_names[$i] = mysql_tablename ($result, $i); echo $tb_names[$i] . "<BR>"; $i++; } ?>

natcasesort
Stosuje algorytm sortowania ciagw w sposb w jaki robia to ludzie. Jest on nazwany porzadkowaniem naturalnym. Funkcja natcasesort() jest wersja funkcji natsort(), ktra nie rozrznia wielkosci liter. Rznica pomiedzy sortowaniem naturalnym a zwyklym algorytmem sortowania pokazana jest w przykladzie zastosowania funkcji natsort(). Wiecej informacji na temat tego algorytmu mozna znalezc na stronie http://www.linuxcare.com.au/projects/natsort/. Patrz rwniez: sort(), natsort(), strnatcmp() i strnatcasecmp().
void natcasesort (array array)

natsort
Stosuje algorytm sortowania ciagw w sposb w jaki robia to ludzie. Jest on nazwany porzadkowaniem naturalnym. Rznica pomiedzy sortowaniem naturalnym a zwyklym algorytmem sortowania pokazana jest na ponizszym przykladzie.
void natsort (array array)

Przyklad: natsort()
$array1 = $array2 = array ("img12.png", "img10.png", "img2.png", "img1.png"); sort($array1); echo "Zwykle sortowanie\n"; print_r($array1); natsort($array2); echo "\nSortowanie w porzadku naturalnym\n"; print_r($array2);

Wykonanie tego kodu da nastepujacy wynik:


Zwykle sortowanie Array ( [0] => img1.png [1] => img10.png [2] => img12.png [3] => img2.png ) Sortowanie w porzadku naturalnym Array ( [3] => img1.png [2] => img2.png

329

PHP Kompendium wiedzy

[1] => img10.png [0] => img12.png )

Wiecej informacji mozna znalezc na stronie poswieconej temu algorytmowi, http://www.linuxcare.com.au/projects/natsort/. Patrz rwniez: natcasesort(), strnatcmp() i strnatcasecmp().

next
Zwraca element tablicy znajdujacy sie na nastepnym miejscu wskazywanym przez wewnetrzny wskaznik tablicy lub False, jezeli nie ma juz wiecej elementw. Funkcja next() zachowuje sie podobnie do current(), z jedna rznica. Next() przesuwa wewnetrzny wskaznik tablicy o jeden element dalej. Jezeli przesuniecie wskaznika spowoduje wyjscie wskaznika poza tablice, next() zwraca False. Jezeli tablica zawiera pusty element lub element o wartosci klucza 0, funkcja wrci False po napotkaniu takiego elementu. Aby prawidlowo przegladac tablice, ktre moga zawierac puste elementy lub klucze o wartosci 0, nalezy uzyc funkcji each(). Patrz rwniez: curent(), end(), prev() i reset().
mixed next (array array)

nl2br
Zwraca ciag ze znacznikami <BR> wstawionymi przed wszystkimi znakami nowej linii. Patrz rwniez: htmlspecialchars(), htmlentities() i word_wrap().
string nl2br (string string)

number_format
Zwraca liczbe $number w sformatowanej postaci. Funkcja moze byc wywolana z jednym, dwoma lub czterema parametrami (nie z trzema). Jezeli podany zostal jeden parametr, liczba $number jest formatowana bez czesci ulamkowej, ale z przecinkami pomiedzy kolejnymi grupami tysiecy. Jezeli podane sa dwa parametry, liczba jest formatowana z $decimals cyfr po przecinku, z kropka dziesietna i przecinkami pomiedzy grupami tysiecy. Jezeli sa podane wszystkie cztery parametry, liczba jest z $decimals cyfr po przecinku, ze znakiem $dec_point zamiast kropki dziesietnej i znakiem $thousand_sep zamiast przecinka pomiedzy grupami tysiecy.
string number_format (float number [, int decimals [, string dec_point [, string thousands_sep]]])

ob_end_clean
Usuwa zawartosc bufora wyjsciowego i wylacza buforowanie wyjscia. Patrz rwniez: ob_end_flush().
void ob_end_clean (void)

ob_start()

ob_end_flush
Wysyla zawartosc bufora wyjsciowego (o ile istnieje) na wyjscie i wylacza buforowanie wyjscia. Jezeli chcesz przetworzyc zawartosc bufora musisz uzyc funkcji ob_get_contents() przed ob_end_flush(), poniewaz zawartosc bufora jest usuwana po wywolaniu ob_get_contents(). Patrz rwniez: ob_start(), ob_get_contents() i ob_end_clean().
void ob_end_flush (void)

ob_get_contents
Zwraca zawartosc bufora wyjsciowego lub rwniez: ob_start() i ob_get_length().
string ob_get_contents (void)

False,

jezeli buforowanie wyjscia nie jest aktywne. Patrz

Dodatek A - Funkcje

330

ob_get_length
Zwraca ilosc danych w buforze wyjsciowym lub rwniez: ob_start() i ob_get_contents().
string ob_get_length (void)

False,

jezeli buforowanie wyjscia nie jest aktywne. Patrz

ob_implicit_flush
Wlacza lub wylacza ukryte oprznianie bufora wyjsciowego (jezeli nie podany zostal znacznik $flag, domyslnie wlacza opcje). Ukryte oprznianie bufora powoduje oprznianie bufora po kazdej operacji wyjscia, wiec nie sa potrzebne jawne wywolania funkcji flush(). Wlaczenie ukrytego oprzniania powoduje wylaczenie buforowania wyjscia i zawartosc bufora wyjsciowego jest wysylana tak samo, jak po wywolaniu funkcji ob_end_flush(). Patrz rwniez: flush(), ob_start() i ob_end_flush().
void ob_implicit_flush ([int flag])

ob_start
Wlacza buforowanie wyjscia. Gdy aktywne jest buforowanie wyjscia, ze skryptu nie sa przesylane zadne dane wyjsciowe. Zamiast tego sa one zbierane w wewnetrznym buforze. Zawartosc tego bufora moze byc skopiowana do zmiennej za pomoca ob_get_contents(). Aby wyslac na wyjscie dane zebrane w buforze, nalezy wywolac funkcje ob_end_flush(). Mozna rwniez usunac cala zawartosc bufora za pomoca funkcji ob_end_clean(). Patrz rwniez: ob_get_contents(), ob_end_flush(), ob_end_clean() i ob_implict_flush().
void ob_start ([string output_callback])

OCIBindByName
Laczy zmienna PHP $variable z obszarem zablokowanym $ph_name. To, czy zostanie on uzyty jako wejscie czy jako wyjscie jest okreslane w czasie pracy i wtedy przydzielana jest niezbedna pamiec. Parametr $length okresla maksymalna dlugosc dla polaczenia. Jezeli ustawisz $length na -1, OCIBindByName() do ustawienia dlugosci uzyje biezacego rozmiaru $variable. Jezeli musisz dolaczyc abstrakcyjny typ danych (LOB, ROWID, BFILE), musisz je najpierw zarezerwowac za pomoca funkcji OCINewDescriptor(). Parametr $length nie jest uzywany dla abstrakcyjnych typw danych i powinien byc ustawiony na -1. Parametr $type okresla typ uzywanego deskryptora. Mozliwymi wartosciami sa: OCI_B_FILE (plik binarny), OCI_B_CFILE (plik znakowy), OCI_B_CLOB (znakowy LOB), OCI_B_BLOB (binarny LOB) i OCI_B_ROWID (ROWID).
int OCIBindByName (int stmt, string ph_name, mixed &variable, int length [, int type])

Przyklad: OCIDefineByName
<?php /* przyklad uzycia OCIBindByPos, thies@thieso.net (980221) wstawia trzy rekordy do emp, i uzywa ROWID do zmiany rekordw zaraz p ich wstawieniu */ $conn = OCILogon("scott","tiger"); $stmt = OCIParse($conn,"insert into emp (empno, ename) ". "values (:empno,:ename) ". "returning ROWID into :rid"); $data = array(1111 => "Larry", 2222 => "Bill", 3333 => "Jim"); $rowid = OCINewDescriptor($conn,OCI_D_ROWID); OCIBindByName($stmt,":empno",&$empno,32); OCIBindByName($stmt,":ename",&$ename,32); OCIBindByName($stmt,":rid",&$rowid,-1,OCI_B_ROWID); $update = OCIParse($conn,"update emp set sal = :sal where ROWID = :rid"); OCIBindByName($update,":rid",&$rowid,-1,OCI_B_ROWID); OCIBindByName($update,":sal",&$sal,32); $sal = 10000; while (list($empno,$ename) = each($data)) { OCIExecute($stmt); OCIExecute($update); } $rowid->free(); OCIFreeStatement($update); OCIFreeStatement($stmt); $stmt = OCIParse($conn,"select * from emp where empno in (1111,2222,3333)"); OCIExecute($stmt); while (OCIFetchInto($stmt,&$arr,OCI_ASSOC)) {

331

PHP Kompendium wiedzy

var_dump($arr); } OCIFreeStatement($stmt); /* usuniecie naszych "smieci" t tabeli emp.... */ $stmt = OCIParse($conn,"delete from emp where empno in (1111,2222,3333)"); OCIExecute($stmt); OCIFreeStatement($stmt); OCILogoff($conn); ?>

Jednoczesne uzycie magic-quotes i OciBindByName() jest bardzo niedobrym pomyslem, poniewaz nie jest potrzebne dodawanie apostrofw na zmiennych. Wszystkie apostrofu i cudzyslowy dodane w sposb automatyczny zostana zapisane w bazie, poniewaz funkcja OciBindByName() nie potrafi odrznic apostrofw dodanych automatycznie od tych dodanych z rozmyslem.

OCIColumnIsNULL
Zwraca True, jezeli kolumna $column znajdujaca sie w wyniku z wyrazenia $stmt ma wartosc NULL. Mozna uzyc numerw kolumn (numerowane od 1) lub nazw. Patrz rwniez: OCINumCols(), OCIColumnType() i OCIColumnSize().
int OCIColumnIsNULL (int stmt, mixed column)

OCIColumnName
Zwraca nazwe kolumny odpowiadajaca przekazanemu numerowi kolumny (numerowane od 1).
string OCIColumnName (int stmt, int col)

Przyklad: OCIColumnName()
<?php print "<HTML><PRE>\n"; $conn = OCILogon("scott", "tiger"); $stmt = OCIParse($conn,"select * from emp"); OCIExecute($stmt); print "<TABLE BORDER=\"1\">"; print "<TR>"; print "<TH>Nazwa</TH>"; print "<TH>Typ</TH>"; print "<TH>Dlugosc</TH>"; print "</TR>"; $ncols = OCINumCols($stmt); for ( $i = 1; $i <= $ncols; $i++ ) { $column_name = OCIColumnName($stmt,$i); $column_type = OCIColumnType($stmt,$i); $column_size = OCIColumnSize($stmt,$i); print "<TR>"; print "<TD>$column_name</TD>"; print "<TD>$column_type</TD>"; print "<TD>$column_size</TD>"; print "</TR>"; } OCIFreeStatement($stmt); OCILogoff($conn); print "</PRE>"; print "</HTML>\n"; ?>

OCIColumnSize
Zwraca rozmiar kolumny Oracle. Do parametru $col mozna uzyc numeru kolumny (numerowane od 1) lub nazwy kolumny. Patrz rwniez: OCINumCols(), OCIColumnName() i OCIColumnSize().
int OCIColumnSize (int stmt, mixed column)

Przyklad OCIColumnSize()
<?php print "<HTML><PRE>\n"; $conn = OCILogon("scott", "tiger"); $stmt = OCIParse($conn,"select * from emp"); OCIExecute($stmt); print "<TABLE BORDER=\"1\">"; print "<TR>"; print "<TH>Nazwa</TH>"; print "<TH>Typ</TH>"; print "<TH>Dlugosc</TH>";

Dodatek A - Funkcje

332

print "</TR>"; $ncols = OCINumCols($stmt); for ( $i = 1; $i <= $ncols; $i++ ) { $column_name = OCIColumnName($stmt,$i); $column_type = OCIColumnType($stmt,$i); $column_size = OCIColumnSize($stmt,$i); print "<TR>"; print "<TD>$column_name</TD>"; print "<TD>$column_type</TD>"; print "<TD>$column_size</TD>"; print "</TR>"; } print "</TABLE>"; OCIFreeStatement($stmt); OCILogoff($conn); print "</PRE>"; print "</HTML>\n"; ?>

OCIColumnType
Zwraca typ danych kolumny o podanym numerze Patrz rwniez: OCIColumnSize().
mixed OCIColumnType (int stmt, int col)

OCINumCols(), OCIColumnName()

Przyklad: OCIColumnType()
<?php print "<HTML><PRE>\n"; $conn = OCILogon("scott", "tiger"); $stmt = OCIParse($conn,"select * from emp"); OCIExecute($stmt); print "<TABLE BORDER=\"1\">"; print "<TR>"; print "<TH>Nazwa</TH>"; print "<TH>Typ</TH>"; print "<TH>Dlugosc</TH>"; print "</TR>"; $ncols = OCINumCols($stmt); for ( $i = 1; $i <= $ncols; $i++ ) { $column_name = OCIColumnName($stmt,$i); $column_type = OCIColumnType($stmt,$i); $column_size = OCIColumnSize($stmt,$i); print "<TR>"; print "<TD>$column_name</TD>"; print "<TD>$column_type</TD>"; print "<TD>$column_size</TD>"; print "</TR>"; } OCIFreeStatement($stmt); OCILogoff($conn); print "</PRE>"; print "</HTML>\n"; ?>

OCICommit
Zatwierdza wszystkie zalegle zapytania dla polaczenia do Oracle $connection.
int OCICommit( int connection )

OCIDefineByName
Powoduje przeslanie zawartosci kolumn SQL do zmiennych PHP. Nalezy pamietac, ze Oracle zapisuje nazwy kolumn zawsze wielkimi literami a wyrazenia SELECT najczesciej piszemy malymi literami. Funkcja OCIDefineByName() oczekuje, ze $column-name bedzie zapisana wielkimi literami. Jezeli zdefiniujesz zmienna nie istniejaca w wyrazeniu SELECT, nie zostanie wygenerowany zaden bled. Jezeli musisz zdefiniowac abstrakcyjny typ danych (LOB, ROWID, BFILE) musisz najpierw uzyc funkcji OCINewDescriptor(). Patrz rwniez: OCIBindByName().
int OCIDefineByName (int stmt, string Column-Name, mixed variable [, int type])

Przyklad: OCIDefineByName()
<?php /* przyklad uzycia OCIDefineByPos, thies@thieso.net (980219) */

333

PHP Kompendium wiedzy

$conn = OCILogon("scott","tiger"); $stmt = OCIParse($conn,"select empno, ename from emp"); /* ta definicja MUSI znajdowac sie przed ociexecute! */ OCIDefineByName($stmt,"EMPNO",$empno); OCIDefineByName($stmt,"ENAME",$ename); OCIExecute($stmt); while (OCIFetch($stmt)) { echo "empno:".$empno."\n"; echo "ename:".$ename."\n"; } OCIFreeStatement($stmt); OCILogoff($conn); ?>

OCIError
Zwraca ostatni napotkany blad. Jezeli nie podany zostanie parametr opcjonalny $stmt|conn|global, zwracany jest ostatni blad, Jezeli nie napotkano bledu, OCIEror() zwraca False. Funkcja zwraca blad w tablicy asocjacyjnej. W tablicy $code zawiera numer bledu Oracle, natomiast $message, komunikat bledu.
array OCIError ([int stmt|conn|global])

OCIExecute
Wykonuje zanalizowane wyrazenie (OCIParse()). Opcjonalny parametr $mode pozwala okreslic tryb wykonania (domyslnie jest to OCI_COMMIT_ON_SUCCESS). Jezeli nie chcesz aby wyrazenia byly automatycznie zatwierdzane, nalezy zastosowac tryb OCI_DEFAULT.
int OCIExecute (int statement [, int mode])

OCIFetch
Pobiera kolejny wiersz (dla wyrazen SELECT) do wewnetrznego bufora wyniku.
int OCIFetch (int statement)

OCIFetchInto
Pobiera kolejny wiersz (dla wyrazen SELECT) do tabeli $result. Funkcja OCIFetchInto() nadpisuje poprzednia zawartosc tablicy $result. Domyslnie $result zawiera tablice (numerowana od 1) wszystkich kolumn majacych wartosci inne niz NULL. Parametr $mode pozwala zmienic domyslny tryb pracy. Mozna podac wiecej niz jeden znacznik dodajac wartosci, na przyklad: OCI_ASSOC+OCIRETURN_NULLS.
int OCIFetchInto (int stmt, array &result [, int mode])

Mozliwymi wartosciami znacznika sa: OCI_ASSOC zwraca tablic asocjacyjna OCI_NUM zwraca tablice o indeksach numerycznych rozpoczynajacych sie od 1 (domyslnie) OCI_RETURN_NULLS zwraca puste kolumny OCI_RETURN_LOBS zwraca wartosci LOB zamiast deskryptorw

OCIFetchStatement
Pobiera
OCIFetchStatement()

wszystkie wiersze wyniku do tablicy zwraca ilosc pobranych wierszy.

zdefiniowanej

przez

uzytkownika.

Funkcja

int OCIFetchStatement (int stmt, array &variable)

Przyklad: OCIFetchStatement()
<?php /* przyklad OCIFetchStatement, mbritton@verinet.com (990624) */ $conn = OCILogon("scott","tiger"); $stmt = OCIParse($conn,"select * from emp"); OCIExecute($stmt); $nrows = OCIFetchStatement($stmt,$results); if ( $nrows > 0 ) { print "<TABLE BORDER=\"1\">\n"; print "<TR>\n"; while ( list( $key, $val ) = each( $results ) ) {

Dodatek A - Funkcje

334

print "<TH>$key</TH>\n"; } print "</TR>\n"; for ( $i = 0; $i < $nrows; $i++ ) { reset($results); print "<TR>\n"; while ( $column = each($results) ) { $data = $column['value']; print "<TD>$data[$i]</TD>\n"; } print "</TR>\n"; } print "</TABLE>\n"; } else { echo "Brak danych<BR>\n"; } print "Wybano $nrows rekordw<BR>\n"; OCIFreeStatement($stmt); OCILogoff($conn); ?>

OCIFreeCursor
Zwraca True, jezeli funkcja sie udala lub False, jezeli sie nie udala.
int OCIFreeCursor (int stmt)

OCIFreeDesc
Zwraca True, jezeli funkcja sie udala lub False, jezeli sie nie udala.
int OCIFreeDesc (object lob)

OCIFreeStatement
Zwraca True, jezeli funkcja sie udala lub False, jezeli sie nie udala.
int OCIFreeStatement (int stmt)

OCIInternalDebug
Wlacza wyjscie wewnetrznego debugera. Nalezy ustawic parametr debugera, 1 aby je wlaczyc.
void OCIInternalDebug (int onoff)

$onoff

na 0 aby wylaczyc wyjscie

OCILogOff
Zamyka polaczenie do Oracle.
int OCILogOff (int connection)

OCILogon
Zwraca identyfikator polaczenia niezbedny we wiekszosci funkcji OCI. Opcjonalny trzeci parametr moze zawierac nazwe lokalnej instancji Oracle, do ktrej funkcja ma sie przylaczyc lub nazwe wpisu w pliku tnsnames.ora. Jezeli nie zostanie podany trzeci parametr, PHP uzywa zmiennej srodowiskowej ORACLE_SID (instancja Oracle) lub TWO_TASK (tnsnames.ora) do okreslenia bazy danych do ktrej ma sie przylaczyc. Uzywajac funkcji OCILogon() polaczenia sa wspldzielone na poziomie strony. Oznacza to, ze operacje CONNECT i ROLLBACK dzialaja dla wszystkich otwartych transakcji nawet, jezeli skrypt tworzy wiele polaczen. Ponizszy przyklad pokazuje sposb wspldzielenia polaczen.
int OCILogon (string username, string password [, string db])

Przyklad: OCILogon()
<?php print $db = $c1 = $c2 = "<HTML><PRE>"; ""; ocilogon("scott","tiger",$db); ocilogon("scott","tiger",$db);

335

PHP Kompendium wiedzy

function create_table($conn) { $stmt = ociparse($conn,"create table scott.hallo (test varchar2(64))"); ociexecute($stmt); echo $conn." tabela utworzona\n\n"; } function drop_table($conn) { $stmt = ociparse($conn,"drop table scott.hallo"); ociexecute($stmt); echo $conn." tabela usunieta\n\n"; } function insert_data($conn) { $stmt = ociparse($conn,"insert into scott.hallo values('$conn' || ' ' || to_char(sysdate,'DD-MON-YY HH24:MI:SS'))"); ociexecute($stmt,OCI_DEFAULT); echo $conn." wstawione dane przykladowe\n\n"; } function delete_data($conn) { $stmt = ociparse($conn,"delete from scott.hallo"); ociexecute($stmt,OCI_DEFAULT); echo $conn." usuniete dane przykladowe\n\n"; } function commit($conn) { ocicommit($conn); echo $conn." zatwierdzone\n\n"; } function rollback($conn) { ocirollback($conn); echo $conn." wycofane\n\n"; } function select_data($conn) { $stmt = ociparse($conn,"select * from scott.hallo"); ociexecute($stmt,OCI_DEFAULT); echo $conn."----wybieranie\n\n"; while (ocifetch($stmt)) echo $conn." <".ociresult($stmt,"TEST").">\n\n"; echo $conn."----gotowe\n\n"; } create_table($c1); insert_data($c1); // Wstawienie wiersza za pomoca c1 insert_data($c2); // Wstawienie wiersza za pomoca c2 select_data($c1); // Zwracamy wynik obu wyrazen INSERT select_data($c2); rollback($c1); // wycofanie przy uzyciu c1 select_data($c1); // Oba inserty ostaly wycofane select_data($c2); insert_data($c2); // Wstawienie wiersza za pomoca c2 commit($c2); // zatwierdzanie za pmoca c2 select_data($c1); // zwrcony jest wynik inserta na c2 delete_data($c1); // usuniecie wszystkich wierszy w tabeli za pomoca c1 select_data($c1); // brak wierszy select_data($c2); // brak wierszy commit($c1); // zatwierdzenie na c1 select_data($c1); // brak wierszy select_data($c2); // brak wierszy drop_table($c1); print "</PRE></HTML>"; ?>

Patrz rwniez: OCIPLogon() i OCINLogon().

OCINewCursor
Przydziela nowy uchwyt wyrazenia do podanego polaczenia.
int OCINewCursor (int conn)

Przyklad: Uzycie kursora REF z procedury przechowywanej


<?php // zakladamy, ze procedura przechowywana info.output zwraca kursor ref w :data $conn = OCILogon("scott","tiger"); $curs = OCINewCursor($conn); $stmt = OCIParse($conn,"begin info.output(:data); end;"); ocibindbyname($stmt,"data",&$curs,-1,OCI_B_CURSOR); ociexecute($stmt); ociexecute($curs); while (OCIFetchInto($curs,&$data)) { var_dump($data); } OCIFreeStatement($stmt); OCIFreeCursor($curs); OCILogoff($conn);

Dodatek A - Funkcje

336

?>

Przyklad: Uzycie kursora REF z wyrazenia SELECT


<?php print "<HTML><BODY>"; $conn = OCILogon("scott","tiger"); $count_cursor = "CURSOR(select count(empno) num_emps from emp " . "where emp.deptno = dept.deptno) as EMPCNT from dept"; $stmt = OCIParse($conn,"select deptno,dname,$count_cursor"); ociexecute($stmt); print "<TABLE BORDER=\"1\">"; print "<TR>"; print "<TH>NAZWA WYDZIALU</TH>"; print "<TH>NR #</TH>"; print "<TH># PRACOWNIKW</TH>"; print "</TR>"; while (OCIFetchInto($stmt,&$data,OCI_ASSOC)) { print "<TR>"; $dname = $data["DNAME"]; $deptno = $data["DEPTNO"]; print "<TD>$dname</TD>"; print "<TD>$deptno</TD>"; ociexecute($data[ "EMPCNT" ]); while (OCIFetchInto($data[ "EMPCNT" ],&$subdata,OCI_ASSOC)) { $num_emps = $subdata["NUM_EMPS"]; print "<TD>$num_emps</TD>"; } print "</TR>"; } print "</TABLE>"; print "</BODY></HTML>"; OCIFreeStatement($stmt); OCILogoff($conn); ?>

OCINewDescriptor
Przydziela pamiec do przechowywania deskryptorw lub lokalizatorw LOB. Prawidlowymi wartosciami $type sa: OCI_D_FILE, OCI_D_LOB i OCI_D_ROWID. Dla deskryptorw LOB z deskryptorami zwiazane sa metody load, save i savefile. Dla BFILE istnieje tylko metoda load. Przyjrzyj sie uwagom z komentarzy w drugim przykladzie.
string OCINewDescriptor (int connection [, int type])

Przyklad: OCINewDescriptor()
<?php /* Skrypt ten jest zaprojektowany do wywolywania z formularza HTML. * Wymaga przekazania zmiennych$user, $password, $table, $where i * $commitsize z formularza. Skrypt usuwa wybrae wiersze * korzystajac z ROWID i zatwierdza operacje po * $commitsize wierszy. (uzywac rozwaznie, brak mozliwosci wycofania) */ $conn = OCILogon($user, $password); $stmt = OCIParse($conn,"select rowid from $table $where"); $rowid = OCINewDescriptor($conn,OCI_D_ROWID); OCIDefineByName($stmt,"ROWID",&$rowid); OCIExecute($stmt); while ( OCIFetch($stmt) ) { $nrows = OCIRowCount($stmt); $delete = OCIParse($conn,"delete from $table where ROWID = :rid"); OCIBindByName($delete,":rid",&$rowid,-1,OCI_B_ROWID); OCIExecute($delete); print "$nrows\n"; if ( ($nrows % $commitsize) == 0 ) { OCICommit($conn); } } $nrows = OCIRowCount($stmt); print "usunieto $nrows .\n"; OCIFreeStatement($stmt); OCILogoff($conn); ?>

<?php /* * * *

Skrypt pokazuje sposb ladowania plikw do kolumn LOB Formularz uzywany w tym przykladzie jes nastepujacy <form action="upload.php3" method="post" enctype="multipart/form-data"> <input type="file" name="lob_upload">

337

PHP Kompendium wiedzy

* ... */ if(!isset($lob_upload) || $lob_upload == 'none'){ ?> <form action="upload.php3" method="post" enctype="multipart/form-data"> Przeslij plik: <input type="file" name="lob_upload"><br> <input type="submit" value="Wyslij"> - <input type="reset"> </form> <?php } else { // $lob_upload zawieera nazwe pliku tymczasowego przeslanego pliku $conn = OCILogon($user, $password); $lob = OCINewDescriptor($conn, OCI_D_LOB); $stmt = OCIParse($conn,"insert into $table (id, the_blob) values(my_seq.NEXTVAL, EMPTY_BLOB()) returning the_blob into :the_blob"); OCIBindByName($stmt, ':the_blob', &$lob, -1, OCI_B_BLOB); OCIExecute($stmt, OCI_DEFAULT); if($lob->savefile($lob_upload)){ OCICommit($conn); echo "Udane przeslanie BLOB-a \n"; }else{ echo "Nieudane przeslanie BLOB-a \n"; } OCIFreeDesc($lob); OCIFreeStatement($stmt); OCILogoff($conn); } ?>

OCINLogon
Zwraca identyfikator nowego polaczenia do bazy Oracle 8 i loguje sie do bazy. Opcjonalny trzeci parametr moze zawierac nazwe lokalnej instancji Oracle, do ktrej funkcja ma sie przylaczyc lub nazwe wpisu w pliku tnsnames.ora. Jezeli nie zostanie podany trzeci parametr, PHP uzywa zmiennej srodowiskowej ORACLE_SID (instancja Oracle) lub TWO_TASK (tnsnames.ora) do okreslenia bazy danych do ktrej ma sie przylaczyc. Funkcja OCINLogon() wymusza powstanie nowego polaczenia. Powinno byc to uzywane jedynie wtedy, gdy musisz odizolowac transakcje. Domyslnie polaczenia sa wspldzielone na poziomie strony, jezeli uzywa sie funkcji OCILogon() lub na poziomie serwera WWW, jezeli uzywa sie funkcji OCIPLogon(). Jezeli posiadasz kilka polaczen otwartych za pomoca OCINLogon() wszystkie operacje CONNECT i ROLLBACK dzialaja tylko dla podanego polaczenia. Ponizszy przyklad pokazuje sposb separowania polaczen. Patrz rwniez: OCILogon() i OCIPLogon().
int OCINLogon (string username, string password [, string db])

Przyklad: OCINLogon()
<?php print "<HTML><PRE>"; $db = ""; $c1 = ocilogon("scott","tiger",$db); $c2 = ocinlogon("scott","tiger",$db); function create_table($conn) { $stmt = ociparse($conn,"create table scott.hallo (test varchar2(64))"); ociexecute($stmt); echo $conn." tabela utworzona\n\n"; } function drop_table($conn) { $stmt = ociparse($conn,"drop table scott.hallo"); ociexecute($stmt); echo $conn." tabela usunieta\n\n"; } function insert_data($conn) { $stmt = ociparse($conn,"insert into scott.hallo values('$conn' || ' ' || to_char(sysdate,'DD-MON-YY HH24:MI:SS'))"); ociexecute($stmt,OCI_DEFAULT); echo $conn." wstawione dane przykladowe\n\n"; } function delete_data($conn) { $stmt = ociparse($conn,"delete from scott.hallo"); ociexecute($stmt,OCI_DEFAULT); echo $conn." usuniete dane przykladowe\n\n"; } function commit($conn) { ocicommit($conn); echo $conn." zatwierdzone\n\n"; }

Dodatek A - Funkcje

338

function rollback($conn) { ocirollback($conn); echo $conn." wycofane\n\n"; } function select_data($conn) { $stmt = ociparse($conn,"select * from scott.hallo"); ociexecute($stmt,OCI_DEFAULT); echo $conn."----wybieranie\n\n"; while (ocifetch($stmt)) echo $conn." <".ociresult($stmt,"TEST").">\n\n"; echo $conn."----gotowe\n\n"; } create_table($c1); insert_data($c1); select_data($c1); select_data($c2); rollback($c1); select_data($c1); select_data($c2); insert_data($c2); commit($c2); select_data($c1); delete_data($c1); select_data($c1); select_data($c2); commit($c1); select_data($c1); select_data($c2); drop_table($c1); print "</PRE></HTML>"; ?>

OCINumCols
Zwraca ilosc kolumn w wyrazeniu.
int OCINumCols (int stmt)

Przyklad: OCINumCols()
<?php print "<HTML><PRE>\n"; $conn = OCILogon("scott", "tiger"); $stmt = OCIParse($conn,"select * from emp"); OCIExecute($stmt); while ( OCIFetch($stmt) ) { print "\n"; $ncols = OCINumCols($stmt); for ( $i = 1; $i <= $ncols; $i++ ) { $column_name = OCIColumnName($stmt,$i); $column_value = OCIResult($stmt,$i); print $column_name . ': ' . $column_value . "\n"; } print "\n"; } OCIFreeStatement($stmt); OCILogoff($conn); print "</PRE>"; print "</HTML>\n"; ?>

OCIParse
Analizuje zapytanie $query korzystajac z polaczenia $conn. Zwraca identyfikator wyrazenia, jezeli zapytanie jest prawidlowe lub False, jezeli nie jest. Parametr $query moze zawierac dowolne prawidlowe zapytanie SQL.
int OCIParse (int conn, string query)

OCIPLogon
Zwraca identyfikator trwalego polaczenia do serwera Oracle 8 i loguje sie do bazy. Opcjonalny trzeci parametr moze zawierac nazwe lokalnej instancji Oracle, do ktrej funkcja ma sie przylaczyc lub nazwe wpisu w pliku tnsnames.ora. Jezeli nie zostanie podany trzeci parametr, PHP uzywa zmiennej srodowiskowej ORACLE_SID 339 PHP Kompendium wiedzy

(instancja Oracle) lub TWO_TASK (tnsnames.ora) do okreslenia bazy danych do ktrej ma sie przylaczyc. Patrz rwniez: OCILogon() i OCINLogon().
int OCIPLogon (string username, string password [, string db])

OCIResult
Zwraca dane z kolumny $column w biezacym wierszu (patrz OCIFetch()). Funkcja wszystko poza typami abstrakcyjnymi (ROWID, LOB, FILE) w postaci ciagw.
mixed OCIResult (int statement, mixed column)

OCIesult()

zwraca

OCIRollback
Wycofuje zmiany wykonane poprzez polaczenie $connection.
int OCIRollback (int connection)

OCIRowCount
Zwraca ilosc wierszy zmienionych przez wyrazenie SQL. Funkcja nie zwraca ilosci wierszy zwracanych przez wyrazenie SELECT.
int OCIRowCount (int statement)

Przyklad: OCIRowCount()
<?php print "<HTML><PRE>"; $conn = OCILogon("scott","tiger"); $stmt = OCIParse($conn,"create table emp2 as select * from emp"); OCIExecute($stmt); print " wstawiono ".OCIRowCount($stmt) . " wierszy.<BR>"; OCIFreeStatement($stmt); $stmt = OCIParse($conn,"delete from emp2"); OCIExecute($stmt); print"usunieto ". OCIRowCount($stmt) . " wierszy.<BR>"; OCICommit($conn); OCIFreeStatement($stmt); $stmt = OCIParse($conn,"drop table emp2"); OCIExecute($stmt); OCIFreeStatement($stmt); OCILogOff($conn); print "</PRE></HTML>"; ?>

OCIServerVersion
string OCIServerVersion (int conn)

Przyklad: OCIServerVersion()
<?php $conn = OCILogon("scott","tiger"); print "Wersja serwera: " . OCIServerVersion($conn); OCILogOff($conn); ?>

OCIStatementType
string OCIStatementType (int stmt)

Funkcja OCIStatementType() zwraca jedna z nastepujacych wartosci:


SELECT INSERT ALTER UNKNOWN UPDATE CREATE BEGIN DELETE DROP DECLARE

Przyklad:
<?php print "<HTML><PRE>"; $conn = OCILogon("scott","tiger"); $sql = "delete from emp where deptno = 10"; $stmt = OCIParse($conn,$sql); if ( OCIStatementType($stmt) == "DELETE" ) { die "Nie mozesz usuwac z tej tabeli<BR>";

Dodatek A - Funkcje

340

} OCILogoff($conn); print "</PRE></HTML>"; ?>

octdec
Zwraca dziesietny odpowiednik liczby semkowej reprezentowanej przez argument $octal_string. Funkcja octdec() konwertuje ciag semkowy na liczbe dziesietna. Najwieksza liczba mozliwa do skonwertowania jest 17777777777 lub dziesietnie 2147483647. Patrz rwniez: decoct().
int octdec( string octal_string )

odbc_autocommit
Funkcja wywolana bez parametru $onoff zwraca stan mechanizmu automatycznego zatwierdzania dla polaczenia $connection_id. Jezeli automatyczne zatwierdzanie jest wlaczone, zwraca True natomiast False, jezeli jest wylaczone lub wystapil blad. Jezeli parametr $onoff ma wartosc True, automatyczne zatwierdzanie jest wlaczane, jezeli ma wartosc False wylaczane. Zwraca True w przypadku sukcesu i False w przypadku bledu. Domyslnie automatyczne zatwierdzanie jest wlaczone dla polaczenia. Wylaczenie automatycznego zatwierdzania jest ekwiwalentem rozpoczecia transakcji. Patrz rwniez: odbc_commit() i odbc_rollback().
int odbc_autocommit (int connection_id [, int OnOff])

odbc_binmode
int odbc_binmode (int result_id, int mode)

(Funkcja ma wplyw na typy SQL ODBC: BINARY, VARBINARY i LONGVARBINARY) ODBC_BINMODE_PASSTHRU Dane BINARY sa przekazywane dalej. ODBC_BINMODE_RETURN Zwraca w takiej postaci jak otrzymal ODBC_BINMODE_CONVERT Konwertuje znaki i konce linii. Gdy dane binarne SQL sa konwertowane do danych znakowych C, kazdy bajt (8 bitw) zrdla jest reprezentowany jako dwa znaki ASCII. Znaki te sa znakami ASCII reprezentujacymi liczbe w postaci szesnastkowej. Na przyklad, liczba binarna 00000001 jest konwertowana na "01" natomiast 11111111 na "FF". Obsluga typu LONGVARBINARY longreadlen Tryb binarny Wynik ODBC_BINMODE_PASSTHRU 0 przelotka ODBC_BINMODE_RETURN 0 przelotka ODBC_BINMODE_CONVERT 0 przelotka ODBC_BINMODE_PASSTHRU 0 przelotka ODBC_BINMODE_PASSTHRU >0 przelotka ODBC_BINMODE_RETURN >0 zwraca w niezmienionej postaci ODBC_BINMODE_CONVERT >0 zwraca jako ciag znakw Jezeli zostanie uzyta funkcja odbc_fetch_into(), przelotka oznacza, ze dla tych kolumn zwracany jest pusty ciag. Jezeli $result_id jest rwny 0, ustawienia te sa wartosciami domyslnymi dla nowych wynikw.
Uwaga Wartoscia domyslna dla longreadlen jest 4096 a tryb binarny ODBC_BINMODE_RETURN. Obsluga kolumn binarnych jest rwniez realizowana przez odbc_longreadlen().

odbc_close
Zamyka polaczenie do serwera bazy danych skojarzonego z podanym identyfikatorem lacza.
Uwaga

341

PHP Kompendium wiedzy

Funkcja ta sie nie uda, jezeli na tym polaczeniu sa otwarte transakcje. W takim przypadku polaczenie pozostanie otwarte.
void odbc_close (int connection_id)

odbc_close_all
Zamyka wszystkie polaczenia do serwera bazy danych.
Uwaga Funkcja ta sie nie uda, jezeli na tym polaczeniu sa otwarte transakcje. W takim przypadku polaczenie pozostanie otwarte.
void odbc_close_all (void)

odbc_columnprivileges
False

Zwraca liste kolumn i uprawnien do nich dla podanej tablicy. Zwraca identyfikator wyniku ODBC lub w przypadku wystapienia bledu.
int odbc_columnprivileges (int connection_id [, string qualifier [, string owner [, string table_name [, string column_name]]]])

Wynik zawiera nastepujace kolumny:


TABLE_QUALIFIER TABLE_OWNER TABLE_NAME GRANTOR GRANTEE PRIVILEGE IS_GRANTABLE

Wynik jest uporzadkowany wedlug TABLE_QUALIFIER, TABLE_OWNER i TABLE_NAME. Argument $column_name pozwala na stosowanie wzorcw przeszukiwania (% zastepuje zero lub wiecej znakw i _ zastepuje jeden znak).

odbc_columns
Tworzy liste kolumn w okreslonym zakresie. Zwraca identyfikator wyniku ODBC lub wystapienia bledu.
int odbc_columns (int connection_id [, string qualifier [, string owner [, string table_name [, string column_name]]]])

False

w przypadku

Wynik sklada sie z nastepujacych kolumn:


TABLE_QUALIFIER COLUMN_NAME PRECISION RADIX TABLE_OWNER DATA_TYPE LENGTH NULLABLE TABLE_NAME TYPE_NAME SCALE REMARKS

Wynik jest uporzadkowany wedlug TABLE_QUALIFIER, TABLE_OWNER i TABLE_NAME. Argument $column_name, $table_name i $column_name pozwalaja na stosowanie wzorcw przeszukiwania (% zastepuje zero lub wiecej znakw i _ zastepuje jeden znak). Patrz rwniez: odbc_columnprivileges().

odbc_commit
Zwraca True w przypadku sukcesu lub False w przypadku bledu. Wszystkie transakcje rozpoczete poprzez $connection_id sa zatwierdzane.
int odbc_commit (int connection_id)

odbc_connect
Zwraca identyfikator polaczenia ODBC lub 0 (False) w przypadku bledu. Identyfikator polaczenia zwracany przez ta funkcje jest wymagany przez inne funkcje ODBC. Mozesz miec jednoczesnie wiele polaczen. Opcjonalny czwarty parametr okresla typ kursora, jaki jest uzywany na tym polaczeniu. Parametr ten nie jest Dodatek A - Funkcje 342

zwykle wymagany, ale moze byc uzyteczny przy obchodzeniu problemw ze sterownikami ODBC. W przypadku niektrych sterownikw ODBC, wykonywanie skomplikowanych procedur przechowywanych moga powodowac blad Cannot open a cursor on a stored procedure that anything other than a single select statement in it. Uzycie SQL_CUR_USE_ODBC moze pomc uniknac bledu. Niektre sterowniki nie obsluguja opcjonalnego parametru $row_number w odbc_fetch_row(). Parametr SQL_CUR_USE_ODBC moze rwniez pomc w tym przypadku.
int odbc_connect (string dsn, string user, string password [, int cursor_type])

Dla parametru $cursor_type zdefiniowane sa nastepujace stale:


SQL_CUR_USE_IF_NEEDED SQL_CUR_USE_ODBC SQL_CUR_USE_DRIVER SQL_CUR_DEFAULT

Dla polaczyc trwalych patrz odbc_pconnect().

odbc_cursor
Zwraca nazwe kursora dla podanego $result_id.
string odbc_cursor (int result_id)

odbc_do
Uruchamia zapytanie na podanym polaczeniu.
int odbc_do (int conn_id, string query)

odbc_exec
Zwraca False w przypadku wystapienia bledu. Zwraca identyfikator wyniku ODBC, jezeli udalo sie poprawnie wykonac wyrazenie SQL. Funkcja odbc_exec() wysyla wyrazenie SQL do serwera bazy danych wskazywanego przez $connection_id. Parametr ten musi byc prawidlowym identyfikatorem zwracanym przez odbc_connect() lub odbc_pconnect(). Patrz rwniez: odbc_prepare() i odbc_execute() dla wielokrotnego wykonania wyrazenia SQL.
int odbc_exec (int connection_id, string query_string)

odbc_execute
Wykonuje zapytanie przygotowanie za pomoca odbc_prepare(). Zwraca True w przypadku udanego wykonania, False w przeciwnym przypadku. Tablica $parameters_array jest potrzebna, jezeli w wyrazeniu SQL wystepuja parametry.
int odbc_execute (int result_id [, array parameters_array])

odbc_fetch_into
Zwraca ilosc kolumn w wyniku lub False w przypadku wystapienia bledu. Tablica $result_array musi byc przekazana przez referencje, ale moze byc to dowolny typ, poniewaz zostanie skonwertowany na typ tablicowy. Tablica zawiera wartosci kolumn pod indeksami rozpoczynajacymi sie od 0.
int odbc_fetch_into (int result_id [, int rownumber, array result_array])

odbc_fetch_row
Jezeli funkcja sie powiedzie (byl wiersz wyniku) zwracana jest wartosc True. Jezeli nie ma juz wierszy, zwracana jest wartosc False. Funkcja pobiera wiersz danych zwrconych przez funkcje odbc_do() lub odbc_exec(). Po wywolaniu odbc_fetch_row() pola z wyniku sa dostepne dla funkcji odbc_result(). Jezeli nie zostanie podany parametr $row_number, funkcja prbuje pobrac kolejny wiersz wyniku. Wywolania funkcji odbc_fetch_row() z parametrem $row_number i bez niego moga byc mieszane. Aby wiecej niz raz odczytac wyniki zapytania, nalezy wywolac odbc_fetch_row() z $row_number rwnym 1 i kontynuowac pobieranie danych za 343 PHP Kompendium wiedzy

pomoca odbc_fetch_row() bez parametru $row_number. Jezeli sterownik nie obsluguje odczytywania wiersza o podanym numerze, parametr ten jest ignorowany.
int odbc_fetch_row (int result_id [, int row_number])

odbc_field_len
Zwraca dlugosc pola wskazywanego przy pomocy numeru w wyniku ODBC o podanym identyfikatorze. Numerowanie pl rozpoczyna sie od 1. Patrz rwniez: odbc_field_scale().
int odbc_field_len (int result_id, int field_number)

odbc_field_name
Zwraca nazwe pola wskazywanego przy pomocy numeru w wyniku ODBC o podanym identyfikatorze. Numerowanie pl rozpoczyna sie od 1. W przypadku wystapienia bledu zwraca False.
string odbc_field_name (int result_id, int field_number)

odbc_field_num
Zwraca numer kolumny o podanej nazwie w wyniku ODBC o podanym identyfikatorze. Numerowanie pl rozpoczyna sie od 1. W przypadku wystapienia bledu zwraca False.
int odbc_field_num (int result_id, string field_name)

odbc_field_precision
Zwraca dokladnosc kolumny o podanym numerze w wyniku ODBC o podanym identyfikatorze. Patrz rwniez: odbc_field_scale().
string odbc_field_precision (int result_id, int field_number)

odbc_field_scale
Zwraca skale kolumny o podanym numerze w wyniku ODBC o podanym identyfikatorze.
string odbc_field_scale (int result_id, int field_number)

odbc_field_type
Zwraca typ SQL pola wskazywanego przy pomocy numeru w wyniku ODBC o podanym identyfikatorze. Numerowanie pl rozpoczyna sie od 1.
string odbc_field_type (int result_id, int field_number)

odbc_foreignkeys
Odczytuje dane na temat kluczy obcych. Zwraca identyfikator wyniku ODBC lub bledu.
int odbc_foreignkeys (int connection_id, string pk_qualifier, string pk_owner, string pk_table, string fk_qualifier, string fk_owner, string fk_table)

False

w przypadku

Wynik sklada sie z nastepujacych kolumn:


PKTABLE_QUALIFIER PKCOLUMN_NAME FKTABLE_NAME UPDATE_RULE PK_NAME PKTABLE_OWNER FKTABLE_QUALIFIER FKCOLUMN_NAME DELETE_RULE PKTABLE_NAME FKTABLE_OWNER KEY_SEQ FK_NAME

Jezeli parametr $pk_table zawiera nazwe tabeli, odbc_foreignkeys() zwraca w wynik zawierajacy klucz glwny i wszystkie klucze obce odwolujace sie do tej tabeli. Jezeli $fk_table zawiera nazwe tabeli, odbc_foreignkeys() zwraca wynik zawierajacy wszystkie klucze obce w podanej tabeli oraz klucze glwne, do ktrych sie odwoluja. Jezeli zarwno $pk_table jak i $fk_table zawieraja nazwy tabel, odbc_foreignkeys() zwraca klucze obce z tabeli okreslonej przez $fk_table odwolujace sie do klucza glwnego z tabeli $pk_table. W wiekszosci przypadkw bedzie to tylko jeden klucz. Dodatek A - Funkcje 344

odbc_free_result
Zawsze zwraca True. Wywolanie tej funkcji jest wymagane jedynie wtedy, gdy skrypt zuzywa zbyt duzo pamieci podczas pracy. Cala pamiec przydzielona do wyniku jest automatycznie zwalniana po zakonczeniu dzialania skryptu. Jezeli jestes pewien, ze nie bedziesz juz uzywal danych z wyniku, mozesz wywolac funkcje odbc_free_result(), aby zwolnic pamiec przydzielona do $result_id.
Uwaga Jezeli automatyczne zatwierdzanie jest zablokowane, (patrz odbc_autocommit()) i wywolasz odbc_free_result() przed zatwierdzeniem, wszystkie otwarte transakcje zostana wycofane.
int odbc_free_result (int result_id)

odbc_gettypeinfo
Pobiera dane na temat typw danych obslugiwanych przez zrdlo danych. Zwraca identyfikator wyniku ODBC lub False w przypadku wystapienia bledu. Mozna uzyc opcjonalnego parametru $data_type do ograniczenia danych do jednego typu.
int odbc_gettypeinfo (int connection_id [, int data_type])

Wynik sklada sie z nastepujacych kolumn:


TYPE_NAME LITERAL_PREFIX NULLABLE UNSIGNED_ATTRIBUTE LOCAL_TYPE_NAME DATA_TYPE LITERAL_SUFFIX CASE_SENSITIVE MONEY MINIMUM_SCALE PRECISION CREATE_PARAMS SEARCHABLE AUTO_INCREMENT MAXIMUM_SCALE

Wynik jest uporzadkowany wedlug DATA_TYPE i TYPE_NAME.

odbc_longreadlen
(Funkcja ma wplyw na typ SQL ODBC LONG i LONGVARBINARY) Ilosc bajtw zwracanych do PHP jest okreslana przez wartosc parametru. Jezeli ma wartosc 0, dane z kolumn long sa przepuszczane do klienta.
Uwaga Obsluga kolumn LONGVARBINARY jest rwniez realizowana przez odbc_binmode().
int odbc_longreadlen (int result_id, int length)

odbc_num_fields
Zwraca ilosc pl (kolumn) w wyniku ODBC. Funkcja zwraca -1 w przypadku wystapienia bledu. Argumentem jest prawidlowy identyfikator wyniku zwracany przez odbc_exec().
int odbc_num_fields (int result_id)

odbc_num_rows
Zwraca ilosc wierszy w wyniku ODBC. W przypadku wystapienia bledu funkcja zwraca -1. Dla wyrazen i DELETE funkcja zwraca ilosc zmienionych wierszy. Dla wyrazen SELECT zwraca ilosc zwracanych wierszy.
INSERT, UPDATE Uwaga Uzycie funkcji odbc_num_rows() do sprawdzenia ilosci wierszy dostepnych po wykonaniu wyrazenia SELECT zwrci dla wielu sterownikw -1.
int odbc_num_rows (int result_id)

345

PHP Kompendium wiedzy

odbc_pconnect
Zwraca identyfikator polaczenia ODBC lub 0 (False) w przypadku wystapienia bledu. Funkcja jest podobna do odbc_connect(), poza tym, ze polaczenie nie jest zamykane po zakonczeniu skryptu. Kolejne zadania polaczenia z ta sama kombinacja $dsn, $user i $password (poprzez odbc_connect() i odbc_pconnect()) powoduja ponowne wykorzystanie polaczenia trwalego.
Uwaga Polaczenia trwale nie dzialaja, jezeli PHP jest uzyty jako program CGI. Opis opcjonalnego parametru $cursor_type znajduje sie przy opisie funkcji odbc_connect(). Wiecej informacji na temat polaczen trwalych znajduje sie w PHP FAQ.
int odbc_pconnect (string dsn, string user, string password [, int cursor_type])

odbc_prepare
Zwraca False w przypadku bledu. Zwraca identyfikator wyniku ODBC dla poprawnie przygotowanego wyrazenia SQL. Wynikowy identyfikator moze byc uzyty do uruchomienia wyrazenia za pomoca odbc_execute().
int odbc_prepare (int connection_id, string query_string)

odbc_primarykeys
Zwraca nazwy kolumn skladajacych sie na klucz glwny tabeli. Zwraca identyfikator wyniku ODBC lub False w przypadku bledu.
int odbc_primarykeys (int connection_id, string qualifier, string owner, string table)

Wynik posiada nastepujace kolumny:


TABLE_QUALIFIER COLUMN_NAME TABLE_OWNER KEY_SEQ TABLE_NAME PK_NAME

odbc_procedurecolumns
Zwraca liste parametrw wejsciowych i wyjsciowych oraz kolumn bedacych wynikiem dzialania procedury. zwraca identyfikator wyniku ODBC lub False w przypadku bledu.
int odbc_procedurecolumns (int connection_id [, string qualifier [, string owner [, string proc [, string column]]]])

Wynik posiada nastepujace kolumny:


PROCEDURE_QUALIFIER COLUMN_NAME TYPE_NAME SCALE REMARKS PROCEDURE_OWNER COLUMN_TYPE PRECISION RADIX PROCEDURE_NAME DATA_TYPE LENGTH NULLABLE PROCEDURE_NAME

Wynik jest posortowany wedlug kolumn znakw i _ zastepuje jeden znak).

PROCEDURE_QUALIFIER,

COLUMN_TYPE.

Argumenty $owner, $proc i $column moga zawierac

wzorzec przeszukiwania (% zastepuje zero lub wiecej

odbc_procedures
Tworzy liste procedur w okreslonym zakresie. Zwraca identyfikator wyniku ODBC lub przypadku bledu.
int odbc_procedures (int connection_id [, string qualifier [, string owner [, string name]]])

False

Wynik zawiera nastepujace kolumny:


PROCEDURE_QUALIFIER NUM_INPUT_PARAMS REMARKS PROCEDURE_OWNER NUM_OUTPUT_PARAMS PROCEDURE_TYPE PROCEDURE_NAME NUM_RESULT_SETS

Argumenty $owner, $proc i $column moga zawierac

wzorzec przeszukiwania (% zastepuje zero lub

wiecej znakw i _ zastepuje jeden znak).

Dodatek A - Funkcje

346

odbc_result
Zwraca zawartosc pola. Parametr zawierajacym nazwe pola. Przyklad:
$item_3 = odbc_result ($Query_ID, 3); $item_val = odbc_result ($Query_ID, "val");

$field

moze byc liczba okreslajaca numer pola lub ciagiem

string odbc_result (int result_id, mixed field)

Pierwsze wywolanie odbc_result() zwraca wartosc trzeciego pola w biezacym rekordzie Drugie wywolanie funkcji odbc_result() zwraca wartosc pola o nazwie val w biezacym rekordzie w wyniku. Blad wystapi, jezeli numer kolumny dla jest mniejsza od jeden lub przekracza ilosc kolumn w biezacym rekordzie. Podobnie blad wystapi, jezeli podana nazwa nie jest nazwa pola znajdujacego sie w wyniku. Numery pl rozpoczynaja sie od 1. W zaleznosci od trybu obslugi kolumn long, zwracane sa dane binarne lub long. Patrz rwniez: odbc_binmode() i odbc_longreadlen().

odbc_result_all
Zwraca ilosc wierszy w wyniku lub False w przypadku bledu. Funkcja odbc_result_all() powoduje wydruk wszystkich wierszy z wyniku tworzonego za pomoca odbc_exec(). Wynikiem funkcji jest tabela HTML. Dodatkowe formatowanie tabeli moze byc realizowane za pomoca opcjonalnego ciagu $format.
int odbc_result_all (int result_id [, string format])

odbc_rollback
Wycofuje transakcje otwarte poprzez polaczenie wykonania operacji lub False w przypadku bledu.
int odbc_rollback (int connection_id)

$connection_id.

Zwraca

True

w przypadku pomyslnego

odbc_setoption
Funkcja pozwala operowac opcjami ODBC dla polaczenia lub wyniku zapytania. Funkcja zostala napisana w celu umozliwienia znalezienia obejscia problemw ze sterownikami ODBC zawierajacymi bledy. Powinienes uzywac tej funkcji jedynie wtedy, gdy jestes programista ODBC i znasz konsekwencje ustawiania rznych opcji. Powinienes rwniez posiadac dobry podrecznik ODBC zawierajacy objasnienie wszystkich opcji i ich wartosci. Rzne wersje sterownikw obsluguja rzne opcje.
int odbc_setoption (int id, int function, int option, int param)

Poniewaz efekty moga bardzo zalezec od sterownika ODBC, uzywanie tej funkcji w skryptach udostepnianych publicznie nie jest zalecane. Niektre opcje ODBC nie sa dostepne dla tej funkcji, poniewaz musza byc ustawiane przed nawiazaniem polaczenia lub przygotowania zapytania. Jednak moze ona pomc w konkretnym przypadku. Parametr $id jest identyfikatorem polaczenia lub identyfikatorem wyniku, na ktrym chcesz zmienic opcje. Dla SQLSetConnectOption() jest to identyfikator polaczenia. Dla SQLSetStmtOption() jest to identyfikator wyniku. Parametr $function jest uzywana funkcja ODBC. Wartoscia moze byc: 1 dla SQLSetConnectOption() i 2 dla SQLSetStmtOption(). Parametr $option jest wartoscia ustawianej opcji. Parametr $param jest wartoscia dla podanej opcji. Przyklad: ODBC SetOption
// 1. Opcje 102 dla SQLSetConnectOption() wynosi SQL_AUTOCOMMIT. // Wartosc 1 dla SQL_AUTOCOMMIT to SQL_AUTOCOMMIT_ON. // Przyklad ten jest analogiczny do wywolania // odbc_autocommit($conn, true); odbc_setoption ($conn, 1, 102, 1); // 2. Opcja 0 dla SQLSetStmtOption() wynosi SQL_QUERY_TIMEOUT. // Przyklad ustawia czas wygasniecia zapytania na 30 sekund. $result = odbc_prepare ($conn, $sql); odbc_setoption ($result, 2, 0, 30); odbc_execute ($result);

347

PHP Kompendium wiedzy

odbc_specialcolumns
Gdy wartoscia parametru $type wynosi SQL_BEST_ROWID, funkcja odbc_specialcolumns() zwraca kolumne lub kolumny, ktre jednoznacznie identyfikuja kazdy wiersz tabeli. Jezeli $typ wynosi SQL_ROWVER, funkcja odbc_specialcolumns() zwraca optymalna kolumne lub zestaw kolumn, ktra po odczytaniu wartosci kolumny lub kolumn pozwala na jednoznaczna identyfikacje wierszy z tablicy. Funkcja zwraca identyfikator wyniku ODBC lub False w przypadku bledu.
int odbc_specialcolumns (int connection_id, int type, string qualifier, string owner, string table, int scope, int nullable)

Wynik zawiera nastepujace kolumny:


SCOPE TYPE_NAME SCALE COLUMN_NAME PRECISION PSEUDO_COLUMN DATA_TYPE LENGTH

Wynik jest uporzadkowany wedlug kolumny SCOPE.

odbc_statistics
Odczytuje statystyki na temat tablicy i indeksw. Zwraca identyfikator wyniku ODBC lub przypadku bledu.
int odbc_statistics (int connection_id, string qualifier, string owner, string table_name, int unique, int accuracy)

False

Wynik zawiera nastepujace kolumny:


TABLE_QUALIFIER NON_UNIQUE TYPE COLLATION FILTER_CONDITION SEQ_IN_INDEX. TABLE_OWNER INDEX_QUALIFIER SEQ_IN_INDEX CARDINALITY TABLE_NAME INDEX_NAME COLUMN_NAME PAGES NON_UNIQUE, TYPE, INDEX_QUALIFIER, INDEX_NAME

Wynik jest uporzadkowany wedlug kolumn:

odbc_tableprivileges
Tworzy liste tabel w zadanym zakresie oraz uprawnien zwiazanych z kazda tabela. Zwraca identyfikator wyniku ODBC lub False w przypadku bledu.
int odbc_tableprivileges (int connection_id [, string qualifier [, string owner [, string name]]])

Wynik zawiera nastepujace kolumny:


TABLE_QUALIFIER GRANTOR IS_GRANTABLE TABLE_OWNER GRANTEE TABLE_NAME PRIVILEGE

Wynik jest uporzadkowany wedlug kolumn: TABLE_QUALIFIER, TABLE_OWNER i TABLE_NAME. Argumenty $owner, $proc i $column moga zawierac wzorzec przeszukiwania (% zastepuje zero lub wiecej znakw i _ zastepuje jeden znak).

odbc_tables
Tworzy liste tabel w zadanym zakresie. Zwraca identyfikator wyniku ODBC lub bledu.
int odbc_tables (int connection_id [, string qualifier [, string owner [, string name [, string types]]]])

False

w przypadku

Wynik zawiera nastepujace kolumny:


TABLE_QUALIFIER TABLE_TYPE TABLE_OWNER REMARKS TABLE_NAME

i TABLE_NAME. Argumenty $owner, $proc i $column moga zawierac wzorzec przeszukiwania (% zastepuje zero lub wiecej znakw i _ zastepuje jeden znak). Aby obsluzyc wyliczanie kwalifikatorw, wlascicieli i typw tabel dostepna jest specjalna skladnia parametrw $qualifier, $owner, $name i $table_type. Jezeli $qualifier zawiera jeden znak procentu (%) natomiast $owner i $name sa pustymi ciagami, wynik zawiera liste kwalifikatorw dla zrdla danych (wszystkie kolumny poza TABLE_QUALIFIER zawieraja wartosci Dodatek A - Funkcje 348

Wynik jest uporzadkowany wedlug:

TABLE_TYPE, TABLE_QUALIFIER, TABLE_OWNER

NULL). Jezeli $owner zawiera znak procentu (%) a $qualifier i $name sa pustymi ciagami, wynik jest lista wlascicieli dla podanego zrdla danych (wszystkie kolumny poza TABLE_OWNER zawieraja wartosci NULL). Jezeli $table_type zawiera znak procentu (%) a $qualifier, $owner i $name sa pustymi ciagami, wynik jest lista typw tabel dla podanego zrdla danych (wszystkie kolumny poza TABLE_TYPE zawieraja wartosci NULL). Jezeli $table_type nie jest pustym ciagiem, musi zawierac liste wartosci rozdzielonych przecinkami interesujacych typw tabel Kazda wartosc moze byc otoczona apostrofami (') lub bez apostrofw, na przyklad: 'TABLE','VIEW' lub TABLE,VIEW. Jezeli zrdlo danych nie obsluguje jakiegos typu tabel, odbc_tables() nie zwraca wynikw dla tego typu. Sposb odczytywania uprawnien opisany jest przy funkcji odbc_tableprivileges().

opendir
Zwraca uchwyt katalogu, ktry jest pzniej uzywany w funkcjach closedir(), readdir() i rewinddir().
resource opendir (string path)

openlog
Otwiera dla programu polaczenie do dziennika systemowego. Ciag $ident jest dodawany do kazdego komunikatu. Wartosci $option i $facility sa wymienione w tabeli ponizej. Argument $option uzywany jest do wskazania, opcji uzywanych przy generowaniu komunikatw. Pozwala to podac (w konfiguracji dziennika systemowego) w jaki sposb sa obslugiwane komunikaty przychodzace z rznych urzadzen. Uzycie funkcji openlog() jest opcjonalne. Jest ona wywolywana w razie potrzeby przez funkcje syslog() i w takim przypadku $ident ma wartosc False.
int openlog (string ident, int option, int facility)

Opis Jezeli wystapil blad przy wysylaniu danych do dziennika systemowego dane sa wypisywane na konsole systemowa. LOG_NDELAY Natychmiast otwiera polaczenie z dziennikiem systemowym. LOG_ODELAY (domyslny) Opznia otwarcie polaczenia do zapisu pierwszego komunikatu. LOG_PERROR Wysyla komunikaty dziennika rwniez na standardowe wyjscie bledw. LOG_PID Dodaje PID do kazdego komunikatu. Mozna korzystac z wiecej niz jednej z tych opcji. Uzywajac kilku opcji do ich laczenia nalezy uzyc operatora OR. Na przyklad, aby uzyskac natychmiastowe otwarcie polaczenia, pisanie na konsole i dodanie PID do kazdego komunikatu nalezy uzyc LOG_CONS | LOG_NDELAY | LOG_PID. Urzadzenia dla openlog() Stala Opis LOG_AUTH Komunikaty systemu bezpieczenstwa (nalezy uzyc LOG_AUTHPRIV w systemach gdzie jest zdefiniowana ta stala). LOG_AUTHPRIV Komunikaty systemu bezpieczenstwa (prywatne). LOG_CRON Demony zegara (cron i at). LOG_DAEMON Inne demony systemowe. LOG_KERN Komunikaty jadra. LOG_LOCAL0 ... Zarezerwowane.
LOG_CONS LOG_LOCAL7 LOG_LPR LOG_MAIL LOG_NEWS LOG_SYSLOG LOG_USER LOG_UUCP

Opcje openlog() Stala

Podsystem drukarki. Podsystem poczty. Podsystem USENET. Komunikaty generowane przez syslogd. Komunikaty generowane przez programy uzytkownika. Podsystem UUCP. PHP Kompendium wiedzy

349

Patrz rwniez: define_syslog_variables(), syslog() i closelog().

Ora_Bind
Zwraca True jezeli wiazanie udalo sie lub False w przeciwnym przypadku. Szczegly na temat bledu moga byc pobrane za pomoca funkcji ora_error() i ora_errorcode(). Funkcja ta wiaze nazwe zmiennej PHP z parametrem SQL. Parametr SQL musi miec postac :nazwa. Za pomoca opcjonalnego parametru $type mozna zdefiniowac, czy parametr ma byc wyjsciowy i wejsciowy (0 domyslnie), wejsciowy (10) lub wyjsciowy (2). Od wersji PHP 3.0.1 mozna korzystac ze stalych ORA_BIND_INOUT, ORA_BIND_IN i ORA_BIND_OUT zamiast liczb. Funkcja ora_bind() musi byc wywolana po ora_parse() i przed ora_exec(). Wartosci wejsciowe moga byc przekazywane poprzez przypisanie do zwiazanych zmiennych PHP. Po wywolaniu ora_exec(), wartosci wyjsciowe, jezeli sa dostepne, sa dostepne w odpowiednich zwiazanych zmiennych.
int ora_bind (int cursor, string PHP variable name, string SQL parameter name, int length [, int type])

Przyklad: ora_bind()
<?php ora_parse($curs, "declare tmp INTEGER; begin tmp := :in; :out := tmp; :x := 7.77; end;"); ora_bind($curs, "result", ":x", $len, 2); ora_bind($curs, "input", ":in", 5, 1); ora_bind($curs, "output", ":out", 5, 2); $input = 765; ora_exec($curs); echo "Wynik: $result<BR>Wyjscie: $output<BR>Wejscie: $input"; ?>

Ora_Close
Zwraca True jezeli udalo sie zamkniecie, False w przeciwnym wypadku. Szczegly na temat bledu moga byc pobrane za pomoca funkcji ora_error() i ora_errorcode(). Funkcja zamyka kursor otwarty za pomoca ora_open().
int ora_close (int cursor)

Ora_ColumnName
Zwraca nazwe kolumny (pola) numer $column z kursora $cursor. Zwracana nazwa zapisana jest wielkimi literami.
string Ora_ColumnName (int cursor, int column)

Ora_ColumnSize
Zwraca rozmiar kolumny (pola) numer $column z kursora $cursor.
int Ora_ColumnSize (int cursor, int column)

Ora_ColumnType
Zwraca typ Oracle kolumny (pola) numer $column z kursora $cursor.
string Ora_ColumnType (int cursor, int column)

Zwracany typ moze byc jedna z ponizszych wartosci:


VARCHAR2 VARCHAR CHAR NUMBER LONG LONG RAW ROWID DATE CURSOR

Dodatek A - Funkcje

350

Ora_Commit
Zwraca True w przypadku powodzenia operacji lub False w przypadku wystapienia bledu. Szczegly na temat bledu moga byc pobrane za pomoca funkcji ora_error() i ora_errorcode(). Funkcja zatwierdza transakcje Oracle. Transakcja jest definiowana jako wszystkie zmiany wykonane poprzez polaczenie od czasu ostatniej operacji COMMIT lub ROLLBACK, wylaczenia automatycznego zatwierdzania lub nawiazania polaczenia.
int ora_commit (int conn)

Ora_CommitOff
Zwraca True w przypadku powodzenia operacji lub False w przypadku wystapienia bledu. Szczegly na temat bledu moga byc pobrane za pomoca funkcji ora_error() i ora_errorcode(). Funkcja wylacza automatyczne zatwierdzanie operacji po kazdej funkcji ora_exec().
int ora_commitoff (int conn)

Ora_CommitOn
Funkcja wlacza automatyczne zatwierdzanie operacji po kazdej funkcji ora_exec() na podanym polaczeniu. Zwraca True w przypadku powodzenia operacji lub False w przypadku wystapienia bledu. Szczegly na temat bledu moga byc pobrane za pomoca funkcji ora_error() i ora_errorcode().
int ora_commiton (int conn)

Ora_Do
Funkcja ta jest kombinacja funkcji ora_parse(), ora_exec() i ora_fetch(). Analizuje, wykonuje wyrazenie oraz pobiera pierwszy wiersz. Zwraca True w przypadku powodzenia operacji lub False w przypadku wystapienia bledu. Szczegly na temat bledu moga byc pobrane za pomoca funkcji ora_error() i ora_errorcode(). Patrz rwniez: ora_parse(), ora_exec() i ora_fetch().
int ora_do (int conn, string query)

Ora_Error
Zwraca komunikat bledu w postaci XXX-NNNNN, gdzie XXX jest zrdlem bledu a NNNNN okresla komunikat bledu.
Uwaga Obsluge identyfikatorw polaczenia zostala dodana w PHP 3.0.4.
string Ora_Error (int cursor_or_connection)

Na Oracle dla systemw Unix mozna znalezc komunikaty bledw podobne do nastepujacych:
$ oerr ora 00001 00001, 00000, "unique constraint (%s.%s) violated" // *Cause: An update or insert statement attempted to insert a duplicate key // For Trusted ORACLE configured in DBMS MAC mode, you may see // this message if a duplicate entry exists at a different level. // *Action: Either remove the unique restriction or do not insert the key

Ora_ErrorCode
Zwraca numeryczny kod bledu ostatniej wykonywanego wyrazenia na okreslonym kursorze lub polaczeniu.
Uwaga Obsluge identyfikatorw polaczenia zostala dodana w PHP 3.0.4.
int Ora_ErrorCode (int cursor_or_connection)

351

PHP Kompendium wiedzy

Ora_Exec
Zwraca True w przypadku powodzenia operacji lub False w przypadku wystapienia bledu. Szczegly na temat bledu moga byc pobrane za pomoca funkcji ora_error() i ora_errorcode(). Patrz rwniez: ora_parse(), ora_fetch() i ora_do().
int ora_exec (int cursor)

Ora_Fetch
Zwraca True (zostal odczytany wiersz) lub False (brak wierszy lub wystapil blad). Szczegly na temat bledu moga byc pobrane za pomoca funkcji ora_error() i ora_errorcode(). Jezeli nie wystapil blad, ora_errorcode() zwraca 0. Pobiera wiersz danych z podanego kursora. Patrz rwniez: ora_parse(), ora_exec() i ora_do().
int ora_fetch (int cursor)

Ora_Fetch_Into
Pobiera wiersz do tablicy.
Uwaga Musisz przekazywac tablice przez referencje.

Patrz rwniez: ora_parse(), ora_exec(), ora_fetch() i ora_do().


int ora_fetch_into (int cursor, array result [, int flags])

Przyklad: Pobranie wiersza wyniku Oracle do tablicy


<?php array($results); ora_fetch_into($cursor, &$results); echo $results[0]; echo $results[1]; ?>

Ora_GetColumn
Zwraca dane kolumny. Jezeli wystapi blad zwracana jest wartosc False, a ora_errorcode() zwraca niezerowa wartosc. Nalezy pamietac, ze sprawdzanie czy funkcja zwrcila wartosc False powoduje, ze beda wykrywane rwniez sytuacje gdy blad nie wystapil (wartosc NULL, pusty ciag, liczba 0, ciag "0"). Pobiera dane z kolumny lub wynik funkcji.
mixed ora_getcolumn (int cursor, mixed column)

Ora_Logoff
Zwraca True w przypadku powodzenia operacji lub False w przypadku wystapienia bledu. Szczegly na temat bledu moga byc pobrane za pomoca funkcji ora_error() i ora_errorcode(). Wylogowuje uzytkownika i odlacza od serwera. Patrz rwniez: ora_logon().
int ora_logoff (int connection)

Ora_Logon
Zestawia polaczenie pomiedzy PHP a baza danych Oracle, korzystajac z podanej nazwy uzytkownika i hasla.
int ora_logon (string user, string password)

Podajac nazwe TNS i uzytkownika polaczenie moze byc zestawione za pomoca SQL*Net:
$conn = Ora_Logon("user@TNSNAME", "pass");

Jezeli dane znakowe zawieraja znaki spoza zakresu ASCII, powinienes ustawic w systemie zmienna srodowiska NLS_LANG. W przypadku korzystania z modulu serwera, zmienna ta powinna byc ustawiona w srodowisku serwera przed uruchomieniem serwera. W przypadku powodzenia operacji zwraca identyfikator Dodatek A - Funkcje 352

polaczenia lub False w przypadku wystapienia bledu. Szczegly na temat bledu moga byc pobrane za pomoca funkcji ora_error() i ora_errorcode().

Ora_Numcols
Zwraca liczbe kolumn w wyniku. Zwraca prawidlowe wartosci jedyni po wykonaniu sekwencji parse exec fetch. Patrz rwniez: ora_parse(), ora_exec(), ora_fetch() i ora_do().
int ora_numcols (int cursor_ind)

Ora_Numrows
Zwraca ilosc wierszy w wyniku.
int ora_numrows (int cursor_ind)

Ora_Open
Otwiera kursor Oracle skojarzony z polaczeniem. Zwraca identyfikator kursora lub False w przypadku bledu. Szczegly na temat bledu moga byc pobrane za pomoca funkcji ora_error() i ora_errorcode().
int ora_open (int connection)

Ora_Parse
Analizuje wyrazenie SQL lub blok PL/SQL i laczy je z podanym kursorem. Zwraca 0 w przypadku powodzenia operacji lub -1 w przypadku bledu. Patrz rwniez: ora_exec(), ora_fetch() i ora_do().
int ora_parse (int cursor_ind, string sql_statement, int defer)

Ora_pLogon
Zestawia trwale polaczenie pomiedzy PHP a baza danych Oracle, korzystajac z podanej nazwy uzytkownika i hasla. Patrz rwniez: ora_logon().
int ora_plogon (string user, string password)

Ora_Rollback
Wycofuje transakcje Oracle (definicja transakcji znajduje sie przy funkcji ora_commit()).Zwraca identyfikator kursora lub False w przypadku bledu. Szczegly na temat bledu moga byc pobrane za pomoca funkcji ora_error() i ora_errorcode().
int ora_rollback (int connection)

OrbitEnum
Klasa ta reprezentuje wyliczenie identyfikowane przez parametr $id. Parametr ten moze byc nazwa wyliczenia (na przyklad: MyEnum) lub pelnym identyfikatorem repozytorium (na przyklad: IDL:MyEnum:1:0)
new OrbitEnum (string id)

Przyklad: przykladowy plik IDL


enum MyEnum { a,b,c,d,e };

Przyklad: kod PHP korzystajacy z MyEnum


<?php $enum = new OrbitEnum ("MyEnum"); echo $enum->a; /* wypisuje 0 */ echo $enum->c; /* wypisuje 2 */ echo $enum->e; /* wypisuje 4 */ ?>

353

PHP Kompendium wiedzy

OrbitObject
Klasa pozwalajaca na dostep do obiektu CORBA. Parametr Interoperable Object Reference (IOR) identyfikujacy zdalny obiekt.
new OrbitObject (string ior)

$id

powinien byc ciagiem zawierajacym

Przyklad: Przykladowy plik IDL


interface MyInterface { void SetInfo (string info); string GetInfo(); attribute int value; }

Przyklad: kod PHP korzystajacy z MyInterface


<?php $obj = new OrbitObject ($ior); $obj->SetInfo ("Obiekt"); echo $obj->GetInfo(); $obj->value = 42; echo $obj->value; ?>

OrbitStruct
Klasa reprezentujaca strukture o identyfikatorze $id. Parametr $id moze byc nazwa struktury (na przyklad MyStruct) lub pelnym identyfikatorem repozytorium (na przyklad: IDL:MyStruct:1:0)
new OrbitStruct (string id)

Przyklad: przykladowy plik IDL


struct MyStruct { short shortvalue; string stringvalue; }; interface SomeInterface { void SetValues (MyStruct values); MyStruct GetValues(); }

Przyklad: kod PHP korzystajacy z MyStruct


<?php $obj = new OrbitObject ($ior); $initial_values = new OrbitStruct ("IDL:MyStruct:1.0"); $initial_values->shortvalue = 42; $initial_values->stringvalue = "HGTTG"; $obj->SetValues ($initial_values); $values = $obj->GetValues(); echo $values->shortvalue; echo $values->stringvalue; ?>

ord
Zwraca wartosc ASCII dla pierwszego znaku ciagu rwniez: chr().
int ord (string string)

$string.

Funkcja jest odwrotnoscia

chr().

Patrz

Przyklad: ord()
if (ord($str) == 10) { echo "Pierwszym znakiem \$str jest znak nowego wiersza.\n"; }

pack
Pakuje podane argumenty do postaci ciagu binarnego zgodnie z formatem $format. Zwraca ciag binarny zawierajacy dane. Idea tej funkcji jest zapozyczona z jezyka Perl i wszystkie kody formatujace dzialaja identycznie. Jednak brakuje kilku kodw, na przyklad kod Perla u. Ciag formatu sklada sie z kodw formatowania po ktrych nastepuja opcjonalne argumenty powtarzania. Argument ten moze byc liczba calkowita lub * dla powtarzania do konca danych wejsciowych. Dla kodw a, A, h i H ilosc powtrzen okresla ilosc pobieranych znakw jednego argumentu danych. Dla @, jest to bezwzgledna pozycja na ktrej nalezy umiescic Dodatek A - Funkcje 354

kolejne dane. Dla pozostalych kodw ilosc powtrzen okresla ile argumentw jest pobieranych i pakowanych do wynikowego ciagu binarnego.
string pack (string format [, mixed args ...])

Zaimplementowane sa nastepujace kody: a ciag dopelniany zerami A ciag dopelniany spacjami h ciag szesnastkowy, pierwszy jest mniej znaczacy plbajt H ciag szesnastkowy, pierwszy jest bardziej znaczacy plbajt c litera ze znakiem C litera bez znaku s krtka liczba ze znakiem (zawsze 16 bitw, kolejnosc bajtw zalezna od komputera) S krtka liczba bez znaku (zawsze 16 bitw, kolejnosc bajtw zalezna od komputera) n krtka liczba bez znaku (zawsze 16 bitw, z malejacym porzadkiem bitw) v krtka liczba bez znaku (zawsze 16 bitw, z rosnacym porzadkiem bitw) i liczba calkowita ze znakiem (rozmiar i porzadek bitw zalezny od komputera) I liczba calkowita bez znaku (rozmiar i porzadek bitw zalezny od komputera) l liczba dluga ze znakiem (zawsze 32 bity, kolejnosc bajtw zalezna od komputera) L liczba dluga bez znaku (zawsze 32 bity, kolejnosc bajtw zalezna od komputera) N liczba dluga bez znaku (zawsze 32 bity, z malejacym porzadkiem bitw) V liczba dluga bez znaku (zawsze 32 bity, z rosnacym porzadkiem bitw) f liczba zmiennoprzecinkowa (rozmiar i reprezentacja zalezna od komputera) d liczba double (rozmiar i reprezentacja zalezna od komputera) x bajt NUL X cofniecie o jeden bajt @ wypelnienie znakami NUL do okreslonej pozycji Przyklad: ciag formatu dla pack()
$binarydata = pack ("nvc*", 0x1234, 0x5678, 65, 66);

Wynikowy ciag bedzie mial 6 bajtw i zawieral sekwencje bajtw: 0x12, 0x34, 0x78, 0x56, 0x41 i 0x42.
Uwaga Rozrznienie pomiedzy wartosciami ze znakiem lub bez znaku jest wazne jedynie dla funkcji unpack(), a funkcja pack() daje identyczne wartosci dla kodw formatowania ze znakiem jak i bez.

Nalezy zauwazyc, ze PHP wewnetrznie przechowuje wartosci calkowite jako wartosci ze znakiem o wielkosci zaleznej od komputera. Jezeli zostanie przekazana zbyt duza wartosc, zostanie ona skonwertowana do double, co moze prowadzic do niespodziewanych wynikw.

parse_str
Analizuje ciag $str tak, jakby byl przekazany poprzez adres URL i ustawia zmienne w biezacym zakresie widocznosci. Jezeli podany jest drugi parametr $arr zmienne sa umieszczane w przekazanej tablicy.
void parse_str (string str [, array arr])

Przyklad: uzycie parse_str()


<?php $str = "first=value&second[]=this+works&second[]=another"; parse_str($str); echo $first; /* wypisuje "value" */ echo $second[0]; /* wypisuje "this works" */ echo $second[1]; /* wypisuje "another" */ ?>

parse_url
port, user, pass, path, query

Zwraca tablice asocjacyjna zawierajaca rzne skladniki podanego adresu URL. Sa dostepne: scheme, host, i fragment. PHP Kompendium wiedzy

array parse_url (string url)

355

passthru
Podobna do funkcji exec(), uruchamia polecenie podane w $command. Jezeli podany jest parametr $return_var, umieszczana jest w nim wartosc kodu powrotu wykonywanego polecenia. Funkcja ta powinna byc uzywana zamiast exec() lub system() dla przypadkw, gdy wynikiem dzialania polecenia sa dane binarne, ktre musza byc wyslane do przegladarki. Czestym zastosowaniem jest uruchomienie programu podobnego do pbmplus, ktry potrafi bezposrednio pisac do strumienia wyjsciowego. Ustawiajac content-type na image/gif i wywolujac pbmplus z opcja tworzenia pliku gif, mozna stworzyc skrypt PHP bezposrednio wyswietlajacy rysunki.
Uwaga Jezeli uruchamiasz program przy pomocy tej funkcji i chcesz pozostawic go aby dzialal w tle, musisz przekierowac jego wyjscie do pliku lub innego strumienia wyjsciowego, poniewaz inaczej PHP zatrzyma sie czekajac na zakonczenie tego programu.

Patrz rwniez: exec(), popen(), EscapeShellCmd() oraz operator `.


void passthru (string command [, int return_var])

pdf_add_outline
Dodaje zakladke z tekstem $text wskazujaca na biezaca strone. Zakladka jest wstawiana w postaci obiektu potomnego do $parent i jest domyslnie otwierana chyba, ze parametr $open jest rzny od 0. Wynikiem jest identyfikator zakladki i moze byc on uzyty jako obiekt nadrzedny dla innych zakladek. Dzieki temu mozna tworzyc hierarchie zakladek. Niestety pdflib nie tworzy kopii ciagu, co powoduje wymuszenie przydzielania pamieci przez PHP. Ten fragment pamieci nie jest zwalniany przez zadna z funkcji PDF i jest to w gestii zarzadcy pamieci PHP.
int pdf_add_outline( int pdf_document, string text [, int parent] [, int open])

pdf_arc
Rysuje luk o srodku w punkcie ($x-coor, $y-coor) i promieniu $radius rozpoczynajac pod katem $start a konczac na $end. Patrz rwniez: pdf_circle() i pdf_stroke().
void pdf_arc (resource pdf_object, float x, float y, float r, float alpha, float beta)

pdf_begin_page
Rozpoczyna nowa strone o wysokosci $height i szerokosci $width. Aby stworzyc prawidlowy dokument musisz co najmniej raz wywolac funkcje pdf_end_page(). Patrz rwniez: pdf_end_page().
void pdf_begin_page (int pdf_object, float width, float height)

pdf_circle
Rysuje okrag o srodku w punkcie ($x-coor, pdf_stroke().
$y-coor)

i promieniu

$radius.

Patrz rwniez:

pdf_arc()

void pdf_circle (int pdf_object, float x, float y, float r)

pdf_clip
Przycina rysunek do biezacej sciezki.
void pdf_clip (int pdf_object)

pdf_close
Zamyka dokument pdf. Patrz rwniez: pdf_open() i fclose().
void pdf_close (int pdf_object)

Dodatek A - Funkcje

356

pdf_closepath
Zamyka biezaca sciezke. Oznacza to, ze rysuje linie od biezacego punktu do punktu, w ktrym zostalo rozpoczete rysowanie sciezki. Wiele funkcji, np. pdf_moveto(), pdf_circle() i pdf_rect() rozpoczyna nowa sciezke.
void pdf_closepath (int pdf_object)

pdf_closepath_fill_stroke
Zamyka biezaca sciezke, wypelnia jej obszar biezacym kolorem wypelnienia i rysuje sciezke. Patrz rwniez: pdf_closepath(), pdf_stroke(), pdf_fill(), pdf_setgray_fill(), pdf_setgray(), pdf_setrbgcolor_fill() i pdf_setrgbcolor().
void pdf_closepath_fill_stroke (int pdf_object)

pdf_closepath_stroke
Polaczenie pdf_closepath() i
pdf_stroke().
void pdf_closepath_stroke (int pdf_object)

pdf_stroke().

Dodatkowo kasuje sciezke. Patrz rwniez:

pdf_closepath()

pdf_close_image
Zamyka rysunek otwarty za pomoca funkcji pdf_open_gif() i pdf_open_memory_image().
void pdf_close_image (int pdf_object, int image)

pdf_open_xxx().

Patrz rwniez:

pdf_open_jpeg(),

pdf_continue_text
Umieszcza tekst przekazany w parametrze $text w kolejnym wierszu. Odstep pomiedzy wierszami moze byc regulowany za pomoca funkcji pdf_set_leading(). Patrz rwniez: pdf_show_xy(), pdf_set_leading() i pdf_set_text_pos().
void pdf_continue_text (int pdf_object, string text)

pdf_curveto
Rysuje krzywa Beziera od punktu biezacego do punktu ($x3, $y3) uzywajac jako punktw kontrolnych ($x1, $y1) i ($x2, $y2). Patrz rwniez: pdf_moveto(), pdf_lineto() i pdf_stroke().
void pdf_curveto (int pdf_object, float x1, float y1, float x2, float y2, float x3, float y3)

pdf_endpath
Konczy biezaca sciezke, ale jej nie zamyka. Patrz rwniez: pdf_closepath().
void pdf_endpath( int pdf_document )

pdf_end_page
Konczy strone. Po zakonczeniu strony nie moze byc ona juz modyfikowana. Patrz rwniez:
pdf_begin_page().
void pdf_end_page (int pdf_object)

pdf_execute_image
Wyswietla rysunek umieszczony w pliku PDF za pomoca funkcji pdf_put_image() na biezacej stronie na podanych wsplrzednych. Rysunek moze byc przeskalowany podczas wyswietlania. Skala 1.0 powoduje wyswietlanie rysunku w oryginalnej wielkosci. 357 PHP Kompendium wiedzy

Uwaga Funkcja stanie sie przestarzala w pdflib 2.01. Bedzie jedynie wyswietlala ostrzezenie.

Przyklad: wielokrotne wyswietlanie rysunku


<?php $im = ImageCreate( 100, 100 ); $col1 = ImageColorAllocate( $im, 80, 45, ImageFill( $im, 10, 10, $col1 ); $pim = pdf_open_memory_image( $pdf, $pim pdf_put_image( $pdf, $pim ); pdf_execute_image( $pdf, $pim, 100, 100, pdf_execute_image( $pdf, $pim, 200, 200, pdf_close_image( $pdf, $pim ) ?> 190 ); ); 1 ); 2 );

pdf_fill
Wypelnia wnetrze biezacej sciezki za pomoca biezacego koloru wypelnienia. Patrz rwniez: pdf_stroke(), pdf_setgray_fill(), pdf_setgray(), pdf_setrgbcolor_fill() i pdf_sergbcolor().
pdf_closepath(),
void pdf_fill_stroke (int pdf_object)

pdf_fill_stroke
Wypelnia wnetrze biezacej sciezki za pomoca biezacego koloru wypelnienia i rysuje biezaca sciezke. Patrz rwniez: pdf_closepath(), pdf_stroke(), pdf_fill(), pdf_setgray_fill(), pdf_setgray(), pdf_setrgbcolor_fill() i pdf_sergbcolor().
void pdf_fill_stroke (int pdf_object)

pdf_get_image_height
wysokosc rysunku pdf w pdf_open_memory_image() i pdf_get_image_width(). Zwraca pikselch. Patrz rwniez:
pdf_open_image_file(),
string pdf_get_image_height (int pdf_object, int image)

pdf_get_image_width
szerokosc rysunku pdf w pdf_open_memory_image() i pdf_get_image_heigth(). Zwraca pikselch. Patrz rwniez:
pdf_open_image_file(),
string pdf_get_image_width (int pdf_object, int image)

pdf_get_parameter
Pobiera kilka z parametrw pdflib bedacych ciagami. Parametr funkcji $modifier okresla parametr do pobrania. Jezeli modyfikator nie jest potrzebny, musi miec wartosc 0 lub nie podany. Patrz rwniez: pdf_get_value(), pdf_set_value() i pdf_set_parameter().
string pdf_get_parameter (int pdf_object, string key [, float modifier])

pdf_get_value
Pobiera kilka numerycznych parametrw pdflib. Parametr funkcji $modifier okresla parametr do pobrania. Jezeli modyfikator nie jest potrzebny, musi miec wartosc 0 lub nie podany. Patrz rwniez: pdf_get_parametr(), pdf_set_value() i pdf_set_parameter().
float pdf_get_value (int pdf_object, string key [, float modifier])

Dodatek A - Funkcje

358

pdf_lineto
Rysuje linie od punktu biezacego do punktu o wsplrzednych ($x, pdf_curveto() i pdf_stroke().
void pdf_lineto (int pdf_object, float x, float y)

$y).

Patrz rwniez:

pdf_moveto(),

pdf_moveto
Ustawia punkt biezacy na $x i $y.
void pdf_moveto (int pdf_object, float x, float y)

pdf_open
Otwiera dokument pdf. Odpowiedni plik musi byc otwarty za pomoca fopen() i deskryptor pliku przekazany jako parametr $file. Jezeli nie przekazane zostana zadne parametry, dokument zostanie utworzony w pamieci a wynikowa strona wyslana do stdout lub przegladarki WWW.
Uwaga Zwracana wartosc jest potrzebna jako pierwszy parametr wszystkich pozostalych funkcji zapisujacych pliki pdf.

Patrz rwniez: fopen() i pdf_close().


int pdf_open( int file )

pdf_open_gif
Otwiera rysunek zapisany w pliku o nazwie identyfikator rysunku pdf.
Uwaga Funkcja nie powinna byc juz uzywana. Prosze uzywac zamiast niej funkcji pdf_open_image_file(). $filename.

Formatem pliku musi byc gif. Funkcja zwraca

Patrz rwniez: pdf_close_image(), pdf_place_image() i pdf_put_image(). Przyklad: Dolaczanie rysunku GIF

pdf_open_jpeg(), pdf_open_memory_image(), pdf_execute_image(),

int pdf_open_gif ( int pdf_document, string filename ) <?php $im = pdf_open_gif( $pdf, "test.gif" ); pdf_place_image( $pdf, $im, 100, 100, 1 ); pdf_close_image( $pdf, $im ); ?>

pdf_open_image_file
Otwiera rysunek o formacie $format, zapisany w pliku o nazwie $filename. Mozliwymi formatami pliku sa: png, tiff, jpeg i gif. Funkcja zwraca identyfikator rysunku pdf. Patrz rwniez: pdf_close_image(), pdf_open_jpeg(), pdf_open_gif(), pdf_open_memory_image(), pdf_execute_image(), pdf_place_image() i pdf_put_image().
int pdf_open_image_file (int PDF-document, string imagetype, string filename [, string stringparam [, string intparam]])

Przyklad: wstawianie rysunku


<?php $im = pdf_image_file( $pdf, "png", "picture.png" ); pdf_place_image( $pdf, $im, 100, 100, 1 ); pdf_close_image( $pdf, $im ); ?>

359

PHP Kompendium wiedzy

pdf_open_jpeg
Otwiera rysunek zapisany w pliku o nazwie identyfikator rysunku pdf.
Uwaga Funkcja nie powinna byc juz uzywana. Prosze uzywac zamiast niej funkcji pdf_open_image_file(). $filename.

Formatem pliku musi byc jpeg. Funkcja zwraca

rwniez: pdf_close_image(), pdf_open_gif(), pdf_execute_image(), pdf_place_image() i pdf_put_image().


int pdf_open_jpeg ( int pdf_document, string filename )

Patrz

pdf_open_png(),

pdf_open_memory_image(),

pdf_open_memory_image
Pobiera rysunek utworzony za pomoca funkcji PHP tworzacych rysunki i udostepnia go dla dokumentu pdf. Funkcja zwraca identyfikator rysunku pdf. Patrz rwniez: pdf_close_image(),pdf_open_jpeg(), pdf_open_gif(), pdf_open_png(), pdf_execute_image(), pdf_place_image() i pdf_put_image().
int pdf_open_memory_image (int pdf_object, int image)

Przyklad: Dolaczanie rysunku z pamieci


<?php $im = ImageCreate( 100, 100 ); $col1 = ImageColorAllocate( $im, 80, 45, 190 ); ImageFill( $im, 10, 10, $col1 ); $pim = pdf_open_memory_image( $pdf, $pim ); ImageDestroy( $im ); pdf_place_image( $pdf, $pim, 100, 100, 1 ); pdf_close_image( $pdf, $pim ) ?>

pdf_open_png
Otwiera rysunek zapisany w pliku o nazwie identyfikator rysunku pdf.
Uwaga Funkcja nie powinna byc juz uzywana. Prosze uzywac zamiast niej funkcji pdf_open_image_file(). $filename.

Formatem pliku musi byc png. Funkcja zwraca

Patrz

rwniez:

pdf_close_image(),

pdf_open_gif(),

pdf_open_jpeg(),

pdf_open_memory_image(),

pdf_execute_image(), pdf_place_image()

i pdf_put_image().

int pdf_open_png ( int pdf_document, string filename )

Przyklad: dolaczanie rysunku PNG


<?php $im = pdf_open_png( $pdf, "test.png" ); pdf_place_image( $pdf, $im, 100, 100, 1 ); pdf_close_image( $pdf, $im ); ?>

pdf_open_tiff
Otwiera rysunek zapisany w pliku o nazwie identyfikator rysunku pdf.
Uwaga Funkcja nie powinna byc juz uzywana. Prosze uzywac zamiast niej funkcji pdf_open_image_file(). $filename.

Formatem pliku musi byc tiff. Funkcja zwraca

Patrz

rwniez:

pdf_close_image(),

pdf_open_gif(),

pdf_open_jpeg(),

pdf_open_png(),

pdf_open_memory_image(), pdf_execute_image(), pdf_place_image()


int pdf_open_tiff( int pdf_document, string filename )

i pdf_put_image().

Dodatek A - Funkcje

360

pdf_place_image
Umieszcza rysunek na stronie na wsplrzednych ($x, $y). Rysunek moze byc w tym czasie przeskalowany. Patrz rwniez: pdf_put_image().
void pdf_place_image (int pdf_object, int image, float x, float y, float scale)

pdf_put_image
Umieszcza rysunek w pliku PDF bez jego pokazywania. Zapisany rysunek moze byc wyswietlony za pomoca pdf_execute_image() dowolna ilosc razy. Jest to uzyteczne, jezeli ten sam rysunek jest wielokrotnie uzywany w celu zmniejszenia pliku wynikowego. Uzycie funkcji pdf_put_image() i pdf_execute_image() jest zalecane dla wiekszych rysunkw (kilka KB), jezeli sa pokazane w dokumencie wiecej niz raz.
Uwaga Funkcja stanie sie przestarzala w pdflib 2.01. Bedzie jedynie wyswietlala ostrzezenie.

Patrz rwniez: pdf_put_image(), pdf_place_image() i pdf_execute_image().

pdf_rect
Rysuje prostokat o dolnym lewym narozniku w punkcie ($x, wysokosc $height. Patrz rwniez: pdf_stroke().
$y).

Jego szerokosc wynosi

$width

void pdf_rect (int pdf_object, float x, float y, float width, float height)

pdf_restore
Przywraca srodowisko zapisane za pomoca Patrz rwniez: pdf_save().
void pdf_restore (int pdf_object) <?php pdf_save( $pdf ); // wykonanie obrotw i innych transformacji pdf_restore( $pdf ); ?>

pdf_save().

Dziala podobnie do polecenia postscript restore.

Przyklad: zapamietywanie i przywracanie srodowiska

pdf_rotate
Ustawia kat obrotu w stopniach na $angle.
void pdf_rotate (int pdf_object, float angle)

pdf_save
Zapisuje biezace srodowisko. Dziala podobnie do polecenia postscript save. Funkcja jest uzyteczna, gdy chcesz przesunac lub obrcic obiekt bez wplywania na inne obiekty. Funkcja pdf_save() powinna zawsze posiadac swoja pdf_restore() odtwarzajaca stan srodowiska sprzed pdf_save(). Patrz rwniez: pdf_restore().
void pdf_save (int pdf_object)

pdf_scale
Ustala wsplczynnik skalowania w obu kierunkach. Ponizszy przyklad powoduje przeskalowanie wsplrzednych x i y o 72. Kolejna linia bedzie miala dzieki temu dlugosc jednego cala w obu kierunkach.
void pdf_scale (int pdf_object, float x-scale, float y-scale)

Przyklad: skalowanie
<?php pdf_scale($pdf, 72.0, 72.0 ); pdf_lineto( $pdf, 1, 1 ); pdf_stroke( $pdf );

361

PHP Kompendium wiedzy

?>

pdf_setdash
Ustawia wzr kreski na zostanie ciagla linia.
$white

bialych punktw i

$black

czarnych. Jezeli obie wartosci sa 0, narysowana

void pdf_setdash (int pdf_object, float black, float white)

pdf_setflat
Ustawia parametr plaskosci na wartosc od 0 do 100.
void pdf_setflat (int pdf_object, float flatness)

pdf_setgray
pdf_setrgbcolor_stroke()

Ustawia biezacy kolor rysowania i wypelnienia na podana wartosc szarego koloru Patrz rwniez: i pdf_setrgbcolor_fill().

void pdf_setgray (int pdf_object, float gray)

pdf_setgray_fill
Ustawia biezacy kolor wypelnienia na podana wartosc szarosci. Patrz rwniez: pdf_setrgbcolor_stroke().
void pdf_setgray_fill (int pdf_object, float gray)

pdf_setgray_stroke
Ustawia biezacy kolor na podana wartosc szarosci. Patrz rwniez: pdf_setrgbcolor_stroke().
void pdf_setgray_stroke (int pdf_object, float gray)

pdf_setlinecap
Ustawia parametr linecap na wartosc od 0 do 2.
void pdf_setlinecap (int pdf_object, int linecap)

pdf_setlinejoin
Ustawia parametr linejoin na wartosc od 0 do 2.
void pdf_setlinejoin (int pdf_object, long linejoin)

pdf_setlinewidth
Ustawia szerokosc linii na $width.
void pdf_setlinewidth (int pdf_object, float width)

pdf_setmiterlimit
Ustawia parametr miter limit na wartosc wieksza lub rwna 1.
void pdf_setmiterlimit (int pdf_object, float miter)

pdf_setrgbcolor
pdf_setrgbcolor_stroke()

Ustawia biezacy kolor wypelnienia i rysowania na podana wartosc koloru RGB. Patrz rwniez: i pdf_setrgbcolor_fill().

void pdf_setrgbcolor (int pdf_object, float red_value, float green_value, float blue_value)

Dodatek A - Funkcje

362

pdf_setrgbcolor_fill
Ustawia wartosc koloru RGB dla wypelnienia sciezki. Patrz rwniez: pdf_setrgbcolor().
void pdf_setrgbcolor_fill (int pdf_object, float red_value, float green_value, float blue_value)

pdf_setrgbcolor_stroke
Ustawia biezaca wartosc koloru RGB do rysowania.
void pdf_setrgbcolor_stroke (int pdf_object, float red_value, float green_value, float blue_value)

pdf_set_border_color
Ustawia kolor prostokata otaczajacego lacza i komentarze. Trzy skladniki koloru musza miec wartosci pomiedzy 0.0 a 1.0. Patrz rwniez: pdf_set_border_dash().
void pdf_set_border_color (int pdf_object, float red, float green, float blue)

pdf_set_border_dash
Ustawia dlugosci czarnych i bialych obszarw linii przerywanej otaczajacej lacza i komentarze. Patrz rwniez: pdf_set_border_color().
void pdf_set_border_dash (int pdf_object, float black, float white)

pdf_set_border_style
Ustawia rodzaj i wielkosc prostokata otaczajacego lacza i komentarze. Parametr wartosci solid lub dashed. Patrz rwniez: pdf_set_border_color() i pdf_set_border_dash().
void pdf_set_border_style (int pdf_object, string style, float width)

$style

moze miec

pdf_set_char_spacing
Ustawia odstep pomiedzy znakami. Patrz rwniez: pdf_set_word_spacing() i pdf_set_leading().
void pdf_set_char_spacing( int pdf_object, float space )

pdf_set_duration
Ustawia czas przerwy, w sekundach, pomiedzy kolejnymi stronami. Patrz rwniez: pdf_set_transition().
void pdf_set_duration ( int pdf_object, float duration )

pdf_set_font
Ustawia biezacy rodzaj czcionki, rozmiar czcionki i kodowanie. Jezeli uzywasz pdflib 0.6, musisz umiescic w katalogu czcionek (domyslnie ./fonts) plik Adobe Font Metrics (plik afm) dla uzytej czcionki. Jezeli uzywasz PHP 3 lub pdflib w wersji pzniejszej niz 2.20, parametr $encoding moze przyjmowac nastepujace wartosci: 0 builtin, 1 pdfdoc, 2 macroman, 3 macexpert lub 4 winansi. Wartosc parametru $encoding wieksza od 4 lub mniejsza od 0 powoduje przyjecie wartosci winansi. Wartosc ta jest zwykle dobrym wyborem. Jezeli uzywasz PHP4 i pdflib w wersji co najmniej 2.20, typ parametru $encoding zostal zmieniony na ciag. Nalezy uzyc winansi, builtin, itd. Jezeli ostatni parametr jest ustawiony na 1, czcionka jest wbudowywana w dokument PDF, w przeciwnym wypadku nie jest. Wbudowywanie czcionek jest dobrym pomyslem, jezeli jest to rzadko wykorzystywana czcionka i nie ma pewnosci, ze osoba ogladajaca dokument bedzie miala ja zainstalowana. Czcionka jest wbudowywana tylko raz, nawet, jezeli funkcja pdf_set_font() bedzie wywolana kilka razy.
void pdf_set_font( int pdf_object, string font_name, float size, string encoding [, int embed]))

363

PHP Kompendium wiedzy

pdf_set_horiz_scaling
Ustawia skalowanie w pionie na $scale procent.
void pdf_set_horiz_scaling( int pdf_object, float scale )

pdf_set_info
Ustawia pole informacyjne dokumentu PDF. Mozliwymi nazwami pl sa: Subject, Title, Creator, Author, Keywords i jedna nazwa zdefiniowana przez uzytkownika. Funkcja moze byc wywolana przed rozpoczeciem strony.
Uwaga Funkcja zastepuje funkcje: pdf_set_info_keywords(), pdf_set_info_title(), pdf_set_info_subject(), pdf_set_info_creator() i pdf_set_info_sybject().
void pdf_set_info (int pdf_object, string key, string value)

Przyklad: Ustawianie informacji o dokumencie


<?php $fd = fopen( "test.pdf", "w" ); $pdfdoc = pdf_open($fd); pdf_set_info( $pdfdoc, "Author", "Jan Kowalski"); pdf_set_info( $pdfdoc, "Creator", "Jan Kowalski"); pdf_set_info( $pdfdoc, "Title", "Testowanie pl informacyjnych"); pdf_set_info( $pdfdoc, "Subject", "Test"); pdf_set_info( $pdfdoc, "Keywords", "Test, Pola"); pdf_set_info( $pdfdoc, "CustomField", "Cokolwiek sensownego"); pdf_begin_page($pdfdoc, 595, 842); pdf_end_page( $pdfdoc ); pdf_close( $pdfdoc ); ?>

pdf_set_leading
pdf_continue_text().

Ustawia odstep pomiedzy wierszami tekstu. Jest on uzywany, gdy tekst jest wysylany za pomoca funkcji Patrz rwniez: pdf_continue_text().

void pdf_set_leading( int pdf_object,float distance )

pdf_set_parameter
Ustawia parametry pdflib bedace ciagami znakw. Patrz rwniez: pdf_get_parameter().
void pdf_set_parameter (int pdf_object, string key, string value)

pdf_get_value(), pdf_set_value()

pdf_set_text_matrix
Ustawia tablice opisujaca transformacje stosowane na biezacej czcionce. Musi byc przekazana tablica z szescioma elementami.
Uwaga Funkcja nie jest dostepna w pdflib od wersji 2.3.
void pdf_set_text_matrix( int pdf_object, array matrix)

pdf_set_text_pos
Ustawia polozenie tekstu dla nastepnego wywolania funkcji pdf_show_xy().
void pdf_set_text_pos (int pdf_object, float x, float y)

pdf_show().

Patrz rwniez:

pdf_show()

Dodatek A - Funkcje

364

pdf_set_text_rendering
Okresla sposb rysowania tekstu. Mozliwymi wartosciami dla parametru $mode sa: 0 tekst wypelniony, 1 tekst przerywany, 2 tekst wypelniony i przerywany, 3 niewidoczny, 4 tekst wypelniony i dodany do sciezki obcinania, 5 tekst przerywany i dodany do sciezki obcinania, 6 tekst przerywany i wypelniony oraz dodany do sciezki obcinania, 7 dodanie do sciezki obcinania.
void pdf_set_text_rendering( int pdf_object, int mode)

pdf_set_text_rise
Ustawia powiekszenie tekstu na $rise punktw.
void pdf_set_text_rise(int pdf_object, float rise )

pdf_set_transition
Ustawia przejscie pomiedzy kolejnymi stronami. Patrz rwniez: pdf_set_duration().
void pdf_set_transition(int pdf_object, int transition)

Wartosciami parametru $transition moga byc: 0 brak 1 dwa wiersze pokazujace sie na ekranie odkrywaja strone 2 kilka wierszy pokazujace sie na ekranie odkrywaja strone 3 prostokat odkrywa strone 4 pojedynczy wiersz pokazujacy sie na ekranie odkrywa strone 5 stara strona rozmywa sie aby pokazac nowa strone 6 efekt rozmywania przesuwa sie od jednej krawedzi strony do drugiej 7 nowa strona po prostu zastepuje stara (domyslnie)

pdf_set_value
Ustawia numeryczne parametry pdflib. Patrz rwniez: pdf_set_parameter().
void pdf_set_value (int pdf_object, string key, float value)

pdf_get_value(),

pdf_get_parameter()

pdf_set_word_spacing
Ustawia odstepy pomiedzy slowami. Patrz rwniez: pdf_set_char_spacing() i pdf_set_leading().
void pdf_set_word_spacing( int pdf_object, float space )

pdf_show
Rysuje tekst $text od biezacej pozycji kursora za pomoca biezacej czcionki. Patrz rwniez: pdf_show_xy(), pdf_show_boxed(), pdf_set_text_pos() i pdf_set_font().
void pdf_show (int pdf_object, string text)

pdf_show_boxed
Rysuje tekst $text w prostokacie o lewym grnym rogu we wsplrzednych ($left, $top). Rozmiar prostokata okreslaja parametry $width i $height. Parametr $mode okresla w jaki sposb ustawiany jest typ tekstu. Jezeli $width i $height maja wartosci 0, $mode moze byc left, right lub center. Jezeli $width lub $height sa rzne od zera $mode moze miec wartosci justify i fulljustify. Jezeli parametr $feature ustawiony jest na blind, tekst nie pokazuje sie. Zwraca ilosc znakw, ktre nie mogly byc przetworzone, poniewaz nie miescily sie w prostokacie. Patrz rwniez: pdf_show() i pdf_show_xy().
int pdf_show_boxed (int pdf_object, string text, float left, float top, float width, float height, string mode [, string feature])

365

PHP Kompendium wiedzy

pdf_show_xy
Rysuje tekst $text na pozycji ($x, $y). Patrz rwniez: pdf_show() i pdf_show_boxed().
void pdf_show_xy (int pdf_object, string text, float x, float y)

pdf_skew
Pochyla system wsplrzednych o wynosic 90 i 270 stopni.
$alpha

(x) i

$beta

(y) stopni. Parametry

$alpha

$beta

nie moga

void pdf_skew (int pdf_object, float alpha, float beta)

pdf_stringwidth
Zwraca szerokosc tekstu $text zapisanego biezaca czcionka. Wymaga wczesniejszego ustawienia czcionki za pomoca pdf_set_font(). Patrz rwniez: pdf_set_font().
float pdf_stringwidth (int pdf_object, string text [, int font [, float size]])

Dodatek A - Funkcje

366

Dodatek B. Predefiniowane zmienne i stale PHP


Zmienne
Kompletna lista predefiniowanych zmiennych oraz inne uzyteczne informacje mozna znalezc w tabeli bedacej wynikiem dzialania funkcji phpinfo(). Ponizsza lista nie jest wyczerpujaca i nigdy taka nie miala byc. Mozna ja traktowac jako przyklad spodziewanych rodzajw zmiennych, z jakich mozna skorzystac w skryptach.

Zmienne Apache
Zmienne te sa tworzone przez serwer Apache. Jezeli korzystasz z innego serwera, nie gwarantuje ze dostepne beda te same funkcje. Moze niektrych brakowac, a beda dostepne inne, nie opisane tutaj. Wiele z tych zmiennych jest definiowanych przez nowa specyfikacje CGI 1.1, wiec mozna sie spodziewac, ze beda one dostepne. Nalezy zauwazyc, ze niektre z wymienionych zmiennych sa dostepne jedynie w przypadku uruchomienia PHP z linii polecen. GATEWAY_INTERFACE Wersja specyfikacji CGI, z ktrej korzysta serwer, na przyklad CGI/1.1. SERVER_NAME Nazwa komputera z serwerem, na ktrym wykonywany jest skrypt. Jezeli skrypt dziala na serwerze wirtualnym, bedzie to nazwa zdefiniowana dla tego serwera wirtualnego. SERVER_SOFTWARE Ciag identyfikujacy serwer przekazywany w naglwkach odpowiedzi na zadanie. SERVER_PROTOCOL Nazwa i wersja protokolu za pomoca ktrego wyslane zostalo zadanie pobrania strony, na przyklad HTTP/1.0. REQUEST_METHOD Metoda zadania uzyta do pobrania strony, na przyklad GET, HEAD, POST lub PUT. QUERY_STRING Ciag zapytania (o ile istnieje) przeslany wraz z biezaca strona. DOCUMENT_ROOT Zdefiniowany w konfiguracji serwera katalog glwny dokumentw, w ktrym jest wykonywany biezacy skrypt.

HTTP_ACCEPT Zawartosc naglwka Accept: z biezacego zadania, o ile istnieje. HTTP_ACCEPT_CHARSET Zawartosc naglwka Accept-Charset: z biezacego zadania, o ile istnieje. Przyklad: iso-8859-1,*,utf-8. HTTP_ENCODING Zawartosc naglwka Accept-Encoding: z biezacego zadania, o ile istnieje. Przyklad: gzip. HTTP_ACCEPT_LANGUAGE Zawartosc naglwka Accept-Language: z biezacego zadania, o ile istnieje. Przyklad: en. HTTP_CONNECTION Zawartosc naglwka Connection: z biezacego zadania, o ile istnieje. Przyklad: Keep-Alive. HTTP_HOST Zawartosc naglwka Host: z biezacego zadania, o ile istnieje. HTTP_REFERER Adres strony, z ktrej przegladarka przeszla na biezaca strone. Jest to ustawiane przez przegladarke uzytkownika, ale nie wszystkie przegladarki to robia. HTTP_USER_AGENT Zawartosc naglwka User_Agent: z biezacego zadania, o ile istnieje. Jest to ciag okreslajacy przegladarke uzyta do ogladania biezacego dokumentu, na przyklad: Mozilla/4.5[en] (X11;U;Linux 2.2.9 i586). Mozna uzyc tej wartosci oraz funkcji get_browser() w celu przystosowania strony do mozliwosci przegladarki uzytej przez uzytkownika. REMOTE_ADDR Adres IP komputera uzywanego do ogladania biezacej strony. REMOTE_PORT Port na komputerze klienta uzyty do komunikacji z serwerem WWW. SCRIPT_FILENAME Bezwzgledna sciezka do wykonywanego skryptu. SERVER_ADMIN Zawartosc dyrektywy konfiguracji Apache SERVER_ADMIN z pliku konfiguracyjnego. Jezeli skrypt jest uruchomiony poprzez serwer wirtualny, jest to wartosc zdefiniowana dla tego serwera wirtualnego. SERVER_PORT Port na serwerze uzywany do komunikacji przez serwer WWW. Domyslnie jest to 80, jezeli wykorzystane jest SSL jest to port zdefiniowany do uzycia przez bezpieczny HTTP. SERVER_SIGNATURE Ciag zawierajacy wersje serwera i nazwe serwera wirtualnego, ktry jest dodawany do stron wygenerowanych przez serwer, o ile opcja ta jest aktywna. Dodatek B. Predefiniowane zmienne i stale PHP 368

PATH_TRANSLATED Sciezka w systemie plikw (a nie wzgledem glwnego katalogu dokumentw) do biezacego skryptu, po dokonaniu przeksztalcen ze sciezek wirtualnych na rzeczywiste. SCRIPT_NAME Zawiera sciezke do biezacego skryptu. Jest to uzyteczna zmienna dla skryptw wskazujacych na samych siebie. REQUEST_URI Adres URI uzyty do dostepu do biezacej strony, na przyklad, /index.html.

Zmienne srodowiska
Zmienne te sa importowane do przestrzeni nazw globalnych ze srodowiska, w ktrym jest uruchamiany analizator PHP. Wiele z nich zalezy od rodzaju powloki, a poniewaz PHP dziala na wielu systemach i rznych rodzajach powlok, zdefiniowanie kompletnej listy jest niemozliwe. Nalezy odszukac taka liste w dokumentacji swojego systemu. Zmienne srodowiska zawieraja zmienne CGI, ktre zamieszczane sa niezaleznie od tego, czy PHP dziala jako modul serwera, czy jako program CGI.

Zmienne PHP
Zmienne te sa tworzone przez PHP. Zmienne $HTTP_*_VARS sa dostepne jedynie wtedy, gdy wlaczona jest opcja konfiguracji track_vars. Od PHP 4.0.3 track_vars jest zawsze wlaczone, niezaleznie od ustawienia w pliku konfiguracyjnym. Jezeli ustawiona jest dyrektywa register_globals, zmienne te beda dostepne w globalnej przestrzeni zmiennych, oprcz wartosci w tablicach $HTTP_*_VARS. Funkcja ta powinna byc uzywana rozwaznie i wylaczana o ile jest to mozliwe. Tablice $HTTP_*_VARS sa bezpieczne, a ich globalne odpowiedniki sa czesto nadpisywane przez wartosci wprowadzone przez uzytkownika, co czesto powoduje trudne do znalezienia bledy. Jezeli nie mozesz wylaczyc opcji register_globals, musisz sie upewnic, ze uzywane dane sa bezpieczne. argv Tablica argumentw przekazanych do skryptu. Gdy skrypt jest uruchomiony z linii komend, pozwala to na dostep do argumentw tak samo jak w jezyku C. Jezeli skrypt jest uruchamiany za pomoca metody GET, zmienna zawiera ciag zapytania. argc Zawiera ilosc parametrw przekazanych do skryptu (jezeli jest on uruchomiony z linii polecen). PHP_SELF Nazwa pliku z wykonywanym skryptem, zapisana wzgledem glwnego katalogu dokumentw. Jezeli PHP jest uruchomiony z linii polecen, zmienna ta nie jest dostepna. HTTP_COOKIE_VARS Tablica asocjacyjna ze zmiennymi przekazanymi do biezacego skryptu poprzez cookie HTTP. HTTP_GET_VARS Tablica asocjacyjna ze zmiennymi przekazanymi do biezacego skryptu za pomoca metody GET. HTTP_POST_VARS Tablica asocjacyjna ze zmiennymi przekazanymi do biezacego skryptu za pomoca metody POST. 369 PHP Kompendium wiedzy

HTTP_POST_FILES
$HTTP_POST_FILES

Tablica asocjacyjna z informacjami na temat plikw przeslanych za pomoca metody POST. Zmienna jest dostepna w PHP od wersji 4.0.0.

HTTP_ENV_VARS Tablica asocjacyjna ze zmiennymi przekazanymi do biezacego skryptu poprzez srodowisko. HTTP_SERVER_VARS Tablica asocjacyjna ze zmiennymi przekazanymi do biezacego skryptu z serwera HTTP. Zmienne te sa analogiczne do opisanych wczesniej zmiennych Apache.

Stale
__FILE__ Nazwa analizowanego wlasnie skryptu. Jezeli zostala w dolaczanym pliku, zwracana jest nazwa tego pliku a nie pliku glwnego. __LINE__ Numer wiersza w biezacym skrypcie. Jezeli zostala w dolaczanym pliku, zwracany jest numer wiersza w tym pliku. PHP_VERSION Ciag zawierajacy wersje uzywanego analizatora PHP, na przyklad, 3.0.8-dev. PHP_OS Nazwa systemu operacyjnego, na ktrym dziala analizator PHP, na przyklad Linux. TRUE Wartosc logiczna prawda. FALSE Wartosc logiczna falsz. E_ERROR Oznacza blad inny niz blad skladni, gdzie nie jest mozliwe kontynuowanie wykonania. E_WARNING Oznacza sytuacje, gdy PHP wykrywa blad, ale mimo to kontynuuje wykonywanie skryptu. Moze byc on przechwycony przez skrypt. Przykladem moze byc nieprawidlowy wzorzec w funkcji ereg(). E_PARSE Analizator napotkal blad skladni. Praca jest przerywana. E_NOTICE Sytuacja nieprawidlowa, ktra moze, ale nie musi byc bledna. Skrypt jest dalej wykonywany. Przykladem moze byc uzycie ciagu bez apostrofw jako indeks w tablicy asocjacyjnej lub skorzystanie z niezainicjowanej zmiennej. Dodatek B. Predefiniowane zmienne i stale PHP 370

E_ALL Wszystkie stale E_*. Jezeli zostanie uzyta w funkcji wszystkich problemw napotkanych przez PHP.
error_reporting(),

powoduje raportowanie

371

PHP Kompendium wiedzy

Dodatek C. Opcje kompilacji PHP


Bazy danych
--with-adabas[=DIR] Dolacz obsluge Adabas D. DIR jest katalogiem gdzie zostala zainstalowana baza Adabas, domyslnie /usr/local. --enable-dba=shared Buduj DBA jako obiekt wspldzielony. --enable-dbase Dolacz wbudowana biblioteke dbase. Nie potrzebne sa zewnetrzne biblioteki. --with-db2[=DIR] Dolacz obsluge Berkeley DB2. --with-db3[=DIR] Dolacz obsluge Berkeley DB3. --with-dbm[=DIR] Dolacz obsluge DBM. --with-dbmaker[=DIR] Dolacz obsluge DBMaker. DIR to katalog instalacji programu DBMaker domyslnie tam, gdzie zostala zainstalowana najnowsza wersja DBMaker (np. /home/dbmaker/3.6). --with-empress[=DIR] Dolacz obsluge Empress. DIR to katalog instalacji Empress, domyslnie $EMPRESSPATH. --enable-filepro Dolacz wbudowana obsluge filePro (tylko do odczytu). Nie potrzebne sa zewnetrzne biblioteki. --with-gdbm[=DIR] Dolacz obsluge GDBM --with-hyperwave Dolacz obsluge Hyperwave --with-ibm-db2[=DIR] Dolacz obsluge IBM DB2. DIR to katalog instalacji DB2, domyslnie /home/db2inst1/sqllib.

--with-informix[=DIR] Dolacz obsluge Informix. DIR to katalog gdzie zostal zainstalowany Informix. Brak wartosci domyslnej. --with-ingres[=DIR] Dolacz obsluge Ingres II. DIR to katalog instalacji programu Ingres, domyslnie /II/ingres. --with-interbase[=DIR] Dolacz obsluge InterBase. DIR to katalog instalacji programu InterBase, domyslnie /usr/interbase. --with-ldap[=DIR] Dolacz obsluge LDAP. DIR to katalog instalacji LDAP. Parametr ten dolacza obsluge protokolu LDAP (Lightweight Directory Access Protocol). DIR to katalog instalacji LDAP, domyslnie /usr/local/ldap. --with-msql[=DIR] Dolacz obsluge mSQL. Parametrem tej opcji jest katalog instalacji mSQL, domyslnie /usr/local/Hughes. Jest to domyslne miejsce instalacji dystrybucji mSQL 2.0. Skrypt configure automatycznie wykrywa ktra wersja mSQL jest zainstalowana PHP obsluguje obie wersje, 1.0 i 2.0, ale jesli skompilujesz PHP z mSQL 1.0, mozesz korzystac tylko z baz danych mSQL 1.0 i odwrotnie. Patrz takze: Dyrektywy konfiguracji mSQL w dodatku D. --with-mysql[=DIR] Dolacz obsluge MySQL. DIR to katalog instalacji MySQL. Jesli nie zostanie podany, uzyte zostana wbudowane biblioteki MySQL. Ta opcja jest domyslnie wlaczona. Patrz takze: Dyrektywy konfiguracji MySQL w dodatku D. --with-ndbm[=DIR] Dolacz obsluge NDBM. --with-oci8[=DIR] Dolacz obsluge Oracle-oci8. Domyslnie DIR to $ORACLE_HOME. --with-oracle[=DIR] Dolacz obsluge bazy danych Oracle-oci7. Domyslnie DIR to $ORACLE_HOME. Zostalo ono przetestowane i powinno dzialac przynajmniej z wersjami Oracle 7.0 do 7.3. Parametrem jest katalog ORACLE_HOME. Nie musisz podawac tego parametru, jesli skonfigurowane zostalo srodowisko Oracle. --with-pgsql[=DIR] Dolacz obsluge PostgreSQL. DIR to katalog instalacji PostgreSQL, domyslnie /usr/local/pgsql. Ustaw DIR na shared aby zbudowac jako obiekt dolaczany dynamicznie (dl), lub shared,DIR aby zbudowac jako dl i jednoczesnie podac DIR. --with-solid[=DIR] Dolacz obsluge Solid. DIR to katalog instalacji Solid, domyslnie /usr/local/solid. --with-sybase-ct[=DIR] Dolacz obsluge Sybase-CT. DIR to katalog domowy Sybase, domyslnie /home/sybase. --with-sybase[=DIR] Dolacz obsluge Sybase-DB. DIR to katalog domowy Sybase, domyslnie /home/sybase. 373 PHP Kompendium wiedzy

--with-openlink[=DIR] Dolacz obsluge OpenLink ODBC. DIR to katalog instalacji OpenLink, domyslnie /usr/local/openlink. --with-iodbc[=DIR] Dolacz obsluge iODBC. DIR jest to katalog instalacji iODBC, domyslnie /usr/local. Ta opcja zostala stworzona dla iODBC Driver Manager, darmowo rozpowszechnianego menedzera sterownikw ODBC, ktry dziala na rznych odmianach Uniksa. --with-custom-odbc[=DIR] Dolacza obsluge niestandardowej biblioteki ODBC. Parametrem jest glwny katalog biblioteki, domyslnie /usr/local. Ta opcja jest uzywana tylko, gdy zdefiniowales CUSTOM_ODBC_LIBS przy uruchomieniu skryptu configure. Niezbedne jest takze wstawienie prawidlowego pliku odbc.h na sciezke include. Jesli nie posiadasz takiego pliku, stwrz go i dolacz stamtad swj wlasny naglwek. Naglwek taki moze wymagac pewnych definicji zwlaszcza, jesli jest to biblioteka wieloplatformowa. Zdefiniuj je w CFLAGS. Mozesz na przyklad uzywac Sybase SQL Anywhere na QNX w nastepujacy sposb:
CFLAGS=-DODBC_QNX LDFLAGS=-lunix CUSTOM_ODBC_LIBS="-ldblib -lodbc" ./configure --with-customodbc=/usr/lib/sqlany50

--with-unixODBC[=DIR] Dolacz obsluge unixODBC. DIR to katalog instalacji unixODBC, domyslnie /usr/local. --with-velocis[=DIR] Dolacz obsluge Velocis. DIR to katalog instalacji Velocis, domyslnie /usr/local/velocis.

Handel elektroniczny
--with-ccvs[=DIR] Dolacza do PHP4 obsluge CCVS. DIR to katalog instalacji CCVS. --with-cybercash[=DIR] Dolacza obsluge CyberCash. DIR to katalog instalacji CyberCash MCK. --with-pfpro[=DIR] Dolacz obsluge Verisign Payflow Pro.

Grafika
--enable-freetype-4bit-antialias-hack Dolacz obsluge FreeType2 (eksperymentalne). --with-gd[=DIR] Dolacz obsluge GD (DIR to katalog instalacji GD). Ustaw DIR jako shared aby zbudowac rozszerzenie jako modul wspldzielony, lub shared,DIR aby zbudowac rozszerzenie jako modul i jednoczesnie podac DIR. --without-gd Wylacz obsluge GD. Dodatek C. Opcje kompilacji PHP 374

--with-jpeg-dir[=DIR] Katalog jpeg dla pdflib 3.x. --with-png-dir[=DIR] Katalog png dla pdflib 3.x. --with-t1lib[=DIR] Dolacz obsluge T1lib. --with-tiff-dir[=DIR] Katalog tiff dla pdflib 3.x. --with-ttf[=DIR] Dolacz obsluge FreeType. --with-xpm-dir[=DIR] Katalog xpm dla gd-1.8+.

Rzne
--disable-libtool-lock Unikaj blokowania (moze to przerwac rwnolegle budowanie). --disable-pear Nie instaluj PEAR. --disable-pic Wylacz PIC dla obiektw wspldzielonych. --disable-posix Wylacz funkcje POSIX. --disable-rpath Wylacz przekazywanie dodatkowych sciezek poszukiwania bibliotek. --disable-session Wylacz obsluge sesji. --enable-bcmath Kompiluj z funkcjami matematycznymi o dowolnej dokladnosci. Przeczytaj plik README-BCMATH aby uzyskac informacje na temat sposobu instalacji tego modulu. Funkcje te pozwalaja operowac na liczbach wykraczajacych poza zakresy dozwolone przez zwykle liczby stalo i zmiennoprzecinkowe. --enable-c9x-inline Wlacz semantyke C9x-inline.

375

PHP Kompendium wiedzy

--enable-calendar Wlacz obsluge konwersji kalendarza. --enable-debug Kompiluj z symbolami dla debuggera. --enable-discard-path Jesli ta opcja zostanie wlaczona, pliki programu CGI PHP moga byc bezpiecznie umieszczone poza drzewem serwera WWW i uzytkownicy nie beda mogli obchodzic zabezpieczen .htaccess. --enable-dmalloc Wlacz dmalloc. --enable-exif Wlacz obsluge exif. --enable-experimental-zts Ta opcja najprawdopodobniej przerwie proces kompilacji. --enable-fast-install[=PKGS] Optymalizacja dla szybkiej instalacji (domyslnie yes). --enable-force-cgi-redirect Wlacz sprawdzanie bezpieczenstwa dla wewnetrznych przekierowan serwera. Powinienes uzyc tej opcji, jesli uzywasz wersji CGI z serwerem Apache.

--enable-inline-optimization
Jesli masz duzo pamieci i uzywasz gcc mozesz sprbowac wlaczyc ta opcje. --enable-libgcc Wlacz jawne laczenie z libgcc. --enable-maintainer-mode Wlacz reguly i zaleznosci programu make nie przydatne (i czasem niejasne) dla zwyklego uzytkownika. --enable-memory-limit Kompiluj z obsluga limitowania pamieci. --enable-safe-mode Wlacz prace w trybie bezpiecznym. --enable-satellite Wlacz obsluge CORBA przez Satellite (wymaga ORBit). --enable-shared[=PKGS] Buduj biblioteki wspldzielone (domyslnie yes).

Dodatek C. Opcje kompilacji PHP

376

--enable-sigchild Wlacz obsluge SIGCHLD przez PHP. --enable-static[=PKGS] Buduj statyczne biblioteki (domyslnie yes). --enable-sysvsem Wlacz obsluge semaforw dla System V. --enable-sysvshm Wlacz obsluge pamieci wspldzielonej dla System V. --enable-trans-sid Wlacz przezroczyste propagowanie identyfikatora sesji. --with-cdb[=DIR] Dolacz obsluge CDB. --with-config-file-path=PATH Ustawia sciezke gdzie powinien sie znajdowac plik php.ini. Domyslnie /usr/local/lib. --with-cpdflib[=DIR] Dolacz obsluge cpdflib (wymaga cpdflib >= 2). DIR to katalog instalacji cpdflib, domyslnie /usr. --with-esoob[=DIR] Dolacz obsluge Easysoft OOB. DIR to katalog instalacji OOB, domyslnie /usr/local/easysoft/oob/client. --with-exec-dir[=DIR] W trybie bezpiecznym pozwl na uruchamianie plikw wykonywalnych tylko w DIR, domyslnie /usr/local/php/bin. --with-fdftk[=DIR] Dolacz obsluge fdftk. DIR to katalog instalacji fdftk, domyslnie /usr/local. --with-gnu-ld Zalz, ze kompilator C uzywa GNU ld [domyslnie no] --with-icap[=DIR] Dolacz obsluge ICAP. --with-imap[=DIR] Dolacz obsluge protokolu IMAP. DIR jest to katalog gdzie znajduja sie pliki naglwkowe IMAP i plik cclient. --with-java[=DIR] Dolacz obsluge jezyka Java. DIR to katalog gdzie zainstalowane jest JDK. To rozszerzenie moze byc zbudowane tylko jako obiekt dynamicznie dolaczany (dl). PHP Kompendium wiedzy

377

--with-kerberos[=DIR] Dolacz obsluge Kerberos w protokole IMAP. --with-mcal[=DIR] Dolacz obsluge MCAL. --with-mcrypt[=DIR] Dolacz obsluge mcrypt. DIR to katalog instalacji mcrypt. --with-mhash[=DIR] Dolacz obsluge mhash. DIR to katalog gdzie zainstalowano mhash. --with-mm[=DIR] Dolacz obsluge mm do przechowywania sesji. --with-mod_charset Wlacz transfer tablic dla mod_charset (Rosyjski Apache). --with-pdflib[=DIR] Dolacz obsluge pdflib 3.x/4.x. DIR to katalog instalacji pdflib, domyslnie /usr/local. --with-readline[=DIR] Dolacz obsluge readline. DIR to katalog instalacji readline. --with-regex=TYPE Typ biblioteki regex: system, apache, php. --with-servlet[=DIR] Dolacz obsluge serwletw. DIR to katalog instalacji JSDK. To SAPI wymaga, aby rozszerzenie Java bylo zbudowane jako obiekt dolaczany dynamicznie. --with-swf[=DIR] Dolacz obsluge swf. --with-tsrm-pth[=pth-config] Uzyj GNU Pth. --with-tsrm-pthreads Uzyj watkw POSIX (domyslnie). --with-zlib-dir[=DIR] Katalog zlib dla pdflib 3.x lub dolacz obsluge zlib. --with-zlib[=DIR] Dolacz obsluge zlib (wymaga zlib >= 1.0.9). DIR to katalog instalacji zlib, domyslnie /usr.

Dodatek C. Opcje kompilacji PHP

378

--without-pcre-regex Nie dolaczaj obslugi Perl Compatible Regular Expressions. Jesli nie chcesz uzywac wbudowanej biblioteki uzyj opcji --with-pcre-regex=DIR, aby podac lokalizacje plikw naglwkowych i bibliotek.

Siec
--with-curl[=DIR] Dolacz obsluge CURL. --enable-ftp Wlacz obsluge FTP. --disable-url-fopen-wrapper Wylacz wrapper adresw URL dla polecenia HTTP lub FTP. --with-mod-dav=DIR Dolacz obsluge DAV poprzez modul Apache mod_dav. DIR to katalog instalacji mod_dav (tylko jako modul Apache). --with-openssl[=DIR] Dolacz obsluge OpenSSL w SNMP. --with-snmp[=DIR] Dolacz obsluge SNMP. DIR to katalog instalacji SNMP, domyslnie przeszukuje wiele czestych lokalizacji instalacji snmp. Ustaw DIR na shared aby zbudowac jako obiekt dynamicznie dolaczany (dl), lub shared,DIR aby zbudowac jako dl i jednoczesnie podac DIR. --enable-ucd-snmp-hack Wlacz poprawke UCD SNMP. --enable-sockets Wlacz obsluge gniazd. --with-yaz[=DIR] Dolacz obsluge YAZ (ANSI/NISO Z39.50). DIR to katalog instalacji YAZ. --enable-yp Dolacz obsluge YP.
fopen(),

ktry pozwala na dostep do plikw przez protokoly

Dzialanie PHP
--enable-magic-quotes Wlacz domyslne magic quotes.

379

PHP Kompendium wiedzy

--disable-short-tags Wylacz mozliwosc uzywania krtkiej formy znacznikw otwierajacych <?.

Serwer
--with-aolserver-src=DIR Okresl sciezke do zrdlowej dystrybucji AOLserver. --with-aolserver=DIR Okresl sciezke do zainstalowanego AOLserver. --with-apache[=DIR] Zbuduj modul Apache. DIR to katalog bazowy Apache, domyslnie /usr/local/etc/httpd. --with-apxs[=FILE] Zbuduj modul wspldzielony Apache. FILE to opcjonalna sciezka do narzedzia apxs z pakietu Apache, domyslnie apxs. --enable-versioning Eksportuj tylko wymagane symbole. Przejrzyj plik INSTALL, aby uzyskac wiecej informacji. --with-fhttpd[=DIR] Buduj modul fhttpd. DIR to katalog ze zrdlami fhttpd, domyslnie /usr/local/src/fhttpd. --with-nsapi=DIR Okresl sciezke do zainstalowanego Netscape. --with-pi3web=DIR Buduj PHP jako modul dla Pi3Web. --with-roxen=DIR Buduj PHP jako modul Pike. DIR to katalog instalacji Roxen, zazwyczaj /usr/local/roxen/server. --enable-roxen-zts Buduj modul Roxen uzywajac Zend Thread Safety ( bezpieczne watki Zend). --with-zeus=DIR Buduj PHP jako modul ISAPI do uzycia z Zeus.

Tekst i jezyk
--with-aspell[=DIR] Dolacz obsluge ASPELL.

Dodatek C. Opcje kompilacji PHP

380

--with-gettext[=DIR] Dolacz obsluge GNU gettext. DIR to katalog instalacji gettext, domyslnie /usr/local. --with-pspell[=DIR] Dolacz obsluge PSPELL. --with-recode[=DIR] Dolacz obsluge redcode. DIR to katalog instalacji redcode.

XML
--with-dom[=DIR] Dolacz obsluge DOM (wymaga libxml >= 2.0). DIR to katalog instalacji libxml, domyslnie /usr. --enable-sablot-errors-descriptive Wlacz bledy opisowe. --with-sablot[=DIR] Dolacz obsluge Sablotron. --enable-wddx Wlacz obsluge WDDX. --disable-xml Wylacz obsluge wbudowanej biblioteki XML expat.

381

PHP Kompendium wiedzy

Dodatek D. Opcje konfiguracji PHP


Oglne dyrektywy konfiguracji
allow_url_fopen boolean Ta opcja wlacza interfejsy do funkcji fopen rozpoznajace adresy URL, pozwalajace na dostep do obiektw URL jak do plikw. Domyslne interfejsy pozwalaja na dostep do zdalnych plikw korzystajac z protokolw ftp lub http. Niektre rozszerzenia, takie jak zlib, moga rejestrowac dodatkowe interfejsy. Dyrektywa ta zostala wprowadzona zaraz po wyjsciu wersji 4.0.3. Dla wersji 4.0.3 i wyzszych mozesz wylaczyc ta opcje w czasie kompilacji uzywajac przelacznika --disable-url-fopen-wrapper. asp_tags boolean Wlacza mozliwosc uzycia znacznikw ASP (<% %>) razem z normalnymi znacznikami (<?php ?>). Dotyczy to takze skrtowego wyswietlania wartosci zmiennych typu <%= $value %>. Obsluga znacznikw ASP zostala dodana w wersji 3.0.4. auto_append_file string Okresla nazwe pliku, ktry jest automatycznie przetwarzany po glwnym pliku. Plik jest dolaczany tak, jakby zostal dolaczony funkcja include(), a wiec uzywana jest opcja include_path. Specjalna wartosc none wylacza automatyczne dolaczanie. Jesli skrypt zostanie zakonczony przez exit(), nie dojdzie do dolaczenia. auto_prepend_file string Okresla nazwe pliku, ktry bedzie automatycznie przetwarzany przed glwnym plikiem. Plik jest dolaczany tak, jakby wywolana byla funkcja include(), a wiec uzywana jest opcja include_path. Specjalna wartosc none wylacza automatyczne poprzedzanie pliku. cgi_ext string display_errors boolean Okresla, czy bledy powinny byc wyswietlane jako czesc wynikowego kodu HTML czy nie. doc_root string Glwny katalog PHP na serwerze. Uzywane tylko, jesli jest to ciag niepusty. Jesli PHP jest skonfigurowane do pracy w trybie bezpiecznym, pliki spoza tego katalogu nie beda udostepniane. engine boolean Ta dyrektywa jest przydatna tylko przy pracy z PHP w postaci modulu Apache. Jest ona uzywana na witrynach, w ktrych chce sie wlaczac i wylaczac analizowanie plikw PHP na podstawie katalogu lub na podstawie nazwy serwera wirtualnego. Umieszczajac engine off we wlasciwych miejscach pliku httpd.conf PHP moze byc aktywne lub nieaktywne.

error_log string Nazwa pliku, gdzie maja byc zapisywane bledy. Jesli uzyta jest specjalna wartosc syslog, bledy wysylane sa do dziennika systemowego. W systemach Unix oznacza to syslog(3) a na Windows NT, dziennik zdarzen. Dziennik systemowy nie jest obslugiwany przez Windows 95. error_reporting integer Ustaw poziom raportowania. Wiecej szczeglw znajduje sie przy opisie funkcji error_reporting(). open_basedir string Ogranicz pliki, ktre moga byc otwierane przez PHP do podanego drzewa katalogw. Jesli skrypt prbuje otworzyc plik, np. przez funkcje fopen() lub gzopen(), sprawdzane jest polozenie pliku. Jezeli plik znajduje sie poza podanym drzewem katalogw, PHP odmawia otwarcia takiego pliku. Wszystkie dowiazania symboliczne sa rozwiazywane, wiec nie jest mozliwe ominiecie tego ograniczenia przez lacza symboliczne. Wartosc specjalna . wskazuje, ze katalog w ktrym znajduje sie skrypt bedzie uznawany jako katalog bazowy dla tej dyrektywy. W systemie Windows, katalogi oddzielaj srednikami. Na wszystkich innych systemach, oddzielaj katalogi dwukropkami. Jezeli PHP pracuje jako modul Apache, sciezki open_basedir katalogw nadrzednych sa automatycznie dziedziczone. Obsluga dla wielu katalogw zostala dodana w 3.0.7. Domyslnie PHP pozwala na otwieranie wszystkich plikw. gpc_order string Ustaw kolejnosc analizowania zmiennych GET, POST i COOKIE. Domyslne ustawienie do GPC. Ustawienie tej dyrektywy np. na GP spowoduje, ze PHP bedzie calkowicie ignorowal cookie i przebijal wszystkie zmienne otrzymane metoda GET zmiennymi o tej samej nazwie otrzymanymi metoda POST. ignore_user_abort string Domyslnie wlaczona. Jesli zostanie zmieniona na Off, skrypty beda przerywane, jak tylko beda prbowaly wyslac cos do klienta, ktry przerwal polaczenie. Patrz rwniez: ignore_user_abort(). include_path string Okresla liste katalogw, gdzie funkcje require(), include() i fopen_with_path() beda szukaly plikw. Format jest podobny do zmiennej srodowiskowej PATH: lista katalogw oddzielona dwukropkiem na systemach Unix lub srednikiem na systemach Windows. Domyslna wartoscia tej dyrektywy jest . (tylko biezacy katalog). isapi_ext string log_errors boolean Ustawia czy komunikaty o bledach skryptu maja byc zapisywane do dziennika bledw serwera. W zwiazku z tym ta opcja jest specyficzna dla poszczeglnych serwerw. magic_quotes_gpc boolean Ustawia stan magic_quotes dla operacji GPC (GET, POST, COOKIE). Jesli magic_quotes sa wlaczone, wszystkie znaki ' (apostrof), " (cudzyslw), \ (lewy ukosnik) i znaki NULL sa zamieniane na sekwencje sterujace przez dodanie przed te znaki znaku \. Jesli wlaczona jest takze dyrektywa magic_quotes_sybase, wszystkie apostrofy sa zamieniane na sekwencje sterujace przez dodanie apostrofu zamiast znaku \. magic_quotes_runtime boolean Jesli wlaczona jest dyrektywa magic_quotes_runtime, wiekszosc funkcji, ktre zwracaja dane z dowolnych zewnetrznych zrdel, wlaczajac w to bazy danych i pliki tekstowe, bedzie zwracala dane z apostrofami i cudzyslowami zamienionymi na sekwencje sterujace przy pomocy znaku \. Jesli wlaczona jest takze opcja magic_quotes_sybase, apostrof beda zamieniany na sekwencje strujaca przy pomocy apostrofu zamiast znaku \. 383 PHP Kompendium wiedzy

magic_quotes_sybase boolean Jesli wlaczona jest opcja magic_quotes_sybase, apostrof bedzie zamieniany na sekwencje sterujaca uzywajac apostrofu zamiast znaku \, jesli wlaczona jest opcja magic_quotes_gpc i (lub) magic_quotes_runtime. max_execution_time integer Dyrektywa to okresla maksymalny czas w sekundach wykonywania skryptu, zanim zostanie przerwany przez analizator. Pomaga to w zapobieganiu blokowania serwera przez zle napisane skrypty. Domyslne ustawienie to 30. memory_limit integer Dyrektywa ta ustawia maksymalna wielkosc pamieci w bajtach, ktra skrypt moze sobie przydzielic. Pomaga to w zapobieganiu przydzieleniu calej dostepnej pamieci serwera przez zle napisane skrypty. nsapi_ext string register_globals boolean Ustala, czy rejestrowac zmienne srodowiska, GET, POST, Cookie, i serwera jako zmienne globalne. Mozesz wylaczyc te opcje, jesli nie chcesz zasmiecic globalnej przestrzeni zmiennych swoich skryptw przez dane uzytkownika. Ma to najwiekszy sens, jesli uzywane jest w polaczeniu z opcja track_vars w takim przypadku do zmiennych EGCPS mozliwy jest przez zmienne globalne $HTTP_ENV_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS, i $HTTP_SERVER_VARS. short_open_tag boolean Ustala, czy dozwolona jest skrcona forma znacznika otwierajacego PHP (<? ?>). Jesli chcesz uzywac PHP w polaczeniu z XML, powinienes wylaczyc ta opcje. Jesli ta opcja jest wylaczona, musisz uzywac dlugiej postaci znacznika otwierajacego. (<?php ?>). sql.safe_mode boolean track_errors boolean Jesli dyrektywa ta jest wlaczona, ostatni komunikat bledu bedzie dostepna jako zmienna globalna $php_errormsg. track_vars boolean Jesli ta dyrektywa jest wlaczona, zmienne srodowiska, GET, POST, Cookie i serwera beda dostepne w globalnych tablicach asocjacyjnych $HTTP_ENV_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS i $HTTP_SERVER_VARS. Zauwaz, ze od PHP 4.0.3 dyrektywa track_vars jest zawsze wlaczona. upload_tmp_dir string Katalog tymczasowy uzywany do przechowywania plikw podczas obslugiwania przesylania plikw. Musi byc to katalog z prawem zapisu dla uzytkownika, jako ktry pracuje PHP. user_dir string Podstawowa nazwa katalogu uzywanego jako katalog domowy uzytkownika dla plikw PHP, na przyklad public_html. warn_plus_overloading boolean Jesli dyrektywa ta jest wlaczona, PHP bedzie wyswietlal ostrzezenie, jesli operator plus (+) zostal uzyty na ciagach. Dzieki temu latwiej jest znalezc skrypty, ktre wymagaja uzycia operatora sklejania ciagw (.). Dodatek D. Opcje konfiguracji PHP 384

Dyrektywy konfiguracji poczty


SMTP string Nazwa DND lub adres IP serwera SMTP, ktrego powinien uzyc PHP dla Windows podczas wysylania poczty za pomoca funkcji mail(). sendmail_from string Pole From: (adres nadawcy) przesylek pocztowych wysylanych z PHP dla Windows. sendmail_path string Katalog w ktrym znajduje sie sendmail, zwykle /usr/sbin/sendmail lub /usr/lib/sendmail. Skrypt configure prbuje samodzielnie odszukac ten program i ustawic wartosc domyslna, ale jezeli nie uda sie to, mozna ja samodzielnie ustawic. Systemy nie korzystajace z sendmail powinny ustawic ta opcje dla jego odpowiednika w zainstalowanym systemie poczty. Na przyklad: uzytkownicy Qmail zwykle ustawiaja ja na /var/qmail/bin/sendmail.

Dyrektywy konfiguracji trybu bezpiecznego


safe_mode boolean Okresla, czy PHP ma pracowac w trybie bezpiecznym. safe_mode_exec_dir string Jesli PHP pracuje w trybie bezpiecznym, funkcje wykonania programw z katalogw innych niz podany.
system()

i inne wywolujace inne programy, odmwia

Dyrektywy konfiguracji debuggera


debugger.host string Nazwa lub adres IP komputera uzywanego przez debugger. debugger.port string Numer portu uzywany przez debugger. debugger.enabled boolean Okresla, czy debugger jest wlaczony.

Dyrektywy ladowania rozszerzen


enable_dl boolean Ta dyrektywa jest jedynie przydatna przy pracy PHP jako modul Apache. Mozesz wlaczac i wylaczac mozliwosc dynamicznego ladowania rozszerzen PHP przez funkcje dl() zaleznie od katalogu lub serwera wirtualnego. Glwnym powodem wylaczania dynamicznego ladowania rozszerzen jest kwestia bezpieczenstwa. Uzywajac dynamicznych rozszerzen mozliwe jest ominiecie praktycznie wszystkich ograniczen safe_mode i open_basedir. Domyslnie zezwalane jest dynamiczne ladowanie, z wyjatkiem pracy w trybie bezpiecznym. W trybie bezpiecznym korzystanie z funkcji dl() jest zawsze zabronione. PHP Kompendium wiedzy 385

extension_dir string Katalog, w ktrym PHP szuka dynamicznie dolaczanych rozszerzen. extension string Ktre dynamicznie ladowane rozszerzenia ladowac przy starcie PHP.

Dyrektywy konfiguracji MySQL


mysql.allow_persistent boolean Czy pozwalac na trwale polaczenia MySQL (persistent connections). mysql.default_host string Domyslny adres serwera, ktry bedzie uzywany przy laczeniu sie z serwerem baz danych, jesli nie zostanie podany zaden inny adres. mysql.default_user string Domyslna nazwa uzytkownika, ktra bedzie uzywana przy laczeniu sie z serwerem baz danych, jesli nie zostanie podana zadna inna nazwa. mysql.default_password string Domyslne haslo, ktre bedzie uzyte przy laczeniu sie z serwerem baz danych, jesli nie zostanie podane zadne inne haslo. mysql.max_persistent integer Maksymalna liczba stalych polaczen MySQL na kazdy proces. mysql.max_links integer Maksymalna liczba polaczen MySQL na proces, wliczajac w to polaczenia stale.

Dyrektywy konfiguracji mSQL


msql.allow_persistent boolean Czy pozwalac na trwale polaczenia mSQL. msql.max_persistent integer Maksymalna liczba trwalych polaczen mSQL na kazdy proces. msql.max_links integer Maksymalna liczba polaczen mSQL na kazdy proces, wliczajac w to polaczenia trwale.

Dyrektywy konfiguracji PostgreSQL


pgsql.allow_persistent boolean Czy pozwalac na trwale polaczenia PostgreSQL. Dodatek D. Opcje konfiguracji PHP 386

pgsql.max_persistent integer Maksymalna liczba trwalych polaczen PostgreSQL na kazdy proces. pgsql.max_links integer Maksymalna liczba polaczen PostgreSQL na kazdy proces, wliczajac w to polaczenia trwale.

Dyrektywy konfiguracji Sybase


sybase.allow_persistent boolean Czy pozwalac na trwale polaczenia Sybase. sybase.max_persistent integer Maksymalna liczba trwalych polaczen Sybase na kazdy proces. sybase.max_links integer Maksymalna liczba polaczen Sybase na kazdy proces, wliczajac w to polaczenia trwale.

Dyrektywy konfiguracji Sybase-CT


sybct.allow_persistent boolean Czy pozwalac na trwale polaczenia Sybase-CT. Domyslnie wlaczone. sybct.max_persistent integer Maksymalna liczba trwalych polaczen Sybase-CT na kazdy proces. Domysla wartoscia jest -1, co oznacza brak limitu. sybct.max_links integer Maksymalna liczba polaczen Sybase-CT na proces, wlaczajac w to polaczenia trwale. Domyslna wartosc to -1, co oznacza brak limitu. sybct.min_server_severity integer Wiadomosci serwera z waga wieksza lub rwna sybct.min_server_severity beda zglaszane jako ostrzezenia. Wartosc ta moze byc zmieniona takze przez wywolanie sybase_min_server_severity(). Domyslna wartosc to 10, co powoduje raportowanie bledw o wadze informacja lub wiekszej. sybct.min_client_severity integer Wiadomosci biblioteki klienta o wadze wieksza lub rwna sybct.min_client_severity beda zglaszane jako bledy. Wartosc ta moze byc zmieniona takze przez wywolanie sybase_min_client_severity(). Domyslna wartosc to 10, co praktycznie wylacza zglaszanie bledw. sybct.login_timeout integer Maksymalny czas oczekiwania na polaczenie zanim zwrcony bedzie blad. Zauwaz, ze jesli dojdzie do skonczenia czasu max_execution_time w trakcie oczekiwania na polaczenie, twj skrypt zostanie zakonczony zanim bedzie mgl podjac jakiekolwiek dzialania wywolywane w przypadku nieudanego polaczenia. Domyslna wartosc to jedna minuta. 387 PHP Kompendium wiedzy

sybct.timeout integer Maksymalny czas (w sekundach) oczekiwania na wykonanie select_db lub zapytania, po ktrym zwrcony zostanie blad. Zauwaz, ze jesli dojdzie do skonczenia czasu max_execution_time w trakcie oczekiwania na polaczenie, twj skrypt zostanie zakonczony zanim bedzie mgl podjac jakiekolwiek dzialania obslugujace bledy wykonania. Domyslnie nie ma zadnych ograniczen. sybct.hostname string Nazwa komputera, ktry bedzie wyswietlany w sp_who. Domyslna wartoscia jest pusty ciag.

Dyrektywy konfiguracji Informix


ifx.allow_persistent boolean Czy pozwalac na trwale polaczenia Informix. ifx.max_persistent integer Maksymalna liczba trwalych polaczen Informix na kazdy proces. ifx.max_links integer Maksymalna liczba polaczen Informix na kazdy proces, wlaczajac w to polaczenia trwale. ifx.default_host string Domyslny adres komputera uzywany, jesli nie podano innego w ifx_connect() lub ifx_pconnect(). ifx.default_user string Domyslny identyfikator uzytkownika uzywany, jesli nie podano innego w
ifx_pconnect(). ifx_connect()

lub

ifx.default_password string Domyslne haslo uzywane jesli nie podano innego w ifx_connect() lub ifx_pconnect(). ifx.blobinfile boolean Ustaw na TRUE jesli chcesz zwracac kolumny blob do pliku, lub wartosc tej dyrektywy korzystajac z ifx_blobinfile_mode(). ifx.textasvarchar boolean Ustaw na TRUE jesli chcesz w zapytaniach zwracac kolumny TEXT jako zwykle ciagi, lub FALSE jesli chcesz uzywac identyfikatorw blob. Mozesz zmienic wartosc tej dyrektywy korzystajac z ifx_textasvarchar(). ifx.byteasvarchar boolean Ustaw na TRUE jesli chcesz w zapytaniach zwracac kolumny BYTE jak zwykle ciagi, lub FALSE jesli chcesz uzywac identyfikatorw blob. Mozesz zmienic wartosc tej dyrektywy korzystajac z ifx_textasvarchar(). ifx.charasvarchar boolean Ustaw na TRUE jesli chcesz obcinac poczatkowe spacje z kolumn CHAR przy ich pobieraniu.
FALSE

jesli do pamieci. Mozesz zmienic

Dodatek D. Opcje konfiguracji PHP

388

ifx.nullformat boolean Ustaw na TRUE jesli chcesz zwracac kolumny NULL jako ciag "NULL", lub na FALSE jesli chcesz aby byly zwracane jako pusty ciag. Mozesz zmienic wartosc tej dyrektywy korzystajac z ifx_nullformat().

Dyrektywy konfiguracji BC Math


bcmath.scale integer Liczba dziesietnych cyfr dla wszystkich funkcji bcmath.

Dyrektywy konfiguracji mozliwosci przegladarek


browscap string Nazwa pliku opisujacego mozliwosci przegladarek. Zobacz takze get_browser().

Dyrektywy konfiguracji Zunifikowanego ODBC


uodbc.default_db string Zrdlo danych ODBC uzywane jesli nie podane zostalo inne w odbc_connect() lub odbc_pconnect(). uodbc.default_user string Nazwa uzytkownika uzywana, jesli inna nie zostala podana w odbc_connect() lub odbc_pconnect(). uodbc.default_pw string Haslo uzywane, jesli inne nie zostalo podane w odbc_connect() lub odbc_pconnect(). uodbc.allow_persistent boolean Czy pozwalac na trwalych polaczenia ODBC. uodbc.max_persistent integer Maksymalna liczba trwalych polaczen ODBC na kazdy proces. uodbc.max_links integer Maksymalna liczba polaczen ODBC na kazdy proces, wlaczajac w to polaczenia trwale.

389

PHP Kompendium wiedzy

Dodatek E. Zasoby Sieci


Podstawowym zrdlem wiedzy na temat PHP jest oficjalna witryna WWW dostepna pod adresem http://www.php.net. Mozna tam znalezc informacje na temat list wysylkowych, innych interesujacych witryn oraz kompletny podrecznik jezyka PHP. Ponizsza tabela zawiera krtka liste interesujacych witryn na temat PHP. URL Opis http://www.php4devguide.com/ Witryna poswiecona tek ksiazce. Zawiera interesujace lacza i poprawki do tej ksiazki. http://www.mysql.com/ Oficjalna witryna bazy danych MySQL. http://phpbuilder.com/ Swietna witryna zawierajaca artykuly, przykladu kodu inne informacje zwiazane z programowaniem w PHP. http://www.thewebmasters.net/ Witryna FastTemplate i innych bibliotek klas uzywanych w tej ksiazce. http://phplib.netuse.de/ Witryna poswiecona PHPLib, biblioteki klas uzywanych w tej ksiazce w niektrych przykladach dotyczacych baz danych, sesji i autoryzacji.

You might also like