WEBES ALKALMAZÁSFEJLESZTÉS 1. 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
Tartalom 2 PHP nyelvi elemei PHP a webszerveren Webes alkalmazások és adatbázis PHP és adatbázis Kódszervezés
3 PHP ismétlés nyelvi alapok
PHP 4 PHP Personal Home Page PHP: Hypertext Preprocesszor Jellemzői nyílt forráskódú általános célú szkriptnyelv HTML-be ágyazható
PHP a webprogramozásban 5.php kiterjesztésű állomány kérése esetén webszerver kikeresi az állományt Átadja a PHP értelmezőnek A program kimenetét a böngésző a kliens felé továbbítja Szerver PHP Kliens
PHP mint programozási nyelv 6 Értelmezett szkriptnyelv Gyengén típusos Változó típusa a tárolt értéktől függ Automatikus konverziókra figyelni kell! Sok minden igaz, amit JavaScriptnél tanultunk Nincs use strict, helyette error_reporting(e_all); PSR (PHP Standards Recommendation) http://www.php-fig.org/
Típusok 7 Négy elemi típus logikai egész lebegőpontos szöveg Két összetett típus tömb objektum Két speciális típus erőforrás NULL
Literálok 8 //Logikai true false TRUE FALSE //Például $l = true; $i = -23; $d = 23.65; //Egész 12 //decimális -34 0123 //oktális 0x0F //hexadecimális 0b0101 //bináris //Lebegőpontos 3.1415 5.6e12-7E-2
Szövegliterál 9 aposztróf macskaköröm heredoc nowdoc Változók behelyettesítése $a = 12; $s1 = 'alma\t{$a} alma'; //alma\t{$a} alma $s1 = 'Több sor is lehet benne'; $s2 = "alma\t{$a} alma"; //alma 12 alma $s2 = "Ez egy több soros szöveg"; $s3 = <<<EOT //behelyettesít Több soros {$a} szöveg EOT; $s4 = <<<'EOT' //nem helyettesít be Ez is lehet {$a} több soros. EOT;
Tömbök 10 Gyűjtemények általános objektuma Összetett adatszerkezet megvalósítása rekord indexelt tömb asszociatív tömb többdimenziós tömb fa, sor, verem, stb. Asszociatív tömb: kulcs-érték párokból áll kulcs: integer vagy string érték: bármilyen típusú lehet
Tömb 11 //Üres tömb $urestomb = array(); //Indexelt tömb $indtomb = array('alma', 'korte', 'szilva'); echo $indtomb[0]; //'alma' print_r($indtomb); /* Array ( [0] => alma [1] => korte [2] => szilva ) */ //Indexelt tömb vegyes értékekkel $indtombvegyes = array('alma', 12, true, -23.34); print_r($indtombvegyes); /* Array ( [0] => alma [1] => 12 [2] => 1 [3] => -23.34 ) */
Tömb 12 //Indexelt tömb egyesével hozzáadva $indtombkezi = array(); $indtombkezi[0] = 'alma'; $indtombkezi[1] = 'korte'; $indtombkezi[2] = 'szilva'; print_r($indtombkezi); /* Array ( [0] => alma [1] => korte [2] => szilva ) */ //Indexelt tömb egyesével hozzáadva $indtombkezi2 = array(); $indtombkezi2[] = 'alma'; $indtombkezi2[] = 'korte'; $indtombkezi2[] = 'szilva'; print_r($indtombkezi2); /* Array ( [0] => alma [1] => korte [2] => szilva ) */
Asszociatív tömb 13 //Asszociatív tömb $assztomb = array( 'alma' => 'piros', 'korte' => 'sarga', 'szilva' => 'kek', ); echo $assztomb['alma']; //piros print_r($assztomb); /* Array ( [alma] => piros [korte] => sarga [szilva] => kek ) */ //Asszociatív tömb kézzel $assztombkezi = array(); $assztombkezi['alma'] = 'piros'; $assztombkezi['korte'] = 'sarga'; $assztombkezi['szilva'] = 'kek'; print_r($assztombkezi); /* Array ( [alma] => piros [korte] => sarga [szilva] => kek ) */
Mátrix 14 Tömbök tömbje Lehet vegyesen használni indexeltben indexelt indexeltben asszociatív //Mátrix $matrix = array( array(1, 2, 3), array(4, 5, 6), array(7, 8, 9), );
Tömbök bejárása 15 foreach reset(), next(), prev(), current(), key(), each() foreach ($t as $key => $value) { echo $key.$value; } foreach ($t as $value) { echo $value; } $fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry'); reset($fruit); while (list($key, $val) = each($fruit)) { echo "$key => $val\n"; }
Osztályok és láthatóság 16 PHP5-ben teljesen újraírták PHP5 objektumorientált class A { public $publikus = 'alapérték'; protected $proti = 'alapproti'; private $privat = 'alapprivi'; } public function kiir() { echo $this->publikus; echo $this->proti; echo $this->privat; } $a = new A(); echo $a->publikus; echo $a->kiir();
Konstruktorok és öröklés 17 class A { function construct() { echo "A konstruktora"; } } class B extends A { function construct() { parent:: construct(); print "B konstruktora"; } } $a = new A(); $b = new B();
Osztályok automatikus betöltése 18 Általában az osztályok külön állományban Egyesével include-olni hibához vezethet autoload function autoload($class) { echo $class; include $class. '.php'; } $a = new A(); $b = new B();
Egyéb osztálytulajdonságok 19 absztrakt osztályok és metódusok interface-ek statikus osztályok és adattagok mágikus metódusok call(), get(), set(), tostring(), clone()
Névterek 20 Definiálás namespace my\namaspace; Használat my\namespace\func()
PHP Standards Recommendation 21 PSR http://www.php-fig.org/psr/
Standard PHP Library (SPL) 22 http://php.net/manual/en/book.spl.php Adatstruktúrák Iterátorok Interface-ek
23 PHP a webszerveren PHP és HTML, PHP és űrlapok
Kliens-szerver architektúra 24 Adatbázis-szerver Webszerver PHP modul Internet Kliens (böngésző)
Frontend Middleware Backend Logikai architektúra 25 Adatbázis-szerver Kapcsolati réteg (adatbázis-absztrakciós réteg) Üzleti logikai réteg Prezentációs réteg Internet Kliens (böngésző)
PHP és HTML (kimenet) 26 <?php?> HTML és PHP kód váltogathatja egymást Lényeg: a PHP eredménye általában HTML kód Mindig nézzük meg a generált forrást HTML elvárásunkat fogalmazzuk meg először <?php PHP kód?> <!-- Nem javasolt --> HTML kód <?php if (felt) {?> HTML kód <?php } else {?> HTML kód <?php }?> HTML kód
PHP és HTML (bemenet) 27 GET: urlben query string http://pelda.hu?alma=piros&korte=kukacos POST: standard inputon a query string A query stringet űrlapküldésnél a böngésző állítja elő (name attribútum szükséges!) PHP $_GET, $_POST, $_COOKIE, $_FILES, $_SESSION, stb.
Űrlapfeldolgozás 28 Első megtekintés: űrlap megjelenítése Űrlap elküldése ugyanannak a szkriptnek Űrlapadatok ellenőrzése Ha hiba volt, akkor hibák megjelenítése, űrlap megjelenítése állapotát megőrizve Ha nem volt hiba, akkor adatok feldolgozása, és megjelenítése vagy más oldal megjelenítése
Űrlapfeldolgozás 29 <?php $a = ''; if ($_POST) { $a = $_POST['a']; //Adatok ellenőrzése... if (siker) { //Adatok feldolgozása } else { //Hibás adatokelőkészítése } }?> <html> <body> <!-- Hiba opcionális megjelenítése --> <form action="x.php" method="post"> <!-- Űrlapadatok --> </form> </body> </html>
30 Webes alkalmazások és adatbázis
Web és adatbázis 31 Adatintenzív, adatközpontú webes alkalmazások Adatvezérelt alkalmazások: alkalmazás felépítése, logikája, megjelenése függ a háttérben tárolt adatok szerkezetétől, jellegétől Adatok tárolása adatbázis-kezelő rendszerben történik a leggyakrabban
Kapcsolat az adatbázissal 32 Szerveroldali technológiától független Adott nyelvben függvények, osztályok az egyes adatbázis-kezelő rendszerekhez Adatbázis-művelet előtt kapcsolódás az adatbázishoz SQL utasítások kiadása a nyelv adatbázisfüggvényeinek segítségével DDL, DML (eredményhalmaz feldolgozása), DCL, TCL Kapcsolat bontása
Általános fogalmak 33 Állandó kapcsolatok átmeneti tároló Előkészített utasítások ld. adatkötés Pufferelt lekérdezések
34 PHP és adatbázis
PHP és adatbázisok 35 Különböző függvénykönyvtárak a különböző adatbázis-kezelő rendszerekhez IBM DB2 IBM DB2 Mssql Microsoft SQL Server MySQL Mysqli MySQL Improved Extension OCI8 Oracle OCI8 PostgreSQL
PHP és MySQL 36 Kétféle interfész MySQL régebbi mind a mai napig gyakran használják Mysqli újabb MySQL verziók funkcióinak kihasználása biztonságosabb kapcsolódás és használat OOP-s interfész manapság ez ajánlott PDO (ld. később)
MySQL függvénykönyvtárak 37 libmysql régebbi kliens megléte szükséges mysqlnd korszerűbb Legkorszerűbb mysqli + mysqlnd pdo + mysqlnd
Tipikus lépések 38 Kapcsolat létesítése az adatbázis-szerverrel Adatbázis kiválasztása Összeállított SQL utasítás futtatása Opcionálisan a visszakapott eredmények feldolgozása
Fontosabb parancsok 39 MySQL mysql_connect() mysql_select_db() mysql_query() mysql_fetch_*() mysql_free_result() mysql_close() Mysqli $mysqli = new myslqi() $r = $mysqli->query() $r->fetch-*() $r->free() $mysqli->close() $s=$mysqli->prepare() $s->bind_param() $s->bind_result()
Tipikus utasítások 40 mysqli bővítmény, pufferelt lekérdezés new mysqli::mysqli() mysqli::real_query() mysqli::store_result() mysqli_result::fetch_assoc() mysqli_result::free() mysqli::close()
Tipikus utasítások 41 mysqli bővítmény, nem pufferelt lekérdezés new mysqli::mysqli() mysqli::real_query() mysqli::use_result() mysqli_result::fetch_assoc() mysqli_result::free() mysqli::close()
Tipikus utasítások 42 mysqli bővítmény, nem pufferelt lekérdezés, előkészített utasítás new mysqli::mysqli() mysqli::prepare() mysqli_stmt::bind_param() mysqli_stmt::execute() mysqli_stmt::bind_result() mysqli_stmt::fetch() mysqli_stmt::free_result() mysqli::close()
Tipikus utasítások 43 mysqli bővítmény, pufferelt lekérdezés, előkészített utasítás new mysqli::mysqli() mysqli::prepare() mysqli_stmt::bind_param() mysqli_stmt::execute() mysqli_stmt::store_result() mysqli_stmt::bind_result() mysqli_stmt::fetch() mysqli_stmt::free_result() mysqli::close()
Tipikus utasítások 44 nem pufferelt lekérdezés, előkészített utasítás new PDO() PDO::prepare() PDOStatement::bindParam() PDOStatement::execute() PDOStatement::fetch()
Tipikus utasítások 45 pufferelt lekérdezés, előkészített utasítás new PDO() PDO::prepare() PDOStatement::bindParam() PDOStatement::execute() PDOStatement::fetchAll()
Adatbázis biztonság 46 Mysqli interfész a preferált (Mysql-lel szemben) Szövegösszefűzés mysql_real_escape_string() sprintf() Adatkötés előkészített kifejezések prepare bind_param() bind_result()
Példa 47 Lekérdezés egy táblából Lépésekre bontva Tábla: CREATE TABLE `albums` ( `id` int(10) unsigned NOT NULL auto_increment, `nev` varchar(45) NOT NULL, `leiras` varchar(200) NOT NULL, PRIMARY KEY (`id`), ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
HTML előkészítése 48 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>albumok</title> </head> <body> <h1>albumok listázása</h1> <table> <tr> <th>azonosító</th> <th>név</th> <th>leírás</th> </tr> <!-- Dinamikus szakasz kezdete --> <tr> <td>1</td> <td>album1</td> <td>album1 leírása</td> </tr> <!-- Dinamikus szakasz vege --> </table> </body> </html>
Mysqli használata 49 $mysqli = new mysqli('servername', 'username', 'password', 'database'); if ($mysqli->connect_error) { die('kapcsolodasi hiba'. $mysqli->connect_errno. $mysqli->connect_error); } $mysqli->query('set names utf8'); $q = 'select * from photo_albums'; $result = $mysqli->query( $q ); if ($result) { while ($sor = $result->fetch_assoc()) { echo <<<EOT <tr> <td>{$sor['id']}</td> <td>{$sor['nev']}</td> <td>{$sor['leiras']}</td> </tr> EOT; } $result->free(); } $mysqli->close();
Paraméterek összefűzéssel 50 $nev = ''; $leiras = ''; echo $q = sprintf( "select * from photo_albums where nev like '%%%s%%' and leiras like '%%%s%%'", mysql_real_escape_string($nev), mysql_real_escape_string($leiras) ); $result = $mysqli->query( $q );
Paraméterek adatkötéssel 51 $nev = ''; $leiras = ''; $stmt = $mysqli->prepare( "select id, nev, leiras from photo_albums where nev like? and leiras like?"); $stmt->bind_param('ss', $nev, $leiras); $nev = "%{$nev}%"; $leiras = "%{$leiras}%"; $stmt->execute(); $stmt->bind_result($r_id, $r_nev, $r_leiras); while ($stmt->fetch()) { echo <<<EOT <tr> EOT; } </tr> <td>{$r_id}</td> <td>{$r_nev}</td> <td>{$r_leiras}</td>
Paraméterek adatkötéssel 52 Általánosabb eredménykötés $stmt->execute(); $meta = $stmt->result_metadata(); $sor = array(); foreach ($meta->fetch_fields() as $field) { $params[] = &$sor[$field->name]; } call_user_func_array(array($stmt, 'bind_result'), $params); while ($stmt->fetch()) { echo <<<EOT <tr> <td>{$sor['id']}</td> <td>{$sor['nev']}</td> <td>{$sor['leiras']}</td> </tr> EOT; }
53 Kód újrarendezése Útban az MVC felé
Kritika 54 HTML és PHP keveredik egymással Különböző funkciójú kódrészletek keverednek egymással vezérlés, adatelérés, megjelenítés, feldolgozás, alkalmazáslogika Konfiguráció kódba épített Több belépési pontja lehet az alkalmazásnak Csoportmunka nem lehetséges Karbantartása nehézkes
Logika és megjelenés szétválasztása 55 Válasszuk szét a logikát a megjelenéstől Határozott vonal húzható a PHP és HTML között Akár külön file-ba kerülhet a megjelenés A HTML-ben lesznek PHP kódrészletek, de ezek már csak a megjelenést szolgálják: sablonnyelv PHP alternatív szintaxis Háromféle utasítás szerepelhet echo, if, foreach HTML nem generálható (echo) Logikában nincs HTML kód <?php if (felt) :?> HTML <?php else :?> HTML <?php endif;?> <?php foreach (...) :?> HTML <?php endforeach;?>
Nézet (view) 56 A logika és megjelenés szétválasztásából születik meg a nézet (view) Előnye Egy logikához többféle nézet is rendelhető HTML, szöveg, PDF, XML Külön szakember foglalkozhat a kétféle résszel Példa: index2.php és list.php
Adatmanipuláció elkülönítése (modell) 57 Adatokkal kapcsolatos rész elkülönítése Előnyei Több helyen felhasználható Módosítások egy helyre összpontosulnak (pl. tábla átnevezés, adatbázis-váltás) Az adatok feldolgozását végző kódrész a modell Ld. albums_model.php
Vezérlő (controller) 58 A maradék kód a folyamat irányításáért felel: vezérlő Inputadatok begyűjtése, adatok átadása, elkérése a modelltől, az eredményt a nézetnek átadni Kérés feldolgozása Munkamenet-kezelés Authentikáció, authorizáció Könnyen áttekinthetővé vált Ld. index3.php
Vezérlő (controller) 59 <?php include('albums_model.php'); $nev = ''; $leiras = ''; if (isset($_post['nev'])) { $nev = $_POST['nev']; } if (isset($_post['leiras'])) { $leiras = $_POST['leiras']; } $albums = get_albums($nev, $leiras); //modell include('list.php'); //view
Modell (model) 60 <?php function get_albums($nev = '', $leiras = '') { $mysqli = new mysqli('localhost', 'wabp3', 'ab2009', 'wabp3'); if ($mysqli->connect_error) { die('kapcsolodasi hiba'. $mysqli->connect_errno. $mysqli->connect_error); } $mysqli->query('set names utf8'); $stmt = $mysqli->prepare( "select * from photo_albums where nev like? and leiras like?"); $stmt->bind_param('ss', $nev, $leiras); $nev = "%{$nev}%"; $leiras = "%{$leiras}%"; $stmt->execute();
Modell (model) 61 $meta = $stmt->result_metadata(); $sor = array(); foreach ($meta->fetch_fields() as $field) { $params[] = &$sor[$field->name]; } call_user_func_array(array($stmt, 'bind_result'), $params); $albums = array(); while ($stmt->fetch()) { $albums[] = array( 'id' 'nev' 'leiras' ); } $stmt->free_result(); $mysqli->close(); => $sor['id'], => $sor['nev'], => $sor['leiras'], } return $albums;
Nézet (view) 62 <html> <head> <title></title> <meta http-equiv="content-type" content="text/html; charset=utf-8"> </head> <body> <h1>albumok listazasa</h1> <form action="index2.php" method="post"> Nev: <input type="text" name="nev" value="<?php echo $nev;?>" ><br> Leiras: <input type="text" name="leiras" value="<?php echo $leiras;?>" ><br> <input type="submit" value="szur"> </form>
Nézet (view) 63 <table> <tr> <th>azonosító</th> <th>név</th> <th>leírás</th> </tr> <!--Dinamikus resz kezdete --> <?php foreach ($albums as $sor) :?> <tr> <td><?php echo $sor['id'];?></td> <td><?php echo $sor['nev'];?></td> <td><?php echo $sor['leiras'];?></td> </tr> <?php endforeach;?> <!--Dinamikus resz vege --> </table> <a href="insert.php">új album...</a> </body> </html>