Sokszor előfordul, hogy olyan nagy mennyiségű információt kell feldolgoznunk PHP-val ami már nem fér bele az olykor nagyon szűkös futási időkeretbe. Ekkor praktikus szétbontani a feladatott több részfeladatra és ezeket a részfeladatokat egymás után végrehajtani. A célom az volt, hogy készítsek egy icipici kis AJAX-os példarendszert a probléma megoldására. Lássuk mi kell ehhez.
Először is szükségünk lesz egy jófajta JavaScript keretrendszerre, hogy ne kelljen feltalálnunk a meleg vizet. Én a JQuery-t választottam, mivel azt jól ismerem és használom már régóta. Lesz két fájlunk. Az egyik ami mutatja, hogy éppen hol tartunk és tartalmazza a kliens oldali programrészeket. A másik lesz a tulajdonképpeni PHP, ami a feldolgozást végzi.
Nézzük az első fájlt, melyet nevezzünk index.html-nek
Kötegelt feldolgozó
/* itt lesz az AJAX-os JavaScript kódunk */
#slider { margin: 30px; border: 1px solid black; }
#slider div { height: 20px; background-color: blue; width: 0px; }
#messages p { margin: 0; padding: 0; border-bottom: 1px dotted black; }
<div id="slider">
<div>
</div>
</div>
<div id="slider_info">
</div>
<div id="messages">
</div>
Mint látható három div elem van. Az első mutatja meg nekünk grafikusan, hogy éppen hol tartunk. Maga a div egy egyszerű kis téglalap ami rendelkezik egy szép elegáns fekete kerettel. Ebben van egy kék hátterű másik div, mely a csíkot fogja húzni. Kezdeti mérete nulla, hisz még nem tartunk sehol sem. A második, slider_info azonosítójú div fogja tartalmazni azt a szöveges információt, hogy éppen hol tartunk és mennyi van még hátra. A harmadik div elembe pedig a PHP-től jövő üzeneteket foguk megjeleníteni. Itt láthatjuk, hogy mi az amit sikerült és mi az amit nem sikerült megtennie a scriptünknek. Nézzük a JavaScriptet!
$.getJSON("send.php?id=0", feldolg);
function feldolg(json){
$('#slider_info').html(json.szam + ' / ' + json.ossz);
hossz = $('#slider').width();
$('#slider div').width(hossz * json.szam / json.ossz);
$('#messages').append(''+ json.message +'');
if(json.szam < json.ossz){
$.getJSON("send.php?id="+ json.szam, feldolg);
}else{
$('#slider div').css('background-color','green');
}
}
Természetesen a működéshez szükségünk lesz még a JQuery függvény könyvtárra is. Nézzük a kódot részletesen.
$('#slider_info').html(json.szam + ' / ' + json.ossz);
Itt annyit csinálunk, hogy beírjuk az információs div-be, hogy éppen hol tartunk és mennyi az összes feldolgozandó rekord. Felhívnám a figyelmet itt és most, hogy ez egy olyan mintakód, mely pusztán a működés bemutatására szolgál. Nincs benne semmifajta hibakezelés. Nem vizsgáljuk, hogy sikerült-e a lekérés, jött-e egyáltalán adat és ha jött az megfelelő-e.
hossz = $('#slider').width();
$('#slider div').width(hossz * json.szam / json.ossz);
Beállítjuk a kék sáv szélességét. A számítás egyszerű. A befoglaló div hosszát annyi részre osztjuk ahány feldolgozandó rekordunk lesz, majd ezt a számot megszorozzuk azzal a számmal, mely jelzi mennyi adatot dogloztunk már fel. A műveletek fordított sorrendje egy rég elfeledett a gépi kódú programozást idéző egész számos aritmetika nyomait idézi.
$('#messages').append(''+ json.message +'');
Kiíratjuk a kapott üzenetet. A friss üzeneteket mindig a többi végére szúrjuk be.
if(json.szam < json.ossz){
$.getJSON("send.php?id="+ json.szam, feldolg);
}else{
$('#slider div').css('background-color','green');
}
Amennyiben nem végeztünk, újra elindítjuk ezt a szép asszinkron folyamatot. Ha már minden elemet feldolgoztunk, akkor szép zöldre állítjuk a csíkot, hogy tudjuk a feldolgozás befejeződött.
Végezetül nézzük a PHP fájlt.
<?
include('dbconnect.php');
$limit = 10;
$sql = "SELECT * FROM tabla ...";
$csql = "SELECT COUNT(*) as db FROM tabla ...";
$db= mysql_fetch_assoc(mysql_query($csql));
$ossz = $db['db'];
$res = mysql_query($sql. ' LIMIT '. (int)$_GET['id'] .','. (int)$limit);
$id = (int) $_GET['id'] + $limit;
if ($id > $ossz) {$id = $ossz;}
$message = '';
while($row = mysql_fetch_assoc($res)){
// itt csináljuk azt amit csinálunk
// az eredményt beletesszük a $message változóba
}
print "{ szam : $szam, ossz : $ossz, message : '$message'}";
Az első természetesen az, hogy betöltjük az adatbázis kapcsolódásához szükséges részeket, ezt itt nem részletezem. A $limit változóba beállítjuk, hogy egy akció során egyszerre hány rekordot szeretnénk feldolgozni.
<?
include('dbconnect.php');
$limit = 10;
Ezután lekérdezzük, hogy hány rekordunk lesz összesen.
$sql = "SELECT * FROM tabla ...";
$csql = "SELECT COUNT(*) as db FROM tabla ...";
$db= mysql_fetch_assoc(mysql_query($csql));
$ossz = $db['db'];
Természetesen az itt látható sql lekérdezés nem egy teljes értékű használható kód, csak egy minta. Az esetek nagy részében elégséges, hogy a rekordok lekérdezésére szolgáló query-ben ($sql) kicseréljük a SELECT és FROM közötti részt a következő kódra: " COUNT(*) as db “. Ne felejtsük el azonban, hogy egy “bonyolultabb” lekérdezésben, ahol pl. GROUP direktívát használunk, vagy egy másik al-lekérdezés eredményét ez nem lesz elég. Ott le kell ülnünk és átgondolnunk, hogy mely lekérdezés fogja a megfelelő eredményt adni. Miután ez megvan lekérdezzük az egyetlen egy rekordot és a kapott eredmény egyetlen egy oszlopát beletöltjük az $ossz változóba. Ezek után jöhet a megfelelő szelet amit feldolgozunk.
$res = mysql_query($sql. ' LIMIT '. (int)$_GET['id'] .','. (int)$limit);
Látszik, hogy csak egyszerűen hozzárakjuk a LIMIT záradékot a megfelelő paraméterezéssel. A kezdő rekord számát ($_GET[‘id’]) az AJAX-os alkalmazástól kapjuk, ezért ezt típus kényszerítjük, ezzel elkerülve az esetleges felhasználótól érkező trükkös hibákat. A $limit paraméter ugyan a saját kódunkból érkezik, de biztos ami ziher arra is rárakjuk a típuskényszerítést. Erre azért van szükség, mert lehetséges, hogy egy óvatlan pillanatban egy ügyes kis függvénybe helyezzük el ezt a kódot és akkor már nem a mi kódunkból, hanem a felhasználót érkezik majd ez a paraméter is. Mindenképpen érdemes azonban megszokni azt, hogy bármely SQL lekérdezés összerakásánál a változókat vagy escape-eljük, vagy típus kényszerítjük. Ez nem véd meg minket minden esetben az SQL-injection támadások ellen, de az alap hibákat ki tudjuk ezzel küszöbölni. Ezek után kiderítjük a következő adag kezdő rekordszámát.
$id = (int) $_GET['id'] + $limit;
if ($id > $ossz) {$id = $ossz;}
Amennyiben a lépésszám ($limit) nem osztója az összes elem számának ($ossz) akkor természtesen az utolsó etapban a következő adag kezdő rekordszáma nagyobb lesz mint az összes elem száma. Ebben az esetben beállítjuk az $id-t az utolsó rekord utánra, így jelezzük a JavaScript függvényünknek, hogy véget ért a feldolgozás. Most következzen kódunk legkidolgozatlanabb része.
$message = '';
while($row = mysql_fetch_assoc($res)){
// itt csináljuk azt amit csinálunk
// az eredményt beletesszük a $message változóba
}
Végigmegyünk az eredmény halmazon és feldolgozzuk. Itt küldhetünk E-mail-t, konvertálhatunk fájlokat, végrehajthatunk bonyolult lekérdezéseket stb. A végén pedig kiírjuk a válaszunkat.
print "{ szam : $szam, ossz : $ossz, message : '$message'}";
Természetesen ez sem egy tökéletes kód. A legfontosabb, hogy a $message változó nem tartalmazhat soremelést, csak ‘\n’ karakterpárost. Figyelj ezt úgy tudod PHP-ben szöveges változóba beletenni, hogy dupla visszaperjelet használsz! A kódból talán kiderül az is, hogy aposztrófot (') sem túl egészséges használni, azt is csak escape-elve tegyük bele az üzeneteinkben.
Remélem hasznos volt ez a kis szösszenet, egészségetekre.