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:
<?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:
<?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:
<?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):
<?php
define('TOKEN', 'Védelem');
//...
?>
A védett fájlok elején pedig a következő sort szükséges elhelyezni:
<?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.
<?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.
<?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.
<?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:
<?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.
<?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:
<?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:
<?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.
<?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:
<?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):
<?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.