Vissza az előzőleg látogatott oldalra (nem elérhető funkció)Vissza a tananyag kezdőlapjára (P)Ugrás a tananyag előző oldalára (E)Ugrás a tananyag következő oldalára (V)Fogalom megjelenítés (nem elérhető funkció)Fogalmak listája (nem elérhető funkció)Oldal nyomtatása (nem elérhető funkció)Oldaltérkép megtekintése (D)Keresés az oldalon (nem elérhető funkció)Súgó megtekintése (S)

Bevezetés a kliens- és szerveroldali webalkalmazások készítésébe / Weboldalak dinamikus generálása PHP-val

Tanulási útmutató

Összefoglalás

A fejezet első részében HTML oldalak PHP-val történő előállítása szerepel kerül részletesebb tárgyalásra, azaz az, hogy hogyan állítja elő a szerveroldali program a HTML oldalt. A második felében azt az utat követjük nyomon, amely során a klienstől adat érkezhet a szerveroldali PHP szkriptnek.

Weboldalak dinamikus generálása PHP-val

Az előző fejezetben a PHP-ra mint programozási nyelvre tekintettünk, és ennek megfelelően a nyelvi elemeivel ismerkedtünk meg, a könnyebb megértés érdekében a JavaScript nyelvvel párhuzamba állítva. Láthattuk, hogy a hasonló nyelvtípusuk és a C szintaxis miatt nem kell túl sok újdonságot elsajátítanunk a nyelv alapfokú használatához. Külön hangsúlyt fektettünk megint csak az adatok modellezésének, az adatszerkezetek leírásának, valamint a feladatmegoldáshoz használt programozási tételek bemutatásának PHP nyelven. A C++ vagy JavaScript megfelelőivel összevetve jól kivehetőek a hasonlóságok és az eltérések is.

A csak nyelvi tulajdonságokat bemutató PHP programokat legegyszerűbb parancssori környezetben kipróbálni, mivel ekkor még a webbel kapcsolatos ismeretek nem lényegesek.

Ebben a fejezetben azonban azokat az ismeretek mutatjuk be, amelyek ahhoz kellenek, hogy a PHP-t dinamikus weboldalak generálására használjuk. Még egyszer áttekintjük, hogy a PHP hogyan illeszkedik az oldalkiszolgálás folyamatába, hogyan tudunk vele webes tartalmat (főleg HTML dokumentumokat) előállítani, és hogyan tudunk szkriptjeinknek paramétereket átadni, hogy valóban dinamikusan tudjanak reagálni környezetük változásaira. A fejezet végén pedig a bemeneti adatok kapcsán az űrlapok adatainak feldolgozásával foglalkozunk részletesebben.

A PHP az oldalkiszolgálás folyamatában

A PHP az oldalkiszolgálás folyamatábanA PHP az oldalkiszolgálás folyamatában

Ahogy a fenti ábra is mutatja, a PHP az oldalkiszolgálás folyamatában igazából egy speciális CGI program, legalábbis olyan értelemben, hogy bizonyos (tipikusan .php kiterjesztésű) állományok esetében a webszerver az állományt a PHP értelmezővel lefuttatja, majd ennek eredményét küldi le a kliensnek. A kommunikáció a webszerver és a PHP szkript között (2. és 3. pont) a CGI interfész szabályainak betartásával történik. A bemenő és kimenő adatok átadását tehát ez az interfész írja le, és szkriptünknek ekként kell működnie.

A fenti ábra szerint tehát webes környezetben a PHP egyetlen célja, hogy a megfelelő webes tartalmat programozottan előállítsa, ami az esetek nagy részében HTML dokumentumok generálását jelenti.

Vissza a tartalomjegyzékhez

Tartalomgenerálás PHP-ban (kimenet)

A CGI szabvány szerint a webszerver által leküldendő tartalmat a programnak a standard kimenetre kell kiírnia. Innen veszi fel a webszerver és továbbítja a kliens felé. A PHP szkriptnek tehát a generált HTML állományt a standard kimenetre kell írnia. Ezt alapvetően kétféleképpen lehet megtenni:

Példaképpen nézzük meg egy nagyon egyszerű, valid oldalsablon kiírását PHP-ban. Célunk a következő HTML forrás generálása:

Forráskód
<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <p>Hello világ!</p>
    </body>
</html>

Első körben ezt a tartalmat soronként kiírva állíthatjuk elő az echo parancs használatával:

Forráskód
<?php
echo '<!doctype html>';
echo '<html>';
echo '  <head>';
echo '      <meta charset="utf-8">';
echo '      <title></title>';
echo '  </head>';
echo '  <body>';
echo '     <p>Hello világ!</p>';
echo '  </body>';
echo '</html>';
?>

Látjuk és érezzük, hogy ez a megoldás nagyon bőbeszédű, és rengeteg felesleges kódrészletet tartalmaz. A HTML forrást nem szükséges soronként feldolgozni. Megadhatjuk egy nagy szövegként, és ezt a szöveget íratjuk ki az echo paranccsal. A szöveg megadását az alábbiakban nowdoc formátumban végezzük el:

Forráskód
<?php
echo <<<'VEGE'
<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <p>Hello világ!</p>
    </body>
</html>
VEGE;
?>

A legegyszerűbb megoldás azonban mégiscsak az, hogy kihasználjuk: ami nincs PHP blokkban, az automatikusan kiírásra kerül. Így a PHP állományunk e példában csupán a HTML forrást tartalmazza, és nincsen benne értelmezendő PHP blokk:

Forráskód
<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <p>Hello világ!</p>
    </body>
</html>

Böngészőből meghívva ezt az állományt (pl. http://localhost/hello.php), a PHP szkript kimenetére ez a HTML forráskód kerül, ezt küldi vissza a webszerver a böngészőnek, amely megjeleníti azt.

Érdemes annyit megjegyezni, hogy a két fejezettel ezelőtti C++ kóddal összehasonlítva itt már nem kellett HTTP fejléceket küldeni (Content-Type). Bár fejléceket PHP is lehet küldeni, a tipikusan előforduló fejlécek generálását átveszi a programozótól, hogy az a lényegi tartalom generálására koncentrálhasson.

Természetesen a fenti példa elég laboratóriumi, azt hivatott bemutatni, hogy statikus tartalom kiírását nem érdemes PHP blokkban elvégezni. Másrészt azt a következtetést is levonhatjuk, hogy statikus HTML állományokat nyugodtan bújtathatunk .php kiterjesztés mögé, azokkal a PHP értelmező semmit sem tesz, csak kiírja őket.

PHP használatának azonban akkor van értelme, ha a kimenet generálásához valamilyen logika kell. Ez a logika jelenik meg a nyelvi elemekben, vezérlési szerkezetekben, mely utóbbiak mindig valamilyen adat feldolgozásához kapcsolódnak. A következőkben nézzük meg a tartalomgenerálás szempontjából előforduló tipikus eseteket.

Példaképpen ragadjuk ki egy nagyobb feladat egy kis részletét: egy termékről a felhasználó visszajelzések alapján adott egy pontszám 1 és 5 között.

Feladat

1. feladat: írjuk ki a pontszámot!

A feladatban szereplő adat, a pontszám egy változóban jelenik meg a programban. Egyelőre nem fontos, hogy hogyan kerül oda, tekintsük adottnak.

Forráskód
<?php
$pontszam = 3.8;
?>

A feladat e változó értékének a kiírása. A megoldáshoz biztosan programot kell használni, hiszen adat csak programban jelenhet meg, és csak programmal lehet feldolgozni. PHP-ban a kiírást programozottan az echo paranccsal tudjuk elvégezni. Kérdés viszont, hogy mit írjunk ki. Csak a változó értékét? Vagy ezt valamilyen HTML elemben tegyük meg? Első lépésként tehát fogalmazzuk meg, hogy milyen kimenetet várunk el. Ebben az esetben a generálandó tartalom legyen a következő:

Forráskód
<p>A termék értékelése: 3.8</p>

A következő lépés, hogy ezt a kimenetet PHP segítségével állítjuk elő. A megoldás adja magát:

Forráskód
<?php
echo "<p>A termék értékelése: {$pontszam}</p>";
?>

Igen ám, de ezt a kimenetet másféleképpen is előállíthatjuk:

Forráskód
<p><?php
echo "A termék értékelése: {$pontszam}";
?></p>

Vagy akár így is:

Forráskód
<p>A termék értékelése: <?php echo $pontszam; ?></p>

Melyiket válasszuk? Ha lefuttatjuk ezeket, akkor mindhárom ugyanazt a kimenetet adja. Ilyen szempontból mindegy is. Viszont legelső példánkból azt vontuk le következtetésként, hogy a statikus tartalmak kiírásához felesleges PHP-t használnunk. Érdemes tehát az elvárt kimenetet elemezni, és megnézni: melyik része dinamikus, mely részének előállításához kell program? Egyedül a 3.8 kiírásához. Ennek az elvnek tehát a fenti három megoldás közül egyedül az utolsó felel meg:

Forráskód
<p>A termék értékelése: <?php echo $pontszam; ?></p>

Mivel egy változó értékének kiírása viszonylag gyakori, ezért bevezettek egy kényelmesebb, rövidebb formulát erre (5.4-es PHP verziótól külön beállítás nélkül is használható):

Forráskód
<p>A termék értékelése: <?=$pontszam?></p>
Feladat

2. feladat: Nem értékelt termékeknél a pontszám 0. Az értékelést csak akkor írjuk ki, ha a pontszám 1 és 5 közé esik, ellenkező esetben jelezzük a felhasználó felé, hogy még nincs értékelés.

Mivel HTML generálásáról van szó, megint csak érdemes az elvárt kimenetből kiindulni, hogy azt aztán össze lehessen vetni a generált tartalommal. Pontszám értékétől függően kétféle kimenetünk lehet:

Forráskód
<p>A termék értékelése: 3.8</p>
<!-- vagy -->
<p>A termék még nincs értékelve.</p>

A feladat megoldásához a pontszám értéke alapján elágazást kell használni. Továbbra is ügyelünk arra, hogy csak a dinamikus rész legyen PHP blokkokban.

Forráskód
<?php if ($pontszam >= 1 && $pontszam <= 5) { ?>
<p>A termék értékelése: <?php echo $pontszam; ?></p>
<?php } else { ?>
<p>A termék még nincs értékelve.</p>
<?php } ?>

Amikor kiíráshoz használjuk a PHP vezérlési szerkezeteit, akkor az utasításblokkok zárójele kevésbé olvasható a sok egyéb jelölő között. Ilyen esetekben (csak kiírásnál!) szokták használni a PHP alternatív szintaxisát, amely a következőképpen néz ki elágazás esetén:

Forráskód
<?php if ($pontszam >= 1 && $pontszam <= 5) : ?>
<p>A termék értékelése: <?php echo $pontszam; ?></p>
<?php else : ?>
<p>A termék még nincs értékelve.</p>
<?php endif; ?>

Ebben jól látszik, hogy az elágazás melyik része, hol van a kódban.

Feladat

3. feladat: Az értékelést vizuálisan is jelezzük annyi csillag kiírásával, ami a pontszám alsó egész része.

A generált HTML-lel kapcsolatos elvárásaink 3.8-as pontszám mellett a következők:

Forráskód
<p>A termék értékelése: 3.8 (***)</p>

A csillagokat egy ciklussal állíthatjuk elő:

Forráskód
<p>A termék értékelése: 3.8 (
<?php for ($i = 1; $i <= floor($pontszam); $i++) { ?>
    *
<?php } ?>
)</p>

Az olvashatóság érdekében itt is érdemes áttérni az alternatív szintaxisra:

Forráskód
<p>A termék értékelése: 3.8 (
<?php for ($i = 1; $i <= floor($pontszam); $i++) : ?>
    *
<?php endfor; ?>
)</p>

Ezekhez az elvekhez ragaszkodva kiírásunk sablonszerű lesz: az alapvetően statikus HTML-ben speciális jelölőkkel jelezzük a dinamikus tartalom beszúrását és annak jellegét. Ha megfigyeljük, akkor a kiíráshoz csupán háromféle utasítást szükséges használni: változók kiírásához az echo parancsot, elágazásokat (if) és ciklusokat (for valamelyik variánsa).

A fenti példa egyes részeit összegyúrva az alábbi végeredmény jön ki:

Forráskód
<?php if ($pontszam >= 1 && $pontszam <= 5) : ?>
    <p>A termék értékelése: <?php echo $pontszam; ?> (
    <?php for ($i = 1; $i <= floor($pontszam); $i++) : ?>
        *
    <?php endfor; ?>
    )</p>
<?php else : ?>
    <p>A termék még nincs értékelve.</p>
<?php endif; ?>

Vissza a tartalomjegyzékhez

CGI (PHP) szkriptek bemenete webes környezetben

Az előzőekben részletesen foglalkoztunk PHP szkriptek kimenetével, azaz a HTML oldalak generálásával. Weblapjaink azonban többek között attól válnak dinamikussá, hogy a körülményektől, általában a felhasználó tevékenységétől függően másképp működnek vagy mást jelenítenek meg. Egy szerveroldali szkriptnek a működését az adatok határozzák meg. A szerveroldali webprogramozásnál a dinamizmust tehát az jelenti, hogy kérésenként eltérő adatokat kap az oldal paraméterül.

Szkriptjeinknek a következő forrásokból érkezhetnek adatok:

Vissza a tartalomjegyzékhez

Kliensről érkező adatok

Paraméterek útja a böngészőtől a PHP szkriptigParaméterek útja a böngészőtől a PHP szkriptig

A PHP szkripthez érkező adatok egy része a böngészőből érkezik. A fenti ábrán látható az a sematikus folyamat, ahogy egy böngészőbeli tevékenység végül a PHP szkript futását eredményezi. A böngészőben keletkező adatokból HTTP kérés lesz (1), és ebben a formában érkezik a szerverre. Itt a webszerver a HTTP kérést a CGI interfész szerint feldolgozza (2), majd a szkriptet elindítja, amely az adatokat beolvassa (3).

HTTP és CGI

A fenti folyamatból egy korábbi fejezetben részletesen foglalkoztunk a közbülső lépéssel, azaz azzal, hogy a HTTP kérés adatait a webszerver a CGI szabvány alapján hogyan készíti elő a szkript számára. Láthattuk, hogy a HTTP kérés során a kérés körülményeiből, az URL-ből és a HTTP fejlécekből környezeti változók lesznek, a HTTP üzenettörzs pedig a standard bemeneten jelenik meg. A HTTP kérés egyes részei közül elsősorban az URL <query> része és az üzenettörzs tartalmazhat szabadon megadható paramétereket. Így a szkript számára felhasználó által megadott adat a QUERY_STRING környezeti változón és a standard bemeneten érkezhet. (Megemlítjük, hogy a kérés körülményei, pl. a kérés módja, és a fejlécek is szabályozhatók kliensoldalról, de ennek mélyebb taglalása nem e tananyag célja.)

Alábbiakban látható egy URL általános felépítése, és az, hogy ennek egyes részei hogyan jelennek meg a kérésben:

<scheme>://<host>:<port>/<path>?<query>#<fragment>
METÓDUS /<path>?<query> VERZIÓ ----> QUERY_STRING Host: <host> FEJLÉC: ÉRTÉK FEJLÉC: ÉRTÉK FEJLÉC: ÉRTÉK ÜZENETTEST ----> Standard bemenet

A folyamatot az alábbi ábra foglalja össze:

Szabadon megadható paraméterek leképezése a HTTP kérésből a CGI szabvány szerintSzabadon megadható paraméterek leképezése a HTTP kérésből a CGI szabvány szerint

Böngésző és HTTP

A következőkben a folyamat elejére koncentrálunk, és azt nézzük meg azt, hogy a böngészőben milyen módon tudunk kérést indítani, és milyen lehetőségeink vannak paraméterek megadására. Az előzőekben kiderült, hogy főleg azt vizsgáljuk, miként tudjuk beállítani az URL <query> részét vagy az üzenettörzset.

HTTP kérést az alábbi módokon tudunk indítani:

Mindegyik esetben az URL megadása szükségszerű, ezzel együtt viszont a <query> is tölthető.

A böngésző címsorát használva vagy hivatkozásra kattintva, a böngésző egy GET kérést indít az URL-ben megadott szerver felé. Ebben az esetben csak az URL <query> része határozható meg. Például egy link esetében ez így néz ki:

Forráskód
<a href="http://server.hu/index.php?adat=ELTE">Valami</a>

A felhasználói interakció és adatmegadás egy másik fő forrását az űrlapok jelentik. Szerveroldali webprogramozás szempontjából a form elem következő attribútumai fontosak:

Az enctype attribútumot ritkán szoktuk beállítani, mivel az alapértelmezett értéke általában megfelelő, mégis néha meg kell határozni az értékét:

Űrlap küldésének lépései a következők:

név1=érték1&név2=érték2&név3=érték3
http://pelda.server.hu/feldolgoz.php?alma=piros&korte=sarga

Az elküldés szempontjából a következőket érdemes az űrlapelemekről ismerni:

Példaképpen tekintsük az alábbi űrlapot:

Forráskód
<form action="http://localhost/cgi-bin/cgi.exe" method="post">
    <input type="text" name="alma" value="piros">
    <input type="password" value="kek">
    <input type="hidden" name="rejtett" value="titkos">
    <input type="checkbox" name="check1" value="ertek1" checked>
    <input type="checkbox" name="check2" checked>
    <input type="submit">
</form>

Elküldéskor az alábbi kérésszöveg kerül elküldésre:

alma=piros&rejtett=titkos&check1=ertek1&check2=on

A password és submit mezőknek nincsen neve, így nem kerülnek az elküldött adatok közé. A második checkboxnak nincsen value attribútuma megadva, így on értékkel kerül elküldésre.

JavaScripttel a fenti folyamatok mind programozottan is elérhetőek a location objektumon keresztül, vagy űrlapok submit metódusával. Ezen kívül programozottan a HTTP fejlécek és mindenféle HTTP metódus megadható, de ezek már nem ennek a tananyagnak a témái.

Kliensoldalon tehát tipikusan kérésszöveget állítunk elő, amely vagy az URL <query> részében, vagy HTTP üzenettörzsben kerül elküldésre. A lehetőségeket az alábbi ábra foglalja össze:

Kérésküldés lehetőségei a böngészőben és a kérésszöveg leképezése a HTTP kérés részeibeKérésküldés lehetőségei a böngészőben és a kérésszöveg leképezése a HTTP kérés részeibe

CGI és PHP

Az adatáramlás utolsó lépéseként azt nézzük meg, hogy a környezeti változókban és a standard bemeneten megjelenő adatokat, tipikusan a kérésszöveget hogyan érhetjük el PHP-ban. Szerencsékre a PHP sok mindenben leveszi a terhet a fejlesztő válláról, és ezeket az adatokat kényelmes formában, szuperglobális asszociatív tömbként készíti elő.

Az URL <query> részében érkező és QUERY_STRING környezeti változóban elérhető kérésszöveg részei a $_GET tömbben érhetőek el, ahol név=érték párosokból a tömb kulcs => érték párosai lesznek.

Forráskód
<?php
//kérésszöveg: alma=piros&korte=sarga
$_GET['alma'];  //"piros"
$_GET['korte']; //"sarga"
?>

Az üzenettörzsben érkező és a standard bemeneten elérhető kérésszöveg adatai a $_POST szuperglobális tömb elemeiként érhetőek el.

Forráskód
<?php
//kérésszöveg: alma=piros&korte=sarga
$_POST['alma']; //"piros"
$_POST['korte'];    //"sarga"
?>

Az egyéb környezeti változókat pedig a $_SERVER szuperglobális tömbön keresztül lehet kiolvasni.

CGI paraméterek elérése PHP-banCGI paraméterek elérése PHP-ban

A folyamat összefoglalása

Ha a folyamat elejét és végét tekintjük csak, akkor azt látjuk, hogy

Paraméterek leképezése a böngészőbeli lehetőségektől a PHP szkript szuperglobális tömbjeiig (a szürke nyilak a tananyag szempontjából nem fontos lehetőségeket mutatják)Paraméterek leképezése a böngészőbeli lehetőségektől a PHP szkript szuperglobális tömbjeiig (a szürke nyilak a tananyag szempontjából nem fontos lehetőségeket mutatják)

Példák a kliensről érkező adatok elérésére

A kliensen tehát vagy hivatkozások, vagy űrlapok formájában adhatunk meg adatokat szerveroldali feldolgozás céljából. Szerveroldalon ezeket vagy a $_GET vagy a $_POST tömbön keresztül tudjuk elérni. Ennek megfelelően a mostani példák ugyanazt a PHP szkriptet (adat.php) hívják meg, ami nem csinál mást, mint hogy kiírja e két tömb tartalmát:

Forráskód
<?php
function kiirTomb($tomb) {
    echo '<pre>';
    print_r($tomb);
    echo '</pre>';
}
kiirTomb($_GET);
kiirTomb($_POST);
?>

Első példánkban egy hivatkozásnak adunk meg rögzített paramétereket:

Forráskód
<a href="adat.php?oldal=12&stilus=sotet">Példa hivatkozás</a>

Rákattintva az alábbi képernyő fogad minket. Elvárásainknak megfelelően az URL-ben megadott paraméterek a $_GET tömbből olvashatók ki.

A hivatkozásban megadott adatok a PHP {forraskod_be}`$_GET`{/forraskod_be} tömbjében jelennek megA hivatkozásban megadott adatok a PHP {forraskod_be}`$_GET`{/forraskod_be} tömbjében jelennek meg

Második példánkban egy űrlapot küldünk el POST metódussal. A dolog specialitását az adja, hogy a meghívandó URL-be ugyancsak rögzített paramétereket csempésztünk:

Forráskód
<form action="adat.php?oldal=42" method="post">
    Név: <input type="text" name="nev" value="valaki"> <br>
    Jelszó: <input type="password" name="jelszo" value="titkos"> <br>
    <input type="submit" name="gomb" value="Bejelentkezés">
</form>

Az űrlapot elküldve láthatjuk, hogy az űrlapadatok a $_POST tömbben jelennek meg, viszont az URL-ben megadott paraméter is elérhető a $_GET tömbön keresztül.

Az űrlap adatai a PHP {forraskod_be}`$_POST`{/forraskod_be} tömbjében jelennek megAz űrlap adatai a PHP {forraskod_be}`$_POST`{/forraskod_be} tömbjében jelennek meg

Kitekintés: CGI adatok feldolgozása C++-ban

Természetesen a CGI szabvány nem korlátozódik a PHP használatára. Egy CGI programnak a környezeti változókat és a standard bemenetet kell kezelni a kliensről érkező adatok eléréséhez. A következő C++ nyelven írt példa a fontosabb paramétereket jeleníti meg.

Forráskód
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
 
using namespace std;
 
int main()
{
    char* request_method;
    char* content_length_str;
    char* query_string_get;
    int content_length;
 
    request_method = getenv("REQUEST_METHOD");
    content_length_str = getenv("CONTENT_LENGTH");
    content_length = atoi(content_length_str);
    query_string_get = getenv("QUERY_STRING");
    string query_string_post = "";
 
    if (strcmp(request_method, "POST") == 0) {
        int db = 0;
        char c;
        while (db < content_length && EOF != (c = fgetc(stdin))) {
            query_string_post += c;
            db++;
        }
    }
 
    cout << "Content-Type: text/plain" << endl;
    cout << endl;
    cout <<  "REQUEST_METHOD = " << request_method << endl;
    cout <<  "CONTENT_LENGTH = " << content_length << endl;
    cout <<  "QUERY_STRING_GET = " << query_string_get << endl;
    cout <<  "QUERY_STRING_POST = " << query_string_post << endl;
    return 0;
}

Vissza a tartalomjegyzékhez

Új Széchenyi terv
A projekt az Európai Unió támogatásával, az Európai Szociális Alap társfinanszirozásával valósul meg.

A tananyag az ELTE - PPKE informatika tananyagfejlesztési projekt (TÁMOP-4.1.2.A/1-11/1-2011-0052) keretében valósult meg.
A tananyag elkészítéséhez az ELTESCORM keretrendszert használtuk.