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 / Szerveroldali adattárolás

Tanulási útmutató

Összefoglalás

Az eddigi példáinkban az adatok élettartama a HTTP kérés kiszolgálásáig tartott. Ebben a fejezetben azokat a technológiákat járjuk körül, amelyek megengedik, hogy különböző kérések között is megőrződjenek adatok. A fejezet a fájlban és adatbázisban történő tárolásra tér ki részletesen.

Adattárolás

Egyik korábbi fejezetben láthattuk, hogy oldalaink attól válnak dinamikussá, hogy adatokat jelenítenek meg HTML formában, és ezek az adatok változhatnak. Az előző fejezetben a klienstől érkező adatok fogadása és feldolgozása volt fókuszban, különös tekintettel az űrlapadatok feldolgozására.

Az oldalkiszolgálás folyamatában a PHP szkriptek csupán a HTTP kérés kiszolgálásának idejére futnak. Ennek az a következménye, hogy minden bennük létrehozott változó a HTTP kérés végén megszűnik. A következő kérés kiszolgálásakor a szkript újra lefut, és benne újra létrejönnek a megfelelő változók, majd meg is szűnnek. Erre mutat példát az alábbi PHP szkript, ahol egy számláló értékét szeretnénk kérésenként növelni. Mivel a $szamlalo változó minden kérés végén megszűnik, így a következő kérésnél nem létezik, így értéke mindig 0-ról indul.

Forráskód
<?php
if (isset($szamlalo)) {
    $szamlalo += 1;
} else {
    $szamlalo = 0;
}
var_dump($szamlalo);
?>

Két kérés kiszolgálása tehát az adatokat, a változókat illetően teljesen független. Ha valamilyen változó adatot szerver oldalon szeretnénk több kérés esetén is elérhetővé tenni, akkor azt az adatot nem szabad PHP változóban tárolni, hanem valamilyen módon a PHP állományon kívül kell elhelyezni. Kérés kiszolgálásakor a PHP szkript ebből a külső forrásból olvashatja be az adatokat, és még a szkript befejezése előtt ide is kell kimentenie.

Az oldalkiszolgálás folyamata adattárolássalAz oldalkiszolgálás folyamata adattárolással
Az oldalkiszolgálás folyamata adattárolássalAz oldalkiszolgálás folyamata adattárolással

Ebben a fejezetben az adatok tárolásával fogunk foglalkozni. Részletesen áttekintjük a fájlkezeléssel kapcsolatos ismereteket, és belekóstolunk az adatbázisok PHP-ból történő kezelésébe.

Bármelyik módszert is választjuk minden esetben az a cél, hogy a külső forrásban valamilyen struktúrában tárolt adatot a feldolgozó függvény számára elfogadható formátumban előállítsuk. Az adatok tárolása tehát tulajdonképpen csak és kizárólag a beolvasás és kiírás folyamatába tartozik, nem szabad a feldolgozási logikában ilyen jellegű műveleteknek megjelennie. Az alábbiakban ezt is szem előtt fogjuk tartani.

Szöveges fájl vs.adatbázis

A bevezetésben említett technológiák mindegyike arra szolgál, hogy a rövid élettartamú szkriptek (és munkamenetek) helyett az adatokat hosszú ideig tudjuk tárolni, függetlenül a folyton változó kérésektől.

Az adatok hosszú távú, biztonságos tárolása szerveroldalon oldható meg. Szöveges fájlok esetén az információ szövegként van tárolva olyan formátumban, hogy az emberi szemmel is érthető, értelmezhető. Az adatok tárolásához és visszanyeréséhez a PHP szkriptnek ismernie kell a fájl szerkezetét.

Adatbázisok esetén először is szükségünk van egy adatbázis-kezelő rendszerre. Adatbázisokban adatainkat típusosan tudjuk tárolni, akár bonyolult szerkezeteket kialakítva. A PHP szkriptnek nem kell ismernie azt, hogy hogyan tárolódnak az adatok, csupán a az adatbázis-kezelő rendszerrel való kapcsolatot szükséges ismernie.

Fájlban tárolás előnyei:

Adatbázisban tárolás előnye:

Manapság adatok tárolását az esetek többségében adatbázisban szokták megoldani. Mivel azonban több ismeretre van szükség ezek kezeléséhez (telepítés, üzembe helyezés, SQL utasítások, PHP függvények), ezért ebben a tananyagban inkább a fájlkezelésre koncentrálunk.

Vissza a tartalomjegyzékhez

Adatok tárolása fájlban

Fájlkezelő függvények

A PHP sokféle nyelvi lehetőséget biztosít a szerveren elérhető fájlok kezelésére. Az általános, de viszonylag alacsony szintű műveletek mellett magasabb szintű függvények segítenek a tipikus feladatok egyszerű elvégzésében. Röviden tekintsük át a fontosabb függvényeket! A fájlkezeléssel kapcsolatos függvények teljes listáját és részletes leírását a dokumentáció tartalmazza.

Alacsony szintű, általános függvények:

Alacsony szintű beolvasó utasítások:

Alacsony szintű kiíró utasítások:

Magas szintű beolvasó utasítások:

Magas szintű kiíró utasítások:

Néhány fontos fájlkezelő függvény:

Hibakezelés

A fájlműveletek hiba esetén hamis értékkel térnek vissza. Így például annak ellenőrzése, hogy sikeresen megnyílt-e a fájl, a következőképpen történhet:

Forráskód
<?php
$f = fopen('nem_letezik.txt', 'r');
if ($f) {
    /* ... */
    fclose($f);
}
?>

Bár egy nem létező állomány esetén a vezérlés nem lép bele az elágazásba, a PHP bizonyos beállítások mellett egy figyelmeztető üzenetet ír ki a képernyőre jelezvén a fájl hiányát. Ha ilyen beállítások mellett szeretnénk elkerülni ezt a hibaüzenetet, akkor erre a @ operátor ad lehetőséget. A fenti kódrészletben a fopen által generált hibaüzenet nem kerül kiírásra, ha a @ jelet elé írjuk:

Forráskód
<?php
$f = @fopen('nem_letezik.txt', 'r');
if ($f) {
    /* ... */
    fclose($f);
}
?>

Adatszerkezet-vezérelt tárolás

Ahogy a bevezetőben írtuk a fájlkezelésre most olyan szemmel nézünk, mint a feldolgozás szempontjából fontos adatszerkezet tárolásának egyik lehetséges formájára. Ez azt jelenti, hogy ha szkriptünkben adott egy adatszerkezet, akkor azt egy megfelelő utasítással szeretnénk kimenteni egy fájlba, és következő alkalommal ebből a fájlból ugyanezt a struktúrát visszaolvasni. Ebben a folyamatban a fájl tartalmának felépítése nem érdekes. Csak az érdekel minket, hogy az adat a megfelelő formátumban rendelkezésre álljon.

Célszerű lenne tehát a PHP-s adatszerkezetet valahogy egy az egyben fájlba írni. Ebben segít nekünk az ún. sorosítás, ami egy adatszerkezet visszaalakítható szöveges megfelelője. A sorosítást elsősorban tároláskor és továbbításkor szokták alkalmazni.

Egy PHP-s adatszerkezet szöveges reprezentánsát többféleképpen előállíthatjuk. Használhatjuk a PHP sorosító függvényeit:

Példaképpen tekintsük az alábbi tömböt mint adatot:

Forráskód
<?php
$filmek = array(
    array(
        'cim'      => 'Passió',
        'rendezo'  => 'Mel Gibson',
        'ev'       => '2004',
        'szereplok'=> array(
            'Jim Caviezel',
            'Maia Morgenstern',
            'Christo Jivkov',
        ),
    ),
    array(
        'cim'      => 'Pio atya - A csodák embere',
        'rendezo'  => 'Carlo Carlei',
        'ev'       => '2000',
        'szereplok'=> array(
            'Sergio Castellitto',
            'Sergio Albelli',
        ),
    ),
);
?>

A serialize függvény a következő szöveget állítja ebből elő:

Forráskód
<?php
echo serialize($filmek);
//a:2:{i:0;a:4:{s:3:"cim";s:7:"Passió";s:7:"rendezo";s:10:"Mel Gibson";s:2:"ev";s:4:"2004";s:9:"szereplok";a:3:{i:0;s:12:"Jim Caviezel";i:1;s:16:"Maia Morgenstern";i:2;s:14:"Christo Jivkov";}}i:1;a:4:{s:3:"cim";s:27:"Pio atya - A csodák embere";s:7:"rendezo";s:12:"Carlo Carlei";s:2:"ev";s:4:"2000";s:9:"szereplok";a:2:{i:0;s:18:"Sergio Castellitto";i:1;s:14:"Sergio Albelli";}}}
?>

Egy másik lehetőséget a szöveges megfelelő előállítására a JSON formátum adja, aminek kezelésére a PHP a következő két függvényt adja:

A fenti példa esetében a json_encode eredménye a következő:

Forráskód
<?php
echo json_encode($filmek);
//[{"cim":"Passi\u00f3","rendezo":"Mel Gibson","ev":"2004","szereplok":["Jim Caviezel","Maia Morgenstern","Christo Jivkov"]},{"cim":"Pio atya - A csod\u00e1k embere","rendezo":"Carlo Carlei","ev":"2000","szereplok":["Sergio Castellitto","Sergio Albelli"]}]
 
//Vagy formázva
 
/*
[
  {
    "cim":"Passi\u00f3",
    "rendezo":"Mel Gibson",
    "ev":"2004",
    "szereplok":[
      "Jim Caviezel",
      "Maia Morgenstern",
      "Christo Jivkov"
    ]
  },
  {
    "cim":"Pio atya - A csod\u00e1k embere",
    "rendezo":"Carlo Carlei",
    "ev":"2000",
    "szereplok":[
      "Sergio Castellitto",
      "Sergio Albelli"
    ]
  }
]
*/
?>

A JSON formátumnak többek között megvan az az előnye, hogy egyrészt nagyon elterjedt formátum az adatleírás és kommunikáció terén, másrészt formázott állapotában szövegesen is áttekinthető és akár szerkeszthető.

Ez utóbbi sorosító függvényekkel és a magas szintű beolvasást és kiírást végző fájlműveletekkel írhatunk két segédfüggvényt, mely tetszőleges adatszerkezet betöltését és mentését végzi el.

Forráskód
<?php
//Betöltés fájlból
function fajlbol_betolt($fajlnev) {
    $s = file_get_contents($fajlnev);
    return json_decode($s, true);
}
 
//Mentés fájlba
function fajlba_ment($fajlnev, $adat) {
    $s = json_encode($adat);
    return file_put_contents($fajlnev, $s, LOCK_EX);
}
?>

Betöltés esetén előfordulhat, hogy a megadott állomány még nem létezik. Ebben az esetben jó lenne, ha valamilyen alapértelmezett struktúrát adna vissza, amit akár paraméterként is megadhatunk.

Forráskód
<?php
function fajlbol_betolt($fajlnev, $alap = array()) {
    $s = @file_get_contents($fajlnev);
    return ($s === false 
        ? $alap 
        : json_decode($s, true));
}
?>

Fájlszerkezet-vezérelt tárolás

Az előző megoldás nem volt tekintettel a fájl tartalmának szerkezetére. Előfordulhat azonban, hogy a fájl szerkezete bizonyos szabályokat követ, és kódunknak ehhez kell igazodnia. Gyakori például, hogy fájljainknak valamilyen mikroformátum szerint kell kinéznie az interoperabilitás vagy a könnyű áttekinthetőség miatt. Ezekben az esetekben a megfelelő fájlműveletekkel kell a megadott formátumot feldolgoznunk vagy előállítanunk.

Nézzünk néhány példát a kötött fájlformátumok feldolgozására!

Feladat

1. példa: Adott filmcímek listája egy fájlban, soronként egy filmmel. Olvassuk ezt be egy tömbbe!

A filmlistát tartalmazó állomány például így nézhet ki:

A hobbit A Gyűrűk Ura Út a vadonba Passió

Beolvasása elvégezhető alacsony szintű fájlműveletekkel, de erre a tipikus feladatra kész megoldást szolgáltat a file függvény. Használatakor el kell döntenünk, hogy az üres sorok is megjelenjenek-e a tömbben üres elemként vagy sem (FILE_SKIP_EMPTY_LINES), illetve hogy a sorok végén lévő új sor karaktereket a PHP levegye-e (FILE_IGNORE_NEW_LINES). Ezeket a file függvény második paraméterében tudjuk szabályozni.

Forráskód
<?php
$filmek = file('lista.txt', 
                FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
/*
Array
(
    [0] => A hobbit
    [1] => A Gyűrűk Ura
    [2] => Út a vadonba
    [3] => Passió
)
*/
?>

Hiányzó fájl esetén feladatfüggő, hogy a szkript futását hibaüzenettel leállítjuk vagy alapértelmezett értéket adunk a tömbünknek:

Forráskód
<?php
//Leállás hiba esetén
$filmek = @file('nem_letezik.txt', 
                FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) 
          or die('Nincs meg a fájl');
 
//Alapértelmezett érték
$filmek = @file('nem_letezik.txt', 
                FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if (!$filmek) {
    $filmek = array();
}
?>
Feladat

2. példa: Készítsük el az előző példa párját, azaz oldjuk meg egy filmcímeket tartalmazó tömb fájlba mentését is (egy cím egy sor)!

Sajnos a file parancsnak nincsen meg a kiíró párja, így vagy alacsony szintű műveletekkel, vagy egy kis trükk segítségével magasabb szintű függvénnyel oldjuk meg a feladatot.

Alacsony szintű műveleteknél a fájlnyitást követően egy ciklussal kell végigmenni a tömbön, és kiírni az elemeket egyesével.

Forráskód
<?php
//A tömb filmcímekkel
$filmek = array(
    'Vuk',
    'Lolka és Bolka',
    'Macskafogó',
    'Kisvakond és barátai',
);
 
//Kiírás alacsony szintű műveletekkel
define('SORVEG', "\n");
$f = @fopen('mesek.txt', 'w') 
     or die('Hiba!');
if ($f) {
    foreach ($filmek as $film) {
        fputs($f, $film . SORVEG);
    }
    fclose($f);
}
?>

Másik lehetőség, hogy először előállítjuk a filmek új sor karakterekkel elválasztott listáját szövegként (implode), és ezt írjuk ki a file_put_contents függvény segítségével.

Forráskód
<?php
define('SORVEG', "\n");
//Elemek összefűzése
$s     = implode(SORVEG, $filmek) . SORVEG;
//Kiírás magas szintű művelettel
$siker = @file_put_contents('mesek.txt', $s);
?>
Feladat

3. példa: Adott egy rekordokból álló tömb. Végezzük el a kiírását úgy, hogy egy sorban egy rekordnyi információ legyen, az egyes értékeket soron belül tabulátorral válasszuk el!

A filmes témánál maradva a következő tömböt vehetjük kiindulási alapnak:

Forráskód
<?php
$filmek = array(
    array(
        'cim'         => 'Passió',
        'rendezo'     => 'Mel Gibson',
        'ev'          => '2004',
    ),
    array(
        'cim'         => 'Pio atya - A csodák embere',
        'rendezo'     => 'Carlo Carlei',
        'ev'          => '2000',
    ),
);
?>

A megoldás során vagy az implode függvénnyel egy sorrá fűzzük először a rekordot, majd kiírjuk, vagy az fputcsv függvényt használjuk.

Forráskód
<?php
define('SORVEG', "\n");
$f = @fopen('filmek.txt', 'w')
     or die('Hiba!');
if ($f) {
    foreach ($filmek as $film) {
        fputcsv($f, $film, "\t");
    }
    fclose($f);
}
?>

Az eredmény:

Passió Mel Gibson 2004 Pio atya - A csodák embere Carlo Carlei 2000
Feladat

4. példa: Az előző példában kapott fájlt olvassuk be rekordok tömbjeként!

A beolvasást a file paranccsal is megtehetjük, ám ekkor a sorokat még fel kell bontani tabulátorjel szerint. Ez utóbbit egy ciklussal tesszük, ahol a tömbelemet referenciaként kapjuk vissza. Másik lehetőségként az fputcsv párja, az fgetcsv kínálkozik. Ez utóbbi esetben a fájlt soronként kell beolvasni, amíg az fgetcsv hamissal nem tér vissza jelezvén a fájl végét.

Forráskód
<?php
//Beolvasás a file paranccsal, és az utólagos soronkénti bontás
$filmek = file('filmek.txt', 
               FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach($filmek as &$film) {
    $film = explode("\t", $film);
} 
 
//Beolvasás soronként az fgetcsv segítségével
$filmek = array();
$f = @fopen('filmek.txt', 'r');
if ($f) {
    while ($sor = fgetcsv($f, 0, "\t")) {
        $filmek[] = sor;
    }
    fclose($f);
}
 
//Az eredmény
/*
Array
(
    [0] => Array
        (
            [0] => Passió
            [1] => Mel Gibson
            [2] => 2004
        )
    [1] => Array
        (
            [0] => Pio atya - A csodák embere
            [1] => Carlo Carlei
            [2] => 2000
        )
)
*/
?>
Feladat

5. példa: Az előző feladatbeli rekordok tömbjét tároljuk úgy a fájlban, hogy a rekord minden egyes mezeje külön sorba kerüljön, és az egyes rekordokat üres sor válassza el egymástól. Oldjuk meg a tömb beolvasását is!

A fájl szerkezete annyira speciális ebben az esetben, hogy a feldolgozást már csak alacsony szintű műveletekkel lehet megoldani. Beolvasásnál a sorvégi új sor karaktereket a trim függvény segítségével távolítjuk el.

Forráskód
<?php
//Mentés fájlba
define('SORVEG', "\n");
$f = @fopen('filmek_tobbsor.txt', 'w')
     or die('Hiba!');
if ($f) {
    foreach ($filmek as $film) {
        fputs($f, $film['cim'] . SORVEG);
        fputs($f, $film['rendezo'] . SORVEG);
        fputs($f, $film['ev'] . SORVEG);
        fputs($f, SORVEG);
    }
    fclose($f);
}
 
//Beolvasás fájlból
$filmek = array();
$f = @fopen('filmek_tobbsor.txt', 'r');
if ($f) {
    while (!feof($f)) {
        $cim = trim(fgets($f));
        $rendezo = trim(fgets($f));
        $ev = trim(fgets($f));
        $ures = fgets($f);
        if ($cim != '') {
            $filmek[] = array(
                'cim'       => $cim,
                'rendezo'   => $rendezo,
                'ev'        => $ev,
            );
        }
    }
    fclose($f);
}
?>

A mentett fájl tartalma:

Passió Mel Gibson 2004 Pio atya - A csodák embere Carlo Carlei 2000

Konkurenciakezelés

Párhuzamos kérések kiszolgálásakor előfordulhat, hogy két szkriptpéldány ugyanazzal a fájllal szeretne dolgozni egy időben. Annak érdekében, hogy feldolgozás közben a fájl szerkezete ne változzék, a fájlok hozzáférését ideiglenesen módosítják. Ezt PHP-ban az flock($f, $op) paranccsal lehet megtenni. Első paraméterében ($f) a lockolni kívánt logikai fájlkezelőt kell megadni, második paraméterében ($op) a lockolás jellege adandó meg:

Íráskor mielőtt a lockot feloldjuk, érdemes az fflush paranccsal az átmeneti pufferből a fájlba írni az adatokat. Példánkban alacsony szintű műveletekkel nézzük meg filmcímek soronkénti fájlba írását.

Forráskód
<?php
define('SORVEG', "\n");
$f = @fopen('mesek.txt', 'w')
     or die('Hiba!');
if ($f) {
    if (flock($f, LOCK_EX)) {
        foreach ($filmek as $film) {
            fputs($f, $film . SORVEG);
        }
        flock($f, LOCK_UN);
    }
    fclose($f);
}
?>

Olvasásnál is érdemes a lockot alkalmazni, hogy feldolgozás közben ne változzon meg a fájl tartalma.

Forráskód
<?php
$filmek = array();
$f = @fopen('lista.txt', 'r');
if ($f) {
    if (flock($f, LOCK_SH)) {
        while (!feof($f)) {
            $sor = trim(fgets($f));
            if ($sor != '') {
                $filmek[] = $sor;
            }
        }
        flock($f, LOCK_UN);
    }
    fclose($f);
}
?>

Vissza a tartalomjegyzékhez

Adatok tárolása adatbázisban

A PHP sokféle adatbázis-kezelő rendszerrel képes kapcsolatot teremteni:

Az adatbázis-kezelő rendszerrel való kapcsolatot a megfelelő adatbáziskezelő-specifikus függvények biztosítják. Külön függvénycsoport van a MySQL adatbázisok kezelésére, külön a PostgreSQL kezelésére, stb. Ezek elérhetőségét biztosítani szükséges.

Az adatok feldolgozása általában a következő lépésekből áll:

Az adatbázisban történő tároláshoz tehát szükségünk van:

SQLite adatbázisok

Azért, hogy a lehető legkönnyebben ismerhessük meg az adatbázisok világát, választásunk az SQLite adatbázis-kezelő rendszerre esett. Ez egy nagyon egyszerű rendszer, amely átmenetet képez a fájlban történő tárolás és a komplex adatbázisok között. Az SQLite esetében minden egyes adatbázisnak egy fájl felel meg. Nincsen külön szerver, maga az API biztosítja a fájlok megfelelő feldolgozását. Az SQLite-nak több verziója is van. Ezek közül a kettes verzió az adatokat – az elsődleges kulcstól eltekintve – kizárólag szöveges formátumban tárolja. A 3-as verzióban már megjelennek további típusok és összetettebb SQL utasítások is, de számunkra a 2-es verzió tudása annál is inkább megfelel, mert még jobban hasonlít az egyszerű szöveges állományokra.

Az SQL utasítások ismeretére természetesen szükségünk van, hiszen adatainkat ezekkel tudjuk az adatbázisban manipulálni, lekérdezni. Ezek alapvető ismeretét feltételezzük az olvasótól a továbbiakban.

Az SQLite adatbázisok kezeléséhez külön függvénycsoport tartozik. Ezek a függvények lefedik a fenti lépések speciális eseteit, és azon túl pl. a hibakezelést is. A fontosabb parancsok a következők:

Hibakezelés

Hiba esetén a legtöbb függvény hamis értékkel tér vissza. Ennek vizsgálatával eldönthető, hogy a parancs sikeresen lefutott-e.

Segédfüggvények

Néhány gyakran előforduló műveletet kiemelhetünk külön függvénybe.

Forráskód
<?php
//Adatbázis megnyitása
function adatbazis_nyit($fajlnev) {
    $db = sqlite_open($fajlnev, 0666, $sqliteerror);
    if (!$db) {
        die($sqliteerror);
    }
    return $db;
}
 
//Adatbázis-kapcsolat bezárása  
function adatbazis_zar($db) {
    sqlite_close($db);
}
 
//Tábla létrehozása, ha még nem létezik
function tabla_init($fajlnev, $tablanev, $create_sql) {
    $db = adatbazis_nyit($fajlnev);
 
    $siker = true;
    $result = sqlite_query($db, 
        "SELECT name FROM sqlite_master WHERE type='table' AND name='{$tablanev}'");
    if (sqlite_num_rows($result) == 0) {
        $siker = sqlite_exec($db, $create_sql);
    }
 
    adatbazis_zar($db);
 
    return $siker;
}
 
//Lekérdezés végrehajtása, eredmény tömbbe
function lekerdezes_tombbe($sql) {
    $db = adatbazis_nyit('filmek.sqlite');
    $ered = sqlite_array_query($db, $sql, SQLITE_ASSOC);
    adatbazis_zar($db);
    return $ered;
}
?>

Vissza a tartalomjegyzékhez

Példa fájlok és adatbázisok használatára

Feladat

Feladat

Adott filmek listája. Minden filmről tároljuk a címét, rendezőjét és megjelenési évét. Listázzuk ki a nyilvántartásunkban lévő filmeket, és adjunk lehetőséget új felvételére!

Közös részek

A feladathoz két felület tartozik. Az egyik a filmek listáját jeleníti meg, a másik egy űrlapot, amelyen keresztül adatokat vehetünk fel. Az oldalak megjelenése és a feldolgozási logika független az adatok tárolásától.

Lista oldal

A lista oldal feldolgozása és oldalsablonja lent látható (lista.php). Egyetlen kérdésként az marad, hogy hogyan kapjuk meg az összes filmet tartalmazó tömböt.

Forráskód
<?php
//Feldolgozó függvények
function osszes_film() {
    //???
}
 
//-----------------------------------------------------
 
//A "főprogram"
$filmek = osszes_film();
 
//---------------------------------------------------------
?>
<!doctype html>
<html>
    <meta charset="utf-8">
    <head>
        <title></title>
    </head>
    <body>
        <h1>Filmlista</h1>
        <a href="ujfilm.php">Új film...</a>
        <table>
            <tr>
                <th>Cím</th>
                <th>Rendező</th>
                <th>Év</th>
            </tr>
            <?php foreach ($filmek as $f) : ?>
            <tr>
                <td><?php echo $f['cim']; ?></td>
                <td><?php echo $f['rendezo']; ?></td>
                <td><?php echo $f['ev']; ?></td>
            </tr>
            <?php endforeach; ?>
        </table>
 
    </body>
</html>

Új film oldal

Az új film felvételéért felelő oldal sablonja és feldolgozási logikája lentebb látható (ujfilm.php). Az űrlapadatok feldolgozása a felülethez tartozik, ezért ez közös. Az új adat tárolása azonban függ a tárolás módjától. Sikeres felvétel után a header parancs segítségével egy olyan HTTP fejlécet küldünk le (Location), amely az oldalunkat a listaoldalra irányítja.

Forráskód
<?php
//Feldolgozó függvények
function film_beszur($cim, $rendezo, $ev) {
    //???
}
 
//-----------------------------------------------------
 
//A "főprogram"
$hibak = array();
$cim = '';
$rendezo = '';
$ev = '';
 
if ($_POST) {
    $cim = $_POST['cim'];
    $rendezo = $_POST['rendezo'];
    $ev = $_POST['ev'];
 
    if ($cim == '') {
        $hibak[] = 'Cím kötelező!';
    }
    if ($rendezo == '') {
        $hibak[] = 'Rendező kötelező!';
    }
    if (!is_numeric($ev) || strlen($ev) != 4) {
        $hibak[] = 'Rossz évszám!';
    }
 
    if (!$hibak) {
        if (film_beszur($cim, $rendezo, $ev)) {
            header('Location: lista_fajl.php');
        };
    }
}
 
//---------------------------------------------------------
?><!doctype html>
<html>
    <meta charset="utf-8">
    <head>
        <title></title>
    </head>
    <body>
        <h1>Új film</h1>
        <?php if ($hibak) : ?>
        <ul>
            <?php foreach ($hibak as $hiba) : ?>
            <li><?php echo $hiba; ?></li>
            <?php endforeach; ?>
        </ul>
        <?php endif; ?>
        <form action="" method="post">
            Cím: <br>
            <input type="text" name="cim" value="<?php echo $cim; ?>"> <br>
            Rendező: <br>
            <input type="text" name="rendezo" value="<?php echo $rendezo; ?>"> <br>
            Év: <br>
            <input type="text" name="ev" value="<?php echo $ev; ?>"> <br>
            <input type="submit">
        </form>
    </body>
</html>

Megoldás fájllal

Az adatokat rekordok tömbjeként ábrázoljuk (ahogy azt az oldalsablonok is sejtetik) és JSON fájlban tároljuk.

Listaoldal

A listaoldalon egyszerűen be kell tölteni a JSON fájlt, és átalakítani PHP tömbbé. Mivel a belső adatábrázolásunk megegyezik az oldalsablonban elvárttal, ezért minden további feldolgozás nélkül kiíratható a $filmek tömb. Ha a tömb további szűrést igényelne, akkor ahhoz pluszban egy kiválogatás tételt kellene implementálnunk.

Forráskód
<?php
//Segédfüggvények
//ld. a fájlkezelésről szóló részt
 
//Feldolgozó függvény
function osszes_film() {
    return fajlbol_betolt('filmek.json');
}
?>

Új film oldal

Az űrlapról érkező és ellenőrzött adatok tárolásához először is be kell tölteni a tömböt, majd egész egyszerűen utolsó sorként fel kell venni az újabb rekordot. Ezt követően elmentjük a tömböt a fájlba.

Forráskód
<?php
//Segédfüggvények
//ld. a fájlkezelésről szóló részt
 
//Feldolgozó függvény
function film_beszur($cim, $rendezo, $ev) {
    $filmek = fajlbol_betolt('filmek.json');
    $filmek[] = array(
        'cim'       =>  $cim,
        'rendezo'   =>  $rendezo,
        'ev'        =>  $ev,
    );
    return fajlba_ment('filmek.json', $filmek);
}
?>

Megoldás adatbázissal

Lista oldal

Az adatbázisban tárolt adatokat egy SELECT SQL parancs segítségével tudjuk lekérdezni. Szerencsénkre a sqlite_array_query elvégzi helyettünk a munka nagy részét, ráadásul a kimenet által elvárt formátumban kapjuk meg az adatokat. Ha további szűrésre lenne szükségünk, akkor egész egyszerűen egy WHERE feltétellel kellene kiegészíteni a lekérdezést, a kiválogatást az adatbázis-kezelő elvégzi helyettünk. Az adatok manipulálása szempontjából az adatbázisban történő tárolás sokkal rugalmasabb.

Forráskód
<?php
//Segédfüggvények
//ld. fentebb
 
//Tábla inicializálása
$filmek_create_sql = 'create table filmek (
                        id integer primary key,
                        cim,
                        rendezo,
                        ev)';
tabla_init('filmek.sqlite', 'filmek', $filmek_create_sql);
 
//Feldolgozó függvények
function osszes_film() {
    return lekerdezes_tombbe('select * from filmek');
}
?>

Új film oldal

Egy új sor beszúrását az INSERT SQL paranccsal tehetjük meg. Mivel nincsen visszatérési érték, ezért az sqlite_exec parancsot használjuk. E köré nem építettünk segédfüggvényt (megtehető egyébként!), ezért ezt most a feldolgozó függvényben hívjuk meg. A paramétereket az sqlite_escaper_string függvénnyel biztosítjuk a helyes karakterek használatáról.

Forráskód
<?php
//Segédfüggvények
//ld. fentebb
 
//Tábla inicializálása
//ld. fentebb
 
//Feldolgozó függvények
function film_beszur($cim, $rendezo, $ev) {
    $cim = sqlite_escape_string($cim);
    $rendezo = sqlite_escape_string($rendezo);
    $ev = sqlite_escape_string($ev);
 
    $db = adatbazis_nyit('filmek.sqlite');
    $result = sqlite_exec($db, 
        "insert into filmek (id, cim, rendezo, ev) values (
            null,
            '{$cim}',
            '{$rendezo}',
            '{$ev}'
         )");
    adatbazis_zar($db);
    return $result;
}
?>

Képernyőképek

Új film felvételeÚj film felvétele
A filmeket listázó oldalA filmeket listázó oldal

Vissza a tartalomjegyzékhez

Feladatok

Feladat
  • Egészítsd ki a példaalkalmazást a következőkkel:
    • Legyen lehetőség törölni egy filmet. Ehhez a lista oldalon minden film mellett jelenjen meg egy „Töröl” hivatkozás!
    • Legyen lehetőség módosítani egy filmet. Ehhez a lista oldalon minden film mellett jelenjen meg egy „Módosít” hivatkozás! Rákattintva jelenjen meg egy űrlap, előre betöltve a kiválasztott film adataival! Mentés után kerüljünk újra a listaoldalra!
    • Legyen lehetőség szűrni a filmek listáját. Ehhez a lista oldal tetején jelenjen meg egy szűrőmezőket tartalmazó űrlap. Az űrlapot elküldve csak azok a filmek jelenjenek meg, amelyek megfelelő mezője tartalmazza a szűrőmezők értékeit!

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.