Vissza az előzőleg látogatott oldalra (nem elérhető funkció)Vissza a modul kezdőlapjáraUgrás a tananyag előző oldaláraUgrás a tananyag következő oldaláraFogalom megjelenítés (nem elérhető funckió)Fogalmak listája (nem elérhető funkció)Oldal nyomtatása (nem elérhető funkció)Oldaltérkép megtekintéseSúgó megtekintése

Tanulási útmutató

Összefoglalás

A leckében megismerkedünk a keretrendszerek fogalmával, előnyeivel. Konkrét tervezési mintaként megismerkedünk a Modell-Nézet-Vezérlő mintával, és az erre épülő webes keretrendszerekkel. A lecke végén egy saját készítésű keretrendszer alapjait és implementálását végezzük el.

Követelmény

A lecke végére tisztában kell lenni az MNV-minta részeivel, és azzal, hogy az erre épülő webes keretrendszerekben az egyes részektől mit várhatunk el. Elvárható, hogy a leckét elolvasva mindenki képes legyen saját kódjait az MNV-minta szerint rendezni, és az általunk bemutatott MNV-s keretrendszert használni.

Önállóan megoldható feladatok

Keretrendszerek, tervezési minták webes alkalmazásokban

Az előző fejezetben láthattuk, hogy egy oldal megjelenítéséhez szükséges kódot hogyan tudjuk rendszerezni. A megoldást az jelentette, hogy a funkcionálisan és technológiailag összetartozó részeket szétválasztottuk, átláthatóbb, modulárisabb felépítést eredményezve. Ennek az is következménye lett, hogy az oldal kiszolgálásához a korábbi egy állomány helyett már három létrehozása volt szükséges: egy a nézetnek, egy a modellnek és egy a vezérlőnek. Ha az alkalmazásunkban több oldal, funkció is van (márpedig így terveztük), akkor alkalmazásunk állományszerkezete hamar kuszává és rendszertelenné válhat. Az egész alkalmazás (és nemcsak egy oldal) átláthatóságát, gyors fejlesztését, karbantarthatóságát csak megfelelő szabályok bevezetésével biztosíthatjuk. Ezekre szolgálnak az ún. keretrendszerek.

Keretrendszer

Ahogy fentebb elhangzott a keretrendszer nem más, mint az alkalmazás fejlesztését szolgáló szabályok gyűjteménye. Ezen szabályok nagyon sokfélék lehetnek, és nincsenek kőbe vésve. Vannak előre megírt keretrendszerek, amelyeket tipikusan egy fejlesztői közösség dolgozott ki, és talált megfelelőnek, de keretrendszert egy fejlesztő maga is kidolgozhat. Vannak általános keretrendszerek, és vannak olyanok, amelyek egyféle feladatkör számára biztosítanak jól bevált megoldásokat. Igazából ahány keretrendszer, annyi féle szabályrendszer.

A keretrendszerben megjelenő szabályok tipikus problémákra adnak jól bevált megoldásokat. Az előbb említettük, hogy egy nagyobb alkalmazás esetén sok állománnyal dolgozhatunk. Erre megoldás lehet az, hogy meghatározzuk a fájlstruktúrát, és az egyes állományokat funkciónként eltérő könyvtárba soroljuk. Sokszor elvárás az is, hogy a fájl neve tükrözze tartalmát, így nagyon gyakoriak az állományok elnevezésére vonatkozó megkötések, sőt néha a kis- és nagybetű is számíthat ezekben. Ugyanilyen elnevezésbeli megkötések lehetnek osztálynevekre, származtatásokra, és egyebekre is. Ezen szabályok értelme kettős: egyrészt kényszeríti a fejlesztőt, hogy következetes legyen az elnevezésekben, másrészt ezekre a szabályokra logika is épülhet a keretrendszer kódjában, be nem tartásuk az alkalmazás működésképtelenségéhez vezet. Ugyancsak általános probléma egy webes alkalmazásban a konfigurációs állományok kezelése, az egy belépési pont biztosítása, munkamenet-kezelés indítása, nyelvi beállítások kezelése, átmeneti tárolással kapcsolatos nehézségek áthidalása, stb. Ezek megoldását egy fejlesztő maga is kigondolhatja, de kényelmesebb és célszerűbb a keretrendszerek által nyújtott kidolgozott megoldást választani.

Ilyen formán a keretrendszer sok mindent elfedhet előlünk, és amit láttat, az sokszor egy nagyon kényelmes interfész, amelyen keresztül már a felesleges sallangoktól megtisztított lényegi logikára koncentrálhatunk. Ennek természetesen megvan a hátránya is. Egy keretrendszer sok tekintetben egy fekete doboz. Írunk egy kódot, aztán abból valahogyan megjelenik egy oldal. Zavaró lehet, hogy nem ismerjük a keretrendszer mélyét. Éppen ezért, amikor keretrendszerekkel kezdünk el dolgozni, először mindig meg kell ismernünk a szabályai mellett a működési elvét is. Szerencsére a PHP-s keretrendszerek többsége nyílt forráskódú, így a forrása is szabadon böngészhető, és általában megjegyzésekkel teli.

A keretrendszerek megértéséhez, bemutatásához nem kell a webes alkalmazásokig menni. Tulajdonképpen minden magasabb szintű programozási nyelv is egy keretrendszer, hiszen kifelé egy egyszerűbb interfészt mutatva elfedi előlünk a gépi vagy assembly kódot, sőt azok nagyfokú szabadságát megregulázva erőltet ránk strukturált programozási elemeket. Ugyanilyen példák lehetnek a különböző asztali RAD (Rapid Application Development - gyors alkalmazásfejlesztési) eszközök (pl. Delphi vagy Visual Studio), amelyekkel pár egérkattintással készíthetünk asztali alkalmazásokat. Az ezekben megjelenő window vagy form objektumok elrejtik előlünk a bonyolult natív ablakkezelési metódusokat, eseményeket, egy egyszerűbb tervezési és programozói felületet biztosítva. A fejlesztő a lényegre tud koncentrálni, hogy mi történjen pl. egy egér kattintásakor, és nem kell azzal törődnie, hogyan érzékelje a kattintást, hogy a gomb hogyan nyomódjon be, hogyan rajzolja ezt ki, összességében milyen natív ablakkezelési kódhalmazt kellene ott megvalósítania.

A keretrendszerek szabályai sokszor korlátok, nem engednek bizonyos dolgokat kedvünk szerint csinálni. Ezeket a korlátokat éppen azért hozták, hogy a fejlesztési folyamatot valamennyire egységes, kiszámítható mederbe tereljék. Ez a kiszámíthatóság fontos fejlesztéskor, de fontos karbantartáskor is, hogy tudjuk, mit hol kell keresnünk. Vannak keretrendszerek, főleg a feladatsepcifikus keretrendszerek, amelyek olyan szabályokat hoznak, amelyek az adott feladattípus elvégzését nagy mértékben megkönnyítik, de más típusú feladatok megvalósítása csak nagy kínszenvedéssel oldható meg bennük. Vannak általánosabb keretrendszerek, amelyek nagyobb szabadságot adnak, de ez több kódolással is járhat. Éppen ezért egy feladat elvégzése előtt érdemes megnézni, hogy melyik keretrendszer mit tud, és a feladathoz illőt válasszuk. Sokszor ugyanahhoz a feladattípushoz többféle keretrendszer is tartozhat, ekkor a döntésben a keretrendszer dokumentáltsága, a mögötte lévő fejlesztői közösség nagysága, az egyéb szolgáltatások, vagy éppen a megvalósítás filozófiája dönthet, hogy melyiket érezzük magunkénak.

A keretrendszerek – főleg a kiszámíthatóságuknak köszönhetően – általában támogatják a csoportmunkát, azaz a feladatot több részre lehet bontani és azon különböző emberek dolgozhatnak.

A fentieket összefoglalva ismertetjük a professzionális használatának előnyeit, illetve hátrányait:

Előnyök

Hátrányok

A keretrendszerek közül mi most a Modell-Nézet-Vezérlő architektúrára épülő keretrendszerekkel fogunk foglalkozni.

Vissza a tartalomjegyzékhez

Modell-Nézet-Vezérlő (MNV) tervezési minta

Az előző fejezetben láthattuk, hogy lépésről lépésre hogyan szedtük szét az oldalkiszolgálási kódunkat nézetre, modellre és vezérlőre. Ebben a részben az MNV-minta részletesebb körüljárását tesszük meg.

Itt érdemes megjegyezni, hogy a Modell-Nézet-Vezérlő megnevezés az angol Model-View-Controller kifejezés fordításából adódik, így a szakirodalomban vagy kapcsolódó írásokban ezzel a kifejezéssel, vagy ennek rövidített változatával, az MVC-mintával találkozhatunk. A továbbiakban mi a magyar kifejezést és annak rövidítését fogjuk használni.

Az MNV egy architekturális tervezési minta, amely arra ad javaslatot, hogy egy alkalmazás milyen módon épüljön fel, hogyan szervezze a benne lévő kódot. Alapvető indíttatása az adat és annak megjelenítésének a szétválasztása, hogy a felület ne befolyásolja az adatkezelést, és az adatok újraszervezhetőek legyen a felület módosítása nélkül. Így elkülöníti az adatokkal kapcsolatos logikát a megjelenítési logikától, a kettő közötti kommunikációt pedig a vezérlő biztosítja. Az MNV-minta általában csak az alkalmazás megjelenítési rétegéhez közeli rétegeket határozza meg, az alkalmazás mélyebb rétegeit (üzleti logikai objektumok, perzisztenciaréteg, adatbázis, szolgáltatásréteg) általában a modellbe sorolja.

Az MNV-mintát először 1979-ben írták le a Xerox PARC nevű cég mérnökei, miközben a Smalltalk nyelv fejlesztésén dolgoztak. A Smalltalk egy tisztán objektumorientált nyelv, amellyel nagyon interaktív alkalmazások írhatók, és ennek hátterében az MNV-minta áll. Szerepe elsősorban abban áll, hogy elválassza az alkalmazáslogikát a felhasználói felülettől, amely lehetővé teszi a modell újrahasznosítását különböző (szöveges, grafikus) felületeken. Az MNV-minta az alábbi részekből áll:

A modell, nézet és vezérlő szétválasztásával az MNV-minta a következő célokat tűzi ki:

A klasszikus MNV-mintában a folyamat a következő:

1. A felhasználói felületen a felhasználó eseményt vált ki, ezt a vezérlő kapja el és dolgozza fel.

2. A vezérlő az eseménynek megfelelően kapcsolatot teremt a modellel, annak adatokat adva át. A modellben tárolt adatok akár meg is változhatnak.

3. A vezérlő meghívja a nézetet, amely a modelltől elkéri az adatokat, és azokat megjeleníti.

A folyamatot az alábbi ábra szemlélteti:

A klasszikus MNV-mintaA klasszikus MNV-minta

Az animációban a klasszikus MNV mintára épülő kiszolgálási folyamatot tekinthetjük meg.

Flash lejátszó letöltése

A klasszikus MNV kiszolgálási folyamat bemutatója.

Vissza a tartalomjegyzékhez

MNV-minta webes alkalmazásokban

Az MNV-minta megjelenése és első használata óta igen népszerű, számos alkalmazása van grafikus, asztali rendszerekben (pl. Apple Cocoa, ami az Apple keretrendszere MacOS és iOS alkalmazások írására), de igazi elterjedtsége és népszerűsége a webes platformon történt. A megjelenés elválasztása az modelltől platformtól függetlenül jól alkalmazhatónak bizonyult, de asztali grafikus alkalmazásokban a felhasználói felületben gyakran összeolvadt a nézet és a vezérlő. A webes világ szerver-kliens architektúrájában azonban ez a két szerep szükségszerűen szétvált: míg a nézet elsősorban a kliensen megjelenítendő adatot definiálta, addig a vezérlő a szerveren futott. A jól bevált (platformfüggetlen) alapelvek mellett tehát az alkalmazások felépítése is indokolta az MNV-minta alkalmazását a weben.

Az MNV-minta alapelvei és az egyes részek szerepei nem változnak meg a webes alkalmazásokban, csupán konkrétabban lehet nyilatkozni a részleteikről, kapcsolataikról.

Egy oldal kiszolgálási folyamata hasonlít a klasszikus mintánál részletezett folyamathoz, amely itt is a felhasználói felületről, a kliens böngészőjéből indul. A felhasználó által kiváltott megfelelő tevékenység (itt most nem a JavaScript által feldolgozható eseményekre kell gondolni) egy HTTP kérést eredményez a szerver felé. A szerveren a vezérlő feldolgozza a kérés, és az abban kapott adatokat átadja a modellnek. A klasszikus minta szerint a modell megváltozik, és majd a nézet – a vezérlő által meghívva – kéri el az adatokat a modelltől. Webes alkalmazásokban ezen a ponton szoktak eltérni a megvalósítások. A vezérlőn folynak ugyanis át az adatok, és nem a nézet kéri el az adatokat a modelltől. Ekkor tehát a vezérlő átadja az adatokat a modellnek, majd el is kéri tőle azokat, amelyek a megjelenítéshez szükségesek. A kapott adatokat aztán a vezérlő adja át a nézetnek, amely azokkal legenerálja az oldalt. Az MNV-minta ilyen jellegű megvalósítása általában egyszerűbb, mint a klasszikus eseté. Ezt a folyamatot szemlélteti az alábbi ábra:

MNV-minta a webenMNV-minta a weben

Az animációban a webes MNV mintára épülő kiszolgálási folyamatot tekinthetjük meg.

Flash lejátszó letöltése

A webes MNV kiszolgálási folyamat bemutatója.

Az MNV-mintának egyik nagy előnye, hogy a fejlesztési munkafolyamatokat támogatja. Három fő szerepkör van egy fejlesztő csapatban:

Vissza a tartalomjegyzékhez

Az MNV-minta részeinek finomítása

Az MNV-minta egy olyan tervezési architekturális minta, mely megfelelő útmutatást ad az alkalmazás funkcionális részeinek szétválasztására, de a megvalósítás részleteit nem elemzi. Mindegyik részében azonban további általánosításokat vagy tervezési mintákat lehet felfedezni, amelyek tovább segítik az MNV-minta implementációját. A következőkben megnézzük, hogy hogyan finomíthatók az MNV-minta egyes részei.

A modell finomítása

A modell finomításáról már az előző tananyagrészben esett szó. A modell a vezérlővel közvetlen kapcsolatban lévő interfésztől az adatbázisig további rétegekre bontható:

Az üzleti logikai réteg tartalmazza magát az adatokkal kapcsolatos lényegi feldolgozó részt. Ebben kerülnek definiálásra az egyes adatszerkezetek, amelyekkel az adatbázis dolgozik. Az alkalmazás méretétől függően itt az adatok már magas fokon absztraháltak, nem feltétlenül tükrözik az alatta lévő adatbázis szerkezetét, akár lényegesen el is térhetnek tőle. Kisebb alkalmazásokban természetesen kisebb fokú az absztrakció is, ilyenkor az adatszerkezetek nagyjából megegyeznek a táblaszerkezettel. Az alkalmazás méretétől függően további eltérő funkcionalitású rétegekre osztható ez a réteg.

Az adatbázis-absztrakciós rétegről az előző rész végén szóltunk. Ebben a rétegben SQL utasításoktól függetlenül végezhetünk adatbázis-műveleteket, az absztrakt interfész dolga az egyes utasításokat megfelelő SQL utasítássá alakítania. Ebben a rétegben az adatbázisbeli táblák és sorok már objektumként jelennek meg, és az interfész dolga az adatbázis és ezek közötti leképezések megvalósítása. Ezért ebben a rétegben nagyon gyakran ún. ORM (Object-Relational Mapping) technológiákat találunk (ActiveRecord, Doctrine, Propel).

Az adatbázis-elérési absztrakciós rétegről részletesen volt szó az előző részben. Lényege egy olyan absztrakt interfész definiálása, amelynek utasításai függetlenek az alkalmazás mögötti adatbázistól. Az SQL utasításokat nekünk kell ebben az esetben is összeállítani. Ez egy olyan réteg, amelyet kis alkalmazásokban is érdemes használni, nem is elsősorban az adatbázis-függetlenség, hanem az átláthatóbb, egyszerűbb programozói felület miatt.

A nézet finomítása

A nézetünk általában egy sablon, amelyben megfelelő módon (mi most PHP nyelvi elemekkel) jelzünk bizonyos logikát (elágazás, ciklus), vagy változóknak a helyét. Ha funkcionálisan tekintünk egy megjelenő oldalra, akkor általában azt vesszük észre, hogy az oldalnak van egy alapvető elrendezése (fejléc, menü, lábléc), és van egy olyan területe, ahová a változó tartalom töltődik be. Ennek megfelelően kétféle részt különböztetünk meg a nézetben: magát az oldal elrendezését, kialakítását (angolul layout), és magát a változó tartalomnak a sablonját. Az előbbi természetesen kevés van (alkalmazásonként általában egy), utóbbiból viszont annyi, ahány különböző oldal, tartalom van. A nézethez tartozó logika a vezérlőben szokott helyet kapni, és ennek során történik meg a sablonban definiált jelölőkhöz a konkrét adatok hozzárendelése.

A vezérlő finomítása

Már fentebb is említettük, hogy a vezérlő az MNV-minta egyik legáltalánosíthatóbb része, azaz ebben könnyű olyan tipikus műveletsorokat felfedezni, amelyet általánosítani lehet. A vezérlőnek egy éles alkalmazásban elég sok mindent kell csinálnia, mielőtt a konkrét művelet végrehajtásába kezd: HTTP adatok előfeldolgozása, biztonsági ellenőrzések, alkalmazásszintű beállítások elvégzése, munkamenet indítása, konfigurációs állományok betöltése, és még sorolhatnánk. Ezek általában mindegyik vezérlőre nézve közös dolgok, így felesleges lenne ezt minden vezérlő elején megismételni, hanem a közös dolgokat külön választják, kiemelik, és a konkrét műveletet elvégző vezérlő elé teszik. Az egyes vezérlők előtti közös műveletek elvégzéséért felelős vezérlőt elővezérlőnek, vagy az angol terminológia alapján Front Controllernek hívjuk.

Az elővezérlőnek van egy másik előnye azon túl, hogy a felesleges kódismétlést elkerüli, mégpedig az, hogy biztosítja az alkalmazás egyetlen belépési pontját (általában index.php). Nélküle minden vezérlő külön-külön meghívható lenne, ami megint nagyfokú kuszaságot vonna maga után, és biztonsági aggályokat vet fel. Az elővezérlő segítségével mindegyik vezérlő rajta keresztül hívódik meg, így alkalmazásunknak egyetlen belépési pontja van, ahol a megfelelő biztonsági ellenőrzéseket és beállításokat elvégezhetjük.

Természetesen ebben az esetben joggal merül fel a kérdés, hogy ha minden vezérlőt az elővezérlőn keresztül érünk el, akkor honnan tudja az alkalmazás, melyik vezérlőt kell meghívnia. A meghívandó vezérlőt tipikusan GET paraméterrel szokták átadni az index.php-nak (pl. index.php?oldal=bemutato_lista). Az elővezérlőnek azt a részét, amely a megfelelő vezérlő meghívásáról gondoskodik, ki szokták emelni, és alkalmazásvezérlőnek hívják (Application Controller). Az alkalmazásvezérlő általában az elővezérlő utolsó lépéseként jelenik meg.

Végül még egy ponton szokták finomítani az elővezérlőt. Az objektumorientált programozás elve szerint az elővezérlőt is meg lehet valósítani osztályként (tipikusan Egyke, azaz Singleton). De ekkor is kell lennie egy olyan kódrészletnek, amely a példányosítást elvégzi, és amely – a PHP nyelvi sajátosságait figyelembe véve – nem objektumorientált, hanem procedurális. Ezt a kis feladatot végző szkriptet szokták Bootstrapnek hívni.

Összefoglalva, a vezérlő az alábbi egymás utáni rétegekre bontható:

A vezérlő finomításaA vezérlő finomítása

Vissza a tartalomjegyzékhez

MNV-s webes keretrendszerek

Az MNV-mintára épülve számos, webes alkalmazás készítéséhez kialakított keretrendszer található. Ezekben a keretrendszerekben szinte kivétel nélkül megjelennek a fent említett terminusok. A kódot állományszinten is modell, nézet és vezérlő elnevezésű mappákba sorolják. Nagyon gyakoriak bennük a különböző elnevezési szabályok, amelyek meghatározzák az osztályok, fájlok neveit, elhelyezkedését. A keretrendszer magja tipikusan külön könyvtárban helyezkedik el, ebbe általában nem kell nyúlnunk, az alkalmazásunknak külön mappája van. Ezáltal könnyen elvégezhető a keretrendszer magjának a frissítése anélkül, hogy az alkalmazásunk mappájába kellene módosításokat végrehajtani. A rendszermag általában sok osztályból áll, ezek végzik el a tipikus folyamatokat elrejtve őket a konkrét alkalmazásfejlesztési folyamat elől. Nagyon gyakori, hogy a szokásos modell, nézet és vezérlő mappák és osztályok mellett egyéb funkcionalitású komponensek is megjelennek: függvénykönyvtárak (library), kisegítő osztályok (helper), modulok, stb. Ezek mind az egyes keretrendszerek sajátos kiegészítői, nehezen általánosíthatóak. A keretrendszerek sokszor biztosítanak tipikus webes problémákra előre elkészített megoldásokat. Ilyen például a felhasználó azonosítása, bejelentkeztetése és jogainak kezelése, vagy űrlapok kezelése, vagy az átmeneti gyorsítótár (cache) kezelése.

Manapság gombamód szaporodnak a webes MNV-s keretrendszerek, nyílt forráskódú közösségektől kezdve a nagyvállalatokig egyaránt jelen vannak a piacon, és szinte minden webes platformon megjelenik Javatól az ASP.NET-en keresztül a PHP-ig. Íme néhány példa:

A megfelelő keretrendszer választásához érdemes az alábbi szempontokat figyelembe venni:

Vissza a tartalomjegyzékhez

Saját MNV-mintára épülő webes keretrendszer készítése (MiniMVC)

A következőkben példaképpen az előző rész MNV-s tudását egy keretrendszerbe foglaljuk, és egy saját MNV-s webes keretrendszert mutatunk be. A készítendő keretrendszer demonstrációs célokat szolgál, nem éles alkalmazásra termett, csupán arra, hogy az ebben a részben bevezetett fogalmakat bemutassa.

A keretrendszer szabálygyűjtemény, így első körben határozzuk meg azokat az alapelveket, amelyek szerint a keretrendszerünket felépíteni szeretnénk:

A fentieknek megfelelően először a keretrendszer könyvtárszerkezetét határozzuk meg, ami a következőképpen alakul:

(D) system

front_controller.php

application_controller.php

(D) controllers

(D) models

(D) views

index.php

Az egyetlen belépési pontot az index.php állomány biztosítja. Ez lesz az elővezérlő. Ez a fentieknek megfelelően három részre bontható: bootstrapre, elővezérlőre és alkalmazásvezérlőre. Az index.php tehát igazából csak a bootstrap lesz, aminek feladata az elővezérlő példányosítása és elindítása.

<?php

define( "TOKEN", "mini_mvc" );

include_once('system/front_controller.php');
$fc = new Front_Controller();
$fc->start();

?>

Az igazi elővezérlő a system/front_controller.php állományban helyezkedik el egy Front_Controller nevű osztály formájában. A példa keretrendszerünk nem sok mindent csinál a vezérlők meghívása előtt, így egyetlen start() függvényt tartalmaz, amelyben példaképpen a munkamenet indítása helyezkedik el. Egy konkrét alkalmazásban az elővezérlő osztály több metódust tartalmaz és a start() metódus is könnyen meghízik.

<?php  if ( ! defined('TOKEN')) exit('Ez a szkript közvetlenül nem elérhető!'); 

class Front_Controller {

    public function start() {
        session_start();

        //Konfiguracio betoltese

        //Jogosultsagok ellenorzese
        
        include_once('system/application_controller.php');
        $ac = new Application_Controller();
        $ac->start();
    }

}
?>

A start() metódus utolsó utasítása az alkalmazásvezérlő példányosítása és meghívása. Mielőtt a konkrét megvalósítását elemezzük, nézzük végig, milyen lehetőségeink vannak az alkalmazásvezérlő központi részének a megírására. Az egyszerűség kedvéért tegyük fel, hogy csak egy GET paramétert kapunk, az oldal-t, amely megmondja, melyik funkciót szeretnénk meghívni. Az első lehetőség az oldal szerinti elágazás:

<?php
switch ($oldal) {
    case "index":
  index();
  break;
 case "page1":
  page1();
  break;
 case "page2":
  page2();
  break;
 case "page3":
  page3();
  break; 
 default:
  index();
}
?>

Hamar beláthatjuk, hogy ez sok funkció esetén átláthatatlan kódhalmazhoz vezet. Megfelelő elnevezési konvencióval azonban, miszerint az oldal és a meghívandó függvény neve ugyanaz, rövidíthetünk rajta:

<?php
if (function_exists($oldal)) {
 call_user_func($oldal);
}
?>

Egy másik lehetőség, hogy az egyes funkciók nem külön függvényekben, hanem külön állományokban helyezkednek el, amelyeket a megfelelő esetben be kell emelni. Ekkor megint választhatjuk a többirányú elágazást:

<?php
switch ($oldal) {
 case "index":
  include "v3_index.php";
  break;
 case "page1":
  include "v3_page1.php";
  break;
 case "page2":
  include "v3_page2.php";
  break;
 case "page3":
  include "v3_page3.php";
  break; 
 default:
  include "v3_index.php";
}
?>

Vagy megfelelő elnevezési szabállyal ezen is egyszerűsíthetünk:

<?php
if (file_exists("v3_" . $oldal . ".php")) {
 include_once("v3_" . $oldal . ".php");
}
?>

A fenti megoldásokkal sokszor találkozhatunk, ezért is érdemes megemlíteni őket. Saját keretrendszerünkben azonban a meghívandó vezérlőkód egy bizonyos osztály egy adott metódusában helyezkedik el (azaz a vezérlő igazából egy osztálymetódus), ezt a két információt GET paramétereken keresztül kapja meg (class és method). Ezek figyelembevételével egy lehetséges megoldás a következő:

<?php  if ( ! defined('TOKEN')) exit('Ez a szkript közvetlenül nem elérhető!'); 

class Application_Controller {

    public function start() {
        $class = 'main';
        if (isset($_GET['class'])) {
            $class = $_GET['class'];
        }

        $method = 'index';
        if (isset($_GET['method'])) {
            $method = $_GET['method'];
        }

        if (file_exists("controllers/" . $class . ".php")) {
            include_once("controllers/" . $class . ".php");
            if (class_exists($class . "_Controller")) {
                $class .= "_Controller";
                $ctrl = new $class();
                if (method_exists($ctrl, $method)) {
                    //call_user_func(array($class, $method));
                    $ctrl->$method();
                }
                else {
                    include_once("error.html"); 
                }
            }
            else {
                include_once("error.html"); 
            }
        }
        else {
            include_once("error.html"); 
        }
    }

}
?>

A megfelelő elnevezési szabályok és a beillesztendő fájl, valamint a meghívandó osztály és metódus meglétének ellenőrzése után a vezérlő kód futtatása az adott osztálymetódus meghívása.

Konkrét példaként a bemutatók listázását implementáltuk kis keretrendszerünkben. A vezérlő osztályt a controllers/bemutato.php állományban találjuk, a megfelelő fájl- és osztályelnevezési szabályokat betartva:

<?php  if ( ! defined('TOKEN')) exit('Ez a szkript közvetlenül nem elérhető!'); 

class Bemutato_Controller {

    function index() {
        include('models/bemutato.php');

        $felhasznalo_id = 1;
        $cim = '';

        $modell = new Bemutato_Model();
        $bemutatok = $modell->bemutatok_lekerese($felhasznalo_id, $cim);

        include('views/bemutato_lista.php');
    }
    
    function uj_bemutato() { /*...*/ }
    function bemutato_szerkeszt() { /*...*/ }
    function bemutato_torol() { /*...*/ }
}
?>

A modell a models/bemutato.php állományban helyezkedik el, az adatbázis eléréséhez PDO-t használva:

<?php  if ( ! defined('TOKEN')) exit('Ez a szkript közvetlenül nem elérhető!'); 

class Bemutato_Model {
    
    function bemutatok_lekerese($felhasznalo_id, $cim) {
        $dbh = new PDO('mysql:host=localhost;dbname=dyss', 'dyss', 'jelszo');
        $dbh->exec('set names utf8');

        $q = "select id, cim, leiras, indexfajl, megtekintes_db, publikus, letrehozas_datuma 
                from bemutato
                where cim like ? and
                    felhasznalo_id = ?";
        $stmt = $dbh->prepare( $q );
        $stmt->bindParam(1, $cim, PDO::PARAM_STR);
        $stmt->bindParam(2, $felhasznalo_id, PDO::PARAM_INT);
        $cim = "%{$cim}%";
        $stmt->execute();
        
        $dbh = null;
        
        return $stmt->fetchAll();
    }
        
}
?>

Végül a nézet az előző részben megismert bemutató lista sablon kódja, a styles könyvtárban pedig a hozzá tartozó stílusfájlok helyezkednek el.

Az elvárások között szerepelt az is, hogy az index.php-n kívül egyéb fájl ne legyen közvetlenül meghívható. Ezt kétféleképpen érhetjük el. Vagy kihasználjuk az Apache webszerver htaccess modulját, amelyen keresztül letiltható bizonyos állományok vagy könyvtárak rekurzív elérése, vagy pedig a bootstrapben bevezetünk egy speciális konstanst (ld. első utasítás), és ennek meglétét ellenőrizzük a többi fájl elején (ld. pl. a bemutato vezérlőt).

A mini MNV-s keretrendszerünk forráskódja innen tölthető le:

Vissza a tartalomjegyzékhez

Fel a lap tetejére
Új Széchenyi terv
A projekt az Európai Unió támogatásával, az Európai Szociális Alap társfinanszirozásával valósul meg.