Kötegelt feldolgozás AJAX és PHP segítségével
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
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>Kötegelt feldolgozó</title> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript"> /* itt lesz az AJAX-os JavaScript kódunk */ </script> <style> #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; } </style> </head> <body> <div id="slider"> <div> </div> </div> <div id="slider_info"> </div> <div id="messages"> </div> </body> </html>
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('<p>'+ json.message +'</p>'); 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('<p>'+ json.message +'</p>');
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 ..."; $ossz = $db['db']; $id = (int) $_GET['id'] + $limit; if ($id > $ossz) {$id = $ossz;} $message = ''; // 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 ..."; $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.
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 = ''; // 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.
Szia pp! Erre jártam, és
Szia pp!
Erre jártam, és megláttam ezt a post-ot. Jó kis post, de én arra lennék még kiváncsi, hogy a fenti munkából mennyit lehet megspórolni, ha Drupal-os megoldást készítünk. Másképpen: a Drupal milyen függvénykkel, hook-okkal segíti az ilyen kötelgelt feldolgozást?
Nyitott kapukat döngetsz!
Nyitott kapukat döngetsz! Terveim közt szerepel egy rövidke írás erről magyarul, amint lesz időm megírom. Addig is: A drupal.org-on van egy nagyon jó leírás - igaz angolul - azt tanulmányozd át. Nem hiszem, hogy túlzottan nagy problémát okozna az ott található kód megértése.
pp
Hozzászólás