Artykuł pochodzi z czasopisma PHP Solutions Do ...kolos.math.uni.lodz.pl/~archive/Inne -...

9
Artykuł pochodzi z czasopisma PHP Solutions . Do ściągnięcia bezpłatnie ze strony: www.phpsolmag.org Bezpłatne kopiowanie i rozpowszechanie artykułu dozwolone pod warunkiem zachowania jego obecnej formy i treści.

Transcript of Artykuł pochodzi z czasopisma PHP Solutions Do ...kolos.math.uni.lodz.pl/~archive/Inne -...

Artykuł pochodzi z czasopisma PHP Solutions.Do ściągnięcia bezpłatnie ze strony:

www.phpsolmag.org

Bezpłatne kopiowanie i rozpowszechanie artykułu dozwolonepod warunkiem zachowania jego obecnej formy i treści.

www.phpsolmag.org

PHP Solutions

1

Pro

jekty

Korzystanie z formularzy jest nieodłącznym ele-mentem działalności niemal każdej firmy. Jed-nakże często – zwłaszcza w dużych przedsię-biorstwach – trudno zdyscyplinować pracow-

ników do przestrzegania pewnych zasad, dzięki którym można uniknąć chaosu, jaki na ogół towarzyszy obiegowi dokumentów oraz korespondencji z kontrahentami. Kilka różnych wersji firmówki, dokumenty formatowane w niejed-nolity sposób, błędnie wypełniane formularze zamówień – to tylko niektóre z problemów nierozerwalnie związanych z przekazywaniem informacji.

Szukając rozwiązania powyższych kwestii, warto zwró-cić uwagę na możliwości oferowane przez język PHP. Dzięki użyciu stosunkowo prostych skryptów można nie tylko zagwarantować istnienie jednakowych wersji dokumentów, ale również wymusić poprawny sposób ich wypełniania.

Podstawowa struktura systemuPrzed przystąpieniem do tworzenia systemu elektronicz-nych formularzy warto określić cele, jakie chcemy zrealizo-wać. W najprostszej formie system taki powinien spełniać trzy poniższe założenia:

• oferować centralny punkt dystrybucji formularzy,• gwarantować jednolity wygląd poszczególnych formu-

larzy,• zapewniać sprawdzanie poprawności wprowadzanych

danych.

Pierwszy z tych punktów jest stosunkowo prosty do realiza-cji. Wystarczy postawić w firmie komputer PC z uruchomio-nym serwerem WWW i udostępnić prostą stronę oferującą możliwość wybrania żądanego formularza. Sposób wypeł-niania tego formularza oraz końcowy produkt będący goto-wym do druku dokumentem to zadanie realizowane przez dwa pozostałe punkty. Strona, o której mowa, może być zaczątkiem firmowego intranetu lub złożonego systemu obiegu dokumentów. Może ona również stanowić uzu-

pełnienie lokalnego intranetu nie wyposażonego jeszcze w tego typu podsystem.

Skoncentrujmy się na elementach mających zagwa-rantować jednolity wygląd formularzy oraz zapewnić sprawdzanie poprawności ich wypełnienia. Tutaj z pomocą przychodzi nam PHP oraz HTML, a także – o ile jest to konieczne – JavaScript (lub inny język działający po stronie przeglądarki).

Podstawowa ścieżka prowadząca do utworzenia typo-wego elektronicznego dokumentu przedstawiona jest na Rysunku 1.Na podstawie powyższego schematu możemy określić elementy, jakie będą nam potrzebne do utworzenia doku-mentu:

• strona wyświetlająca formularz HTML,• szablon dokumentu (w formacie RTF, PDF, TXT, PS,

itp.), w którym dane wprowadzane przez użytkownika reprezentowane będą przy pomocy stałych symbolicz-nych (symboli zastępczych),

• skrypt PHP zamieniający symbole zastępcze w szablo-nie dokumentu na dane źródłowe pochodzące bezpo-średnio z formularza HTML oraz dane wyliczone na podstawie informacji źródłowych.

Tworzenie systemu generowania elektronicznych formu-larzy powinniśmy zacząć od końca, tj. od przygotowania szablonów dokumentów. Popatrzmy, jak powinien wyglądać taki szablon.

Szablon dokumentuPrzede wszystkim musimy wybrać format, w jakim prze-chowywane będą szablony dokumentów (a tym samym dokumenty tworzone na podstawie tych szablonów). Naj-rozsądniejszym wydaje się wybór formatu RTF (Rich Text Format), gdyż jest on rozpoznawany przez większość edy-torów tekstu, a jego stosowanie nie wymaga korzystania

Autor od ośmiu lat pracuje jako administrator sieci kom-puterowej w dużej firmie, ponadto zajmuje się tworzeniem aplikacji bazodanowych oraz aplikacji internetowych, przygotowanych głównie pod kątem usprawnienia obiegu informacji w przesiębiorstwie.

Rysunek 1. Schemat generowania elektronicznego dokumentu

Piotr Listosz

Formularze elektroniczne w PHP

Art

ykuł

poc

hodz

i z c

zaso

pism

a „P

HP S

olut

ions

”. D

o śc

iągn

ięci

a be

zpła

tnie

ze

stro

ny: w

ww

.php

solm

ag.o

rg

www.phpsolmag.org 2

Formularze elektroniczne

z narzędzi komercyjnych. Alternatywą dla plików RTF jest powszechny w Internecie format PDF. Problem w tym, że chcąc skorzystać z tego formatu należy zakupić komer-cyjne oprogramowanie Adobe Acrobat, a także uporać się z kilkoma dodatkowymi problemami, o których będzie mowa w dalszej części artykułu.

Innym rozwiązaniem może być zastosowanie szablonu utworzonego przy wykorzystaniu języka PostScript, użycie zwykłego pliku tekstowego lub skorzystanie z kodu HTML. Jednakże na tle formatu RTF trzy ostatnie propozycje wypadają dość blado. Format postscriptowy nie jest zbyt powszechny (przynajmniej w systemach Windows), format tekstowy oferuje bardzo ubogie możliwości formatowania dokumentu, natomiast dokumenty HTML, które – jak mogłoby się wydawać – powinny być oczywistym wyborem, zależą od rodzaju przeglądarki, a także sprawiają kłopoty przy drukowaniu.

Reasumując, w zestawieniu tym zdecydowanie najlepiej wypada format RTF, dlatego to on zostanie użyty do utwo-rzenia szablonów dokumentów.

Szablony, o których mowa, to zwykłe dokumenty, w któ-rych dane wprowadzane przez użytkownika reprezentowane są przez symbole zastępcze. To, jak będzie wyglądał taki symbol, zależy wyłącznie od programisty; ważne jest jedy-nie, by był on unikalny w kontekście zwykłej treści doku-mentu, a także by różnił się od każdego innego symbolu zastępczego umieszczonego w tym dokumencie. W przedstawianym przykładzie jako symbolu zastępczego użyjemy podwójnych znaków ,̂ pomiędzy którymi umiesz-czona zostanie stała symboliczna, reprezentująca dane wprowadzane przez użytkownika, na przykład:

• ^^NAZ^^ – symbol zastępujący nazwisko,• ^^IMI^^ – symbol zastępujący imię,• ^^ADR^^ – symbol zastępujący adres, itp.

Na Rysunku 2 przedstawiony jest szablon przykładowego dokumentu w formacie RTF (popularna kilometrówka).

Po przygotowaniu szablonu RTF pora na przejście do kolejnego etapu zadania – utworzenia formularza HTML

i kodu JavaScript, zapewniającego wstępną walidację da- nych.

Wybór formularzaChcąc uniknąć kłopotów podczas przyszłego rozbudo-wywania systemu o kolejne formularze należy zaprojek-tować go tak, aby takie rozszerzanie było stosunkowo proste. W tym celu warto rozdzielić zadania pomiędzy trzy skrypty, z których pierwszy będzie oferował listę formula-rzy do wyboru, drugi będzie odpowiedzialny za wyświetle-nie i wstępne przetworzenie formularza HTML, trzeci zaś za przekształcenie szablonu w gotowy dokument. Kod skryptu prezentującego listę formularzy przedstawiony jest na Listingu 1.

Podstawowym elementem skryptu formularze.php jest tablica asocjacyjna $TabForm, w której rolę kluczy pełnią symbole formularzy (F001, F002, itd.), będące jednocze-śnie nazwami skryptów PHP wyświetlających te formularze. Wartościami odpowiadającymi owym kluczom są nazwy formularzy. Pierwsze uruchomienie skryptu spowoduje wywołanie funkcji wybor_formularza(), wyświetlającej nazwy formularzy przechowywane we wspomnianej tablicy (instrukcja foreach()). Nazwy te pojawią się na ekranie w postaci hiperłączy prowadzących ponownie do skryptu formularze.php. Do każdego hiperłącza dołączony jest łańcuch query string przekazujący w kluczu o nazwie dok wartość zmiennej $Symbol, w której przechowywany jest symbol wybranego formularza (klucz tablicy asocjacyjnej $TabForm). Kliknięcie dowolnego hiperłącza spowoduje ponowne pobranie z serwera skryptu formularze.php. Tym razem jednak nie nastąpi wyświetlenie listy formularzy, lecz

Rysunek 2. Szablon dokumentu w formacie RTF

Listing 1. Kod skryptu formularze.php

<?php Function wybor_formularza() { $TabForm = array("F001"=> "Firmówka - wersja polska", "F002"=>"Wniosek o urlop", "F003"=>"Kilometrówka", );

print "<BIG>WYKAZ FORMULARZY:</BIG><BR><BR>";

// wyświetlenie tabeli z wykazem formularzy print "<TABLE BORDER>"; foreach($TabForm as $Symbol=>$Opis) print "<TR> <TD><A HREF=\" formularze.php?dok=$Symbol&op=$Opis\">". $Opis."</A></TD></TR>"; print "</TABLE>"; }

If (Empty($_GET["dok"])) wybor_formularza(); Else include("{$_GET['dok']}.php");?>

Art

ykuł

poc

hodz

i z c

zaso

pism

a „P

HP S

olut

ions

”. D

o śc

iągn

ięci

a be

zpła

tnie

ze

stro

ny: w

ww

.php

solm

ag.o

rg

www.phpsolmag.org

PHP Solutions

3

Pro

jekty wywołanie funkcji include() wczytującej plik zawierający

kod wybranego formularza. Warto zwrócić uwagę na fakt, że – zgodnie z najnowszy-

mi zaleceniami dotyczącymi bezpiecznego programowania w PHP – w celu odczytania symbolu wybranego formularza nie posługujemy się zmienną globalną $dok, lecz tablicą suberglobalną $_GET, której elementami są wartości prze-kazywane w łańcuchu query string (tj. wartości otrzymane w wyniku użycia metody GET).

Chcąc dodać do systemu obsługę kolejnego formularza wystarczy uzupełnić tablicę asocjacyjną $TabForm o nowy element, a także – o czym będzie mowa za chwilę – utwo-rzyć skrypt PHP wyświetlający ten formularz.

Formularz HTMLMożna zastanawiać się, dlaczego do wyświetlenia formu-larza HTML potrzebny jest skrypt PHP – przecież do tego celu wystarczyłaby zwykła strona HTML? Jest to oczywi-ście wniosek słuszny. Skrypt PHP nie jest tu elementem koniecznym, jednak pozwala wyposażyć formularz w dodat-kową logikę (dzięki której można na przykład sprawdzać poprawność danych, wyliczać wartości niektórych pól na podstawie innych itp.). W przypadku prostych formularzy może to być rzecz zupełnie zbędna, jednak w założeniu nasz system ma obsługiwać dowolne dokumenty – nawet te bardzo skomplikowane – a zatem nie możemy poprze-stać na zwykłym kodzie HTML.

Na Listingu 2 przedstawiony jest kod formularza HTML (sam formularz zaprezentowany jest na Rysunku 3), który posłuży do utworzenia wspomnianego wcześniej dokumen-tu (kilometrówki). Zwróćmy uwagę, że nazwy pól formu-larza są (poza wielkością znaków) takie same jak nazwy symboli zastępczych w szablonie dokumentu. Pomimo iż takie spójne nazewnictwo nie jest wymogiem, to dzięki niemu będziemy mogli utworzyć jeden uniwersalny skrypt PHP obsługujący zamianę danych z formularzy na symbole zastępcze w szablonie dowolnego dokumentu. Skrypt ten zostanie przedstawiony w dalszej części artykułu.

Kod przedstawiony na Listingu 2 jest stosunkowo prosty. Większą jego część stanowi formularz HTML, złożony z pól

występujących w dokumencie kilometrówki. W momencie kliknięcia przycisku Generuj dokument wywoływana jest funkcja JavaScript Sprawdz(), w argumencie której prze-kazywana jest nazwa formularza (zauważmy, że nazwa ta pobierana jest z supergobalnej tablicy PHP $_GET; jest to możliwe, ponieważ została ona przekazana do omawiane-go skryptu w łańcuchu query string). Wspomniana funkcja sprawdza, czy użytkownik wypełnił wszystkie obowiązkowe pola formularza. Nazwy tych pól oraz komunikaty błędów pojawiające się w przypadku pominięcia określonego pola umieszczane są w dwuwymiarowej tablicy tab. Jeżeli któreś z wymaganych pól jest puste, wówczas do łańcucha blad doklejany jest komunikat skojarzony z tym polem. Jeśli po skontrolowaniu zawartości pól formularza łańcuch blad okaże się niepusty, zostanie on wyświetlony przy pomocy funkcji alert(). W przypadku gdy wszystkie obowiązkowe pola są wypełnione, wywoływana jest metoda submit(), przesyłająca formularz do serwera. Oczywiście takie spraw-dzanie poprawności wypełnienia formularza mogłoby być wykonane w kodzie PHP, jednak rozwiązanie to nie byłoby zbyt efektywne, gdyż wymagałoby przesłania formularza do serwera, sprawdzenia i – w przypadku niepoprawnego wypełnienia – odesłania do klienta. Chcąc uniknąć takiego przeładowywania strony należy tego typu czynności kon-trolne wykonywać przy pomocy kodu interpretowanego po stronie przeglądarki.

W wyniku przesłania formularza wywoływany jest skrypt konwersja.php (o czym decyduje parametr ACTION znacznika FORM), do którego – w łańcuchu query string – przekazy-wana jest nazwa formularza (w tym celu znów używamy tablicy superglobalnej). Skrypt konwersja.php stanowi najważniejszy element całego systemu generowania for-mularzy, gdyż to on jest odpowiedzialny za przekształcenie danych z formularza HTML na symbole zastępcze umiesz-czone w szablonie dokumentu. Przyjrzyjmy się jak działa ten mechanizm.

Generowanie dokumentuKod skryptu konwersja.php przedstawiony jest na Listin-gu 3.

Skrypt ten rozpoczyna się od wysłania do przeglądar-ki odpowiednich nagłówków, informujących o typie MIME generowanego dokumentu (application/msword) oraz sposobie jego przedstawienia (inline – otwierany w oknie przeglądaki lub attachment – otwierany jako załącznik). Następnie wywoływana jest funkcja wylicz(), której zadaniem jest wyliczenie pewnych danych wymaganych w dokumencie kilometrówki na podstawie danych wpro-wadzonych przez użytkownika do formularza HTML. Warto zwrócić uwagę na fakt, że obliczone dane umieszczane są w ukrytych polach formularza HTML. Dzięki temu że wszystkie dane wymagane przez dokument (zarówno te wprowadzone bezpośrednio jak i te obliczone) są skład-nikami jednego formularza, łatwo jest zautomatyzować mechanizm zamiany symboli zastępczych na odpowia-dające im wartości. W kolejnych liniach skryptu kon-

Rysunek 3. Formularz HTML utworzony przez kod z Listingu 2

Art

ykuł

poc

hodz

i z c

zaso

pism

a „P

HP S

olut

ions

”. D

o śc

iągn

ięci

a be

zpła

tnie

ze

stro

ny: w

ww

.php

solm

ag.o

rg

www.phpsolmag.org 4

Formularze elektroniczne

<HTML> <HEAD> <TITLE>Formularz kilometrówki</TITLE> <SCRIPT LANGUAGE="JavaScript" > <!--// funkcja sprawdzająca czy zostały wypełnione // wszystkie obowiązkowe pola formularza function Sprawdz(formularz) { var tab=Array(); var blad="";

with(formularz) tab=[[dat,"Data"], [naz,"Nazwisko"], [umo,"Numer umowy"], [rej,"Numer rejestracyjny"], [poj,"Pojemność silnika"], [ryc,"Ryczałt miesięczny"], [kil,"Stawka kilometrówki"]];

for (i=0;i<tab.length;i++) if (tab[i][0].value=="") blad=blad+" -"+tab[i][1]+"\n";

if (blad!="") alert("Brak następujących danych:\n" +blad); else formularz.submit(); } --> </SCRIPT> </HEAD>

<BODY>

<!-- utworzenie formularza dokumentu kilometrówki --> <FORM NAME="<?php print $_GET["dok"] ?>" ACTION="konwersja.php?dok=<?php print $_GET["dok"] ?>" METHOD="POST"> <TABLE> <TR><TD ALIGN="center"><BIG><B><?php print strtoupper($_GET["op"]) ?> </B></BIG></TD> </TR> </TABLE> <BR><BR> <TABLE WIDTH> <TR><TD><B>Data:</B></TD> <TD><INPUT NAME="dat" SIZE=12 MAXLENGHT=12></TD> </TR> <TR><TD>Imię:</TD> <TD><INPUT NAME="imi" SIZE=20 MAXLENGTH=20></TD> </TR> <TR><TD><B>Nazwisko:</B></TD> <TD><INPUT NAME="naz" SIZE=30 MAXLENGTH=30></TD> </TR>

<TR><TD><B>Nr umowy:</B></TD> <TD><INPUT NAME="umo" SIZE=20 MAXLENGHT=20></TD> </TR> <TR><TD><B>Przejazdy w miesiącu:</B></TD> <TD><SELECT NAME="mie"> <OPTION>styczniu <OPTION>lutym <OPTION>marcu <OPTION>kwietniu <OPTION>maju <OPTION>czerwcu <OPTION>lipcu <OPTION>sierpniu <OPTION>wrześniu <OPTION>październiku <OPTION>listopadzie <OPTION>grudniu </SELECT></TD> </TR> <TR><TD><B>Nr rejestracyjny:</B></TD> <TD><INPUT NAME="rej" SIZE=15 MAXLENGTH=15></TD> </TR> <TR><TD><B>Poj. silnika:</B></TD> <TD><INPUT NAME="poj" SIZE=12 MAXLENGTH=12></TD> </TR> <TR><TD><B>Ryczałt miesięczny:</B></TD> <TD><INPUT NAME="ryc" SIZE=15 MAXLENGTH=15></TD> </TR> <TR><TD><B>Stawka kilometrówki:</B></TD> <TD><INPUT NAME="kil" SIZE=15 MAXLENGTH=15></TD> </TR> <TR><TD><I>Dni nieobecności w pracy: </I></TD> <TD>&nbsp;</TD> </TR> <TR><TD>urlop wypoczynkowy:</TD> <TD><INPUT NAME="url" SIZE=10 MAXLENGTH=10></TD> </TR> <TR><TD>zwolnienie lekarskie:</TD> <TD><INPUT NAME="zwo" SIZE=10 MAXLENGTH=10></TD> </TR> <TR><TD>delegacja służbowa:</TD> <TD><INPUT NAME="del" SIZE=10 MAXLENGTH=10></TD> </TR> </TABLE> <!-- pola ukryte – ich wartości zostaną obliczone na podstawie wartości innych pól --> <INPUT TYPE="HIDDEN" NAME="kwo_m"> <INPUT TYPE="HIDDEN" NAME="dni"> <INPUT TYPE="HIDDEN" NAME="kwo_r"> <INPUT TYPE="HIDDEN" NAME="kwo_z"> <INPUT TYPE="HIDDEN" NAME="wyp"> <BR> <HR> <INPUT TYPE="button" value="Generuj dokument" onClick="Sprawdz(<?php print $_GET["dok"] ?>)"> </FORM> </BODY> </HTML>

Listing 2. Skrypt f003.php wyświetlający jeden z formularzy HTML i wstępnie przetwarzający dane

Art

ykuł

poc

hodz

i z c

zaso

pism

a „P

HP S

olut

ions

”. D

o śc

iągn

ięci

a be

zpła

tnie

ze

stro

ny: w

ww

.php

solm

ag.o

rg

www.phpsolmag.org

PHP Solutions

5

Pro

jekty

wersja.php otwierany jest plik zawierający szablon RTF. Szablon ten musi mieć taką samą nazwę jak skrypt PHP zawierający skojarzony z nim formularz HTML (oczywiście z wyjątkiem rozszerzenia). Dzięki temu można odwołać się do szablonu przez wartość przekazywaną w łańcu-chu query string (tj. w tablicy superglobalnej $_GET), tę samą, która była używana we wszystkich poprzednich skryptach. Takie rozwiązanie pozwala otwierać dowolne dokumenty RTF przy pomocy tego samego fragmentu kodu. Gdyby nazewnictwo skryptów i dokumentów RTF nie było spójne, wówczas do każdego z dokumentów musielibyśmy odwoływać się indywidualnie, co jedynie skomplikowałoby skrypt konwersja.php.

Cała treść szablonu RTF wczytywana jest do zmien-nej $tresc i przekazywana do funkcji przeksztalc(), będącej kluczowym elementem całego systemu. Zada-niem tej funkcji jest zamiana występujących w ciągu znaków $tresc symboli zastępczych na odpowiadającą im zawartość pól formularza. Zamiana ta realizowana jest przez funkcję str_replace(). Zauważmy, iż dzięki temu, że nazwy pól formularza odpowiadają nazwom symboli w pliku RTF, kod funkcji przeksztalc() jest tak krotki. Gdyby nazewnictwo to nie było spójne, wówczas każde pole każdego formularza należałoby zamieniać indywidualnie, przez co skrypt konwersja.php straciłby

swoją uniwersalność. Pola formularza i nazwy symboli zastępczych różnią się jedynie wielkością znaków, stąd też konieczność użycia funkcji strtoupper().

Typowym problemem, na jaki możemy natknąć się podczas konwersji, jest niewłaściwe przekształcanie pol-skich znaków. Aby się z tym uporać najlepiej skorzystać ze sposobu doświadczalnego. W tym celu należy otworzyć w zwykłym edytorze tekstu (na przykład w windowsowym Notatniku) dowolny dokument RTF z tekstem zawierającym polskie znaki i podejrzeć w jaki sposób są one kodowane. Następnie można skorzystać z funkcji PHP strtr(), zamie-niając polskie znaki na odpowiadające im kody formatu RTF. Tak właśnie zostało to zrobione w skrypcie konwer-sja.php. Efekt działania zaprezentowanego skryptu, czyli gotowy dokument w formacie RTF, przedstawiony jest na Rysunku 4.

Inne możliwości – format PDFJak zostało wspomniane na początku artykułu, korzystanie z formatu RTF nie jest koniecznością. Innym rozwiązaniem może być zastosowanie opracowanego przez firmę Adobe formatu PDF (Portable Document Format). Chcąc utworzyć dokument PDF możemy skorzystać z komercyjnej aplika-cji Adobe Acrobat lub narzędzia takiego jak na przykład ps2pdf, zamieniającego pliki w formacie PostScript na PDF

<?php// obliczanie wartości niektórych pól formularza na // podstawie danych wprowadzonych do innych pól;// wykorzystywana jest tu tablica superglobalna $_POST,// przechowująca dane z formularza przesłanego // metodą POST function wylicz() { $_POST["kwo_m"] = $_POST["ryc"] * $_POST["kil"]; $_POST["dni"] = $_POST["url"] + $_POST["zwo"] + $_POST["del"]; $_POST["kwo_r"] = round($_POST["kwo_m"]/22, 2); $_POST["kwo_z"] = round($_POST["dni"] * $_POST["kwo_r"], 2); $_POST["wyp"] = round($_POST["kwo_m"] – $_POST["kwo_z"], 2); }

// konwersja symboli zastępczych szablonu na// wartości pól formularza function przeksztalc($tresc) { foreach($_POST as $symbol=>$wartosc) $tresc = str_replace("^^". strtoupper($symbol)."^^", polskie($wartosc),$tresc); return $tresc; }

// konwersja polskich znaków na kody formatu // unicode, wykorzystywane w plikach RTF

function polskie($co) { $tab = array("ą"=>"\u261a", "Ą"=>"\u260A","ę"=>"\u281e", "Ę"=>"\u280E","ć"=>"\u263c", "Ć"=>"\u262C","ł"=>"\u322l", "Ł"=>"\u321L","ń"=>"\u324n", "Ń"=>"\u323N","ś"=>"\u347s", "Ś"=>"\u346S","ź"=>"\u378z", "Ź"=>"\u377Z","ż"=>"\u380z", "Ż"=>"\u379Z"); $po_zamianie = strtr($co,$tab); return $po_zamianie; }

// wysłanie nagłowka określającego typ MIME// dokumentu header("Content-type: application/msword"); header("Content-Disposition: inline"); wylicz();// odczytanie nazwy szablonu RTF $plik = $_GET["dok"].".rtf";// otwarcie szablonu RTF i pobranie// jego zawartości $fp = fopen($plik,"r"); $tresc = fread($fp,filesize($plik)); $tresc = przeksztalc($tresc);// wyświetlenie gotowego dokumentu print $tresc;?>

Listing 3. Skrypt konwersja.php zamieniający dane z formularza HTML na symbole zastępcze w szablonie RTF

Art

ykuł

poc

hodz

i z c

zaso

pism

a „P

HP S

olut

ions

”. D

o śc

iągn

ięci

a be

zpła

tnie

ze

stro

ny: w

ww

.php

solm

ag.o

rg

www.phpsolmag.org 6

Formularze elektroniczne

(oczywiście należy przedtem wygenerować plik postscip-towy, co można osiągnąć przez instalację odpowiedniego sterownika drukarki i skierowanie wydruku do pliku). Jed-nakże to drugie rozwiązanie nie zawsze generuje poprawne dokumenty PDF. Poza tym podczas tworzenia szablonu w formacie PDF symbole zastępcze mogą zostać wymiesza-ne z kodami formatującymi, zawierającymi informacje o tym jaka powinna być odległość pomiędzy znakami w symbo-lach zastępczych. Oto fragment źródła takiego szablonu:

^^N)-13(AZ)-10(^)-6(^

^^I)-9(M)0(I)-18^^

Dodatkowe znaki formatujące można oczywiście usunąć ręcznie (ich brak nie wpłynie istotnie na wygląd dokumen-tu), jednak przy dużej ilości skomplikowanych dokumentów jest to zadanie dość karkołomne.

Dokumenty PDF można również tworzyć z poziomu języka PHP, korzystając z biblioteki PDFlib. Trzeba jednak

wiedzieć, że używanie tej biblioteki w celach komercyj-nych wiąże się z koniecznością uiszczenia opłaty licen-cyjnej. Pomimo iż możliwość wygenerowania gotowego dokumentu PDF przy pomocy skryptu PHP wydaje się bardzo zachęcająca, to należy wspomnieć, że posługiwa-nie się funkcjami biblioteki PDFlib nie należy do łatwych. Konieczność ustalenia formatu dokumentu i rozmiesz-czenia na nim elementów należy do twórcy skryptu, a nie – jak poprzednio – autora szablonu. Co prawda biblioteka PDFlib udostępnia API pozwalające na realizację tych zadań, jednak w efekcie tworzenie dokumentu PDF spro-wadza się do metody prób i błędów i jest dość mocno czaso- i pracochłonne. Listing 5 przedstawia fragment skryptu pozwalający wygenerować prosty dokument PDF. Konieczność ręcznego określania współrzędnych tekstu jest dosyć zniechęcająca.

Lepszym rozwiązaniem wydaje się zastosowanie formularza PDF utworzonego przy użyciu aplikacji Adobe

Rysunek 4. Wygenerowany dokument

Listing 5. Fragment skryptu pozwalający wygenerować

prosty dokument PDF

...$fp = fopen("test.pdf","w"); // otwarcie pliku$pdf = pdf_open($fp); // otwarcie obiektu PDF

// ustalenie wielkości stronypdf_begin_page($pdf, 8.5*72, 11*72);

//ustalenie wielkości i rodzaju czcionkipdf_set_font($pdf, "Helvetica-Bold", 24, "cp1250");

//ustalenie pozycji kursorapdf_set_text_pos($pdf, 50, 700);

//wypisanie tekstu w pozycji kursorapdf_show($pdf, "Witaj Świecie");

pdf_end_page($pdf); //zakończenie stronypdf_close($pdf); //zamknięcie obiektu PDFfclose($fp); // zamknięcie pliku...

Listing 4. Skrypt generujący dokument na podstawie

formularza PDF

<?php// utworzenie pliku .fdf i wypełnienie go danymi // pochodzącymi z formularza PDF$plik_fdf = fopen("in_test.fdf", "w");fwrite($plik_fdf, $HTTP_RAW_POST_DATA, strlen($HTTP_RAW_POST_DATA));

fclose($plik_fdf);

// otwarcie pliku (dokumentu) FDF i odczytanie danych // umieszczonych w polu formularza PDF $in_fdf = fdf_open("in_test.fdf");$nazwisko = fdf_get_value($in_fdf, "nazwisko"); fdf_close($in_fdf);

// utworzenie nowego dokumentu FDF i zapisanie do // jego pola danych odczytanych z formularza PDF$out_fdf = fdf_create(); fdf_set_value($out_fdf, "nazwisko", $nazwisko, 0);

// skojarzenie dokumentu FDF z dokumentem wyjściowym // (szablonem) PDF fdf_set_file($out_fdf, "http://test/formularz.pdf");

//zapisanie i zamknięcie dokumentu FDFfdf_save($out_fdf, "out_test.fdf"); fdf_close($out_fdf);

// wysłanie do przeglądarki nagłówka określającego // typ MIMEHeader("Content-type: application/vnd.fdf");

// otwarcie, wyświetlenie zawartości (tj. wyświetlenie // wynikowego dokumentu PDF) i usunięcie dokumentu FDF$plik = fopen("out_test.fdf", "r"); fpassthru($plik);

unlink("out_test.fdf"); ?>

Art

ykuł

poc

hodz

i z c

zaso

pism

a „P

HP S

olut

ions

”. D

o śc

iągn

ięci

a be

zpła

tnie

ze

stro

ny: w

ww

.php

solm

ag.o

rg

www.phpsolmag.org

PHP Solutions

7

Pro

jekty

Acrobat. Formularz ten – podobnie jak formularz HTML – może składać się z szeregu pól tekstowych, przycisków opcji, pól wyboru itp. Oprócz takiego formularza programi-sta powinien przygotować szablon PDF, który docelowo zostanie uzupełniony danymi z formularza, a także skrypt PHP odpowiedzialny za przeniesienie danych z formularza do szablonu. Warto wspomnieć, że funkcję szablonu może tutaj pełnić źródłowy formularz PDF, którego pola zostaną wypełnione przez skrypt PHP. Oczywiście jest to rozwią-zanie opcjonalne; równie dobrze szablonem może być niezależny dokument PDF. Szukając analogii do poprzed-niego rozwiązania, możemy zauważyć, że szablon PDF jest odpowiednikiem szablonu HTML, skrypt PHP o którym mowa to ekwiwalent zaprezentowanego wcześniej skryptu konwersja.php, natomiast szablonowi PDF odpowiada sza-blon RTF.

Każdy formularz PDF wyposażony jest w przycisk submit, powodujący przesłanie danych do serwera. Przy-cisk ten można skojarzyć ze skryptem PHP odpowiedzial-nym za odebranie tych danych. Format, w jakim zapisane są dane przychodzące z formularza PDF, określany jest mianem FDF (Forms Data Format). Skrypt PHP rejestruje dane FDF w tablicy $HTTP_RAW_POST_DATA, która jest odpo-wiednikiem tablicy $HTTP_POST_DATA, gromadzącej dane z formularza HTML. Zadaniem skryptu odczytującego dane FDF jest skojarzenie ich z przygotowanym wcześniej szablonem PDF. Po tej operacji dane FDF należy wysłać do przeglądarki, poprzedzając je nagłówkiem określającym odpowiedni typ MIME (tym razem jest to typ application/vnd.fdf). Przeglądarka zareaguje na ten typ uruchomieniem wtyczki (ang. plug-in) do aplikacji Acrobat Reader, która uzupełni szablon PDF danymi FDF (tj. danymi pochodzący-mi z formularza PDF). Chcąc korzystać z przedstawionego rozwiązania, należy zainstalować bibliotekę FDF Toolkit oraz udostępnić w PHP rozszerzenie pozwalające przetwa-rzać dane FDF. Listing 4 przedstawia przykładowy skrypt obsługujący formularz PDF.

Największym ograniczeniem przedstawionej metody jest konieczność korzystania z komercyjnego oprogramo-wania (Adobe Acrobat).

Na tle tych rozwiązań zastosowanie dokumentu RTF wygląda zdecydowanie najlepiej.

Dalsze rozszerzanie systemu Wzbogacanie systemu o nowe formularze wydaje się dość logicznym sposobem jego rozbudowy. Dzięki spój-

nemu nazewnictwu skryptów i dokumentów oraz pól formularzy i symboli zastępczych dodanie obsługi kolej-nego formularza jest sprawą stosunkowo prostą. W tym celu wystarczy uzupełnić tablicę $TabForm w skrypcie formularze.php o kolejny element (będący symbolem i nazwą nowego dokumentu), utworzyć skrypt z kodem HTML formularza oraz odpowiadający mu szablon RTF. W przypadku, gdyby nowy dokument wymagał wykonania jakichś obliczeń, należy dodać odpowiednie funkcje do skryptu konwersja.php. Chcąc uczynić ten system jeszcze bardziej uniwersalnym można usunąć ze skryptu konwer-sja.php funkcje odnoszące się do konkretnych formularzy i umieścić je w skryptach odpowiedzialnych za wyświe-tlanie tych formularzy. Oczywiście kod PHP powinien być wówczas zastąpiony kodem JavaScript, wykonywanym przed przesłaniem dokumentu do serwera. Na przykład znajdującą się w skrypcie konwersja.php funkcję wylicz() (dotyczącą wyłącznie dokumentu kilometrówki) można zastąpić taką oto funkcją JavaScript, umieszczoną w pliku f003.php (patrz Listing 6).

Obie przedstawione funkcje realizują to samo zada-nie – wyliczają wartości określonych pól formularza na podstawie innych pól. Oczywiście wartości uzyskane przy pomocy powyższej funkcji należałoby zaokrąglić, jednak-że JavaScript nie oferuje odpowiednika dostępnej w PHP funkcji round(). Programista musi zatem sam napisać taką funkcję.

Przed zamianą symboli zastępczych na dane z formu-larza (tj. przed wykonaniem metody formularz.submit() w skrypcie f003.php) warto wywołać kod JavaScript, któ-rego zadaniem byłoby wstawienie spacji do wszystkich pól nie wypełnionych przez użytkownika. Dzięki takiemu dzia-łaniu zabezpieczymy się przed wyświetlaniem w gotowym dokumencie nie zamienionych na dane symboli zastęp-czych. Na Listingu 7 zaprezentowany jest kod uniwersalnej

Listing 6. Funkcja wylicz() zaimplementowana w JavaScript

function Wylicz(formularz){ formularz.kwo_m.value = formularz.ryc.value * formularz.kil.value; formularz.dni.value = (formularz.url.value*1) + (formularz.zwo.value*1) + (formularz.del.value*1); formularz.kwo_r.value = formularz.kwo_m.value/22); formularz.kwo_z.value = formularz.dni.value * formularz.kwo_r.value; formularz.wyp.value = (formularz.kwo_m.value*1) - (formularz.kwo_z.value*1).;}

Listing 7. Kod JavaScript wstawiający spacje w pola

niewypełnione przez użytkownika

function Spacja(formularz){ for(i=0;i<formularz.elements.length;i++) if (formularz.elements[i].type=="text" && formularz.elements[i].value=="") formularz.elements[i].value=" ";}

Art

ykuł

poc

hodz

i z c

zaso

pism

a „P

HP S

olut

ions

”. D

o śc

iągn

ięci

a be

zpła

tnie

ze

stro

ny: w

ww

.php

solm

ag.o

rg

8

Formularze elektroniczne

funkcji realizującej przedstawione zadanie dla dowolnych formularzy.

Możliwość zapisywania formularzy do bazy danych to kolejna propozycja rozbudowy systemu. W tym przypad-ku istnieją dwa rozwiązania. Można zapisywać do bazy tekst dokumentu RTF lub wartości poszczególnych pól formularza HTML. Pierwsze rozwiązanie jest stosunkowo proste, lecz pozwala jedynie na przechowywanie wyge-nerowanych dokumentów, bez możliwości ich późniejszej edycji. Drugie rozwiązanie umożliwia modyfikowanie wartości pól wstawianych do dokumentu, lecz wymaga by każdy dokument posiadał odrębną tabelę w bazie danych. Możemy również stosować rozwiązania pośred-nie, na przykład zapisywać do jednego pola tabeli bazy danych symbole zastępcze, do drugiego zaś ich wartości, a następnie – analizując łańcuchy znaków – dopasowy-wać wartości do symboli.

Możliwość przechowywania treści w bazie danych może być zaczątkiem implementacji systemu obiegu dokumentów. Kolejnym etapem byłoby wyposażenie takich dokumentów w metryki (informujące kto utworzył dokument, kto i w jakiej kolejności ma go podpisać oraz kto ma go zrealizować), a także zaimplementowanie systemu przekazywania dokumentów odpowiednim użyt-kownikom.

W każdym razie pierwszym krokiem na drodze do wdrożenia takich zaawansowanych rozwiązań jest zbudo-wanie systemu generowania dokumentów, pozwalające-

W Sieci

• Specyfikacja formatu RTF: http://msdn.microsoft.com/library/specs/

rtfspec.htm• Specyfikacja formatu PDF: http://partners.adobe.com/asn/developer/

technotes.html • Biblioteka PHP PDFlib: http://www.pdflib.com• Opis formatu FDF: http://www.adobe.com/support/techdocs/

16196.htm• Dokumentacja funkcji PHP do obsługi dokumentów

FDF: http://www.php.net/manual/ref.fdf.php

Art

ykuł

poc

hodz

i z c

zaso

pism

a „P

HP S

olut

ions

”. D

o śc

iągn

ięci

a be

zpła

tnie

ze

stro

ny: w

ww

.php

solm

ag.o

rg

go ujednolicić ich wygląd i sposób tworzenia oraz weryfi-kowania. Koszt wprowadzenia takiego systemu oraz czas jaki należy poświęcić na jego utworzenie jest stosunko-wo niewielki (zwłaszcza wówczas, gdy będziemy dyspo-nować gotowymi dokumentami, na podstawie których szybko utworzymy szablony). System o którym mowa z pewnością okaże się przydatny w firmach, gdzie oprócz popularnej firmówki używa się jeszcze wielu innych doku-mentów.

www.phpsolmag.org