III. RÉSZ Munka a PHP-vel 9. óra Ûrlapok 10. óra Fájlok használata 11. óra A DBM függvények használata 12. óra Adatbázisok kezelése MySQL 13. óra Kapcsolat a külvilággal 14. óra Dinamikus képek kezelése 15. óra Dátumok kezelése 16. óra Az adatok kezelése 17. óra Karakterláncok kezelése 18. óra A szabályos kifejezések használata 19. óra Állapotok tárolása sütikkel és GET típusú lekérdezésekkel 20. óra Állapotok tárolása munkamenet-függvényekkel 21. óra Munka kiszolgálói környezetben 22. óra Hibakeresés
9. ÓRA Ûrlapok A könyv eddigi példáiban egy nagyon fontos dolgot nem láttunk. Létrehoztunk változókat és tömböket, készítettünk és meghívtunk különbözõ függvényeket, különféle objektumokkal dolgoztunk, eddigi ismereteink azonban értelmetlenek, amíg a felhasználó által megadott adatokat kezelni nem tudjuk. Ebben az órában ezt a témakört tekintjük át. A Világhálón alapvetõen a HTML ûrlapokon keresztül áramlik az információ a felhasználó és a kiszolgáló között. A PHP-t úgy tervezték, hogy a kitöltött HTML ûrlapokat könnyen fel tudja dolgozni. Ebben az órában a következõket tanuljuk meg: Hogyan férjünk hozzá a környezeti változókhoz és hogyan használjuk azokat? Hogyan férjünk hozzá az ûrlapmezõkben megadott információkhoz? Hogyan dolgozzunk az ûrlapok több elem kiválasztását engedélyezõ elemeivel?
150 9. óra Hogyan készítsünk olyan kódot, amely egyszerre tartalmazza a HTML ûrlapot és az ezt kezelõ PHP programot? Hogyan mentsük az állapotot rejtett mezõkkel? Hogyan irányítsuk a felhasználót új oldalra? Hogyan készítsünk fájlfeltöltõ HTML ûrlapot és hogyan írjunk olyan PHP programot, amely kezeli ezt? Globális és környezeti változók Mielõtt elkészítenénk elsõ igazi ûrlapunkat, kis kitérõt kell tennünk, hogy újra áttekintsük a globális változókat. A globális változókkal elõször a függvényekrõl szóló hatodik órában találkoztunk. A globális változók azok a változók, amelyeket a program legfelsõ szintjén, azaz a függvényeken kívül vezettünk be. Minden függvény számára elérhetõ a beépített $GLOBALS nevû tömb. A $GLOBALS tömb használatát láthatjuk a 9.1. példában, amelyben egy ciklussal kiírjuk programunk összes globális változóját. 9.1. program A $GLOBALS tömb elemeinek kiírása 1: <html> 2: <head> 3: <title>9.1. program A $GLOBALS tömb elemeinek kiírása</title> 4: </head> 5: <body> 6: <?php 7: $user1 = "Judit"; 8: $user2 = "István"; 9: $user3 = "János"; 10: foreach ( $GLOBALS as $kulcs=>$ertek ) 11: { 12: print "\$GLOBALS[\"$kulcs\"] == $ertek<br>"; 13: } 14:?> 15: </body> 16: </html>
Ûrlapok 151 Három változót vezettünk be és a $GLOBALS tömb elemein végiglépkedve kiírtuk a változók neveit és értékeit a böngészõben. Láthatjuk az általunk megadott változókat, de a program ezeken kívül másokat is kiírt, a PHP ugyanis automatikusan bevezet néhány globális változót, amelyek a kiszolgáló és az ügyfél környezetét írják le. Ezeket a változókat környezeti változóknak nevezzük. A kiszolgálótól, a rendszertõl és a beállításoktól függõen különféle környezeti változók létezhetnek, ezek ismerete rendkívül fontos. A 9.1. táblázatban a leggyakoribb környezeti változókat soroltuk fel. A környezeti változók értéke közvetlenül vagy a $GLOBALS tömb részeként érhetõ el. 9 9.1. táblázat Környezeti változók Változó Tartalma Példa $HTTP_USER_AGENT A böngészõ neve és Mozilla/4.6 (X11;I; változatszáma Linux2.2.6-15apmac ppc) $REMOTE_ADDR Az ügyfél IP címe 158.152.55.35 $REQUESTED_METHOD A kérelem módja POST (GET vagy POST) $QUERY_STRING A GET kérelmeknél nev=janos&cim= az URL-hez kapcsolt ismeretlen kódolt adat $REQUEST_URI A kérelem teljes címe /php-konyv/urlapok/ a lekérdezõ 9.14.program.php?nev= karaktersorozattal janos $HTTP_REFERER Az oldal címe, http://www.proba.hu/ amelyrõl a kérelem egy_oldal.html érkezett A PHP létrehoz más környezeti változókat is. Például a $GLOBALS["PHP_SELF"] az éppen futó program elérési útját adja meg. A szerzõ rendszerén az érték a következõ volt: /php-konyv/urlapok/9.1.program.php
152 9. óra A változó értéke közvetlenül is elérhetõ, $PHP_SELF néven. Ebben az órában még sokszor fogjuk használni ezt a változót. A HTML oldalt leíró és az ûrlapot elemzõ PHP kódot gyakran tároljuk egy állományban. Az oldal nevének tárolásához a $PHP_SELF változó értékét a HTML FORM elemének ACTION paraméteréhez rendeljük. A $GLOBALS tömb ezenkívül még sok másra is használható. Adatok bekérése a felhasználótól Jelenleg a HTML és PHP kódot külön állományban tároljuk. A 9.2. példában egy egyszerû HTML ûrlap kódját láthatjuk. 9.2. program Egy egyszerû HTML ûrlap 1: <html> 2: <head> 3: <title>9.2. program Egy egyszerû HTML ûrlap</title> 4: </head> 5: <body> 6: <form action="9.3.program.php" method="get"> 7: <input type="text" name="felhasznalo"> 8: <br> 9: <textarea name="cim" rows="5" cols="40"> 10: </textarea> 11: <br> 12: <input type="submit" value="rendben"> 13: </form> 14: </body> 15: </html> Egy HTML ûrlapot hoztunk létre, amely egy "felhasznalo" nevû szövegmezõt, egy "cim" nevû szövegterületet, és egy gombot tartalmaz. Könyvünk nem foglakozik részletesen a HTML ismertetésével, ha mégis nehéznek találjuk a példákat, olvassunk el egy, a HTML nyelvvel foglalkozó kötetet vagy számítógépes leírást. A FORM elem ACTION paramétere a 9.3.program.php fájlra mutat, amely feldolgozza az ûrlapon megadott adatokat. Mivel az ACTION csak a fájl nevét adja meg, a HTML és PHP kódot tartalmazó fájloknak egy könyvtárban kell lenniük. A 9.3. példaprogram kiírja a felhasználó által megadott információkat.
Ûrlapok 153 9.3. progran A 9.2. példa ûrlapjának feldolgozása 1: <html> 2: <head> 3: <title>9.3. program A 9.2. példa ûrlapjának feldolgozása</title> 4: </head> 5: <body> 6: <?php 7: print "Üdvözlet <b>$felhasznalo</b><p>\n\n"; 8: print "A címe:<p>\n\n<b>$cim</b>"; 9:?> 10: </body> 11: </html> 9 Ez a könyv elsõ olyan programja, amelyet nem hivatkozáson keresztül hívunk meg és nem közvetlenül a böngészõbe írjuk be a címét. A 9.3. példában található kódot az 9.3.program.php fájlban tároljuk. A fájlban lévõ kódot akkor hívjuk meg, amikor a felhasználó kitölti a 9.2. példában található ûrlapot. A program a $felhasznalo és a $cim változók értékét írja ki, amelyek a HTML ûrlap "felhasznalo" szövegmezõjének és "cim" területének értékét tartalmazzák. Látható, hogy a PHP 4 segítségével milyen egyszerûen kezelhetõek az ûrlapok. Bármilyen megadott információ globális változóként hozzáférhetõ és a változók neve megegyezik a megfelelõ HTML elem nevével. Több elem kiválasztása a SELECT elemmel Elõzõ példánkban olyan HTML ûrlap szerepelt, amely egy elemhez egyetlen érték hozzárendelését engedélyezte. Most megtanuljuk a SELECT elem kezelését, melynek segítségével több elem kiválasztását engedélyezhetjük. Ha a SELECT elemnek egyszerû nevet adunk: <select name="termekek" multiple> akkor a feldolgozó program csak az egyik kiválasztott elemhez fér hozzá. Ha minden elemet el szeretnénk érni a programból, az elem neve után írjunk üres szögletes zárójeleket. Ezt láthatjuk a 9.4. példában.
154 9. óra 9.4. program SELECT elemet tartalmazó HTML ûrlap 1: <html> 2: <head> 3: <title>9.4. program SELECT elemet tartalmazó HTML ûrlap</title> 4: </head> 5: <body> 6: <form action="9.5.program.php" method="post"> 7: <input type="text" name="felhasznalo"> 8: <br> 9: <textarea name="cim" rows="5" cols="40"> 10: </textarea> 11: <br> 12: <select name="termekek[]" multiple> 13: <option>ultrahangos csavarhúzó 14: <option>tricorder 15: <option>orac AI 16: <option>hal 2000 17: </select> 18: <br> 19: <input type="submit" value="rendben"> 20: </form> 21: </body> 22: </html> Az ûrlapot feldolgozó programban a SELECT elemben kiválasztott adatok a $termekek tömbben találhatóak. Ezt mutatjuk be a 9.5. példában 9.5. program A 9.4. példában látott ûrlap feldolgozása 1: <html> 2: <head> 3: <title>9.5. program A 9.4. példában látott ûrlap feldolgozása</title> 4: </head> 5: <body> 6: <?php 7: print "Üdvözlet <b>$felhasznalo</b><p>\n\n"; 8: print "A címe:<p>\n\n<b>$cim</b>"; 9: print "A következõ termékeket választotta:<p>\n\n"; 10: print "<ul>\n\n";
Ûrlapok 155 9.5. program (folytatás) 11: foreach ( $termekek as $termek ) 12: { 13: print "<li>$termek<br>\n"; 14: } 15: print "</ul>"; 16:?> 17: </body> 18: </html> 9 Nem csak a SELECT elem engedélyezi több elem kiválasztását. Ha több jelölõnégyzetnek ugyanazt a nevet adjuk, ahol a felhasználó több elemet is kiválaszthat, csak az utolsó kiválasztott értéket kapjuk meg, de ha a nevet üres szögletes zárójelek követik, az adott nevû elemeket a PHP tömbként kezeli. A 9.4. példa SELECT elemét jelölõnégyzetekre cserélhetjük és ugyanazt a hatást érjük el: <input type="checkbox" name="termekek[]" value="ultrahangos å csavarhúzó">ultrahangos csavarhúzó<br> <input type="checkbox" name="termekek[]" å value="tricorder">tricorder<br> <input type="checkbox" name="termekek[]" value= å "ORAC AI">ORAC AI<br> <input type="checkbox" name="termekek[]" value= å "HAL 2000">HAL 2000<br> Az ûrlap minden mezõjének hozzárendelése egy tömbhöz Az eddig megtanult módszerek mindaddig jól mûködnek, amíg programunk tudja, milyen mezõkkel dolgozik. Gyakran azonban olyan programra van szükségünk, amely az ûrlap változásaihoz alkalmazkodik vagy egyszerre többféle ûrlapot képes kezelni, anélkül, hogy keverné a mezõk neveit. A PHP 4 globális változói erre a problémára is megoldást nyújtanak. Attól függõen, hogy a kitöltött ûrlap GET vagy POST metódust használt, elérhetõvé válnak a $HTTP_GET_VARS vagy a $HTTP_POST_VARS változók. Ezek az asszociatív tömbök tartalmazzák az ûrlap mezõinek neveit és a hozzájuk rendelt értékeket. A 9.6. példa azt mutatja be, hogyan listázható ki az ûrlap minden mezõje egy GET kérelem esetén.
156 9. óra 9.6. program A $HTTP_GET_VARS tömb használata 1: <html> 2: <head> 3: <title>9.6. program A $HTTP_GET_VARS tömb használata</title> 4: </head> 5: <body> 6: <?php 7: foreach ( $HTTP_GET_VARS as $kulcs => $ertek ) 8: { 9: print "$kulcs == $ertek<br>\n"; 10: } 11:?> 12: </body> 13: </html> A fenti kód a GET kérelmen keresztül érkezett paraméterek neveit és értékeit írja ki. Természetesen itt még nem kezeltük azt az esetet, amikor valamelyik átadott paraméter tömb. Ha a 9.4. példaprogrammal olyan HTML ûrlapról érkezõ adatok feldolgozását végeztetjük, amelyben több elem kiválasztását engedélyezõ SELECT mezõ szerepel, valami hasonlót olvashatunk: felhasznalo == Kiss Iván cim == Budapest, Magyarország termekek == Array A termekek tömböt tartalmazza a $HTTP_GET_VARS tömb, de kódunk még nem tudja ezt kezelni. A 9.7. példaprogram ellenõrzi, hogy a paraméter típusa tömb-e és ha igen, kiírja a tömb elemeit. 9.7. program A $HTTP_GET_VARS tömb használata, ha tömböt tartalmaz 1: <html> 2: <head> 3: <title>9.7. program A $HTTP_GET_VARS tömb használata, ha tömböt tartalmaz</title> 4: </head> 5: <body> 6: <?php
Ûrlapok 157 9.7. program (folytatás) 7: foreach ( $HTTP_GET_VARS as $kulcs => $ertek ) 8: { 9: if ( gettype( $ertek ) == "array" ) 10: { 11: print "$kulcs == <br>\n"; 12: foreach ( $ertek as $tombelem ) 13: print "...$tombelem<br>"; 14: } 15: else 16: { 17: print "$kulcs == $ertek<br>\n"; 18: } 19: } 20:?> 21: </body> 22: </html> 9 Mielõtt a forearch segítségével a $HTTP_GET_VARS tömb elemein végiglépkednénk, a gettype() függvénnyel ellenõrizzük, hogy a következõ elem tömb-e. Ha az elem tömb, egy második foreach segítségével végiglépkedünk az elemein és kiírjuk azokat a böngészõbe. Különbségek a GET és a POST továbbítás között A program akkor rugalmas, ha el tudja dönteni, hogy $HTTP_POST_VARS vagy $HTTP_GET_VARS tömbbõl olvassa-e ki az elemeket. A továbbítás típusát (GET vagy POST) a legtöbb rendszerben a $REQUEST_METHOD környezeti változó tartalmazza, értéke értelemszerûen "get" vagy "post". Érdemes tudni, hogy a $HTTP_POST_VARS tömb csak POST továbbítási mód esetén tartalmaz elemeket. A 9.8. program mindig a megfelelõ tömbbõl olvassa ki a paramétereket.
158 9. óra 9.8. program A GET és POST kérelmek kezelése 1: <html> 2: <head> 3: <title>9.8. program A GET és POST kérelmek kezelése</title> 5: </head> 6: <body> 7: <?php 8: $PARAMETEREK = ( count( $HTTP_POST_VARS ) ) 9:? $HTTP_POST_VARS : $HTTP_GET_VARS; 10: foreach ( $PARAMETEREK as $kulcs => $ertek ) 11: { 12: if ( gettype( $ertek ) == "array" ) 13: { 14: print "$kulcs == <br>\n"; 15: foreach ( $ertek as $tombelem ) 16: print "...$tombelem<br>"; 17: } 18: else 19: { 20: print "$kulcs == $ertek<br>\n"; 21: } 22: } 23:?> 24: </body> 25: </html> A feltételes mûveletjellel beállítjuk a $PARAMETEREK változó értékét. A count() függvénnyel ellenõrizzük, hogy a $HTTP_POST_VARS változó tartalmaz-e elemeket. A count() visszatérési értéke a tömb elemeinek száma: pozitív, ha a paraméterében megadott változó tartalmaz elemeket és 0 (false), ha nem. Ha a $HTTP_POST_VARS tartalmaz elemeket, akkor a $PARAMETEREK változót egyenlõvé tesszük vele, egyébként a $PARAMETEREK a $HTTP_GET_VARS értékét veszi fel. Most már kiírathatjuk a $PARAMETEREK tömb tartalmát a korábban látott módon.
Ûrlapok 159 PHP és HTML kód összekapcsolása egy oldalon Néhány esetben szükség lehet rá, hogy az ûrlapot leíró HTML kódot és az ûrlapot kezelõ PHP kódot egyetlen fájlban tároljuk. Ez akkor lehet hasznos, amikor a felhasználó számára többször adjuk át ugyanazt az ûrlapot. Természetesen kódunk sokkal rugalmasabb, ha dinamikusan írjuk meg, de ekkor elveszítjük a PHP használatának elõnyét. A HTML és PHP kódot ne keverjük a közös fájlon belül, mert így a forrás nehezebben lesz olvasható és módosítható. Ahol lehetséges, készítsünk HTML kódból meghívható PHP függvényeket, amelyeket késõbb fel tudunk használni. 9 A következõ példákban olyan oldalt fejlesztünk, amely az ûrlapról beérkezõ egész számról megmondja, hogy kisebb vagy nagyobb-e egy elõre megadott egész értéknél. A 9.9. példában a fenti feladat megoldását tartalmazó HTML kódot láthatjuk. A kód egy egyszerû szövegmezõt és némi PHP kódot tartalmaz. 9.9. program Saját magát meghívó HTML kód 1: <html> 2: <head> 3: <title>9.9. program Saját magát meghívó HTML kód</title> 4: </head> 5: <body> 6: <form action="<?php print $PHP_SELF?>" method="post"> 7: Ide írja a tippjét: <input type="text" name="tipp"> 8: </form> 9: </body> 10: </html> A fenti ûrlap saját magát hívja meg, mert a FORM elem ACTION paraméterének a $PHP_SELF értéket adtunk. Vegyük észre, hogy nem készítettünk gombot, amely elküldi a beírt számot. Az újabb böngészõk a szövegmezõ kitöltése és az ENTER lenyomása után automatikusan elküldik a megadott adatot, viszont néhány régebbi böngészõ ezt nem teszi meg. A 9.9. példában lévõ program nem dinamikus, hiszen nem ír ki semmit, ami a felhasználótól függ. A 9.10. példában további PHP kódot építünk az oldalba. Elõször meg kell adnunk a számot, amit a felhasználónak ki kell találnia. A teljes változatban valószínûleg véletlenszámot állítanánk elõ, most azonban egyszerûen megadjuk, mondjuk a 42-t. Ezután megnézzük, hogy az ûrlapot kitöltötték-e már, különben
160 9. óra olyan változóval számolnánk, amely még nem létezik. A $tipp változó létezésének ellenõrzésével megtudhatjuk, hogy az ûrlapot kitöltötték-e már. Amikor az ûrlap elküldi a "tipp" paramétert, a $tipp változó globális változóként hozzáférhetõ lesz a programban. A $tipp változó létezése esetén egészen biztosak lehetünk benne, hogy az ûrlapot a felhasználó kitöltötte, így elvégezhetjük a további vizsgálatokat. 9.10. program Számkitalálós PHP program 1: <?php 2: $kitalalando_szam = 42; 3: $uzenet = ""; 4: if (! isset( $tipp ) ) 5: { 6: $uzenet = "Üdvözlöm a számkitalálós játékban!"; 7: } 8: elseif ( $tipp > $kitalalando_szam ) 9: { 10: $uzenet = "A(z) $tipp túl nagy, próbáljon egy kisebbet!"; 11: } 12: elseif ( $tipp < $kitalalando_szam ) 13: { 14: $uzenet = "A(z) $tipp túl kicsi, próbáljon egy nagyobbat!"; 15: } 16: else // egyenlõk kell, hogy legyenek 17: { 18: $uzenet = "Telitalálat!"; 19: } 20:?> 21: <html> 22: <head> 23: <title>9.10. program Számkitalálós PHP program</title> 24: </head> 25: <body> 26: <h1> 27: <?php print $uzenet?> 28: </h1> 29: <form action="<?php print $PHP_SELF?>" method="post"> 30: Ide írja a tippjét: <input type="text" name="tipp"> 31: </form> 32: </body> 33: </html>
Ûrlapok 161 A program törzsében egy if szerkezettel vizsgáljuk a $tipp változót és adunk értéket az $uzenet változónak. Ha a $tipp változó még nem létezik, a felhasználó csak most lépett az oldalra, ezért üdvözöljük. Különben megvizsgáljuk az elõre megadott számot és a $tipp értékét, és ez alapján rendeljük az $uzenet változóhoz a megfelelõ szöveget. Végül a HTML oldal törzsében csak ki kell írnunk az $uzenet értékét. A program persze még továbbfejleszthetõ. A PHP és a HTML kódot szétválasztva tartva egy grafikus könnyen módosíthatja az oldalt, a programozó közremûködése nélkül. 9 Állapot mentése rejtett mezõkkel A 9.10. példában található program nem tudja, hogy a felhasználó hányszor tippelt, egy rejtett mezõ bevezetésével azonban ez is számon tartható. A rejtett mezõ ugyanúgy mûködik, mint a szövegmezõ, de a felhasználó nem látja, hacsak meg nem nézi a HTML forráskódot. A 9.11. példában található programban bevezetünk egy rejtett mezõt, amely a találgatások számát tartalmazza. 9.11. program Állapot mentése rejtett mezõvel 1: <?php 2: $kitalalando_szam = 42; 3: $uzenet = ""; 4: $probalkozasok = ( isset( $probalkozasok ) )? ++$probalkozasok : 0; 5: if (! isset( $tipp ) ) 6: { 7: $uzenet = "Üdvözlöm a számkitalálós játékban!"; 8: } 9: elseif ( $tipp > $kitalalando_szam ) 10: { 11: $uzenet = "A(z) $tipp túl nagy, próbáljon egy kisebbet!"; 12: } 13: elseif ( $tipp < $kitalalando_szam ) 14: { 15: $uzenet = "A(z) $tipp túl kicsi, próbáljon egy nagyobbat!"; 16: } 17: else // egyenlõk kell, hogy legyenek 18: { 19: $uzenet = " Telitalálat!"; 20: }
162 9. óra 9.11. program (folytatás) 21: $tipp = (int) $tipp; 22:?> 23: <html> 24: <head> 25: <title>9.11. program Állapot mentése rejtett mezõvel</title> 26: </head> 27: <body> 28: <h1> 29: <?php print $uzenet?> 30: </h1> 31: Tippelés sorszáma: <?php print $probalkozasok?> 32: <form action="<?php print $PHP_SELF?>" method="post"> 33: Ide írja a tippjét: 34: <input type="text" name="tipp" value="<?php print $tipp?>"> 35: <input type="hidden" name="probalkozasok" value="<?php print $probalkozasok?>"> 36: </form> 37: </body> 38: </html> A rejtett mezõ neve "probalkozasok". A PHP segítségével kiírjuk a "probalkozasok" és a "tipp" mezõ értékét, hogy a felhasználó tudja, hányszor próbálkozott és mit tippelt utoljára. Ez az eljárás akkor lehet hasznos, amikor a kitöltött ûrlapot elemezzük. Ha az ûrlapot rosszul töltötték ki, a felhasználó tudni fogja, mit rontott el. A beadott tipp értékét egész számmá alakítjuk a kérdõívbe írás elõtt. Egy kifejezés értékének kiírásához a böngészõben a print() vagy az echo() utasításokat használhatjuk. PHP módban ezt egyszerûbben is megtehetjük. Ha egyenlõségjelet (=) teszünk a PHP blokkot nyitó elem után, a böngészõ az azt következõ kifejezés értékét kiírja, így a <? print $proba?> helyett írhatjuk a következõt is: <?=$proba?>
Ûrlapok 163 A PHP kód törzsében egy feltétellel megvizsgáljuk, hogy kell-e növelni a $probalkozasok változó értékét. Ha a változó létezik, akkor növeljük az értékét, különben 0-ra állítjuk. A HTML kód törzsében folyamatosan kiírjuk, hányszor próbálkozott a felhasználó. 9 Ne bízzunk meg feltétel nélkül a rejtett mezõkben. Nem tudhatjuk, hogy honnan származik az értékük. Nem mondjuk, hogy ne használjuk õket, csak azt, hogy nagy körültekintéssel tegyük. A felhasználó a forrás megváltoztatásával könnyedén csalhat a programban. A rejtett mezõk használata nem biztonságos. A felhasználó átirányítása Programunknak van egy nagy hátulütõje. Az ûrlap mindig újratöltõdik, akár kitalálta a felhasználó a számot, akár nem. A HTML nyelvben sajnos elkerülhetetlen az egész oldal újratöltése, a felhasználót azonban átirányíthatjuk egy gratuláló oldalra, ha kitalálta a számot. Amikor az ügyfélprogram elkezdi a kapcsolatot a kiszolgálóval, elküld egy fejlécet, amely különbözõ információkat tartalmaz az azt követõ dokumentumról. A PHP ezt automatikusan megteszi, de a header() függvénnyel mi is beállíthatjuk a fejléc egyes elemeit. Ha a header() függvényt szeretnénk használni, biztosnak kell benne lennünk, hogy a böngészõnek nem írtunk ki semmit, különben a függvényhívás elõtt a PHP elküldi a saját fejlécét. Ez mindenféle kiírás, még sortörés és szóköz karakter esetén is bekövetkezik. A header() függvény használatakor semmi nem lehet a függvényhívás elõtt, így ellenõriznünk kell a felhasználandó külsõ állományokat is. A 9.12. példában egy jellemzõ PHP fejlécet láthatunk. 9.12. példa Egy jellemzõ PHP fejléc 1: HEAD /php-konyv/urlapok/9.1.program.php HTTP/1.0 2: HTTP/1.1 200 OK 3: Date: Sun, 09 Jan 2000 18:37:45 GMT 4: Server: Apache/1.3.9 (Unix) PHP/4.0 5: Connection: close 6: Content-Type: text/html
164 9. óra A fejlécet a Telnet programmal írathatjuk ki. Kapcsolódjunk a 80-as kapun a webkiszolgálóhoz és gépeljük be a következõt: HEAD /utvonal/fajl.html HTTP/1.0 Az ügyfélprogram ekkor kiírja a fejlécet. Egy "Location" fejléc elküldésével a böngészõt egy másik lapra irányíthatjuk: header( "Location: http://www.kiskapu.hu/" ); Tegyük fel, hogy készítettünk egy "gratulacio.html" oldalt, ahova átirányítjuk a felhasználót, amikor kitalálta a megadott számot. A megoldást a 9.13. példában találjuk. 9.13. program Fejléc küldése a header() függvénnyel 1: <?php 2: $kitalalando_szam = 42; 3: $uzenet = ""; 4: $probalkozasok = ( isset( $probalkozasok ) )? ++$probalkozasok : 0; 5: if (! isset( $tipp ) ) 6: { 7: $uzenet = "Üdvözlöm a számkitalálós játékban!"; 8: } 9: elseif ( $tipp > $kitalalando_szam ) 10: { 11: $uzenet = "A(z) $tipp túl nagy, próbáljon egy kisebbet!"; 12: } 13: elseif ( $tipp < $kitalalando_szam ) 14: { 15: $uzenet = "A(z) $tipp túl kicsi, próbáljon egy nagyobbat!"; 16: } 17: else // egyenlõk kell, hogy legyenek 18: { 19: header( "Location: gratulacio.html" ); 20: exit; 21: } 22: $tipp = (int) $tipp;
Ûrlapok 165 9.13. program (folytatás) 23:?> 24: <html> 25: <head> 26: <title>9.13. program Fejléc küldése a header() függvénnyel</title> 27: </head> 28: <body> 29: <h1> 30: <?php print $uzenet?> 31: </h1> 32: Tippelés sorszáma: <?php print $probalkozasok?> 33: <form action="<?php print $PHP_SELF?>" method="post"> 34: Ide írja a tippjét: 35: <input type="text" name="tipp" value="<?php print $tipp?>"> 36: <input type="hidden" name="probalkozasok" 37: value="<?php print $probalkozasok?>"> 38: </form> 39: </body> 40: </html> 9 Az if szerkezet else ágában a böngészõt átirányítjuk a "gratulacio.html" oldalra. A header() függvény meghívása után az oldalnak exit utasítással kell végzõdnie, hogy befejezze az ûrlap vizsgálatát. Fájlfeltöltõ ûrlapok és programok Megtanultuk, hogyan kérhetünk be adatokat a felhasználótól, de a Netscape Navigator 2-tõl és az Internet Explorer 4-tõl kezdve lehetõségünk van fájlok feltöltésére is. Ebben a részben azzal foglalkozunk, hogyan lehet a fájlok feltöltését kezelni a PHP 4 segítségével. Elõször létre kell hoznunk egy HTML ûrlapot, amely tartalmazza a fájlfeltöltõ mezõt, melynek egyik paramétere kötelezõen a következõ: ENCTYPE="multipart/form-data" A feltöltõ mezõ elõtt meg kell adnunk egy rejtett mezõt is. Ennek neve MAX_FILE_SIZE kell, hogy legyen, és a fogadandó fájl lehetséges legnagyobb méretét adja meg, bájtban. Nem lehet nagyobb, mint a php.ini fájlban megadott
166 9. óra upload_max_filesize értéke, amely alapértelmezés szerint 2 megabájt. Miután kitöltöttük a MAX_FILE_SIZE mezõt, a fájlt egy egyszerû INPUT elemmel tölthetjük fel, melynek TYPE paramétere "file". Bármilyen nevet adhatunk neki. A 9.14. példában a fájlt feltöltõ HTML kódot láthatjuk. 9.14. program Fájlfeltöltõ ûrlap 1: <html> 2: <head> 3: <title>9.14. program Fájlfeltöltõ ûrlap</title> 4: </head> 5: <body> 6: <form enctype="multipart/form-data" action="<?print $PHP_SELF?>" method="post"> 7: <input type="hidden" name="max_file_size" value="51200"> 8: <input type="file" name="fajl"><br> 9: <input type="submit" value="feltöltés!"> 10: </form> 11: </body> 12: </html> Vegyük észre, hogy a program meghívja az oldalt, amely tartalmazza, hogy PHP kóddal kezeljük a fájlt. A legnagyobb fájlméretet 50 kilobájtban adjuk meg és "fajl"-nak nevezzük el. Amikor a fájlt feltöltöttük, az egy ideiglenes könyvtárban tárolódik (ez alapbeállításban a /tmp, ha UNIX rendszerrõl van szó). A fájl elérési útját a betöltõ mezõ nevével megegyezõ globális változó tartalmazza (példánkban a $fajl). A fájlról a különbözõ információkat a PHP globális változókban tárolja. Nevük a fájl elérési útját tartalmazó változónév, kiegészítve a "name", "size" és "type" utótagokkal. A változók jelentését a 9.2. táblázat tartalmazza. 9.2. táblázat Feltöltött fájlhoz kapcsolódó globális változók Változónév Tartalma Példa $fajl A fájl ideiglenes elérési útja /tmp/php5pq3fu $fajl_name A feltöltött fájl neve test.gif $fajl_size A feltöltött fájl mérete bájtban 6835 $fajl_type A feltöltött fájl típusa image/gif
Ûrlapok 167 A PHP 4 a feltöltött fájlok adatainak tárolására beépített tömb típusú változókat használ. Ha egy vagy több fájlt töltünk fel egy ûrlapon keresztül, a fájlok adatai a $HTTP_POST_FILES tömbben tárolódnak. A tömb indexei a feltöltést meghatározó mezõk nevei. A 9.3. táblázatban láthatjuk a tömb elemeinek nevét és értékét. 9 9.3. táblázat Feltöltött fájlhoz kapcsolódó globális változók Elem Tartalma Példa $HTTP_POST_FILES["fajl"]["name"] A feltöltött fájl neve test.gif $HTTP_POST_FILES["fajl"]["size"] A feltöltött fájl mérete 6835 bájtban $HTTP_POST_FILES["fajl"]["type"] A feltöltött fájl típusa image/gif A 9.15. példában látható program kiírja a rendelkezésre álló információkat a feltöltött fájlról, és ha az GIF formátumú, megjeleníti. 9.15. program Fájlfeltöltõ program 1: <html> 2: <head> 3: <title>9.15. program - Fájlfeltöltõ program</title> 4: </head> 5: <?php 6: $feltoltes_konyvtar = "/home/httpd/htdocs/feltoltesek"; 7: $feltoltes_url = "http://php.kiskapu.hu/feltoltesek"; 8: if ( isset( $fajl ) ) 9: { 10: print "elérési út: $fajl<br>\n"; 11: print "név: $fajl_name<br>\n"; 12: print "méret: $fajl_size bájt<br>\n"; 13: print "típus: $fajl_type<p>\n\n"; 14: if ( $fajl_type == "image/gif" ) 15: { 16: copy ( $fajl, "$feltoltes_konyvtar/$fajl_name") or die ("Nem lehet másolni"); 17: 18: print "<img src=\"$feltoltes_url/$fajl_name\"><p>\n\n"; 19: } 20: }
168 9. óra 9.15. program (folytatás) 21:?> 22: <body> 23: <form enctype="multipart/form-data" action="<?php print $PHP_SELF?>" method="post"> 24: <input type="hidden" name="max_file_size" value="51200"> 25: <input type="file" name="fajl"><br> 26: <input type="submit" value="feltöltés!"> 27: </form> 28: </body> A 9.15. példában elõször ellenõrizzük, hogy a $fajl globális változó létezik-e. Ha létezik, feltehetjük, hogy a feltöltés sikeres volt (legalábbis e példa erejéig). Mindig csak megbízható forrásból fogadjunk fájlt és ellenõrizzük, hogy programunk számára megfelelõ formátumú-e. A rosszindulatú látogatók olyan ûrlapot készíthetnek, amelyben megegyezõ nevû elemek találhatóak, de teljesen más tartalommal, így programunk nem a várt adatokat kapja meg. Lehet, hogy ez paranoiának tûnik, de jegyezzük meg, hogy a kiszolgálóoldali programozásban a paranoia jó dolog. Soha ne bízzunk külsõ forrásból érkezõ adatokban, még akkor sem, ha a külsõ forrás egy olyan ûrlap, amit éppen mi készítettünk. Miután feltöltöttük a fájlt, a böngészõben megjelenítjük a $fajl, $fajl_name, $fajl_size és $fajl_type változók tartalmát, amelyek a fájlról információkat tartalmaznak. Ezután ellenõrizzük a $fajl_type változót. Ha értéke "image/gif", akkor az érkezett állományt GIF képként megjeleníthetjük. A típust a fájlkiterjesztés alapján állapítja meg a rendszer, ezért érdemes ellenõrizni, hogy a fájl valóban GIF formátumú-e. Ennek módjáról a tizenhetedik, karakterláncokkal foglalkozó órában tanulunk. A copy() függvénnyel a feltöltött fájlt a kiszolgáló másik könyvtárába másolhatjuk. A copy() függvénynek két paramétert kell megadni: az elsõ a másolandó fájl elérési útja, a második a fájl új elérési útja. A fájl eredeti elérési útja a $fajl változóban található. Az új elérési út számára létrehozunk egy $feltoltes_konyvtar nevû változót, amihez hozzáfûzzük a $fajl_name értéket. Ezután a copy() függvénnyel átmásoljuk a fájlt. UNIX rendszerben a kiszolgálóprogramok a 'nobody' felhaszná-
Ûrlapok 169 lónév alatt futnak, ezért mielõtt másolatot készítenénk a fájlról, ellenõriznünk kell, hogy a mûvelet engedélyezett-e. Az or mûvelettel a die() függvényt használjuk, ha a másolás sikertelen. Ezt a módszert a tizedik, a fájlokkal foglalkozó órában részletesebben áttekintjük. 9 Másolás után az eredeti fájlt nem kell törölnünk, a PHP ezt megteszi helyettünk. Ha nem másoljuk vagy helyezzük át a feltöltött állományt, a fájl elvész, mivel az a PHP kód végrehajtása után törlõdik az ideiglenes könyvtárból. Amikor létrehozzuk a $feltoltes_konyvtar változót, létrehozzuk a $feltoltes_url változót is, a célkönyvtár URL címének tárolására. A lemásolt fájlt HTML kép elemként jelenítjük meg. Összefoglalás Eddig olyan dolgokat tanultunk, amelyek segítségével igazi interaktív környezetet hozhatunk létre. Van azonban még néhány tanulnivaló. A felhasználóról képesek vagyunk információkat szerezni, de mit tegyünk ezekkel? Például fájlba írhatjuk. Ez lesz a következõ óra témája. Ebben az órában megtanultuk, hogyan használjuk a $GLOBALS tömböt, az ûrlapok adatait, a feltöltött fájlokat és a globális változókat. Megtanultuk, hogyan küldhetünk fejlécet az ügyfélnek a böngészõ átirányítása érdekében. Megnéztük, hogyan listázzuk ki az ûrlapról kapott adatokat és rejtett mezõket használtunk, adatok átadására a programtól a böngészõnek. Kérdések és válaszok Létre lehet hozni tömböt olyan elemek tárolására is, amelyek nem választómezõvel vagy jelölõnégyzetekkel megadottak? Igen. Minden elem, amely nevének végén üres szögletes zárójel van, tömbként tárolódik, így az elemek csoportba rendezhetõk. A header() függvény nagyon hasznosnak tûnik. Tanulunk még a HTTP fejlécekrõl? Magáról a HTTP-rõl még beszélünk a tizenharmadik órában. Az elemek nevének automatikus változónévvé alakítása veszélyesnek tûnik. Kikapcsolható valahol ez a lehetõség? Igen a php.ini fájl register_globals elemét kell off-ra állítani a lehetõség kikapcsolásához.
170 9. óra Mûhely A mûhelyben kvízkérdések találhatók, melyek segítenek megszilárdítani az órában szerzett tudást. A válaszokat az A függelékben helyeztük el. Kvíz 1. Melyik környezeti változó tartalmazza a felhasználó IP címét? 2. Melyik környezeti változó tartalmaz a böngészõrõl információkat? 3. Hogyan nevezzük el az ûrlap mezõjét, hogy a rá hivatkozó globális változó $urlap_tomb nevû tömb legyen? 4. Melyik beépített tömb tartalmazza a GET kérelmen keresztül érkezõ változókat? 5. Melyik beépített tömb tartalmazza a POST kérelmen keresztül érkezõ változókat? 6. Melyik függvényt használjuk a böngészõ átirányítására? Milyen karaktersorozatot kell átadnunk a függvénynek? 7. Hogyan lehet korlátozni egy ûrlapról feltölthetõ fájl méretét? 8. Hogyan korlátozható az összes ûrlapról vagy programból feltölthetõ fájl mérete? Feladatok 1. Készítsünk számológép-programot, amelyben a felhasználó megadhat két számot és a rajtuk végrehajtandó mûveletet (összeadás, kivonás, szorzás vagy osztás ezeket ismerje a program). 2. Készítsünk programot, amely rejtett mezõ használatával megmondja, hogy a felhasználó hányszor használta az elsõ feladatban szereplõ számológépet.