WEBFEJLESZTÉS 2. ADATTÁROLÁS, MUNKAMENET- KEZELÉS, AJAX Horváth Győző Egyetemi adjunktus 1117 Budapest, Pázmány Péter sétány 1/C, 2.420 Tel: (1) 372-2500/1816
2 Ismétlés
Ismétlés 3 Dinamikus szerveroldali webprogramozás: program (PHP) állítja elő a tartalmat (HTML) Input kliens: link, űrlap szerver: CGI program: környezeti változók standard input Szerver Kliens PHP
Ismétlés 4 PHP linkben? után $_GET tömb űrlap get $_GET tömb űrlap post $_POST Űrlapfeldolgozás Adatok (nincsen: $_POST, $_GET, HTML) Beolvasás, ellenőrzés ($_POST, $_GET) Kimenet (HTML)
Adatok tárolása 5 Szükséges input output Hogyan? memória (nem jó, külön kérések vannak) fájl adatbázis
6 Fájlkezelés PHP-ban
Fájlműveletek PHP-ban 7 PHP-ban van lehetőség fájlok használatára (írás, olvasás, stb) Mint a legtöbb programozási nyelvben Csak a szerver helyi fájljai érhetők el Sokféle nyelvi lehetőség Tipikus folyamat megnyitás feldolgozás bezárás
Általános fájlműveletek 8 $f = fopen($fájlnév, $mód) fájl vagy URL megnyitása $f: logikai fájlkezelő $mód határozza a megnyitás módját r (csak olvasás) r+ (olvasás, írás) w (csak írás, üres fájl) w+ (olvasás, írás, üres fájl) a (hozzáfűzés) a+ (hozzáfűzés, olvasás) x (csak írás, üres fájl, ha létezik a fájl, akkor hiba) x+ (olvasás, írás, üres fájl, ha létezik, akkor hiba) c (csak írás, ha létezik, akkor elejére áll) c+ (írás, olvasás, ha létezik, elejére áll)
Általános fájlműveletek 9 feof($f) fájl vége? Beolvasás fread($f, $hossz) $hossz byte beolvasása fscanf($f, $formátum) formátum szerinti beolv. fgets($f[, $hossz]) sor beolvasása fclose($f) fájl bezárása Kiírás fwrite($f, $s) $s kiírása fputs($f, $s) ld. fwrite()
Példa filmcímek beolvasása 10 Cél: filmcímeket táblázatban kilistázni Kimenet <!doctype html> <html> <head> <meta charset="utf-8"> <title>fájl</title> </head> <body> <table border="1"> <?php foreach ($filmek as $film) :?> <tr> <td><?php echo $film;?></td> </tr> <?php endforeach;?> </table> </body> </html>
Példa filmcímek beolvasása 11 A hobbit A Gyűrűk Ura Út a vadonba Passió $filmek = array(); $f = fopen('lista.txt', 'r'); while (!feof($f)) { $sor = fgets($f); $filmek[] = $sor; fclose($f);
Példa filmcímek beolvasása 12 Javítandó Új sor karakterek a sor végén trim($s) Üres sor a fájl végén ellenőrzés $filmek = array(); $f = fopen('lista.txt', 'r'); while (!feof($f)) { $sor = trim(fgets($f)); if ($sor!= '') { $filmek[] = $sor; fclose($f);
Hibaellenőrzés 13 A fájlműveletek hamis értékkel térnek vissza hiba esetén általában hamis érték ellenőrzése $filmek = array(); $f = fopen('lista_.txt', 'r'); if ($f) { while (!feof($f)) { $sor = trim(fgets($f)); if ($sor!= '') { $filmek[] = $sor; fclose($f);
Hibaellenőrzés 14 Hibaüzenet kiírását a @ operátorral nyomhatjuk el $filmek = array(); $f = @fopen('lista_.txt', 'r'); if ($f) { while (!feof($f)) { $sor = trim(fgets($f)); if ($sor!= '') { $filmek[] = $sor; fclose($f);
Magasabb szintű fájlműveletek 15 Beolvasás file($fájlnév[, módosítók]) fájl soronként beolvas egy tömbbe file_get_contents($fájlnév) egész fájlt szövegként beolvassa readfile($fájlnév) A fájlt a kimenetre írja pl. képek kiírása fpassthru($f) Megnyitott fájl maradék részét a kimenetre írja pl. képek kiírása
Példa file() használatával 16 Új sor karakterek és üres sor nélkül $filmek = file('lista.txt', FILE_IGNORE_NEW_LINES FILE_SKIP_EMPTY_LINES); Hibaellenőrzéssel $filmek = @file('lista_.txt', FILE_IGNORE_NEW_LINES FILE_SKIP_EMPTY_LINES) or die('nincs meg a fájl'); vagy $filmek = @file('lista_.txt', FILE_IGNORE_NEW_LINES FILE_SKIP_EMPTY_LINES); if (!$filmek) { $filmek = array();
Példa file_get_contents() 17 Beolvasni, feldarabolni //$s szövegbe beolvasni $s = file_get_contents('lista.txt'); //feldarabolni új sor szerint $filmek = explode("\n", $s); //utolsó üres elemet kivenni array_pop($filmek); Hibaellenőrzés (hasonló a file()-hoz) //$s szövegbe beolvasni $s = @file_get_contents('lista_.txt') or die('nincs meg a fájl'); //feldarabolni új sor szerint $filmek = explode("\n", $s); //utolsó üres elemet kivenni array_pop($filmek);
Példa tömb kiírása listába 18 Nyitás módja: w, a, x Konstans definiálása Hibaellenőrzés Írási jog az adott könyvtárra Vuk Lolka és Bolka Macskafogó Kisvakond és barátai $filmek = array( 'Vuk', 'Lolka és Bolka', 'Macskafogó', 'Kisvakond és barátai', ); define('sorveg', "\n"); $f = @fopen('mesek.txt', 'w') or die('hiba!'); if ($f) { foreach ($filmek as $film) { fputs($f, $film. SORVEG); fclose($f);
Példa új sor hozzáfűzése 19 Hozzáfűzésre megnyitás Egy sor kiírása $uj_film = 'Hupikék törpikék'; define('sorveg', "\n"); $f = @fopen('mesek.txt', 'a') or die('hiba!'); if ($f) { fputs($f, $uj_film. SORVEG); fclose($f); Vuk Lolka és Bolka Macskafogó Kisvakond és barátai Hupikék törpikék
Magasabb szintű fájlműveletek 20 Kiírás file_put_contents($fájlnév, $s) Szöveget a fájlba írja $filmek = array( 'Vuk', 'Lolka és Bolka', 'Macskafogó', 'Kisvakond és barátai', ); define('sorveg', "\n"); //Elemek összefűzése $s = implode(sorveg, $filmek). SORVEG; $siker = @file_put_contents('mesek.txt', $s);
Konkurens fájlhasználat 21 Ha egyszerre többen hívják meg a szkriptet konkurens használat flock($f, $op) $op LOCK_SH (olvasáshoz) LOCK_EX (íráshoz) LOCK_UN (kioldáshoz) fflush($f) 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); fájlpuffer ürítése
Konkurens fájlhasználat 22 Olvasáshoz is érdemes lockolni a fájlt, hogy közben ne kezdődhessen el egy írási folyamat. $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);
URL-ek olvasása 23 A fájlműveletek többsége nemcsak fájlt, hanem URL-t is képes olvasni (általában folyamokat) PHP-ban fel tudunk dolgozni más oldalakat Egy egyszerű oldal megjelenítése: $s = file_get_contents('http://www.elte.hu/'); echo $s;
További fájlműveletek 24 mkdir($útvonal) könyvtár létrehozása rmdir($könyvtárnév) könyvtár törlése copy($forrás, $cél) másolás rename($mit, $mire) átnevezés, mozgatás unlink($fájlnév) törlés is_dir($fájlnév) is_file($fájlnév) is_readable($fájlnév) is_writable($fájlnév) is_link($fájlnév) is_executable($fájlnév)
További fájlműveletek 25 basename($útvonal) fájlnevet adja vissza chown($fájl, $user) chmod($fájl, $mód) chgrp($fájl, $group) stat($fájl) fájl adatai tömbben fseek($f, $offset) fájlmutató mozgatása
Összefoglalás 26 Alacsony és magas szintű fájlműveletek Beolvasást és a kiírást meghatározza: a fájl szerkezete; vagy az adat szerkezete Továbblépés adatszerkezetek
27 Adatszerkezetek és sorosításuk
Adatszerkezetek 28 //Rekord $rekord = array( 'mezo1' => 'ertek1', 'mezo2' => 'ertek2', 'mezo3' => 'ertek3', ); //Tömb $indtomb = array( 'ertek1', 'ertek2', 'ertek3', ); //Rekordok tömbje $rektomb = array( array( 'mezo1' => 'ertek1', 'mezo2' => 'ertek2', ), array( 'mezo1' => 'ertek1', 'mezo2' => 'ertek2', ), array( 'mezo1' => 'ertek1', 'mezo2' => 'ertek2', ), );
29 Példa Rekordok tömbje cím rendező év szereplők $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', ), ), );
Példa feldolgozása 30 Nehézségek, kérdések Milyen legyen a fájl szerkezete? egy rekord egy sor? több sor (behúzásokkal) Feldolgozó algoritmushoz már nem használhatók a kényelmes függvények soronként, rekordonként kell feldolgozni megoldható, de sok idő
Sorosítás 31 Sorosítás egy adatszerkezet visszaalakítható szöveges megfelelője. Tároláshoz, átküldéshez szokták használni Sorosító függvények serialize($érték) szöveg unserialize($szöveg) érték json_encode($érték) szöveg json_decode($szöveg) érték
Serialize, unserialize 32 $s = serialize($filmek); echo $s; //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:"car lo Carlei";s:2:"ev";s:4:"2000";s:9 :"szereplok";a:2:{i:0;s:18:"ser gio Castellitto";i:1;s:14:"Sergio Albelli"; $filmek2 = unserialize($s); print_r($filmek2); /*Array ( [0] => Array ( [cim] => Passió [rendezo] => Mel Gibson [ev] => 2004 [szereplok] => Array ( [0] => Jim Caviezel [1] => Maia Morgenstern [2] => Christo Jivkov ) )*/ ) [1] => Array ( [cim] => Pio atya - A csodák embere [rendezo] => Carlo Carlei [ev] => 2000 [szereplok] => Array ( [0] => Sergio Castellitto [1] => Sergio Albelli ) )
33 json_encode $s = json_encode($filmek); echo $s; //[{"cim":"passi\u00f3","rendez o":"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"]] /* [ { "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" ] ] */
json_decode 34 $filmek3 = json_decode($s, true); print_r($filmek3); /*Array ( [0] => Array ( [cim] => Passió [rendezo] => Mel Gibson [ev] => 2004 [szereplok] => Array ( [0] => Jim Caviezel [1] => Maia Morgenstern [2] => Christo Jivkov ) ) [1] => Array ( [cim] => Pio atya - A csodák embere [rendezo] => Carlo Carlei [ev] => 2000 [szereplok] => Array ( [0] => Sergio Castellitto [1] => Sergio Albelli ) )*/ )
Fájl és sorosítás 35 Két segédfüggvény Betöltés Mentés Akármilyen adatszerkezetre működik function fajlbol_betolt($fajlnev) { $s = file_get_contents($fajlnev); return json_decode($s, true); function fajlba_ment($fajlnev, $adat) { $s = json_encode($adat); return file_put_contents($fajlnev, $s, LOCK_EX);
Hibakezelés 36 Hibalehetőségek beolvasásnál nincs (még) meg a fájl egyéb hiba történik alapértelmezett szerkezet megadása function fajlbol_betolt($fajlnev, $alap = array()) { $s = @file_get_contents($fajlnev); return (s === false? $alap : json_decode($s, true)); $filmek = fajlbol_betolt('filmek.txt', array()); //vagy $filmek = fajlbol_betolt('filmek.txt');
Példa új szereplő hozzáadása 37 $filmek = fajlbol_betolt('filmek.txt'); $filmek[0]['szereplok'][] = 'Monica Bellucci'; fajlba_ment('filmek.txt', $filmek); [{"cim":"passi\u00f3","rendezo":"mel Gibson","ev":"2004","szereplok":["Jim Caviezel","Maia Morgenstern","Christo Jivkov","Monica Bellucci"],{"cim":"Pio atya - A csod\u00e1k embere","rendezo":"carlo Carlei","ev":"2000","szereplok":["Sergio Castellitto","Sergio Albelli"]]
38 Munkamenet-kezelés
Probléma 39 A HTTP protokoll állapotmentes Nem emlékezik az előző kérés adataira Függetlenül kezeli a kéréseket Klienstől is függetlenül Bizonyos esetekben jól jönne, ha szamol.php tudnánk azonosítani a klienst, és hozzá adatot tárolnánk. munkamenet (session angolul) Kliens1 Kliens2 Kliens3 Kliens4
Állapotmentesség 40 $szamlalo mindig 0 Két kérés nem őrzi meg az értékét Nem tudjuk, melyik kliens kérte if (isset($szamlalo)) { $szamlalo += 1; else { $szamlalo = 0; var_dump($szamlalo); szamlal.php szamlal.php szamlal.php Kliens1 Kliens1 Kliens1 Kliens1
Munkamenet példák 41 Mindenhol, ahol bejelentkezés szükséges, hogy a saját adatainkhoz férjünk hozzá (cloud) levelezés internetbank feljegyzések Bejelentkezés nélküli alkalmazások webshop kosár online szerkesztők (doodle, stb)
Megoldás 42 Ha a HTTP protokoll állapotmentes, akkor az alkalmazásnak kell gondoskodnia az állapot megtartásáról. Alkalmazás = kliens + szerver HTTP a kettejük kommunikációs formája Állapot megtartása: az adat kliensenként történő megőrzése Megvalósítás kliens oldalon szerver oldalon
Példa 43 Példa: számláló kliensenként eltérő érték webshop kosara kliensenként eltérő kosarak sok oldal böngészése egy-egy termék kosárba helyezése
Kliens oldali állapottartás 44 Az adatot a kliensen tároljuk Minden kérésnél felküldjük a szerverre A szerver visszaadja a kliensnek szamlal.php szamlal.php szamlal.php Kliens1 Kliens1 Kliens1 Kliens1
Kliens oldali állapottartás 45 Kliens oldali technológiák URL Rejtett mező Süti
Állapottartás URL-ben 46 URL querystring részében menjen az adat szamol.php?szamlalo=1 Hátránya: Minden linkhez oda kell generálni Ha egyről is lemarad, elvész az adat Sok adat nem fér el benne URL hossza legfeljebb 2kB Feltűnő (zavaró) Könnyen átírható Könyvjelzőzhető (nem mindig hátrány)
Példa - számláló 47 <?php $szamlalo = 0; if (isset($_get['szamlalo'])) { $szamlalo = $_GET['szamlalo']; $szamlalo += 1; var_dump($szamlalo);?> <a href="szamlalo2.php?szamlalo=<?php echo $szamlalo;?>">növel</a>
Állapottartás rejtett mezőben 48 URL: kevés adat, feltűnő, manipulálható űrlap rejtett mezője <input type="hidden" name="szamlalo" value="4"> Előny sok adat nem feltűnő Hátrány manipulálható csak űrlapok esetén normál linkeknél JavaScript kell
Példa számláló 49 <?php $szamlalo = 0; if (isset($_post['szamlalo'])) { $szamlalo = $_POST['szamlalo']; $szamlalo += 1; var_dump($szamlalo);?> <form action="szamlalo3.php" method="post"> <input type="hidden" name="szamlalo" value="<?php echo $szamlalo;?>"> <input type="submit" value="növel"> </form> <!-- Ez nem működik --> <a href="szamlalo3.php">növel</a>
Állapottartás sütivel 50 Rejtett mező: macerás, manipulálható süti setcookie($név, $érték, $lejárat); Előny nem feltűnő automatikus küldése Hátrány manipulálható (kódolható) limitált adatmennyiség letiltható
Példa számláló 51 <?php $szamlalo = 0; if (isset($_cookie['szamlalo'])) { $szamlalo = $_COOKIE['szamlalo']; $szamlalo += 1; setcookie('szamlalo', $szamlalo); print_r($_get); print_r($_post); print_r($_cookie); var_dump($szamlalo);?> <a href="szamlalo4.php">növel</a>
52 Példa számláló
Kliensoldali megoldások 53 Adat a kliensen van Manipulálható Sok adat esetén feleslegesen sok adat megy odavissza a kliens és szerver között szamlal.php szamlal.php szamlal.php Kliens1 Kliens1 Kliens1 Kliens1
Szerveroldali megoldások 54 Tároljuk az adatot a szerveren nem manipulálható kliens oldalon nem kell sok adatot küldözgetni A kliens megkülönböztetése továbbra is szükséges tokent kap, amivel azonosítja magát és hozzáfér a tokenhez tartozó adatokhoz Token kliensoldali megoldással közlekedik süti (alapértelmezett) url (ha nincs süti)
Szerveroldali megoldás szamol.php 55 Kliens1 Kliens3 Kliens2 Kliens4 szamlal.php szamlal.php szamlal.php Kliens1 Kliens1 Kliens1 Kliens1
Szerveroldali megoldás 56 Folyamat van a sütik között bizonyos nevű süti ha van, akkor az értéke a token ha nincs, akkor van-e az URL-ben bizonyos nevű paraméter ha van, akkor az értéke a token ha nincs, akkor újat kell kezdeni, és a kliensnek odaadni ha van token, akkor a tokenhez tartozó adatokat a program rendelkezésére bocsátani
Szerveroldali megoldás 57 Adatok tárolása fájlban (ld. PHP) adatbázisban Plusz erőforrás a szervertől A tokenre nagyon kell vigyázni ellopható kilépés
58 Munkamenet-kezelés PHP-ban
Munkamenet-kezelés PHP-ban 59 session_start() session_destroy() $_SESSION tömb SID konstant (PHPSESSID=token)
Példa számláló 60 <?php session_start(); print_r($_get); print_r($_session); $szamlalo = 0; if (isset($_session['szamlalo'])) { $szamlalo = $_SESSION['szamlalo']; $szamlalo += 1; $_SESSION['szamlalo'] = $szamlalo; var_dump($szamlalo);?> <a href="szamlalo5.php?<?php echo SID;?>">Növel</a>
Példa számláló 61 Munkamenet megszüntetése <?php session_start(); print_r($_get); print_r($_session); $_SESSION = array(); session_destroy(); print_r($_session);?> <a href="szamlalo5.php">vissza</a>
Példa - számláló 62 Süti letiltása token az URL-ben
63 Hitelesítés
Hitelesítés 64 Ki használja az alkalmazást? azonosított felhasználó felhasználónév teljes név névtelen felhasználó vendég Bizonyos oldalak csak azonosított felhasználók számára érhetőek el
Technológiák 65.htaccess,.htpasswd könyvtár alapú védelem htdigest md5 kódolt jelszó WWW-Authenticate HTTP része PHP-ból kiolvasható Ezek PHP-tól független technológiák Plusz adat tárolására nem alkalmasak Csak hitelesítésre
Hitelesítés munkamenettel 66 Azonosított felhasználó munkamenetében egy speciális kulcsot helyezünk el ezzel jelezzük, hogy már azonosítottuk Folyamat beléptető űrlap (login form) sikeres belépés esetén kulcs minden oldalon: ha ez a kulcs megvan, akkor azonosított ettől függően más logika, más nézet lehet
Hitelesítés ellenőrzése 67 munkamenet indítása létezik-e a kulcs a munkamenet adatai között kulcs értéke indifferens külön fájlba tehető session_start(); function azonositott_e() { return isset($_session['belepve']);
Regisztráció 68 Űrlap <?php print_r($hibak);?> <form action="reg.php" method="post"> Felhasználónév: <input type="text" name="felhnev"> <br> Jelszó: <input type="password" name="jelszo"> <br> <input type="submit" name="reg" value="regisztrál"> </form>
Regisztráció 69 $hibak = array(); if ($_POST) { $felhnev = trim($_post['felhnev']); $jelszo = $_POST['jelszo']; $jelszavak = fajlbol_betolt('jelszavak.txt'); if (strlen($felhnev) == 0) { $hibak[] = 'Nincs felhnev!'; if (strlen($jelszo) == 0) { $hibak[] = 'Nincs jelszo!'; if (array_key_exists($felhnev, $jelszavak)) { $hibak[] = 'Letezo felhnev!'; if (!$hibak) { $jelszavak[$felhnev] = md5($jelszo); fajlba_ment('jelszavak.txt', $jelszavak); header('location: login.php'); exit();
Beléptetés 70 Űrlap <?php print_r($hibak);?> <form action="login.php" method="post"> Felhasználónév: <input type="text" name="felhnev"> <br> Jelszó: <input type="password" name="jelszo"> <br> <input type="submit" name="belep" value="belép"> </form>
Beléptetés 71 $hibak = array(); if ($_POST) { $felhnev = trim($_post['felhnev']); $jelszo = $_POST['jelszo']; $jelszavak = fajlbol_betolt('jelszavak.txt'); if (!(array_key_exists($felhnev, $jelszavak) && $jelszavak[$felhnev] == md5($jelszo))) { $hibak[] = 'Nem jó!'; if (!$hibak) { $_SESSION['belepve'] = true; $_SESSION['felhnev'] = $felhnev; header('location: szamlalo5.php'); exit();
72 Fájlfeltöltés
Űrlap és feldolgozás 73 <?php print_r($hibak);?> <form action="" method="post" enctype="multipart/form-data"> <input type="file" name="fajl"> <input type="submit" value="feltölt"> </form> $hibak = array(); if ($_FILES) { if (array_key_exists('fajl', $_FILES) && $_FILES['fajl']['error'] == 0) { $honnan = $_FILES['fajl']['tmp_name']; $hova = 'fajlok\\'. $_FILES['fajl']['name']; move_uploaded_file($honnan, $hova); else { $hibak[] = 'Hiba tortent!';
$_FILES 74 Array ( [fajl] => Array ( [name] => Desert_small.jpg [type] => image/jpeg [tmp_name] => C:\eltescorm\tmp\php1750.tmp [error] => 0 [size] => 18218 ) )
Könyvtárlista 75 <ul> <?php foreach($fajlok as $f) :?> <li><?php echo $f;?></li> <?php endforeach;?> </ul> function fajlok($kvt) { $fajlok = array(); $d = opendir($kvt); while (($f = readdir($d))!== false) { $fajlok[] = $f; closedir($d); return $fajlok; $fajlok = fajlok('fajlok\\');
76 AJAX
Hagyományos oldalak 77 HTTP kapcsolat Kérés-válasz Mindig a böngésző kezdeményez url-t beírva Hivatkozás űrlap
Hagyományos oldalak 78 Feldolgozás vagy a kliensen, vagy a szerveren Időben picit eltolva Szerver Kliens Idő
Következmény 79 Állandóan frissül a böngészőbeli oldal Szaggatott folyamat Villog Kényelmetlen Oldal tetejére ugrik Néha feleslegesen nagy adattömeg közlekedik
Megoldás 80 Csak a szükséges adatok továbbítása a teljes oldal újratöltése nélkül Remote scripting iframe Java applet XMLHttpRequest objektum Régi technológiák, a 90-es évek végén léteztek Akkoriban használták is őket szórványosan
Szélesebb körű elterjedtség 81 Sok tényező együttállása Egyre nagyobb internetpenetráció Egyre több webes alkalmazás Szélesebb társadalmi rétegek kapcsolódnak be Nagyobb igények a webes alkalmazások iránt Úttörő, innovatív vállalatok (Google GMail, GMaps, GDocs, stb.) Nevet kap az XMLHttpRequest-es technológia AJAX (2005, Jesse James Garrett)
AJAX 82 Aszinkron JavaScript és XML Nem új technológia Meglévő, kiforrott, szabványos technológiák együttese HTML, XHTML, CSS megjelenítés DOM dinamikus felhasználói felület, interakció XML, XSLT adatleíró formátum XMLHttpRequest aszinkron kliens-szerver adatátvitel JavaScript ezeket irányító programozási nyelv
AJAX oldalkiszolgálás 83 Szerver XHR XHR XHR Kliens Felhasználó felület Idő
AJAX-os oldal 84 A felhasználói felület folyamatosan használható Nincs szaggatottság, villogás, ugrálás A szerverrel való kommunikáció a háttérben történik Aszinkron módon, azaz párhuzamosan a többi eseménnyel Csak a szükséges adatok közlekednek a szerver és kliens között
AJAX hívás 85 HTTP kommunikáció url megadása GET és POST adatok küldése válasz feldolgozása Nem a böngésző végzi a HTTP kapcsolat kialakítását, hanem programból vezéreljük XMLHttpRequest objektum
XMLHttpRequest: metódusok 86 open( method, URL ) open( method, URL, async, username, password) A cél URL, metódus, stb. hozzárendelése send(content) Kérés küldése, ha van, akkor POST-olt adatokkal vagy DOM objektum adataival abort() Az aktuális kérés leállítása getallresponseheaders() Header-ök visszaadása szövegként név=érték formában getresponseheader( header ) Adott header értékét adja vissza setrequestheader( label, value ) A kérés fejlécét állítja be küldés előtt
XMLHttpRequest: tulajdonságok 87 onreadystatechange Eseménykezelő, ami a státusz minden változásánál meghívódik Saját függvényt kell ide implementálni readystate a kérés aktuális státusza 0 = uninitialized 1 = loading 2 = loaded 3 = interactive (néhány adat érkezett) 4 = complete status A szerverről érkező HTTP Status, pl. 200 = OK statustext A szerverről érkező státusz szövege responsetext A szerverről visszaérkezett adat szöveges változata responsexml A szerverről érkezett adat XML DOM dokumentuma
88 Példa lépésről lépésre Kódevolúció
Példa 89 Ping szerver megszólítása válaszban az aktuális idő érkezik vissza Felhasználói felület gomb div kimenet Szerver ping.php XHR Kliens Felhasználó felület
ping.html 91 <!doctype html> <html> <head> <meta charset="utf-8"> <title>ajax példa</title> <script type="text/javascript" src="ping.js"></script> </head> <body> <input type="button" id="gomb" value="ping"> <hr> <div id="output"></div> </body> </html>
ping.php 92 print_r($_get); print_r($_post); echo date('y.m.d. G:i:s');
Szinkron megoldás 93 ping.js function $(id) { return document.getelementbyid(id); window.onload = function () { $('gomb').onclick = ping; function ping() { var xhr = new XMLHttpRequest(); xhr.open('get', 'ping.php', false); xhr.send(null); $('output').innerhtml = xhr.responsetext;
Szinkron megoldás 94 Szinkron = akkor folytatódik a szkript futása, ha a válasz megérkezett (ld. alert) Ha sokára érkezik válasz egy ideig nem használható a felület Szaggatott élmény Aszinkronitás Szerver ping.php XHR Kliens
Aszinkron kommunikáció 95 Az elküldést követően a szkript továbbfut Eseményen keresztül értesülünk a válasz megérkezéséről readystate tulajdonság változik onreadystatechange eseménykezelőt kell írnunk
Aszinkron megoldás 96 var xhr; function ping() { xhr = new XMLHttpRequest(); xhr.open('get', 'ping.php', true); xhr.onreadystatechange = pingkezelo; xhr.send(null); function pingkezelo() { if (xhr.readystate == 4 && xhr.status == 200) { $('output').innerhtml = xhr.responsetext;
Aszinkron megoldás 97 Két függvény Mindkettőben szükség van az xhr objektumra Globális xhr objektum Ez problémás több kérés esetén újrahasznosítás globális névtér teleszemetelése adjuk át paraméterként
XHR objektum paraméterként 98 Névtelen függvény segítségével function ping() { var xhr = new XMLHttpRequest(); xhr.open('get', 'ping.php', true); xhr.onreadystatechange = function () { pingkezelo(xhr); xhr.send(null); function pingkezelo(xhr) { if (xhr.readystate == 4 && xhr.status == 200) { $('output').innerhtml = xhr.responsetext;
XHR objektum paraméterként 99 A lényegi részt még jobban leválasztva function ping() { var xhr = new XMLHttpRequest(); xhr.open('get', 'ping.php', true); xhr.onreadystatechange = function () { if (xhr.readystate == 4 && xhr.status == 200) { pingkezelo(xhr); xhr.send(null); function pingkezelo(xhr) { $('output').innerhtml = xhr.responsetext;
GET paraméterek 100 Query String az URL-ben function ping() { var xhr = new XMLHttpRequest(); xhr.open('get', 'ping.php?alma=piros', true); xhr.onreadystatechange = function () { if (xhr.readystate == 4 && xhr.status == 200) { pingkezelo(xhr); xhr.send(null); function pingkezelo(xhr) { $('output').innerhtml = xhr.responsetext;
POST paraméterek 101 Query String az üzenettörzsben send() metódus paramétereként speciális kódolás beállítása kérés fejléceként Content-Type: application/x-www-form-urlencoded
POST paraméterek 102 function ping() { var xhr = new XMLHttpRequest(); xhr.open('post', 'ping.php?alma=piros', true); xhr.setrequestheader('content-type', 'application/x-www-form-urlencoded'); xhr.onreadystatechange = function () { if (xhr.readystate == 4 && xhr.status == 200) { pingkezelo(xhr); xhr.send('korte=sarga'); function pingkezelo(xhr) { $('output').innerhtml = xhr.responsetext;
XMLHttpRequest objektum 103 Manapság minden böngészőben new XMLHttpRequest() Régebben böngészőnkénti eltérés: IE-ben másképp function getxhr() { var xhr = null; try { xhr = new XMLHttpRequest(); catch(e) { try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); catch(e) { try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); catch(e) { xhr = null; return xhr; function ping() { var xhr = getxhr(); //...
Hibakezelés 104 function ping() { var xhr = getxhr(); xhr.open('post', 'ping.php?alma=piros', true); xhr.setrequestheader('content-type', 'application/x-www-form-urlencoded'); xhr.onreadystatechange = function () { if (xhr.readystate == 4) { if (xhr.status == 200) { pingkezelo(xhr); else { console.log('hiba'); xhr.send('korte=sarga');
Általánosítás 105 AJAX hívás nagy része mindig ugyanaz Változó url metódus (GET/POST) GET adatok POST adatok feldolgozó függvény siker esetén feldolgozó függvény hiba esetén ajax() függvény
Általánosítás ajax() függvény 106 Alapértelmezett értékek function ajax(opts) { var method = opts.method 'GET', url = opts.url '', getdata = opts.getdata '', postdata = opts.postdata '', success = opts.success function(){, error = opts.error function(){; method = method.touppercase(); url = url+'?'+getdata; var xhr = getxhr(); xhr.open(method, url, true); if (method === 'POST') { xhr.setrequestheader('content-type', 'application/x-www-form-urlencoded');
Általánosítás ajax() függvény 107 Folytatás xhr.onreadystatechange = function () { if (xhr.readystate == 4) { if (xhr.status == 200) { success(xhr, xhr.responsetext); else { error(xhr); ; xhr.send(method == 'POST'? postdata : null); return xhr;
Megoldás ajax() függvénnyel 108 function ping() { ajax({ method: 'post', url: 'ping.php', getdata: 'alma=piros', postdata: 'korte=sarga', success: pingkezelo ); function pingkezelo(xhr, text) { $('output').innerhtml = text;
Megoldás ajax() függvénnyel 109 Névtelen függvénnyel még rövidebb function ping() { ajax({ method: 'post', url: 'ping.php', getdata: 'alma=piros', postdata: 'korte=sarga', success: function (xhr, text) { $('output').innerhtml = text; );
Összefoglalás 110 Segédfüggvény getxhr() ajax() Alkalmazás deklaratív az ajax() függvény paraméterezése
111 Válaszformátumok
AJAX I/O 112 Kérés (input) GET paraméterek POST paraméterek HTTP fejlécek Válasz (output) Text JSON HTML JavaScript stb. (CSS, )
Tartalom előállítása 113 A válasz az előállítás módjától függően lehet Statikus tartalom Dinamikus tartalom A kliens szempontjából mindegy, hogy ki állítja elő a tartalmat (nem is tud róla) Csak a válasz formátumára koncentrálunk
Statikus kiszolgálás 114 A fájlok tartalma előre adott Kérés pillanatában már létezik a válasz a szerveren Példa gyümölcsök listája felsorolás
Statikus kiszolgálás 115 Szerver text json html xml XHR Kliens Felhasználó felület
format.html 116 <!doctype html> <html> <head> <meta charset="utf-8"> <title>ajax példa</title> <script type="text/javascript" src="ajax.js"></script> <script type="text/javascript" src="format.js"></script> </head> <body> <input type="button" id="btntext" value="text"> <input type="button" id="btnjson" value="json"> <input type="button" id="btnhtml" value="html"> <input type="button" id="btnxml" value="xml"> <input type="button" id="btnscript" value="szkript"> <hr> <div id="output"></div> </body> </html>
Szöveges válasz feldolgozása 117 gyumolcs.txt és a feldolgozó szkript alma,körte,szilva,barack,eper,málna,szeder function lista(t) { return '<ul><li>' + t.join('</li><li>') + '</li></ul>'; function text() { ajax({ url: 'gyumolcs.txt', success: function (xhr, text) { console.log(text); var t = text.split(','); $('output').innerhtml = (new Date()).toLocaleString() + lista(t); );
Szöveges válasz feldolgozása 118 A szöveges válasz formátumától függ Egyedi feldolgozás Sokszor bonyolult logika Bármi lehet Ritkábban használják
JSON válasz és feldolgozása 119 gyumolcs.json és a feldolgozó szkript lista() függvény (ld. a szöveges feldolgozásnál) [ ] "alma", "körte", "szilva", "barack", "eper", "málna", "szeder" function json() { ajax({ url: 'gyumolcs.json', success: function (xhr, text) { var json = eval(text); // vagy var json = JSON.parse(text); console.log(json); $('output').innerhtml = (new Date()).toLocaleString() + lista(json); );
JSON válasz 120 JSON általános adatleíró formátum Nagyon elterjedt Gyakran használatos Egyszerű az értelmezése eval JSON.parse Utána más JavaScript adatszerkezetekkel kell dolgozni
HTML válasz és feldolgozása 121 gyumolcs.html feldolgozó szkript <ul> <li>alma</li> <li>körte</li> <li>szilva</li> <li>barack</li> <li>eper</li> <li>málna</li> <li>szeder</li> </ul> function html() { ajax({ url: 'gyumolcs.html', success: function (xhr, text) { var html = text; console.log(html); $('output').innerhtml = (new Date()).toLocaleString() + html; );
HTML válasz 122 Szabványos formátum Elterjedt Egyszerű a feldolgozása tipikusan a választ egy másik elembe kell helyezni
XML válasz és feldolgozása 123 gyumolcs.xml <?xml version="1.0" encoding="utf-8"?> <gyumolcsok> <gyumolcs>alma</gyumolcs> <gyumolcs>körte</gyumolcs> <gyumolcs>szilva</gyumolcs> <gyumolcs>barack</gyumolcs> <gyumolcs>eper</gyumolcs> <gyumolcs>málna</gyumolcs> <gyumolcs>szeder</gyumolcs> </gyumolcsok>
XML válasz és feldolgozása 124 function feldolgozó xml() { szkript ajax({ url: 'gyumolcs.xml', success: function (xhr, text) { var xmldom = xhr.responsexml; console.log(xmldom); ); var gyumolcsok = xmldom.getelementsbytagname('gyumolcs'); var t = []; for (var i = 0; i < gyumolcsok.length; i++) { t.push(gyumolcsok[i].firstchild.nodevalue); ; $('output').innerhtml = (new Date()).toLocaleString() + lista(t);
XML válasz 125 Szabványos adatleírási formátum Nagyon elterjedt főleg vállalati alkalmazásokban webes alkalmazásokban kevésbé Eredetileg ezt várták fő formátumnak xhr.responsexml responsexml az XML dokumentum értelmezett DOM fáját tartalmazza (ld. HTML DOM)
Dinamikus válasz 126 A választ egy program (PHP) állítja elő Válasz formátuma bármi lehet text json html xml stb. Szerver gyumolcs.php XHR Kliens Felhasználó felület
gyumolcs.php 127 JSON válasz generálása egyszerű $gyumolcsok = array( "alma", "körte", "szilva", "barack", "eper", "málna", "szeder", ); echo json_encode($gyumolcsok);
128 További tudnivalók
Eszközök 129 JavaScript konzolok Nyomon követik az AJAX-os hívásokat kérés válasz értelmezett válasz lekérés időtartama console.log
Korlátozások 130 Biztonsági okokból nem engedélyezett különböző domainek között ajax kommunikáció Kivéve JSONP (JSON with Padding): script elem dinamikus beszúrásával idegen tartalom futtatása Nincsen szerver push itt sem: ajax kéréseket mindig a kliens kezdeményezi
Ergonómiai szempontok 131 Más oldalszervezés HASZNÁLHATÓSÁG Jelezni, hogy a háttérben művelet zajlik A felhasználó adatait ne írjuk át Jelezni, ha hiba van Jelezni, ha jó
Előnyök és hátrányok 132 Előnyök Nincs szaggatás Kényelmes felület Gyors Jóval kisebb adatforgalom Párhuzamos kérések Hátrányok JavaScript kell Eltérő támogatottság Vissza gomb Frissít gomb Más oldalszervezési logika