Ebben a fejezetben a szerveroldali szkriptek kódjának szervezési kérdéseit és eszközeit tekintjük át. Megnézzük a legelemibb jelölésektől kezdve a bonyolultabb fájlszintű szervezést kívánó megoldásokig a lehetőségeket.
Szerveroldali megoldásaink során is valószínűleg sok kis függvény keletkezik. Ahogy ezek száma nő, a kód úgy válhat nehezen áttekinthetővé. A függvények egy része általános célú segédfüggvény (ld. például fájl- vagy adatbázis-használat), mások az adott feladat megoldásához szükségesek. A következőkben azokat a lehetőségeket tekintjük át, amelyek segítenek kódjaink megfelelő elrendezésében.
Érdemes megjegyzésben feltüntetni az adott függvény funkcióját, paramétereit, rövid leírását. Másik lehetőségként érdemes a nagyobb összefüggő blokkokat vízszintes vonallal elválasztani. Az előző fejezetekben erre több példa is látható.
Példaként vegyük a fájlkezelésnél vett filmlistás példát. Új film beszúrásakor a kódot a következőképpen megjegyzésekkel ellátni:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | <? php //-------------------------------------------------------- //Fájlkezeléssel kapcsolatos segédfüggvények //Adatszerkezet JSON fájlból betöltése function fajlbol_betolt( $fajlnev , $alap = array ()) { //... } //Adatszerkezet JSON fájlba mentése function fajlba_ment( $fajlnev , $adat ) { //... } //-------------------------------------------------------- //Adatfeldolgozás //Új film beszúrása function film_beszur( $cim , $rendezo , $ev ) { //... } //-------------------------------------------------------- //Kérés feldolgozása (főprogram) $hibak = array (); //... if ( $_POST ) { //... if (! $hibak ) { //... } } //--------------------------------------------------------- //Kimenet ?> <!doctype html> < html > <!-- ... --> </ html > |
A megjegyzések nagyobb blokkjai jól jelölik a funkcionálisan összetartozó részeit. Általánosságban a következő részek különböztethetők meg:
A funkcionálisan elkülönülő részeket érdemes külön fájlban tárolni a hosszútávú karbantarthatóság és a kód újrafelhasználása érdekében. A fájlokba kiszervezett függvények beemelésére több megoldás is van. Mindegyik úgy működik, mintha a fájl tartalmát a helyükre másolnánk.
Példánkra visszatérve a következő fájlokat érdemes létrehozni:
A kiszervezés után az eddig meghívott ujfilm_fajl.php állomány a következőképpen néz ki:
1 2 3 4 5 6 7 8 9 | <?php //Függvények beemelése include('fileio.php'); include('filmadat.php'); //Kérés feldolgozása //... include('ujfilm_sablon.php'); |
Mivel egy adott kérést feldolgozó szkript a fenti szervezésnek köszönhetően több fájlba esett szét, egy bonyolultabb alkalmazás esetében ez azt jelentené, hogy az alkalmazás könyvtárában az állományok száma nagyon hamar áttekinthetetlen mértékben megnövekszik. Ennek elkerülése érdekében érdemes a fájlokat a szerepük szerinti könyvtárba helyezni. A könyvtárstruktúra egyedi kialakítás kérdése, de a fent vázolt funkcióknak megfelelően az alábbi könyvtárakat különíthetjük el első körben:
Példánkban a főszkript a következőképpen alakul:
1 2 3 4 5 6 7 8 9 | <?php //Függvények beemelése include('kozos/fileio.php'); include('adat/filmadat.php'); //Kérés feldolgozása //... include('kimenet/ujfilm_sablon.php'); |
A több fájlba szétszedéssel azonban megjelennek olyan állományok a fájlrendszerben, amelyek önmagukban nem képesek kéréseket feldolgozni (fenti példánkban ilyen a fileio.php, a filmadat.php és ujfilm_sablon.php). Ezen fájloknál szükség van a közvetlen meghívást elkerülni. A védelmet különböző szinteken lehet megtenni.
Az első lehetőség az, hogy a kérést ténylegesen kiszolgáló szkript elején definiálunk egy tokent. A védendő szkriptek elején pedig ennek a tokennek a jelenlétét vizsgáljuk. Ha ezeket a védett fájlokat közvetlenül hívjuk meg, akkor hiányzik a token, hibaüzenettel leáll a futtatás. Ha főszkriptet hívjuk meg, akkor viszont létezik a token, és lefut a védett fájl tartalma.
A főszkript elején a token definiálása nem más, mint egy konstans létrehozása (példánkban ez az ujfilm_fajl.php állomány):
1 2 3 4 5 | <? php define( 'TOKEN' , 'Védelem' ); //... ?> |
A védett fájlok elején pedig a következő sort szükséges elhelyezni:
1 | <?php if ( ! defined('TOKEN')) exit('Közvetlenül nem elérhető!'); |
Az Apache webszerver egyik modulja lehetőséget ad könyvtár alapú konfigurációk, többek között hozzáférési jogosultságok ellenőrzésére. Ehhez a könyvtárban egy .htaccess nevű állományt kell elhelyezni. Ha már állományaink könyvtárba vannak szervezve, akkor minden könyvtárban egy-egy .htaccess állományt szükséges elhelyezni, amely az illetéktelen kiszolgálástól óv. Tartalma:
A webszerverek csak egy meghatározott mappának és azok alkönyvtárainak elérését engedélyezik kívülről. Ezt a könyvtárat hívják webes gyökérkönyvtárának. A PHP azonban tetszőlegesen használhatja a fájlrendszert. Így adja magát, hogy a kívülről védendő fájlokat tegyük a webes gyökérkönyvtáron kívülre.
A fájlokba való szervezés még nem oldja meg azt a problémát, ha két különböző részfeladat ugyanazt a függvénynevet használja, vagy ugyanolyan nevű globális változókat hoz létre. Eleve a globális változók használata több szempontból kétséges. Jó lenne valamilyen módon egységbe zárni az adott funkcióhoz tartozó adatokat és függvényeket. Erre – ahogy JavaScriptben is – az objektumok szolgálnak. PHP-ban objektumokat a klasszikus objektum-orientáltság elvének megfelelően osztályok példányosításával hozhatunk létre.
A PHP 5-ös verziójától kezdve kifinomult és hatékony nyelvi elemek biztosítják az osztályok kezelését. A PHP-ban szinte minden megtalálható, ami a többi korszerű OOP-s nyelvben is megvan:
Osztályokat a class kulcsszóval vezetjük be. Az osztályon belül adattagokat és metódusokat definiálhatunk. Ezek kívülről való elérhetőségét a public, protected és private kulcsszavakkal szabályozhatjuk. Egy metóduson belül az aktuális objektumra a $this mutat, az adattagokat a -> operátorral érjük el. A példányosításkor a konstruktorfüggvény fut le, ebben lehet az objektum alapértékeit beállítani.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <? php class Gyerek { public $kor ; public $nev ; public function __construct( $nev , $kor ) { $this ->nev = $nev ; $this ->kor = $kor ; } public function bemutatkozik() { echo "A nevem: {$this->nev}\n" ; } public function alszik() { echo "Zzzzzzz....\n" ; } } ?> |
Az osztály egy példányát a new kulcsszóval tudjuk létrehozni. A példánynak kívülről csak a publikus adattagjait és metódusait érhetjük el.
1 2 3 4 5 6 7 8 9 10 | <? php $zsofi = new Gyerek( 'Zsófia' , 7); $matyi = new Gyerek( 'Mátyás' , 2); $zsofi ->bemutatkozik(); $matyi ->bemutatkozik(); $zsofi ->nev = 'Zsozsó' ; $zsofi ->bemutatkozik(); ?> |
Eredménye:
Az adattagokat érdemes kívülről elrejteni és publikus metódusokon keresztül elérni.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <? php class Gyerek { private $kor ; private $nev ; public function __construct( $nev , $kor ) { $this ->nev = $nev ; $this ->kor = $kor ; } public function getNev() { return $this ->nev; } public function setNev( $value ) { $this ->nev = $value ; } public function getKor() { return $this ->kor; } public function setKor( $value ) { $this ->kor = $value ; } public function bemutatkozik() { echo "A nevem: {$this->nev}\n" ; } public function alszik() { echo "Zzzzzzz....\n" ; } } ?> |
Használata:
1 2 3 4 5 6 7 | <? php $sari = new Gyerek( 'Sári' , 7); $sari ->bemutatkozik(); $sari ->setNev( 'Sarah' ); $sari ->bemutatkozik(); ?> |
Eredménye:
A tulajdonságok újrahasznosítását örökléssel érjük el. Erre PHP-ban az extends kulcsszó való. A konstruktorfüggvényben érdemes a szülő konstruktorfüggvényét meghívni.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <? php class Ovodas extends Gyerek { private $jel ; public function __construct( $nev , $kor , $jel ) { parent::__construct( $nev , $kor ); $this ->jel = $jel ; } public function getJel() { return $this ->jel; } public function setJel( $value ) { $this ->jel = $value ; } public function miAJeled() { echo "A jelem: {$this->jel}\n" ; } } ?> |
Használata:
1 2 3 4 5 6 7 8 | <? php $zsofi = new Gyerek( 'Zsófia' , 7); $zsofi ->bemutatkozik(); $david = new Ovodas( 'Dávid' , 4, 'perec' ); $david ->bemutatkozik(); $david ->miAJeled(); ?> |
Eredménye:
Példánkban a sablonokon kívül minden kiemelt függvénycsoportot osztályokba szervezhetünk.
A fájlkezelő segédfüggvényeket érdemes statikus metódusnak felvenni, mivel nem dolgoznak saját adattal. A fileio.php tehát így néz ki:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php if ( ! defined('TOKEN')) exit('Közvetlenül nem elérhető!'); class FileIO { public static function fajlbol_betolt($fajlnev, $alap = array()) { $s = @file_get_contents($fajlnev); return ($s === false ? $alap : json_decode($s, true)); } public static function fajlba_ment($fajlnev, $adat) { $s = json_encode($adat); return file_put_contents($fajlnev, $s, LOCK_EX); } } |
A filmadatok feldolgozásához kapcsolódó funkciók egy osztályba kerülnek. Azért, hogy elkerüljük a folyamatos betöltést és mentést, az osztály példányosításakor betöltjük egy privát adatmezőbe a filmek listáját, és azzal dolgozunk a további műveletekben. A példány megszűnésekor (destruktor) a tömböt elmentjük fájlba.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <? php if ( ! defined('TOKEN')) exit('Közvetlenül nem elérhető!'); class FilmAdat { private $filmek; private $fajlnev; public function __construct($ fajlnev = '' ) { if (!$fajlnev) { die('Nincs adatfájl!'); } $this->fajlnev = $fajlnev; $this->filmek = FileIO::fajlbol_betolt($this->fajlnev); } public function __destruct() { FileIO::fajlba_ment($this->fajlnev, $this->filmek); } public function osszes_film() { return $this->filmek; } public function film_beszur($cim, $rendezo, $ev) { $this->filmek[] = array( 'cim' => $cim, 'rendezo' => $rendezo, 'ev' => $ev, ); return true; } } |
A listázó főszkript (lista_fajl.php) így változik:
1 2 3 4 5 6 7 8 9 10 11 | <? php define('TOKEN', 'Védelem'); include('kozos/fileio.php'); include('adat/filmadat.php'); $ fajlnev = dirname (__FILE__) . '/filmek.json'; $ filmadat = new FilmAdat($fajlnev); $filmek = $filmadat->osszes_film(); include('kimenet/lista_sablon.php'); |
Az új film felvevésekor a filmadat objektumot csak mentéskor példányosítjuk (ujfilm_fajl.php):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <? php define('TOKEN', 'Védelem'); include('kozos/fileio.php'); include('adat/filmadat.php'); //----------------------------------------------------- $ fajlnev = dirname (__FILE__) . '/filmek.json'; $ hibak = array (); $ cim = '' ; $ rendezo = '' ; $ ev = '' ; if ($_POST) { $cim = $_POST['cim']; $rendezo = $_POST['rendezo']; $ev = $_POST['ev']; if ($cim == '') { $hibak[] = 'Cím kötelező!'; } if ($rendezo == '') { $hibak[] = 'Rendező kötelező!'; } if (!is_numeric($ev) || strlen($ev) != 4) { $hibak[] = 'Rossz évszám!'; } if (!$hibak) { $ filmadat = new FilmAdat($fajlnev); if ($filmadat->film_beszur($cim, $rendezo, $ev)) { header('Location: lista_fajl.php'); }; } } include('kimenet/ujfilm_sablon.php'); |
![]() |
![]() |
![]() |
A tananyag az ELTE - PPKE informatika tananyagfejlesztési projekt (TÁMOP-4.1.2.A/1-11/1-2011-0052) keretében valósult meg.
A tananyag elkészítéséhez az ELTESCORM keretrendszert használtuk.