Linux Programming Professional, R-16-t, Szablon dla tlumaczy


16. Tworzenie interfejsu WWW za pomocą PHP

Pojawienie się sieci komputerowej o ogólnoświatowym zasięgu WWW zaowocowało u swego zarania pojawieniem się kilku technologii umożliwiających wykorzystanie aplikacji WWW do zadań poważniejszych niż zwykłe pokazywanie witryn i obrazków. Nie wszystkie technologie były produktem komercyjnych firm wytwarzających oprogramowanie. Niektóre z odnoszących największe sukcesy były technologiami z otwartym dostępem do kodu źródłowego lub bezpłatnym oprogramowaniem. Jedną z takich technologii jest preprocesor hipertekstu PHP (ang. Hypertext Preprocessor PHP), który jest wytwarzającym strony dynamiczne językiem skryptowym po stronie serwera (ang. server side scripting language).

Wraz z wprowadzeniem PHP stało się możliwe wdrożenie profesjonalnych aplikacji WWW dla Linuksa, dużo mniejszym nakładem pracy niż poprzednio. PHP jako język skryptowy po stronie serwera uzupełnia solidność i otwartość Linuksa i razem tworzą poważną i profesjonalną alternatywę dla komercyjnych rozwiązań wdrożenia aplikacji WWW.

W tym rozdziale będziemy poznawać PHP, zwłaszcza w charakterze narzędzia do instalacji aplikacji WWW dla Linuksa. Używać przy tym będziemy bazy danych DVD z poprzednich rozdziałów. Ważniejsze tematy, które poruszymy w tym rozdziale to:

PHP i skrypty po stronie serwera

Ogólnoświatowa sieć komputerowa WWW, jak wiadomo, ewoluowała z obsługi statycznych stron WWW, gdzie witryny WWW odgrywały rolę nieco ważniejszych elektronicznych tablic ogłoszeniowych, aż po pojawienie się stron programowanych poprzez wspólny interfejs bramkowy CGI (ang. Common Gateway Interface). Współczesne witryny WWW mają bardziej wyrafinowane interfejsy użytkownika, jakimi są dynamiczne strony WWW, odpowiadające na działania użytkownika. Skrypty uruchomione czy to na serwerze, czy na przeglądarce pozwalają na dostęp do aplikacji i danych w taki sposób, jaki dotąd był możliwy jedynie przez tradycyjne, tj. nie oparte na WWW, interfejsy użytkownika.

Praca przy pomocy skryptów po stronie klienta (zazwyczaj przy użyciu JavaScript, ale też, okazjonalnie, VBScript) jest ograniczona interpretacją przez przeglądarkę. Natomiast skrypty po stronie serwera, które są albo wbudowane w strony serwera albo są samodzielnymi plikami skryptowymi, są interpretowane przez serwer sieciowy. Serwer następnie wytwarza HTML, który zostaje przekazany do przeglądarki. Rzeczywista siła języków skryptowych po stronie serwera tkwi nie tyle w samej tej właściwości, ale raczej w fakcie, że kilka z tych języków (a PHP jest doskonałym tego przykładem) ma szeroki zestaw funkcji łączności i dostępności interfejsów programowych aplikacji (API), które umożliwiają skryptom oddziaływanie z różnymi bazami danych, serwerami pocztowymi i innymi modułami aplikacji. Wydaje się, że aplety (małe programy użytkowe) Java, czy rozwiązania Sun Microsystems dla osiągania zdolności programowania wewnątrz stron WWW nie sprawdziły się po stronie klienta tak, jak tego oczekiwano.

Praca przy pomocy skryptów po stronie serwera

Tworzenie dynamicznej zawartości, niezbędnej dla aplikacji z prawdziwego zdarzenia po to, by były dostępne poprzez strony WWW, zostało osiągnięte dzięki językom skryptowym po stronie serwera, takim jak PHP. Sposób działania takich języków zazwyczaj zależy od ich indywidualnych właściwości. To doprowadza nas do różnorodnych technologii po stronie serwera i porównania innych języków skryptowych z PHP

Skrypty CGI

Tradycyjnie tworzenie stron WWW odbywa się głównie poprzez CGI, czyli wspólny interfejs bramkowy. Faktyczny skrypt może być napisany w każdym języku skryptowym (a właściwie, w każdym języku programowania, o ile tylko na serwerze jest dostępny jego kompilator lub interpreter), pod warunkiem, że wytworzone dane wyjściowe będą zrozumiałe dla interfejsu CGI. Takie podejście zmniejsza jednak wydajność przedsięwzięcia, ponieważ serwer sieciowy musi tworzyć osobny proces do obsługi wykonania skryptu CGI.

Serwer stron aktywnych

ASP, czyli serwer stron aktywnych (ang. Active Server Pages) jest rozwiązaniem pracy ze skryptami po stronie serwera zaproponowanym przez Microsoft. ASP pozwala programiście łączyć HTML, JScript (propozycja Microsoftu — skrypt po stronie klienta, zbliżony do JavaScript z Netscape) i VBScript w celu wytworzenia dynamicznych stron HTML. Z interfejsem COM, czyli modelem obiektów składowych (ang. Component Object Model) jest możliwe łączenie z wieloma innymi modułami aplikacji. Istotnym ograniczeniem ASP jest to, że jest obsługiwany tylko na platformach Microsoftu.

Serwer stron Java i serwlety

JSP, czyli serwer stron Javy (ang. Java Server Pages) jest rozwiązaniem Java pełnej krwi, bardzo zbliżonym do PHP. Różnica polega tylko na tym, że skrypt JSP jest interpretowany przez wirtualną maszynę Javy, tj. JVM (ang. Java Virtual Machine). Pojawienie się prośby o skrypt JSP powoduje utworzenie przez serwer WWW serwletu Java (ang. Java Servlet), który wykonuje się na JVM, produkując HTML. Inny aspekt JSP to znaczna liczba właściwości i związana z tym dłuższa krzywa uczenia przy zapoznawaniu się z tą technologią.

Pisanie skryptów w PHP

Obecnie PHP jest obsługiwany na wielu platformach systemowych i w powiązaniu z licznymi serwerami WWW. Na serwerze Apache PHP może być zainstalowany albo jako interpreter CGI, albo jako moduł Apache. To drugie rozwiązanie jest zalecanym sposobem instalacji PHP w sytuacji, gdy głównym kryterium jest wydajność, ponieważ nie wiąże się to z tworzeniem osobnego procesu tak, jak byłoby to konieczne przy instalacji PHP pierwszą metodą. Czytelnicy wystarczająco zachęceni do używania PHP, mogą przejść od razu do podrozdziału na temat instalacji PHP.

Z serwerem Apache, działającym na platformie Linux, PHP jest bardzo groźnym rywalem dla wszystkich wspomnianych wcześniej technologii. Oprócz Linuksa, PHP jest także obsługiwany na platformach systemowych Microsoft Windows NT i Windows 95/98. Niektóre z obsługiwanych serwerów WWW obejmują: fhttpd (o otwartym kodzie dostępu); HS3 do HS5; OmniHTTPd i inne. Na wszystkich tych serwerach WWW, z wyjątkiem Apache, PHP działa tylko jako interpreter CGI, a nie jako wbudowany moduł. I wreszcie najważniejsza cecha: PHP ma otwarty dostęp do kodu źródłowego i jest dostępny całkowicie za darmo.

Można przyjąć (w uogólnieniu), że większość języków skryptowych po stronie serwera zazwyczaj wbudowuje swoje komponenty skryptowe do dokumentu HTML. Kiedy więc serwer WWW odczytuje te komponenty z systemu plików, obsługując żądanie z przeglądarki, to interpretuje skrypt i wytwarza właściwy HTML, który zostanie zwrócony do przeglądarki. Kontrastuje to ze zwykłymi stronami WWW, gdzie serwer pobiera statyczną stronę HTML bezpośrednio z systemu plików i przekazuje ją, bez żadnej interpretacji, do przeglądarki. Przykłady poniżej ilustrują ten przypadek z drobnymi wariacjami na nieśmiertelny temat „Witaj Świecie!”. Pierwszy przykład pokazuje statyczną stronę HTML, a drugi stronę dynamiczną HTML:

<HTML>

<HEAD><TITLE>Witaj Statyczny Swiecie</TITLE></HEAD>

<BODY>

Witaj Swiecie

</BODY>

</HTML>

<HTML>

<HEAD><TITLE>Witaj Dynamiczny Swiecie</TITLE></HEAD>

<BODY>

<?php printf( "Witaj Swiecie\n" ); ?>

</BODY>

</HTML>

Obydwa przykłady wygenerują, w przybliżeniu, te same dane wyjściowe, ale w drugim przykładzie wynik jest interpretacją skryptu PHP przez serwer WWW. Uściślając, to niekoniecznie serwer WWW interpretował skrypt — równie dobrze, interpreter PHP (występujący albo jako moduł serwera WWW, albo jako interpreter CGI) mógł dokonać faktycznej interpretacji.

Możliwości PHP

Rzeczywista siła PHP wyrasta z faktu, że z PHP możliwy jest bezproblemowy dostęp do kilku innych modułów, dzięki dostarczanej przez PHP obsłudze interfejsu programowego aplikacji API. W tym momencie nie od rzeczy jest przyjrzenie się różnorakim modułom, które PHP obsługuje:

Powyższa lista nie wyczerpuje wszystkich możliwości PHP. Wciąż też, wraz z pojawianiem się nowych technologii, zakres obsługi PHP zwiększa się i ewoluuje. W czasie pisania tej książki, ukazała się wersja 4.0, wydana wraz z Zend, który jest dużo szybszym i skrupulatniejszym mechanizmem interpretacyjnym.

Instalacja i konfiguracja PHP

Nadeszła wiekopomna chwila, abyśmy podjęli próbę ujarzmienia PHP na naszych Linuksowych „pudłach”, by od tej pory móc poznawać tajemnice PHP we własnym zakresie.

Dla naszej przykładowej aplikacji niezbędne jest zainstalowanie na komputerze oprogramowania Apache, PHP i PostgreSQL. Kilka wersji dystrybucyjnych Linuksa, w tym RedHat 6.1, zawiera standardowo moduły Apache i PHP (zwykle umieszczone w /usr/lib/apache/), z tym, że plik konfiguracyjny Apache httpd.conf wydaje się mieć wyłączone potrzebne ustawienia. Można te ustawienia uaktywnić przez pozbawienie znaków komentarza następujących wierszy w tym pliku:

AddModule mod_php

LoadModule php_module modules/libphp.so

AddType application/x-httpd-php .php

Po wprowadzeniu tych zmian, należy ponownie uruchomić Apache, by spowodować uwzględnienie poprawek w działaniu. Można to zrobić tak:

# apachectl stop

# apachectl start

Jest to w gruncie rzeczy najszybsza metoda rozpoczęcia pracy z PHP, przy założeniu, że używana dystrybucja Linuksa ma zainstalowane wstępnie moduły Apache i PHP.

Jeśli Apache lub PHP nie zostały zainstalowane wstępnie w wersji dystrybucyjnej, będzie trzeba zainstalować je albo przez zbudowanie ich z kodu źródłowego, albo z pakietów takich jak RedHat RPM, czy Debian .debs. W tym rozdziale będziemy próbować zainstalować i skonfigurować PHP w sposób najbardziej odpowiedni dla tworzonej tutaj aplikacji. Wyczerpującą dyskusję na temat instalacji i konfiguracji zawiera pozycja wydana przez Wrox Press „Professional PHP Programming”, rozdział 2. Dystrybucję PHP można uzyskać w postaci wykonywalnej wersji binarnej, jako RPM, lub jako dystrybucję źródłową. My podążymy drogą Linuksa i zainstalujemy PHP z kodu źródłowego. Na oficjalnej witrynie WWW dla PHP: http://www.php.net udostępniona jest wersja źródłowa PHP.

Budowa i instalacja PHP jako interpretera CGI

Zakładamy, że Apache i PostgreSQL są już zainstalowane, zgodnie z opisem, zamieszczonym w rozdziale o PostgreSQL. Powinniśmy wiedzieć w jakim katalogu Apache i PostgreSQL zostały zainstalowane. Potrzebujemy dystrybucji źródłowej PHP.

$ tar xvfz php-4.x.y.tar.gz

$ ./configure --with-pgsql=DIR

To poinformuje skrypt konfiguracyjny o zamiarze zbudowania PHP z obsługą PostgreSQL. Będziemy później potrzebować PostgreSQL dla naszej aplikacji DVD. Argument DIR opcji --with-pgsql wskazuje katalog dystrybucji PostgreSQL. Jeśli DIR nie jest określony, domyślną lokalizacją jest /usr/local/pgsql.

$ make

Niewielkie prawdopodobieństwo wystąpienia niepowodzenia w trakcie konsolidacji, wiąże się zwykle z brakiem dostępu do bibliotek, wymaganych dla określonych modułów, albo z zainstalowaniem tych bibliotek w nietypowych miejscach. Jeśli biblioteka ma niestandardową lokalizację, należy sprawdzić zmienną środowiskową LD_LIBRARY_PATH. W przypadku jej braku, należy dodać ścieżkę tej biblioteki do zmiennej. Można użyć polecenia ldd aby sprawdzić, czy plik wykonywalny wie, gdzie szukać współużytkowanych bibliotek. Dla przykładu: jeżeli biblioteka libxyz.so ma niestandardową lokalizację: /var/mojalibdir, powinniśmy przed ponownym uruchomieniem make, wykonać w powłoce Bash coś takiego:

$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/var/mojalibdir

# make install

Mamy teraz plik binarny PHP, który może być wykorzystany jako interpreter CGI. Jeśli wszystko przebiegło pomyślnie, mamy teraz interpreter, który możemy użyć do interpretacji skryptów PHP. Na koniec przypominamy o zajrzeniu do podrozdziału „Konfiguracja PHP” poniżej, by dowiedzieć się o możliwości skonfigurowania PHP w minimalnym zakresie, potrzebnym do jego uruchomienia.

Jak wcześniej wspomnieliśmy, możliwa jest również instalacja PHP jako modułu Apache. Jeśli Czytelnika interesuje taki wariant, zapraszamy do kolejnego podrozdziału.

Budowa i instalacja PHP z Apache, jako moduł Apache

Do zbudowania PHP jako modułu Apache również potrzebna jest dystrybucja źródłowa z serwera http://www.apache.org.

$ tar xvfz apache_1.3.x.tar.gz

$ tar xvfz php-4.x.y.tar.gz

$ cd apache_1.3.x

$ ./configure --opcje-konfiguracji-dla-apache

Skrypty configure mogą przyjmować opcje budowania Apache. Opcja -prefix=/www spowoduje skierowanie dystrybucji do katalogu /www , a nie do domyślnego katalogu, jakim zwykle jest /usr/local/apache.

$ cd ../php-4.x.y

$ ./configure --with-apache=../apache_1.3.x --with-pgsql

Opcja --with-apache=../apache_1.3.x wskazuje na budowę do postaci modułu Apache i określa katalog, w którym znajdują się pliki z kodem źródłowym Apache.

$ make

# make install

$ cd ../apache_1.3.x

$ ./configure --activate-module=src/modules/php4/libphp4.a -inne-opcje-apache

Należy zwrócić uwagę, że biblioteka src/modules/php4/libphp4.a została wcześniej utworzona i skopiowana do katalogu dystrybucyjnego Apache podczas procesu budowania PHP. Dla PHP3.x tą biblioteka będzie src/modules/php3/libphp3.a.

# make

# /usr/local/apache/bin/apachectl stop

Powinniśmy to zrobić wyłącznie wtedy, gdy mamy już zainstalowany i uruchomiony serwer Apache. Jeśli dana dystrybucja Linuksa nie zawiera polecenia apachectl, można zakończyć pracę uruchomionej kopii Apache, używając 'killall -9 apache'.

# make install

# /usr/local/apache/bin/apachectl start

Instalacja PHP z pliku RPM

Dla zatwardziałych zwolenników RPM (ang. Red Hat Package Manager), zamierzających ominąć monotonną procedurę ustawienie-konfiguracja-wytworzenie i obrać wyjście RPM (co w tej sytuacji oznaczać będzie instalację PHP z pakietu o formacie specyficznym dla dystrybucji) mamy pewne ostrzeżenie. Wstępnie skompilowane zbiory binarne (rozpowszechniane jako RPM-y) PHP mają taką wadę, że nie oferują plastyczności wyboru odpowiednich połączeń modułów dodawanych add-on. Co więcej, instalacja z RPM nie zapewnia opieki nad niektórymi procesami post-instalacyjnymi, takimi jak zmiana, czy dodawanie wpisów do niektórych plików konfiguracyjnych, jak na przykład, plik konfiguracyjny Apache httpd.conf. Jeśli jednak ktoś decyduje się na wariant RPM, musi pamiętać o modyfikacji pliku konfiguracyjnego Apache httpd.conf (zwykle zlokalizowanego w /etc/httpd/conf/httpd.conf) i ponownie uruchomić Apache. Należy również zapoznać się z treścią podrozdziału poniżej, traktującego o konfiguracji PHP.

Konfiguracja PHP

Po pomyślnym zainstalowaniu dystrybucji PHP, aby móc z korzystać z PHP konieczne jest jego skonfigurowanie w zakresie co najmniej minimalnym. Szczegółowy opis konfiguracji PHP znaleźć można w publikacji wydawnictwa Wrox „Professional PHP Programming”.

Zaczynamy od skopiowania przykładowego pliku konfiguracyjnego PHP, włączonego do dystrybucji PHP, do katalogu instalacyjnego. Zakładając, że jest nim /usr/local/lib postąpilibyśmy tak:

# cp php.ini-dist /usr/local/lib/php.ini

Dla zapewnienia działania PHP z Apache mogą okazać się potrzebne również pewne zmiany w pliku konfiguracyjnym Apache.

W większości dystrybucji Linuksa plikiem konfiguracyjnym Apache jest /etc/httpd/conf/httpd.conf. W niektórych dystrybucjach można jednak napotkać taką jego odmianę: /etc/apache/conf/httpd.conf.

Oto kilka spośród koniecznych modyfikacji i dodatków, które należy wprowadzić do pliku konfiguracyjnego:

AddModule mod_php

LoadModule php4_module modules/libphp4.so

AddType application/x-httpd-php .php .php3

Dyrektywa AddType powoduje, że Apache rozpoznaje pliki z rozszerzeniem .php lub .php3 jako skrypty PHP i używa do ich interpretacji modułu PHP.

W celu przetestowania sprawności instalacji zaleca się utworzenie małego skryptu PHP o nazwie test.php, tak jak zrobiono to poniżej, i pozostawienie go w katalogu Apache, w którym znajduje się reszta plików HTML. Zazwyczaj jest to katalog główny dokumentów Apache /usr/local/apache/htdocs.

<?php

phpinfo( );

?>

Jeśli PHP został zainstalowany jako interpreter CGI, w katalogu na przykład: /usr/local/bin/php, to wtedy skrypt będzie wyglądał tak:

#/usr/local/bin/php

<?php

phpinfo( );

?>

Jeśli Apache działa na mojkomputer.mojadomena.com, używamy przeglądarki, aby sięgnąć do adresu URL: http://mojkomputer.mojadomena.com/test.php. Jeśli zobaczymy zestaw zmiennych przechowywanych wewnętrznie przez PHP, a nie komunikaty o błędach, oznaczać to będzie, że instalacja się powiodła. Zasadniczo powinniśmy zobaczyć coś w tym rodzaju:

Rys., str. 559

Podjęcie decyzji o instalacji PHP jako modułu Apache lub jako interpretera CGI jest często podyktowane pierwszoplanowymi względami wykorzystywanego miejsca. Używanie PHP jako interpretera CGI może w rzeczywistości zmniejszyć wydajność, bo interpreter działa jako osobny proces, w przeciwieństwie do modułu Apache, który działa w przestrzeni adresowej serwera WWW. Niektóre cechy, takie jak na przykład trwałe połączenia bazy danych (ang. persistent database connections) są dostępne wyłącznie w wersji dla modułu Apache. Jest to też rozwiązanie mniej ryzykowne z punktu widzenia bezpieczeństwa. Natomiast wersja dla interpretera CGI pozwala użytkownikom uruchamiać skrypty PHP pod różnymi identyfikatorami użytkowników. Wersja CGI jest też lepszym rozwiązaniem dla nieuprzywilejowanych użytkowników, którzy nie mogą zainstalować PHP jako modułu Apache.

Zanim przejdziemy do szczegółów składni PHP, spójrzmy na przykład wbudowania PHP wraz z HTML w stronę WWW:

<HTML>

<TITLE>skrypt PHP wbudowany w HTML</TITLE>

<BODY>

Co powiedzial Austin Powers, kiedy wyszedl z zamrazarki ?

<BR>

<?php

$aargh = "Jak to dobrze byc soba!!";

echo( $aargh );

?>

<BR>

</BODY>

</HTML>

Wprowadzenie do składni PHP

W tym podrozdziale zapoznamy się z podstawową składnią PHP. Dla PHP znalazł się tylko jeden rozdział w tej obszernej publikacji, nie mamy więc miejsca, by rozwodzić się na temat bardziej wyrafinowanych szczegółów jego składni. W zastępstwie polecamy wyczerpujący przewodnik, wydany przez Wrox „Professional PHP Programming”. Nie mniej jednak zamierzamy szczegółowo zapoznać się ze wszystkim, co ma zasadniczy związek z tworzoną przez nas aplikacją.

Zmienne, stałe i typy danych

Skrypty PHP mogą być wbudowane w dokument HTML, a ponadto i przede wszystkim, zawsze same wytwarzają jakiś HTML. Przyjrzymy się więc najpierw koegzystencji HTML i PHP. Jak wcześniej widzieliśmy, skrypt PHP może być wbudowany w strony HTML między znacznikami <?php i ?>. Możemy także umieścić skrypty PHP pomiędzy znacznikami <? i ?> oraz między znacznikami <% i %>. Jest możliwe wbudowanie kodu PHP do plików HTML, ale należy pamiętać o nazwaniu plików z rozszerzeniem .php lub .php3 tak, aby serwer WWW interpretował wbudowane skrypty. Równie dobrze z takimi rozszerzeniami (.php3 lub .php) można mieć plik tylko ze skryptem PHP.

Spójrzmy na zmienne w PHP. W PHP nie trzeba zmiennych deklarować tak, jak robi się to w wielu innych językach programowania. Spójrzmy na następujący przykład:

<?php

$foo = "Witaj Swiecie"; // Przypisanie lancucha do zmiennej foo

echo ( $foo );

?>

Powyższy skrypt produkuje wszechobecne pozdrowienie programisty. Skrypt pokazuje również jeden z kilku sposobów zaznaczania kodu komentarza w PHP. W rzeczywistości możliwe jest również umieszczenie komentarza między /* i */, dodanie komentarza po znaku #, albo po //, aż do końca wiersza.

Zmienne są zawsze poprzedzone prefiksem $. Zasadniczo PHP ma trzy typy danych — całkowity (ang. integer), zmiennoprzecinkowy podwójnej precyzji (ang. double) i łańcuchowy (ang. string). Tablice i obiekty mogą być utworzone przy pomocy tych trzech podstawowych typów danych. Przypisanie zmiennej PHP wartości za pomocą znaku = odbywa się tak:

$str = "To jest zmienna lancuchowa "; // Lancuch

$a = 1.5; // Zmiennoprzecinkowy podwojnej precyzji

$b =6; // Calkowity

Spójrzmy na niektóre funkcje, przydatne przy posługiwaniu się zmiennymi. Na określenie typu zmiennej pozwala funkcja gettype:

<?php

$x = 2;

echo( gettype( $x ));

?>

Wycinek kodu powyżej wydrukuje integer. Jest to typ danych zmiennej $x. Funkcja gettype( ) zwraca typ integer, double, string, array, object, class i unknown dla zmiennych typu: całkowity, zmiennoprzecinkowy podwójnej precyzji, łańcuchowy, tablicowy, obiektowy, klasowy i nieznany.

Funkcja settype( ) jest używana do ustawienia typu dla zmiennej tak, jak kod poniżej to ilustruje. Funkcja zwraca logiczny fałsz, gdy nie udaje się jej dokonać konwersji albo logiczną prawdę, gdy konwersja się powiodła:

<?php

$wasADouble = 3.5;

settype( $wasADouble, "integer" ); // przeksztalca zmienna na typ calkowity

echo( $wasADouble ); // drukuje 3

?>

Funkcje isset( ), empty( ) i unset( ). Funkcja isset( ) określa, czy zmienna została przypisana i zwraca logiczna prawdę, jeśli tak i logiczny fałsz, jeśli nie. Funkcja empty( ) działa w opozycji do isset( ) i zwraca logiczna prawdę, jeśli zmienna nie była ustawiona i logiczny fałsz, jeśli była. Funkcja unset( ) przywraca przypisaną zmienną do stanu początkowego.

Stałe mogą być zadeklarowane przy użyciu funkcji define( ), tak jak pokazano poniżej:

<?php

define( "helloString", "Witaj Swiecie" );

echo( helloString);

?>

PHP ma kilka wbudowanych stałych, na przykład PHP_OS jest zdefiniowana jako nazwa systemu operacyjnego w którym działa binarny PHP. Numer używanej wersji dystrybucji PHP definiuje stałą PHP_VERSION. Dostęp do stałych jest dosłowny, co znaczy, że nie poprzedza się ich znakiem $. Przykładowo, chcąc wydrukować numer wersji PHP, użylibyśmy: echo(PHP_VERSION);.

Operatory w PHP

Jak można było oczekiwać, PHP posiada bogaty zestaw operatorów do konstrukcji prostych i złożonych wyrażeń i instrukcji. Przyjrzyjmy się z bliska niektórym z najważniejszych typów operatorów w PHP:

Operatory arytmetyczne

Operatorami arytmetycznymi są: +, -, *, / i % dla, odpowiednio, dodawania, odejmowania, mnożenia, dzielenia i reszty z dzielenia.

Operatory porównań

Operatory porównań (ang. comparison operators) są używane do testowania warunków. Wykaz operatorów porównań znajduje się poniżej:

==

lewy argument operacji (ang. operand) jest równy prawemu argumentowi operacji

<

lewy argument operacji jest mniejszy niż prawy argument operacji

>

lewy argument operacji jest większy niż prawy argument operacji

<=

lewy argument operacji jest mniejszy lub równy prawemu argumentowi operacji

>=

lewy argument operacji jest większy lub równy prawemu argumentowi operacji

!=

lewy argument operacji nie jest równy prawemu argumentowi operacji

<>

lewy argument operacji nie jest równy prawemu argumentowi operacji

Operatory logiczne

Operatory logiczne są używane do oceny prawdziwości instrukcji. Są również używane do łączenia wyrażeń, co wkrótce zilustrujemy przykładem. Poniżej zamieszczono wykaz obsługiwanych operatorów logicznych:

&&

wyznacza wartość prawdziwą, jeśli lewe i prawe wyrażenia są prawdziwe

||

wyznacza wartość prawdziwą, jeśli lewe, albo prawe albo oba wyrażenia są prawdziwe

And

wyznacza wartość prawdziwą, jeśli lewe i prawe wyrażenia są prawdziwe

Or

wyznacza wartość prawdziwą, jeśli lewe, albo prawe albo oba wyrażenia są prawdziwe

Xor

wyznacza wartość prawdziwą, jeśli tylko jedno z dwóch — lewe albo prawe wyrażenie jest prawdziwe

!

przełącza wartość prawdziwości argumentu operacji

Inne operatory

Operator jednoargumentowy (ang. unary operator) - (minus jednoargumentowy) neguje wartość liczby. Operator potrójny (ang. ternary operator) ? (pytajnik) wyznacza wartość warunku logicznego (boolowskiego) i zwraca jedną z dwóch wartości w oparciu o uzyskany wynik. Operator . (kropka) może być użyty do łączenia (ang. concatenate) dwóch łańcuchów. Istnieją jeszcze inne operatory, rzadziej używane, jak na przykład operatory bitowe (ang. Bitwise operators), operatory obiektowe (ang. Object operators), czy operatory zawieszenia błędu (ang. Error suspension operators) nie będziemy ich jednak tutaj omawiać. Więcej informacji na ten temat można uzyskać ze wspomnianej już pozycji wydawnictwa Wrox „Professional PHP Programming”. Poniższy fragment kodu demonstruje działanie operatorów jednoargumentowego, potrójnego i kropkowego:

<?php

$a =1;

$a = -$a;

$prepend = "Ta zmienna jest ";

$str = $a < 0 ? "ujemna" : "dodatnia";

echo( $prepend.$str ); // To powinno wydrukowac lancuch: ujemna

?>

Instrukcje

Instrukcje w PHP skupiają różne wyrażenia i określają logiczny przepływ skryptu. Instrukcje PHP można sklasyfikować szeroko jako instrukcje warunkowe (ang. conditional statements) i instrukcje pętli (ang. loop statements). Instrukcje PHP wydadzą się znajome dla obeznanych z językiem C i innymi językami, które od C zapożyczyły swoją składnię instrukcji.

Najważniejszymi instrukcjami warunkowymi są instrukcje if oraz switch. Kod poniżej zilustruje ich użycie:

<?php

$a = 10 --> [Author:RG] ;

if ( $a < 10 )

echo( "Mniej niz 10 " ); // ta instrukcja sie wykonuje

else

echo( "Wiekszy niż lub rowny 10 " );

switch ( $a ) {

case 8: echo( "Osiem" ); break;

case 9: echo( "Dziewiec" ); break; // ta instrukcja sie wykonuje

case 10: echo( "Dziesiec" ); break;

}

?>

Instrukcje pętli są używane, gdy mamy wykonać warunkowo kilkakrotnie jakiś segment kodu. Instrukcjami pętli są instrukcje: while, do..while i for. Poniższy kod ilustruje użycie tych instrukcji; wszystkie produkują te same dane wyjściowe:

<?php

$i = 1;

while ( $i <= 10 )

{

echo( $i );

++$i;

}

$i = 1;

do {

echo( $i );

++$i;

}

while ( $i <= 10 );

for ( $i = 1; $i <= 10; ++$i )

echo( $i );

?>

Funkcje

W PHP funkcje są używane właściwie z tych samych powodów, z jakich korzysta się z funkcji w innych językach programowania. Funkcje pomagają w nadawaniu struktury modułowej dla kodu, często wywoływanego w programie. Funkcje w PHP są deklarowane za pomocą słowa kluczowego function. Jak widzieliśmy wcześniej, zmienne w PHP nie muszą być zadeklarowane przed użyciem. Standardowo zmienne użyte w funkcjach spowodują utworzenie nowej zmiennej lokalnej, dostępnej wyłącznie w obrębie danej funkcji. Jeśli z wnętrza funkcji będziemy chcieli dotrzeć do zmiennej globalnej, musimy zadeklarować ją używając słowa kluczowego global. Poniższy kod ilustruje ten przypadek:

<?php

$a = 10;

$b = 20;

function SayHello( $first, $last ){

global $a; // Sprawia, ze funkcja uzywa zmiennej globalnej $a

$final = $first.$last; // W tym wierszu dwa lancuchy sa laczone

echo( $final );

$b = $b +1; //Zwieksza o jeden zmienna lokalna $b - zmiana nie jest widoczna na zewnatrz tej funkcji

$a = $a + 1; //Zwieksza o jeden zmienna globalna $a - zmiana widoczna na zewnatrz tej funkcji

}

$hello = "Witaj "; $world = "Swiecie";

SayHello( $hello, $world ); // Tak, istotnie drukuje Witaj Swiecie

echo( $a ); // Drukuje 11

echo( $b ); // Drukuje 20

?>

Argumenty są standardowo przekazywane do funkcji poprzez wartości, tak więc modyfikacje lokalnej kopii przekazanego argumentu nie powodują zmian w funkcji wywołującej. Przykładem niech będzie zmienna $first , której wartość Witaj zostałaby zmieniona na itaj. Efekt tej zmiany będzie tylko widoczny w funkcji SayHello. Zmienna $hello w funkcji wywołującej miałaby nie zmienioną wartość Witaj.

Funkcje mogą mieć przekazywane argumenty także poprzez odsyłacz (ang. reference). Oznacza to, że jeśli zmienna przekazana poprzez odsyłacz zostaje zmodyfikowana w wywołanej funkcji, to wtedy zmiana znajduje odzwierciedlenie w funkcji wywołującej. Przed argumentem w definicji funkcji dołączamy znak &, który oznacza zmienną przekazaną poprzez odsyłacz. Poniższy przykład ilustruje ten przypadek:

<?php

function SayHello( &$first, $last ){

$first = "itaj ";

$final = $first.$last; // W tym wierszu dwa lancuchy sa laczone

echo( $final );

}

$hello = "Witaj "; $world = "Swiecie";

SayHello( $hello, $world ); // Tak, istotnie drukuje itaj Swiecie

?>

Tablice

Tablice w PHP są używane, podobnie jak w innych językach programowania, do przechowywania różnych wartości tego samego typu danych. Różnica polega na ich większej uniwersalności. PHP może indeksować tablice dwiema metodami. Pierwsza metoda polega na indeksowaniu numerycznym, a druga na indeksowaniu asocjacyjnym, czyli łańcuchowym. W indeksowaniu numerycznym wykorzystuje się położenia wartości zmiennej do wskazania elementu tablicy, a w indeksowaniu asocjacyjnym element w tablicy określa się przypisując łańcuch związany z jakąś wartością. Zagadnienie to stanie się jaśniejsze, gdy niebawem przystąpimy do analizy odpowiedniego przykładu.

Tablice PHP mają kilka dodatkowych funkcji wbudowanych, służących do ich sprawnej obsługi. Funkcja current( ), na przykład służy do uzyskania wartości aktualnie dostępnego elementu, jaki właśnie został osiągnięty w tablicy. Poniżej kilka przykładów tablic w PHP:

<?php

$color{0] = "violet ";

$color{1] = "indigo ";

$color{2] = "blue ";

$abbreviations["ps"] = "Post Script";

$abbreviations["etc"] = "Et Cetera";

$abbreviations["PHP"] = "Personal HomePage tools";

echo( $color[0] ); // Drukuje lancuch: violet;

echo( $abbreviations["PHP"] ); // Drukuje: Personal HomePage tools

?>

Realizacja projektu DVD z pomocą PHP

W poprzednich podrozdziałach postawiliśmy pierwsze chwiejne kroki na nowym gruncie, zwanym PHP i spenetrowaliśmy do pewnego stopnia tajniki instalacji oraz składnię tego języka. W dalszej części tego rozdziału skupimy się na wykorzystaniu PHP i PostrgreSQL do budowy aplikacji PHP, która dostarczy interfejsu do projektowanej Filmoteki DVD.

HTTP, HTML i PHP

Jak się tego można było spodziewać, do przyjęcia wprowadzonych przez użytkownika danych wejściowych z wyświetlonych stron HTML będzie nam potrzebny jakiś mechanizm. Zazwyczaj do przyjęcia danych wejściowych użytkownika służą formularze HTML. Potrzebny więc będzie mechanizm do uzyskania wartości danego elementu formularza, powiedzmy pola tekstowego w formularzu HTML, który jest dostępny dla skryptu PHP. Aby to ułatwić, zmienna PHP nazwana tak jak dany element formularza, zawiera wartość tego elementu. Poniższy skrypt ilustruje tę sytuację:

<HTML><BODY>

<FORM ACTION="getform.php" METHOD=GET>

Who goes there? :

<INPUT TYPE=TEXT NAME=yourname>

<BR><BR>

<INPUT TYPE=SUBMIT>

</FORM></BODY></HTML>

Skrypt poniżej jest plikiem getform.php, używanym do przetwarzania formularza dostarczonego przy użyciu GET:

<HTML><BODY>

<?php

echo( "Hmm, So you are ". $yourname);

?>

</BODY></HTML>

Rys., str. 565

Przetworzony formularz będzie wyglądał tak:

Rys., str. 566

Widzimy, że zmienna yourname formularza, będąca częścią formularza HTML jest dostępna dla skryptu PHP jako zmienna PHP pod nazwą $yourname.

Dane mogą być zwrócone do serwera dwoma sposobami. Pierwszy sposób polega na kodowaniu danych w URL i przesyłaniu ich do serwera WWW przy użyciu metody GET. Załóżmy, że formularz HTML pobiera dane wejściowe, takie jak imię użytkownika i powinien przesłać je do skryptu PHP, aby ten mógł się nim zająć. GET spowoduje wytworzenie się URL, który zostanie odesłany do serwera WWW (i tym sposobem do skryptu), a będzie wyglądał w przybliżeniu tak:

http://www.example.net/php/egofind.php?user=incognito

Dla skryptu PHP jest teraz dostępna wartość zmiennej $user i może stwierdzić, że jest nią „incognito”. Dowiemy się podczas programowania tej aplikacji, jak kodować taki łańcuch.

Metoda POST to drugi możliwy sposób zwracania danych do serwera, nie związany z kodowaniem URL dla odesłania danych skryptowi PHP. Metoda POST jest najczęściej używana wtedy, gdy istnieje potrzeba wysyłania dużej ilości danych, a także wtedy, gdy wysyłane dane zazwyczaj zmieniają istniejący na serwerze zasób danych. Dla lepszego porównania, zestawimy obok siebie formularz HTML i skrypt, używający metody POST, aby osiągnąć możliwości wcześniejszego skryptu, wykorzystującego metodę GET.

<HTML><BODY>

<FORM ACTION="getform.php" METHOD=POST>

Who goes there? :

<INPUT TYPE=TEXT NAME=yourname>

<BR><BR>

<INPUT TYPE=SUBMIT>

</FORM></BODY></HTML>

Możemy użyć skryptu PHP, pokazanego poniżej, do przetworzenia dostarczonego metodą POST formularza.

<?php

echo( "Hmm, so you are ". $yourname);

?>

Metoda GET jest często używana do przesyłania małych ilości danych, czy zapytań do zasobu danych po stronie serwera. W tej metodzie przedłożone dane są widoczne w URL i dlatego są mniej bezpieczne. Dane mogą być podpatrzone w URL na przeglądarce (oczywiście, przy założeniu, że ktoś czyha na te dane, podglądając je zza naszych pleców).

Zmienne mogą być przekazywane między skryptami w postaci zakodowanych ujednoliconych adresów zasobów URL. Kolejne tego przykłady poznamy podczas analizowania naszej aplikacji. Sesja aplikacji może być utrzymana poprzez przekazywanie zmiennych między skryptami. Już wkrótce przejdziemy do tego zagadnienia.

Aplikacja

Możemy już przejść do konstruowania pełnej aplikacji PHP. Użytkownik aplikacji będzie nie tylko mógł poprzez przeglądarkę kierować zapytania do bazy danych, ale także rezerwować (albo rezygnować z rezerwacji) płyt DVD poprzez serwis WWW.

Kod w naszej przykładowej aplikacji ma zarówno charakter modułowy, jak też i korzysta z funkcjonalnego rozdziału kodów HTML i PHP. Na tyle, na ile było to możliwe zachowano, stosowaną w poprzednich rozdziałach semantykę i składnię funkcji dostępu do bazy danych.

Rejestracja w systemie (ang. Login)

Stan rezerwacji

Wyszukiwanie tytułów

Rezerwacja tytułów

Odwołanie

Sam kod znajduje się poniżej. Plik skryptu poniżej zawiera funkcje dostępu do bazy danych. Kilka z tych funkcji nie jest ostatecznie wykorzystanych przez główny kod aplikacji. Znajdują się tam one dla celów ilustracyjnych. Mogą także być wykorzystane w przyszłości dla ewentualnego poszerzenia aplikacji. Przed próbą uruchomienia tego kodu, przypominamy Czytelnikowi, że konieczne jest posiadanie zainstalowanego kodu z rozdziału 4. Instrukcje można znaleźć w odpowiednich plikach README.

dvdstorefunctions.php

Tutaj definiujemy i przypisujemy zestaw zmiennych, które będą używane tylko do realizowania dostępu do bazy danych. Zmienna db_name jest nazwą bazy danych i musi być identyczna z nazwą istniejącej bazy danych, używanej przez inne interfejsy dla aplikacji Filmoteki DVD (ang. DVD store). Użytkownik bazy danych jest definiowany zmienną $db_user:

<?php

//dvdstorefunctions.php

// Global Variables

$host="localhost";

$port="";

$db_name="dvd_store";

$options="";

$tty="";

$db_user="dvd_user";

$db_password="";

$err_mesg;

$db_conn;

dvd_open_db()

Ta funkcja otwiera trwałe połączenie (ang. persistent connection) z bazą danych. Takie trwałe połączenie oszczędza nam nadmiernego obciążenia inicjowania połączenia do bazy danych za każdym razem, gdy chcemy uzyskać do niej dostęp. Trwałe połączenia nie zamykają się wraz z zakończeniem wykonywania się skryptu. Kiedy następuje żądanie otwarcia połączenia z bazą danych i trwałe połączenie jest uaktywnione, wtedy PHP sprawdza, czy już istnieje wcześniejsze połączenie . Jeśli tak, używa go, jeśli nie, inicjuje nowe:

function dvd_open_db() {

global $db_conn, $err_mesg;

global $host, $db_name, $db_user, $db_password;

// Open a persistent database connection

if (($db_conn = pg_pConnect("host=$host dbname=$db_name user=$db_user password=$db_password ")) == false) {

$err_mesg = "Could not connect to the database";

}

return $db_conn;

}

dvd_err_text()

Ta funkcja zapełnia łańcuch komunikatu o błędzie:

function dvd_err_text() {

global $err_mesg;

return $err_mesg;

}

dvd_close_db()

Ta funkcja jest wykorzystywana do zamykania połączenia z bazą danych:

function dvd_close_db() {

return;

}

dvd_member_get()

Ta funkcja zapełnia strukturę klienta poprzez zapytania do bazy danych. Sprawdzamy, czy jest już dostępne trwałe połączenie z bazą danych, testując zmienną $db_conn. Jeśli nie, inicjujemy trwałe połączenie, wywołując funkcję dvd_open_db. Dla wykonania zapytań SQL do bazy danych używamy funkcji pg_exec:

function dvd_member_get($member_id, &$member_object) {

global $db_conn, $err_mesg;

// Get the database connection

if (!$db_conn) {

if (!($db_conn = dvd_open_db())) {

return null;

}

}

// Execute the select query

if (( $result_id = pg_exec($db_conn, "select * from member

where member_id=$member_id")) == false) {

$err_mesg=pg_errormessage($db_conn);

return false;

} else {

$member_object = pg_Fetch_Object($result_id, 0);

return true;

}

}

dvd_member_search()

Ta funkcja wyszukuje klientów, na podstawie podanego nazwiska oraz wykonuje również rutynowe sprawdzenie trwałego połączenia z bazą danych. Wykonując zapytanie SELECT wyszukujemy potrzebnych zapisów w polu lastname, a następnie zapełniamy strukturę identyfikatora identyfikatorami dopasowanych klientów:

function dvd_member_search($lname, &$ids) {

global $db_conn, $err_mesg;

// Get the database connection

if (!$db_conn) {

if (!($db_conn = dvd_open_db())) {

return null;

}

}

if (( $result_id = pg_exec($db_conn, "select * from member

where lname= `$lname'")) == false) {

$err_mesg=pg_errormessage($db_conn);

return false;

} else {

$row=0;

for($row=0; $row<pg_numrows($result_id); $row++) {

$store_member_object = pg_Fetch_Object($result_id, 0);

$ids[$row] = $store_member_object->member_id;

}

return true;

}

}

dvd_title_get()

Ta funkcja zapełnia obiekt tytułu płyty DVD, na podstawie podanego identyfikatora tytułu DVD. W oparciu o różne kryteria dokonuje zapytania SELECT w bazie danych. Pobiera też rzeczywisty obiekt tytułu, w oparciu o wyniki zapytania SELECT:

function dvd_title_get($title_id, &$title_object) {

global $db_conn, $err_mesg;

if (!$db_conn) {

if (!($db_conn = dvd_open_db())) {

return false;

}

}

if (( $result_id = pg_exec($db_conn, "select title_id, title_text, asin, director, classification, actor1, actor2, release_date, rental_cost, genre_name from title, genre where title_id=$title_id and title.genre_id = genre.genre_id"))

== false) {

$err_mesg=pg_errormessage($db_conn);

return false;

} else {

$title_object = pg_Fetch_Object($result_id, $row);

return true;

}

}

dvd_title_search()

Funkcja ta wyszukuje płyt DVD na podstawie podanego tytułu. Wykonuje zapytanie SQL, aby pobrać płyty DVD z żądanymi tytułami:

function dvd_title_search($title, $name, &$matches) {

global $db_conn, $err_mesg;

// Get the database connection

if (!$db_conn) {

if (!($db_conn = dvd_open_db())) {

return null;

}

}

$title = strtolower($title);

$name = strtolower($name);

// Generate the sql query

if ((strlen(trim($title)) == 0) && (strlen(trim($name)) == 0)) {

return false;

} else if ((strlen(trim($title)) == 0) || (strlen(trim($name)) == 0)) {

if (strlen(trim($title)) == 0) {

$sql_query = "SELECT * FROM title WHERE lower(director) LIKE '%$name%' or lower(actor1) LIKE '%$name%' or lower(actor2) LIKE '%$name%'";

} else {

$sql_query = "SELECT * FROM title WHERE lower(title_text) LIKE '%$title%'";

}

} else {

$sql_query = "SELECT * FROM title WHERE lower(title_text) LIKE '%$title%' or lower(director) LIKE '%$name%' or lower(actor1) LIKE '%$name%' or lower(actor2) LIKE '%$name%'";

}

if (( $result_id = pg_exec($db_conn,$sql_query)) == false) {

$err_mesg=pg_errormessage($db_conn);

return false;

} else {

for($row=0; $row<pg_numrows($result_id); $row++) {

$title_object = pg_Fetch_Object($result_id, $row);

$matches[$row] = $title_object->title_id;

}

return true;

}

}

dvd_title available()

Ta funkcja sprawdza, czy podany tytuł jest dostępny w dniu, określonym podaną datą:

// Check if the title is available

function dvd_title_available($title_id, $date, &$disk) {

global $db_conn, $err_mesg;

if (!$db_conn) {

if (!($db_conn = dvd_open_db())) {

return null;

}

}

// Get the list of all the disks from the table disk

if (( $result_id = pg_exec($db_conn, "select * from disk

where title_id = $title_id ")) == false){

$err_mesg=pg_errormessage($db_conn);

return false;

} else {

$disk=0;

for($row=0; $row<pg_numrows($result_id); $row++) {

$disk_object = pg_Fetch_Object($result_id, $row);

if ($disk_object->member_id == 0) {

$disk = $disk_object->disk_id;

}

}

return true;

}

}

dvd_reserve_title()

Ta funkcja rezerwuje podany tytuł płyty pod wskazaną datą:

function dvd_reserve_title($date, $title_id, $disk_id, $member_id) {

global $db_conn, $err_mesg;

if (!$db_conn) {

if (!($db_conn = dvd_open_db())) {

return null;

}

}

if (( $result_id = pg_exec($db_conn, "insert into member_booking(member_id, title_id, date_required) values

($member_id, $title_id, '$date')")) == false) {

$err_mesg=pg_errormessage($db_conn);

return false;

} else if (( $result_id = pg_exec($db_conn, "update disk set member_id=$member_id where disk_id=$disk_id "))== false) {

$err_mesg=pg_errormessage($db_conn);

return false;

} else{

return true;

}

}

dvd_reserve_title_cancel()

Ta funkcja anuluje już wcześniej dokonaną rezerwację danego tytułu:

function dvd_reserve_title_cancel($member_id) {

global $db_conn, $err_mesg;

if (!$db_conn) {

if (!($db_conn = dvd_open_db())) {

return null;

}

}

// This function assumes that there will be only one

// reservation for the member in the member_booking table

if (( $result_id = pg_exec($db_conn, "delete from member_booking

where member_id= $member_id ")) == false) {

$err_mesg=pg_errormessage($db_conn);

return false;

} else if (( $result_id = pg_exec($db_conn, "update disk set member_id=0

where member_id= $member_id ")) == false) {

$err_mesg=pg_errormessage($db_conn);

return false;

}else {

return true;

}

}

dvd_reserve_title_query_by_member

Ta funkcja zapytuje o tytuły zarezerwowane przez danego klienta:

function dvd_reserve_title_query_by_member($member_id, &$tmpTitle) {

global $db_conn, $err_mesg;

// Get the database connection

if (!$db_conn) {

if (!($db_conn = dvd_open_db())) {

return null;

}

}

// This function assumes that there will be only one

// reservation for the member in member_booking table

if (( $result_id = pg_exec($db_conn, "select * from member_booking

where member_id= $member_id ")) == false) {

$err_mesg=pg_errormessage($db_conn);

return false;

} else {

if (pg_NumRows($result_id) > 0) {

$member_booking_object = pg_Fetch_Object($result_id, 0);

$tmpTitle = $member_booking_object->title_id;

}

else {

$tmpTitle= 0;

}

return true;

}

}

dvd_begin_transaction()

Ta funkcja inicjuje transakcję bazy danych (ang. database transaction):

function dvd_begin_transaction() {

global $db_conn;

// Get the database connection

if (!$db_conn) {

if (!($db_conn = dvd_open_db())) {

return null;

}

}

return pg_exec($db_conn, "begin");

}

dvd_commit_transaction()

Ta funkcja powierza transakcję bazie danych:

function dvd_commit_transaction() {

global $db_conn;

// Get the database connection

if (!$db_conn) {

if (!($db_conn = dvd_open_db())) {

return null;

}

}

return pg_exec($db_conn, "commit");

}

Skrypt poniżej posiada kilka wspólnych definicji i funkcji, używanych także przez inne skrypty. Większość z poniższych funkcji została zaimplementowana w celu oddzielenia generowanej przez HTML wizualizacji (ang. rendering) od logiki biznesowej (ang. business logic) aplikacji.

dvdstorecommon.php

<?php

// dvdstorecommon.php3

// Functions and other definitions used by other scripts

require( 'dvdstoredbfunctions.php' );

Dla usunięcia niejednoznaczności wywołań funkcji graficznych (ang. rendering functions) i określenia, czy wywołanie dotyczy procedur „Status check” („Sprawdzenie stanu”), czy „Search routines” („Procedury wyszukiwania”) służą te stałe:

define( "FROM_STATUS", 0 );

define( "FROM_SEARCH", 1 );

GenerateLoginForm()

Ta funkcja tworzy, posługując się formularzem HTML, stronę dla rejestracji, skrypt operacyjny (ang. action script) w którym odbywać będzie się uwierzytelnienie rejestracji w systemie. Należy zwrócić uwagę na fakt, że zmienne $memberID oraz $lastName staną się dostępne dla skryptu operacyjnego dopiero, kiedy zostanie dostarczony formularz:

function GenerateLoginForm( )

{

printf( "<FORM METHOD=POST ACTION=dvdstorelogin.php>\n" );

printf("<TABLE>");

printf( "<TR><TD><B>Lastname:</B></TD><TD> <INPUT TYPE=text SIZE=30 NAME=lastName><TD></TR><BR>\n" );

printf( "<TR><TD><B>Member ID:</B> </TD><TD><INPUT TYPE=text SIZE=30 NAME=memberID></TD></TR><BR>\n" );

printf( "<TR><TD><INPUT TYPE=submit VALUE=\"Submit\"></TD></TR>\n" );

printf("</TABLE>");

printf( "</FORM>" );

}

GenerateHTMLHeader()

Ta funkcja wyświetla komunikat nagłówka, w tym przypadku bardzo prosty. Czytelnik może użyć swej wyobraźni i urozmaicić go, wprowadzając dodatkowy HTML z obrazkami, reklamami itp.:

function GenerateHTMLHeader( $message )

{

printf( "<H1>%s</H1>\n", $message );

}

DisplayErrorMessage()

Ta funkcja wyświetla komunikaty o błędach w HTML. Kod HTML poniżej jest skonstruowany bardziej z myślą o korzystnym przedstawieniu go na kartce papieru, niż jako ułatwienie czytelności. Zasadniczo funkcja wyświetla komunikat o błędzie z dużym, przyciągającym uwagę, rozmachem. Jest wywoływana przez inne funkcje, chcące powiadomić użytkownika o błędzie:

function DisplayErrorMessage( $message )

{

printf( "<BLOCKQUOTE><BLOCKQUOTE><BLOCKQUOTE><H3><FONT COLOR=\"#cc0000\">%s</FONT></H3></BLOCKQUOTE></BLOCKQUOTE></BLOCKQUOTE>\n", $message );

}

DisplaySearchMenu()

Ta funkcja wyświetla menu wyszukiwania, aby użytkownik Filmoteki DVD mógł przeszukiwać bazę danych DVD:

function DisplaySearchMenu($memberID)

{

printf( "<FORM METHOD=POST ACTION=dvdstoresearch.php?memberID=%s>\n", $memberID);

printf("<TABLE>\n");

printf( "<TR><TD><B>Movie title:</B></TD> <TD><INPUT TYPE=text SIZE=40 NAME=title></TD></TR>\n" );

printf( "<TR><TD><B>Director/ Actors:</B></TD> <TD> <INPUT TYPE=text SIZE=30 NAME=director><BR></TD></TR>\n" );

printf( "<TR><TD><INPUT TYPE=submit VALUE=\"Search\"></TD></TR>\n" );

printf("</TABLE>\n");

printf( "</FORM>" );

}

DisplayUserMenu()

Ta funkcja oferuje użytkownikowi do wyboru możliwość sprawdzenia dokonanych rezerwacji lub wyszukiwania nowego tytułu:

function DisplayUserMenu( $memberID )

{

printf( "<A HREF=\"dvdstorestatus.php?memberID=%s\"><H3>Check your reservation status</H3></A>", $memberID );

printf( "<A HREF=\"dvdstoresearch.php?memberID=%s\"><H3>Search for movies</H3></A>", $memberID );

}

DisplayDVDDetails()

Ta funkcja wyświetla tytuł płyty DVD — zarezerwowanej przez użytkownika, albo zwróconej, jako wynik wyszukiwania. W zależności od funkcji, która spowodowała jej wywołanie funkcja DisplayDVDDetails() wyświetla odpowiedni nagłówek. Jeśli funkcją wywołującą jest search, wyświetlona będzie strona z nagłówkiem Search, a jeśli funkcją wywołującą jest reservation status, wtedy wyświetlona strona będzie mieć nagłówek Status. Jeśli funkcja jest wywołana, aby wyświetlić wyniki wyszukiwania, udostępni też ona użytkownikowi opcję rezerwacji wyszukanego tytułu. Funkcja wywołana w celu wyświetlenia stanu rezerwacji, przedstawi użytkownikowi możliwość odwołania zarezerwowanego tytułu:

function DisplayDVDDetails( $titleID, $searchORstatus )

{

global $memberID;

if (dvd_title_get( $titleID, $title_object) == false) {

DisplayErrorMessage( "dvd_title_get failed" );

} else {

if ( $searchORstatus == SEARCH ) {

printf( "<B>Search results:</B><BR>\n" );

}

if ( $searchORstatus == STATUS ) {

printf( "<B>You have the following DVD reserved:</B><BR>\n" );

}

printf( "<BR><BR> <B>Title:</B> %s<BR>\n", $title_object->title_text);

printf( "<B>Director:</B> %s<BR>\n", $title_object->director );

printf( "<B>Genre:</B> %s<BR>\n", $title_object->genre_name );

printf( "<B>Rated:</B> %s<BR>\n", $title_object->classification );

printf( "<B>Cast:</B> %s", $title_object->actor1);

if (strlen($title_object->actor2)>0) {

printf(", %s<BR>\n", $title_object->actor2);

} else {

printf("\n");

}

printf( "<B>Year:</B> %s<BR>\n", $title_object->release_date );

printf( "<B>Rental cost:</B> %s<BR>\n", $title_object->rental_cost );

if ( $searchORstatus == SEARCH )

printf( "<BR><BR>Click <A HREF=\"dvdstorereserve.php?memberID=%s&titleID=%s&date=0\">here </A> to reserve this title<BR><BR><BR>\n", $memberID, $titleID );

if ( $searchORstatus == STATUS )

printf( "<BR><BR>Click <A HREF=\"dvdstorecancel.php?memberID=%s\">here </A> to unreserve this title<BR><BR><BR>\n", $memberID );

}

}

GetReserveDate()

Ta funkcja uzyskuje od użytkownika termin rezerwacji pożądanego tytułu płyty DVD:

function GetReserveDate( $memberID, $titleID )

{

GenerateHTMLHeader( "Reserve a DVD title" );

printf( "<FORM METHOD=POST ACTION=\"dvdstorereserve.php?memberID=%s&title=%s\">\n", $memberID, $titleID );

printf( "<B>Enter a date to reserve this title (MM/DD/YYYY format):</B> <INPUT TYPE=text SIZE=10 NAME=dateToReserve><BR>\n" );

printf( "<INPUT TYPE=submit VALUE=\"Submit\">\n" );

printf( "</FORM>" );

}

Poniższy skrypt obsługuje uwierzytelnienie rejestracji użytkownika do systemu, uzyskując nazwisko użytkownika i jego numer identyfikacyjny klienta i dopasowując te dane.

dvdstorelogin.php

Funkcja require udostępnia dla tego pliku skryptowego funkcje i zmienne, zdefiniowane w dvdstorecommon.php:

<?php

// dvdstorelogin.php

// Process login with this script

require( './dvdstorecommon.php' );

Ten skrypt może być wywołany albo po raz pierwszy, bez żadnych wartości przypisanych zmiennym $lastName i $memberID, albo z wartościami przypisanymi do tych zmiennych. W pierwszym przypadku, skrypt powinien wyświetlić formularz rejestracji (ang. login form), a w drugim przypadku, powinien przetworzyć informację o rejestracji.

if ( empty( $lastName ) && empty( $memberID ))

{

//First time this script is invoked

GenerateHTMLHeader( "Login to DVD store online" );

GenerateLoginForm( );

} else {

if ( empty( $lastName ) || empty( $memberID ))

{

//User submitted an incomplete form

GenerateHTMLHeader( "Login to DVD store online" );

DisplayErrorMessage( "Lastname and MemberID needs to be entered" );

GenerateLoginForm( );

} else {

//We search for matching last names

if (dvd_member_search( $lastName, $matches) == false) {

DisplayErrorMessage("Error in dvd_member_search");

} else if ( !$matches ||( count($matches) == 0) ) {

//No matches for last name

GenerateHTMLHeader( "Login Error" );

DisplayErrorMessage( "No such User in the database" );

} else {

//Found at least one match for lastname

for ( $i = 0; $i < count($matches); $i++ )

{

if ( $matches[$i] == $memberID )

{

//Login succeded

GenerateHTMLHeader( "Welcome to DVD store online" );

DisplayUserMenu( $memberID );

return;

}

}

// Login Error

GenerateHTMLHeader( "Login Error" );

DisplayErrorMessage( "Last Name and the Member ID don't match!");

}

}

}

?>

Aplikacja wyglądałaby tak, jak zrzut ekranu poniżej, przy założeniu, że użytkownik postępuje zwykłym trybem. Poniższy ekran jest ekranem rejestracji (ang. Login screen), w postaci zaprezentowanej użytkownikowi:

Rys. 1., str. 579

Kolejny ekran pokazuje rejestrację w systemie, przetworzoną przez aplikację i proponowany przez aplikację wybór — sprawdzenie stanu rezerwacji lub wyszukiwanie tytułów płyt DVD:

Rys. 2., str. 579

dvdstoresearch.php

Poniższy skrypt implementuje zespół funkcji wyszukiwania tytułów płyt DVD:

<?php

// dvdstoresearch.php

// Search for DVDs

require( './dvdstorecommon.php' );

GenerateHTMLHeader( "DVD titles search" );

Ten skrypt może być wywołany (po raz pierwszy) bez żadnych wartości przypisanych do zmiennych $title i $director, albo z przypisanymi im wartościami. W pierwszym przypadku skrypt powinien wyświetlić menu wyszukiwań, a w drugim powinien przetworzyć przekazana mu informację o wyszukiwaniach:

if ( empty( $title ) && empty( $director )){

//First call to this script

DisplaySearchMenu($memberID);

}else {

//The case where search criteria is sent to the script through the form

if (dvd_title_search( $title, $director, $matches)== false) {

DisplayErrorMessage( "dvd_title_search() failed" );

} else if ( count($matches)== 0) {

//Zero matches

DisplayErrorMessage( "No matches found" );

} else {

//Display all the matches found

for ( $i = 0; $i < count($matches); ++$i ) {

DisplayDVDDetails( $matches[$i], SEARCH );

}

}

}

?>

Poniżej znajduje się widok ekranu wyszukiwań aplikacji, gdzie użytkownik może szukać tytułu płyty DVD:

Rys., str. 580

Wyniki wyszukiwania pokazane są na kolejnym zrzucie ekranu. Użytkownik może kliknąć umieszczone tam łącze, aby zarezerwować wyszukany tytuł:

Rys., str. 581

dvdstorestatus.php

Poniższy kod obsługuje sprawdzanie reservation status (stanu rezerwacji) dla danego użytkownika, zapytując o aktualnie zarezerwowane przez niego tytuły i wyświetlając ewentualną rezerwację:

<?php

// dvdstorestatus.php

// Check a user's reservation status

require( './dvdstorecommon.php' );

GenerateHTMLHeader( "Reservation Status" );

if (dvd_reserve_title_query_by_member( $memberID, $titleID) == false) {

DisplayErrorMessage("dvd_reserve_title_query_by_member failed");

} else if ($titleID > 0) {

//Found the DVD reserved by this user

DisplayDVDDetails( $titleID, STATUS );

} else {

//No DVDs found

printf( "<B>You have no DVDs reserved as of now</B>\n" );

}

?>

Poniższej umieszczony ekran pokazuje stronę stanu rezerwacji dla danego użytkownika. Użytkownik może kliknąć łącze na dole ekranu i anulować podaną na tej stronie swoją rezerwację.

Rys.1., str. 582

dvdstorecancel.php

Poniższy kod obsługuje odwoływanie rezerwacji, poczynionych dla danego tytułu, przez danego użytkownika:

<?php

// dvdstorecancel.php

// Cancel the title reserved by this member

require( './dvdstorecommon.php' );

if ( dvd_reserve_title_cancel( $memberID ) == false )

DisplayErrorMessage( "dvd_reserve_title_cancel failed" );

else

printf( "<B>Cancel succeeded</B>" );

?>

i stąd:

Rys.2., str. 582

dvdstorereserve.php

Kod zamieszczony poniżej obsługuje rezerwację tytułów dla danego użytkownika:

<?php

// dvdstorereserve.php

// Reserve a title for this member

require( './dvdstorecommon.php' );

if ( $dateToReserve == 0 )

{

//User has not yet specified a date to reserve the title

//Prompt the user to enter a date

GetReserveDate( $memberID, $titleID );

} else {

// Begin the transaction

dvd_begin_transaction();

//We have the reservation date, member ID and the title ID now

if ( dvd_reserve_title_query_by_member( $memberID, $tmpTitle ) == false )

DisplayErrorMessage( "dvd_display_title_query_by_member failed" );

else {

if ( $tmpTitle > 0 )

//Member already has a title reserved

DisplayErrorMessage( "Sorry you already have a title reserved" );

else {

//Try reserving the title for this member

$dateArray = split( '[/.-]', $dateToReserve );

Analizujemy składnię łańcucha daty, aby otrzymać datę rezerwacji tego tytułu:

$absReserveTime = mktime( 0, 0, 0, $dateArray[0], $dateArray[1], $dateArray[2] );

$absToday = time( );

if (( $absReserveTime - $absToday ) > ( 24 * 60 * 60*7 ))

{

//Reservations can only be made 7 days in advance

DisplayErrorMessage( "You can reserve a title only 7 days in advance" );

GetReserveDate( $memberID, $title );

} else {

//Check if the title is available for the day

if ( dvd_title_available( $title, $date, $disk ) == false )

DisplayErrorMessage( "dvd_title_available failed" );

else

if ( $disk == 0)

DisplayErrorMessage( "The title is not available on this date" );

else

if ( dvd_reserve_title( $dateArray[2] . $dateArray[0] . $dateArray[1], $title, $disk, $memberID ) == false ) {

DisplayErrorMessage( "dvd_reserve_title failed" );

} else {

printf( "<B>Reservation succeeded</B>" );

}

}

}

// End the transaction

dvd_commit_transaction();

}

}

?>

Podsumowanie

W tym rozdziale zgłębialiśmy tajniki PHP jako języka skryptowego po stronie serwera i porównaliśmy go z kilkoma innymi rozwiązaniami. Przyjrzeliśmy się kwestii instalacji PHP na platformie Linuksa i skonfigurowaliśmy go stosownie do naszych potrzeb. Omówiliśmy zarys składni języka skryptowego na poziomie elementarnym. W dalszej części wykładu poznaliśmy zmienne, stałe, operatory, funkcje i tablice. Uwieńczyliśmy dzieło poznawcze próbą praktycznego wykorzystania PHP do budowy aplikacji, która stanowi rozszerzenie aplikacji Filmoteki DVD (ang. DVD store), rozwiniętej w poprzednich rozdziałach.

Materiały źródłowe

Rysunek Pingwina na plaży, str.586.

Dyskusja online: http://www.p2p.wrox.com

2 Część I Podstawy obsługi systemu WhizBang (Nagłówek strony)

2 C:\Robert\Helion\plp16_D.doc

Można spotkać się też z innym rozwinięciem skrótu: protokół dostępu do wiadomości internetowych (IMAP, Internet Message Access Protocol). Patrz, Tim Parker i Mark Sportack „TCP/IP. Księga eksperta” (Helion, Gliwice 2000), strona 354.

W oryginale błędnie (w kontekście dalszego części tego przykładu) $a = 10;

Chyba chodzi o nazwisko Matthew (kolejność nazwisk chyba też odwrotna, albo niewłaściwa kolejność nazwisk w wydaniu polskim, albo to jakaś inna książka...)



Wyszukiwarka

Podobne podstrony:
Professional Linux Programming, R-12-01, Szablon dla tlumaczy
Praktyczne programowanie, R 5c-04, Szablon dla tlumaczy
Praktyczne programowanie, R 5b-04, Szablon dla tlumaczy
Praktyczne programowanie, R 1do4-04, Szablon dla tlumaczy
Linux Programming Professional, r-13-01, Szablon dla tlumaczy
Professional Linux Programming, R-08-t, Szablon dla tlumaczy
Praktyczne programowanie, R 6-04, Szablon dla tlumaczy
Praktyczne programowanie, R 8-04, Szablon dla tlumaczy
Praktyczne programowanie, R 8-04, Szablon dla tlumaczy
C++1 1, r00-05, Szablon dla tlumaczy
Dreamweaver 4 Dla Każdego, ROZDZ07, Szablon dla tlumaczy
Dreamweaver 4 Dla Każdego, ROZDZ03, Szablon dla tlumaczy
Doc20, Szablon dla tlumaczy
Doc04, Szablon dla tlumaczy
Doc17, Szablon dla tlumaczy
C++1 1, r01-06, Szablon dla tlumaczy
Dreamweaver 4 Dla Każdego, STR 788, Szablon dla tlumaczy
Doc19, Szablon dla tlumaczy

więcej podobnych podstron