A PHP programozási nyelv

PHP Keretrendszrek

Bevezetés

A PHP segítségével nagyon sok feladatot tudunk elkészíteni. Ezeket a feladatokat, azaz beépített alap tulajdonsággal rendelkező jól körül írható funkcionalitásokat, keretrendszerben tudják előállítani. A keretrendszer egy egységes architektúra, ami a gyűjtemények használatára és manipulálására szolgál. Olyan programot célszerű készíteni, amely szoftvertermék teljes ciklusában kevés költséggel, de maximálisan megfelel egy terméknek.

A probléma megközelítése

A keretrendszerek kiválasztásánál felmerül egy pár kérdés.

Előnyök: Már kevés idő alatt is megtanulható egy-egy keretrendszer kezelése. A hozzáadott költség hamar is visszatérül. A készített programcsomag megfelel a dobozos terméknek.

Hátrányok: Egyes dobozos keretrendszernek nagyon sok korlátai vannak, kisebb feladat esetén is fel kell használni a teljes csomagot, ami nem mindig gyors az automatizált eljárások miatt.

Keretrendszerek felsorolása, összehasonsítása

Az alábbi táblázatban összeszedtem egy pár keretrendszert, illetve egy pár tulajdonságot, amit elsőre keresnek a fejlesztők.

Keretrendszer Hivatalos website PHP4 PHP5 MVC Templétek Adatbázis kapcsolatok
Akelos

ash.MVC http://www.ash-mvc.org/
CakePHP
CodeIgniter
DIY
eZ Components
Fusebox
Kohana
PHP on TRAX
PHPDevShell
PhpOpenbiz OpenBiz & Cubi
Prado
QPHP QPHP
Seagull
Symfony
WACT Web Application Component Toolkit
WASP http://wasp.sourceforge.net/content/
Yii
Zend
ZooP

MVC megközelítés általánosságban

A Model-View-Controller (Modell-Nézet-Vezérlő) egy gyakran használatos szoftver tervezési minta, amely három meghatározó részre osztja az alkalmazást.

  1. Modell: az alkalmazás által kezelt információk ábrázolására szolgál.
  2. Nézet: jellemzően felhasználói felületet biztosít a modell adatainak megtekintésére, kezelésére.
  3. Vezérlő: az eseményeket, felhasználói műveleteket dolgozza fel és közvetíti a megfelelő modulokhoz.
Az ilyen típusú felbontás eredménye képpen a felhasználói felület nem befolyásolja az adatkezelést, így szükség esetén könnyebben átszervezhető a struktúra, a külön csoportba tartozó modulok változtatása nélkül. Ennek hatására az MVC-n keresztül csökken az alkalmazás szerkezeti bonyolultsága és nő a rugalmasság.
A következőekben egy példát mutatunk egy egyszerű MVC keretrendszer felépítésére PHP alkalmazáshoz.

MVC megvalósítása PHP-ban

Alap felépítés

PHP alkalmazás készítésekor az alapvető MVC struktúra létrehozásához szükségünk lesz három mappára (models, views, controllers) és egy index.php fájlra, ami az elsődleges általános vezérlő lesz és keresztül fog menni rajta minden kérés, amiket rögtön továbbít is a megfelelő konkrét vezérlőknek. A fájlokat a következő szempontok szerint választjuk szét:

Az index.php fájl egészen egyszerű lehet. Érdemes benne definiálni az alkalmazás gyökér könyvtárát a szerveren és az URL cím elérését, hogy ezeket később kényelmesen tudjuk használni, amire viszont mindenképpen szükség van, az annak a vezérlőnek a meghívása, ami a megfelelő vezérlők betöltését végzi. Ez a következő példában a router.php fájlban található.

<?php //alkalmazás gyökér könyvtára a szerveren define('SERVER_ROOT', '/h2/public/tanulok/proginfo2008/hogqaai/public_html/php/myMVC/'); //URL cím az alkalmazás gyökeréhez define('SITE_ROOT', 'http://people.inf.elte.hu/hogqaai/php/myMVC/'); require_once(SERVER_ROOT . 'controllers/' . 'router.php');

Vezérlők

A vezérlők közül az elsődleges az előbb említett router.php, ami a kérés GET paraméterezése alapján határozza meg, hogy melyik további vezérlőt hívja meg. Egy link tehát a következőképpen fog kinézni:
http://.../myMVC/index.php?test&data=mvc
Ahol a 'myMVC' könyvtár a webes alkalmazás gyökér könyvtárát jelöli a serveren, a 'test' az aloldal, amit megnyitni szeretnénk a 'data=mvc' paraméterezéssel. Az utóbbi a router számára még nem fontos információ, ezt majd a konkrét vezérlő kezeli le.

Első lépésben felbontjuk a paramétereket a megfelelő részekre. Az & jel menténi felbontás megfelelő lesz, ezek közül az első elem a megtekinteni kívánt oldal neve, ezt egy külön változóban tároljuk.

<?php $request = $_SERVER['QUERY_STRING']; $params = explode('&', $request); $page = array_shift($params); $vars = array(); foreach($params as $p) { list($variable, $value) = split('=', $p); $vars[$variable] = $value; }

Következő lépésként meghatározzuk a kért oldalhoz tartozó vezérlőt és ha megtaláltuk a fájlt és a hozzá tartozó vezérlő oldalt is, akkor betöltjük az előbbiekben lekérdezett paramétereket továbbadva.

$target = SERVER_ROOT.'controllers/'.$page.'.php'; if(file_exists($target)) { include_once($target); $class = ucfirst($page).'_Controller'; if(class_exists($class)) { $controller = new $class; } else { die('class does not exists!'); } } else { die('page does not exist!'); } $controller->main($vars);

Érdemes még itt felhasználni a PHP-ban ismert __autoload függvényt is, ami ismeretlen osztály hívásokkor, megpróbálja automatikusan behúzni a megfelelő fájlt. Mivel nekünk fix struktúránk van, pontosan megtudjuk adni, hogy hol kell keresni az éppen szükséges fájlokat. (Ehhez az is kell, hogy egységesen nevezzük el fájlainkat pl: osztály nevével megegyező, csupa kisbetűs .php)

function __autoload($className) { $file = SERVER_ROOT.'models/'.strtolower($className).'.php'; if(file_exists($file)) { include_once($file); } else { die("File '$filename' containing class '$className' not found."); } }

A konkrét vezérlő (jelen esetben Test_Controller) egy osztály, ami a meghívott oldal viselkedését definiálja. Jelen példában csak egy main függvénye van, ez töltődik be kezdetkor. Szükség van egy modell és egy Nézet betöltésére erre látható példa az alábbiakban. (A modell és nézet működésének leírása később.)

<?php class Test_Controller { public $baseName = 'test';//meghatározni, hogy melyik oldalon vagyunk public function main(array $vars)//a router által továbbított paramétereket kapja { $testModel = new Test_Model;//az osztályhoz tartozó modell if(isset($vars['data'])) { $reqData = $testModel->get_data($vars['data']);//modellből lekérdezzük a kért adatot $view = new View_Loader($this->baseName.'_main');//betöltjük a nézetet $view->assign('title', $reqData['title']);//átadjuk a lekérdezett adatokat a nézetnek $view->assign('content', $reqData['content']); } else { echo "No data to show"; } } }

Modellek

Következőnek a modelleket definiáljuk. Mint láttuk a vezérlő osztályunkban, mindenképpen szükségünk lesz egy konkrétan a vezérlőhöz tartozó modellre, ez lesz a Test_Model. Ezen kívül lesz egy általánosabb modell osztályunk, ami a nézetek betöltéséért felel majd, ez a View_Loader nevet kapta a példában.

A Test_Model bevezetésével kezdjük. Jelen példában az egyszerűség kedvéért csak egy privát adattagként definiált tömbben tároljuk az adatokat, de jellemzően a modell része szokott lenni valamiféle adatbázissal való kommunikáció is. Esetünkben az egyszerű megvalósítás a következő képpen néz ki.

<?php class Test_Model { private $data = array ('new' => array('title' => 'New Website', 'content' => 'Welcome to the site!'), 'mvc' => array('title' => 'PHP MVC Framework', 'content' => 'works good')); public function get_data($title) { $retData = $this->data[$title]; return $retData; } }

A View_Loader osztály fog felelni a nézetek megfelelő módon történő betöltéséért. Ehhez először is be kell azonosítani a kívánt nézet fájlt, ami tudjuk, hogy a views mappában lesz. Ezt már a konstruktorban megtehetjük.
Továbbá meg kell oldanunk, hogy a nézet megjelenítésekor, a kívánt értékek elérhetők legyenek. Ehhez egy hozzárendelő függvényt hozunk létre assign névvel, ami egy privát tömbben tárolja le ideiglenesn az adatokat.
Végül az osztály destruktorában átadjuk a lekért adatokat egy változónak, ami elérhető lesz a nézetünkből és betöltjük a nézetet magát.

<?php class View_Loader { private $data = array(); private $render = FALSE; public function __construct($viewName) { $file = SERVER_ROOT . 'views/' . strtolower($viewName) . '.php'; if (file_exists($file)) { $this->render = $file; } } public function assign($variable , $value) { $this->data[$variable] = $value; } public function __destruct() { $viewData = $this->data; include($this->render); } }

Nézetek

A nézetek megvalósításánál már nagyon egyszerű dolgunk van, alapvetően HTML kódot kell készítenünk, amibe beszúrhatjuk a kívánt helyre, a View_Loader által eltárolt változók értékeit. A következő példában az előbb látott viewData tömbbe kimentett értékeket tudjuk használni a beillesztéshez.

<html> <head> </head> <body> <h1> Welcome! </h1> <hr/> <h2> Requested data: </h2> <h4> <?php echo $viewData['title']; ?> </h4> <p> <?php echo $viewData['content']; ?> </p> </body> </html>

A test nézet helyes definiálása után a http://.../myMVC/index.php?test&data=mvc hivatkozásra meg kell, hogy jelenjenek a modellben az 'mvc' azonosítóhoz definiált adatok, ami jelen esetben a 'works well' szöveg.

Összetettebb keretrendszerek

Az előbb bemutatott példa egy nagyon egyszerű alkalmazása az MVC struktúrának, ennél jóval összetettebb és több funkcióval rendelkező keretek érhetőek el.
Egy ilyen rendszerben megírt alkalmazásra található példa, a Példaprogramok fejezetben a Recept név alatt, ez az alkalmazás CodeIgniter felhasználásával készült.