Webes kliens megvalósítása PHP segítségével

A PHP egy HTML-be ágyazott script-nyelv, aminek célja a dinamikus weblapok generálásának egyszerűvé tétele. A szintaxisa főleg a C nyelvből vezethető le, Java és Perl nyelvekből is kölcsönöz, mindez pár specifikus függvénnyel kiegészítve. A rövidítés: PHP - Hypertext Preprocessor. A PHP architekturája:

A feladathoz szükséges architektúra elemei:
- web server: az a komponens, ami a kliens kéréseire válaszolva a helyben tárolt forrásanyagot szolgálja ki, jelen esetben Apache HTTP Server (http://www.apache.org/)
- PHP : html preprocesszor. Ha a webszerver olyan kérést kap, amely weblap kódrészleteket is tartalmaz, ezeket a PHP értelmezője fogja feldolgozni, majd az eredményt HTML formátumban átadja a böngészőnek. (http://www.php.net/)
- web content: a szerver által szolgáltatott tartalom, pédául: weboldalak (HTML), képek, PHP kódolt oldalak...
- mysql database: az adatbázis, ami jelen esetben MySql, de lehetne bármi más, amihez képes a PHP kapcsolódni. (http://www.mysql.com/)
- mysql extension: a PHP modulja, ami tetszőleges MySql adatbázishoz kapcsolódik. Lehetne ez a felület ODBC, vagy OCI (Oracle kapcsolódási felület) is.


Egy egyszerű példa a PHP használatára:

HTML kód:

<p>Hello, World!</p>

Csak PHP kód:

<? echo "<p>Hello, World!</p>"; ?>

PHP kód HTML kódba ágyazva:

<p><?php print "Hello,"; ?> World!</p>


A véletlenszám-rendező példa megoldása PHP-ben


A példaprogram PHP kódja (rendezo.php):

<html><body>
<table border=1 cellpadding=10><tr><td>
<font size=1><strong>
<?
$num
=20;
$max=200;

for(
$i=0;$i<$num;$i++) {
    
$szamok[$i]=rand(0,$max);
    echo
$szamok[$i]."<BR>";
}
?>
<strong></font>
</td><td>
<font size=1><strong>
<?
for($i=sizeof($szamok)-1;$i>=0;$i--) {
    for(
$j=0;$j<=$i-1;$j++) {
        if(
$szamok[$j]>$szamok[$j+1]) { //csere
            
$temp=$szamok[$j];
            
$szamok[$j]=$szamok[$j+1];
            
$szamok[$j+1]=$temp;
        }
    }
}

for(
$i=0;$i<$num;$i++) {
    echo
$szamok[$i]."<BR>";
}
?>
<strong></font>
</td></tr></table>
</body></html>

Feladat: hozzuk létre ennek a weblapnak egy továbbfejlesztett változatát, ami bekéri a num (hány számot rendezzen) és max (felso értékhatár) paramétereket! A feladat hasonló a Visual Basicben megvalósítotthoz, itt egy formot kell létrehozni, ami ezt a két változót kéri be, és adja át ugyanennek az oldalnak.

HTML form emlékeztető: (form használati-PHP-példa, forrás)
<form action=target.html method=post>
<input type=text name=parameterName value=parameterValue>
<input type=submit value=Send>
</form>

(működés közben)

Megjegyzések: A program hiányosságai közül a legszembetűnőbb a hibaellenőrzés hiánya. Ha a felhasználó számok helyett betűket ír, bizonyos mértékig a PHP automatikus cast-olása megpróbálja azt kezelni ("33w" => "33" konvertálja). Megoldás lehet erre, ha PHPban ellenőrizzük a kapott értéket, de ez már csak a form elküldése után lehetséges. Ezzel ellentétben egy JavaScript-es ellenőrzés még az adatok elküldése, és így azok feldolgozása elott kiszúrhatja a hibás adatbevitelt. (működés közben)


PHP és MySQL

A PHP-ben a konfigurálható MySQLi modul segítségével könnyen érhetjük el az adatbázisunkat, néhány sor paranccsal: (connect.php)

<?
    $host
="localhost";
    
$user="php";
    
$pass="php";
    
$db="biblio";

    
$mysqllink=mysqli_connect($host,$user,$pass) or die("Could not connect");
    
mysqli_select_db($mysqllink,"$db") or die("Could not select database");

?>

Egy SQL parancs végrehajtása, és annak az eredményeinek kezelése sem bonyolultabb:

  include "connect.php";

  
// tagok adatainak lekerese
  
$query="SELECT * FROM member";
  
$resultset=mysqli_query($mysqllink,$query) or die("lekérdezési hiba: ".mysqli_error($mysqllink));
  echo
"találatok száma: " .mysqli_affected_rows($mysqllink);
  
// az adatok mentese a row nev asszociativ tombbe
  
while($row=mysqli_fetch_assoc($resultset)) {
    echo
$row[MemberName]."<BR>"
;
    ...
  }

Míg a Visaul Basicben az adatbázis-kapcsolat tárolódott a program futása során folyamatosan, a PHP lapok egymástól teljesen függetlenek, ezért a kapcsolatot minden lapon külön fel kell építenünk, majd az ismétlődő lekérdezéseket újra végrehajtani. Ez okból kifolyólag érdemes a PHP-nek az include funkcióját használni, ami az éppen feldolgozás alatt álló lap végrehajtása során a kódban található include parancs helyett a hivatkozott fájl tartalmát hajtja végre.


Könyvtári kölcsönző rendszer

A használt adatbázis:

Feladat: Egy könyvtári nyilvántartó rendszer létrehozása, ami egy tag-szám alapján azonosítja a könyvtári tagot, majd megmutatja a kölcsönzéseit. A tag kereshet a könyvek között (legalább a címtöredék alapján), majd kölcsönözheti azokat. Visszavitelkor leveszi a kölcsönzött könyvek listájáról az adott tételt.


A megvalósítás részletei

A példa-implementáció a következő főbb képernyőkből (view) áll:


index.php


tag.php


kolcsonoz.php


visszahoz.php

A megvalósítás során jól érezhető, hogy a bejelentkezés után mindig ugyanazzal a taggal fogunk foglalkozni, ezért a tag azonosítóját minden nézeten (az egyes PHP oldalakon) tudnunk kell. A Visaul Basic-es megvalósítással szemben, ahol globális változókat lehetett definiálni, hogy megkönnyebbítsük a form-ok közti adatátadást, PHP-ben erre nincs ilyen egyszerű megvalósítás.

- egy kézenfekvő módszer, hogy létrehozunk úgynevezett session-öket, amik tárolnak számunkra lényeges változókat. Ennek hátránya, hogy speciális beállításokat követel meg mind a PHP, mind az alatta muködő webszerver, és a böngésző kliens részéről. A szerver-oldali biztonság érdekében célszerű a cookie-k használata, amit viszont a böngészők eloszeretettel tiltanak, kliens-oldali biztonsági okokra hivatkozva.

- másik, ennél egyszerűbb módszer a kívánt változók átadása formok, vagy az URL segítségével, minden egyes oldalváltáskor (a példa-implementáció ezt használja)

- a harmadik, talán legbiztonságosabb módszer, a saját session-kezelés megvalósítása: bejelentkezéskor a tagnak valamilyen módon egy, a böngészés idejére állandó session-változó létrehozása, majd annak tárolása a használt változókkal együtt adatbázisban. A lapok között csak a session változót kell átadni plusz-információként, viszont többletmunkát jelent az adatbázisból visszanyerni a tárolt változókat.

A második módszer egyszerűsége miatt jelent példában megfelelő. Egy ilyen form mindig tartalmaz rejtett mezoket (input type=hidden), amiket viszont a forrást megtekintve láthatunk is, ezért lényeges, fontos információkat (például egy banki rendszerben a felhasználó bankszámlaszáma, egyenlege) ne ilyen módon adjunk át!

echo "<center><form action=kolcsonoz.php method=post>
      <input type=hidden name=tagID value=$tagID>
      <input type=submit value=\"Könyv kölcsönzése\" class=submitbutton>
      </form></center>"
;



A megvalósított rendszer felépítése

A nyilak az egyes view-k (PHP oldalak) közötti átmeneteket jelképezik: vékonnyal a felhasználói művelet, vastaggal a két oldal között átadott információ látható.

forráskód

connect.php: adatbázis-kapcsolatot létrehozó kódrészlet, az összes többi PHP oldal include-olja
index.php: a kezdőoldal, a tag kiválasztására szolgál
tag.php: a kiválasztott tag adatait és kölcsönzéseit mutató oldal
kolcsonoz.php: könyv keresésére, és kölcsönzésre jelölésére szolgáló oldal
kivesz.php: a kölcsönzés konkrét folyamatát futtató kód, az adatbázisban eltárolja a könyvek kölcsönzését
visszahoz.php: a tag.php oldalon kiválasztott kölcsönzött könyvek visszavételét és adatbázisbeli módosításokat oldja meg


Feladat: a forráskód tanulmányozása, megértése.


Feladat: a funkcionalitásból hiányzó könyv visszahozatal (visszahoz.php) megvalósítása a kivesz.php alapján. A megvalósítandó 3 lépés:
- könyv kivétele a tag kölcsönzései közül
- a kölcsönzési idő ellenőrzése: 15 napon felül minden nap 20kr büntetés levonása a tag számlájáról
- a "visszavitt" könyv kölcsönözhetőségének beállítása a titles táblában (isOnLoan)


PHP dokumentáció: http://www.php.net/manual/en/
MySQL dokumentáció: http://dev.mysql.com/doc/mysql/en/
UniServer (PHP+MySQL+Apache egyben Windowsra): http://miniserver.sourceforge.net/

Futtatáshoz használt környezet: PHP 5.0.2 + MySQL 4.1 + Apache 2.0.52