WEBFEJLESZTÉS 2. – ADATTÁROLÁS, MUNKAMENETKEZELÉ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:
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 í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)
$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); }
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); }
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;
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 szamol.php Bizonyos esetekben jól jönne, ha tudnánk
azonosítani a klienst, és hozzá adatot tárolnánk.
munkamenet (session angolul)
Kliens1
Kliens3 Kliens2
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 szamlal.php
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
Kliens1
szamlal.php
Kliens1
szamlal.php
Kliens1
Kliens1
Kliens oldali állapottartás 45
Kliens oldali technológiák URL Rejtett
Süti
mező
Állapottartás URL-ben 46
URL querystring részében menjen az adat szamol.php?szamlalo=1
Hátránya: Minden Ha
Sok
linkhez oda kell generálni
egyről is lemarad, elvész az adat
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)
Adat a kliensen van Manipulálható Sok adat esetén feleslegesen sok adat megy odavissza a kliens és szerver között szamlal.php
Kliens1
szamlal.php
Kliens1
szamlal.php
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
szamlal.php
Kliens1
szamlal.php
Kliens1
Kliens4
szamlal.php
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
Munkamenet megszüntetése
$_SESSION = array(); session_destroy(); print_r($_SESSION); ?> Vissza
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']); }
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
Kliens Felhasználó felület Idő
XHR
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
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 Szerver ping.php Szaggatott élmény Aszinkronitás 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
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
alma
körte
szilva
barack
eper
málna
szeder
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 almakörteszilvabarackepermálnaszeder
XML válasz és feldolgozása 124
feldolgozó szkript
function xml() { 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