spájame
slovenskú
IT komunitu
pridaj sa
Registrácia · Login

Andrej Mihaliak 9.8.2011
Hodnoť článok:
2 0

Tvorba MVC Frameworku

V tomto článku sa dozvieťe čo je to MVC Pattern, ako pracuje a ako vytvoriť MVC Framework.

MVC Pattern

MVC (Model View Controller) Pattern je softwarová architektúra, ktorá rozdeľuje dátovy model, užívateľské rozhranie a riadiacu logiku do troch nezávislých na sebe komponentov.

Krok 1.

V tomto kroku si vytvoríme súbor .htaccess ktorý nám bude presmerovávať linky na indexovú stránku frameworku:

/.htaccess

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]

Krok 2.

Teraz si vytvoríme indexovú stránku frameworku ktorá bude spúštať naše aplikácie.

/index.php

<?php
// definujeme si root webu
define("BASE_PATH", dirname(realpath(__FILE__))."/");
// inkludujeme framework
include_once BASE_PATH . "framework.php"; 

// spustíme framework
$application = new Framework();
// a načítame controller
$application->loadController(); 

?>

Krok 3.

Konečne sme pri tom frameworku.

Základ

/framework.php

<?php
if(!defined("BASE_PATH")) exit("No direct script access allowed");

// definujeme triedu Framework
class Framework
{

Error function

// definujeme metódu show_error
public function show_error()
{
	die("404 Error - File not found.");
}

Model

// definujeme metódu loadModel
public function loadModel( $model )
{
	// pridáme koncovku _model
	$model .= "_model"; 

	// odkaz na model
	$model_file  = BASE_PATH . "application/models/".$model.".php"; 

	// ak model neexistuje
	if(!file_exists($model_file))
	{
		// zobrazí sa chyba
		$this->show_error();
	} else {
		// inak inkludneme model
		include_once $model_file; 

		// a vytvorí object s týmto modelom
		$this->$model = new $model;
	}
}

View

// definujeme metódu loadView
public function loadView($view, $view_data = array())
{
	// pridáme koncovku _view
	$view .= "_view"; 

	// odkaz na view
	$view  = BASE_PATH . "application/views/".$view.".php"; 

	// ak existujú dáta(array) a nieje prádzny
	if(is_array($view_data) && count($view_data) > 0)
	{
		// tak klúče arrayu sa prepíšu na premennu
		extract($view_data, EXTR_PREFIX_SAME, "wddx");
	}

	// ak view neexistuje
	if(!file_exists($view))
	{
		// zobrazí sa chyba
		$this->show_error();
	} else {
		// inak inkludneme view
		include_once $view;
	}
}

Controller

// definujeme metódu loadController
public function loadController()
{
	// rozbijeme uri
	$uri = preg_split("[\\/]", getenv("REQUEST_URI"), -1, PREG_SPLIT_NO_EMPTY); 

	$cmv = array(
				 // definujeme defaultný controller
				 "controller" => "welcome", 

				 // definujeme metódu ktorá sa zavolá ak nieje zadaná metóda
				 "method"	  => "index",   

				 // array klúč do ktorého sa uložia dáta, ak nejaké budú
				 "vars"		  => NULL);     

	// ak je nejaké uri
	if(count($uri) > 0)
	{
		// zistíme a zapíšeme controller
		$cmv['controller'] = $uri[0]; 

		// potom vymažeme zbytočné miesto
		unset($uri[0]); 

		// ak ešte existuje uri tak to bude metóda
		if(isset($uri[1]))
		{
			// zistíme a zapíšeme metódu
			$cmv['method'] = $uri[1]; 

			// potom vymažeme zbytočné miesto
			unset($uri[1]);
		}

		// ak stále existujú uri, tak to budú premenné
		if(isset($uri))
		{
			foreach($uri as $key => $value)
			{
				// zapíšeme premenné do premennej vars
				$cmv['vars'][] = $value;
			}

			// potom vymažeme zbytočné miesto
			unset($uri);
		}
	}

	// odkaz na controller
	$controller = BASE_PATH . "application/controllers/".$cmv['controller'].".php"; 

	// ak controller neexistuje
	if(!file_exists($controller))
	{
		// zobrazí sa chyba
		$this->show_error();
	} else {
		// inak inkludneme controller
		include_once $controller; 

		// spustíme controller
		$controller = new $cmv['controller']; 

		// ak existuje metóda
		if(method_exists($controller, $cmv['method']))
		{
			// tak spustíme aj tú,s dátami
			$controller->{$cmv['method']}($cmv['vars']);
		}
	}
}

Krok 4.

Prvý controller!

Prvý controller si môžme urobiť nejaký jednoduchý napr. na výpis textu.
POZOR! Názov triedy v controlleri sa musí volať tak isto ako samotný controller!

/application/controllers/welcome.php

<?php
if(!defined("BASE_PATH")) exit("No direct script access allowed");

// vytvoríme triedu s názvom controlleru,teda welcome.php => welcome
class welcome extends Framework
{
	// metóda ktorá sa zavolá ak nebude zadaná metóda
	function index()
	{
		// načítame view
		$this->loadView("index");
	}

	// metóda test s uri a modelom
	function test($args="")
	{
		// načítame model names
		$this->loadModel("names");

		// načítame dáta s modelu
		$data = $this->names_model->getNames();

		// a zapíšeme uri
		$data['uri'] = $args;

		// načítame view
		$this->loadView("hello", $data);
	}
}

Prvý model

/application/models/names_model.php

<?php
if(!defined("BASE_PATH")) exit("No direct script access allowed");

// vytvoríme triedu s názvom modelu teda names_model.php => names_model
class names_model extends Framework
{
	// metóda ktorá vypíše dáta
	function getNames()
	{
		$names = array(
						"nick" => "nipid",
						"firstname" => "Andrej",
						"surname" => "Mihaliak");

		return $names;
	}
}

Prvý controller - views

/application/views/index_view.php

<!doctype html>
<html>
<head>
	<title>Welcome!</title>
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<meta name="description" content="">
	<meta name="keywords" content="">
</head>
<body>
	Welcome in framework!
</body>
</html>

/application/views/hello_view.php

<!doctype html>
<html>
<head>
	<title>Hello!</title>
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<meta name="description" content="">
	<meta name="keywords" content="">
</head>
<body>
	Hello <?=$nick;?> <small>(<?=$firstname;?> <?=$surname;?>)</small>.<br/><br/>

	<?php
	if(isset($uri))
	{
		echo "URI:<br/><pre>";
			print_r($uri);
		echo "</pre>";
	}
	?>

</body>
</html>

Celý framework si môžete stiahnuť TU.

Hodnoť článok:
2 0

26 komentárov k článku:

Komentovať môžu iba prihlásení

Zaregistruj sa cez bezplatnú registráciu alebo použi login cez Facebook (FB Connect)

Prihlás sa tu, ak už máš profil na Zajtra.sk:


Zabudol som heslo

1 1 Peter Payter Gašparík 28.8.2012 21:46:33
odporúčam radšej tento článok http://symfony.com/doc/current/book/from_flat_php_to_symfony2.html je tam pekne na príklade ukázané aký má vôbec MVC význam (angličtina potrebná)
1 1 Andrej Molnar 16.9.2011 11:13:42
Velmi pekne dakujem, exceletne napisane, sarmantne a lahkopochopitelne nakodovany cms .

A neviem co maju ini vyhrady proti short tags ste normalni? toto neni produkcny cms, aj keby to napisal v ASP a dal nadpis PHP cms ide o princip ako to spravit.

shorttagy su v tutorialoch tohto typu ovela prehladnejsie.

tento clanok je velmi dobry, normalne sa programatori do velkych php frameworkov ani nepustia, kvoli zlozitosti.
0 0 Moďerný Občan 14.8.2011 13:03:06
Jonas asi ide prevazne o kvantitu...
0 0 shanoy 14.8.2011 12:07:26
tak preco to redakcia schvalila, ked je zbytocne matuci?
0 0 zelinko 12.8.2011 09:30:32
nic v zlom, ale prave taketo clanky zbytocne matu ludi zacinajucich s OOP a dajme tomu MVC.
0 0 Pilo Ponth 11.8.2011 10:14:00
Dnes uz moc nedava zmysel pisat clanky typu "sprav si vlastny PHP framework". Na vyucovanie OOP v PHP je vhodnejsie zvolit prave existujuci zabehnuty FW a riesit v nom nejaku vec "zo zivota vyvojara".

Serialy maju ak teda maju byt seriove, musia prezentovat kod, ktory bude citatel do buducna sam rozsirovat. A to mam velke pochybnosti, ze "vlastny PHP framework" je na toto vhodny. Je to pre citatela zabity cas, lebo v buducnosti (ked dosiahne urcitu uroven) aj tak switchne na "velky" FW.
0 0 Michal Mišiak Kvasničák 10.8.2011 22:30:18
@Zdenko Vrabel:
Add1.: mne to prislo ako by tym extendovanim Frameworku chcel povedat ze to patri do package frameworku ale to stacilo napisat do anotacie alebo pouzit php 5.3 namespace ale urcite nie modelom ani controllerom rozsirovat Framework.. to nema nic spolocne ani len logicky, Framework je skor len cieleny nazov na tu skupinu skriptov, ktore tvoria nejaku zakladnu strukturu aplikacie

Add 2.: vacsina frameworkov aspon co poznam jasne oddeluje view od controllera/presentera, modelu (nette, zend, cakephp,...) :) ale to je vlastne jedno :D
0 0 Zdenko Vrabel 10.8.2011 22:14:35
Ahoj,

Neda mi nezareagovat na clanok. Podla mojho nazoru ide o dost zvlastny MVC. Priznam sa ze niesom PHPckar ale princip je vsade rovnaky takze par poznamok k tomu:

Add 1. Ak si clanok dava za ciel vysvetlit MVC, tak podla mna ciel nebol splneny. Totizto uz len uvodny obrazok uplne deformuje MVC. Doporucujem GoF Dessign Patterns kde je MVC popisany. Ide o starsiu publikaciu ale myslim ze MVC sa za poslednych 18 rokov nezmenilo. Chapem ze ide o ilustracny clanok ale z neho mi vypliva ze tie kompetencie toho vsetkeho su nejake rozhadzane. Na co narazam. Podla clanku cloveku pride ze napriklad data z DB (skrz nejake DAO) by sa mali teda riesit v Model. To je vsak vec controllera a model by mal byt v podstate len datova struktura (najlepsie immutable). Samozrejme mozno som to len zle vyrozumel z clanku. Doporucoval by som teda ten obrazok aspon znazornit tak ako ma byt plus presne popisat ktora cast je presne za co zodpovedna.

add 2. Celkovo problem u MVC a PHP (ASP a JSP) je ten ze to viewu clovek moze narvat kod a casto ho tam aj narve. Par frameworkov ako Lift a aj vela programatorov to riesi ze na views pouzivaju templates mechanizmy.

Add 3. Priklanam sa k nazoru Andreja Sykoru. Dedicnost je u juniorov akosi zle chapana. Toto je nieco co dodnes nechapem. Kazda knizka o OOP zacina dedicnostou, kazda prednaska zacina dedicnostou. Potom kazdy vsetko riesi cez dedicnost. Ono si to mozno teraz clovek neuvedomi ale neskutocne si zavaris tym, ze vsetko naviazes na jedneho predka. Preco sa pri OOP nespomina golden rule 'Prefer composition over inheritance'? Obzvlast u frameworkov to plati.

Neber to ako utok ale skor ako konstruktivnu kritiku. Sam som implementoval MVC. Nebola to vec ktora mi zabrala 2 tyzdne ale stravil som pol roka len studovanim ako sa veci maju. Urobil som vela chyb a tiez sa mi to zo zaciatku zdalo ako jasna vec.Kazdopadne drzim palce. Zimplementovat MVC nieje lahka zalezitost. Studuj, skusaj, experimentuj, rad sa.

Sorrac za gramatiku.
0 0 Vladimir Poluch 10.8.2011 22:11:54
nie som v MVC moc peceny vareny, no pripojenie na db v controlleri nepotrebujes z toho titulu ze vybery z db by mal managovat vyhradne model. No je to len moj skormny nazor a vlastne chapanie MVC :) Inak vela zdaru v programovani :) clanok ma zaujal hlavne svojou jednoduchostou, ktora niekedy urcitym veciam chyba :)
0 0 Ike Sallas 10.8.2011 17:11:36
Andrej, prepáč za kritiku, ale podľa toho, ako si reagoval na výčitky pána Knesla, nemáš vôbec poňatie o princípoch OOP a tým pádom Tvoj článok viac mätie ako pomáha.

Trieda Framework reprezentuje základňu frameworku, akési prostredie, environment, OK. Ako môžeš potom z tejto triedy odvodiť triedu, ktorá reprezentuje model, čiže nástroj na získavanie dát, a controller, čiže nástroj kontrolujúci určitú funkčnú časť aplikácie? To sú 3 úplne iné objekty, ktoré nemôžu mať jedného spoločného predka, pokiaľ sa teda nejedná o nejakú základnú definíciu objektu s pomocnými metódami. (o čo sa v Tvojom prípade nejedná)

Skúsim príklad. Je to ako by si napísal triedu Les, z ktorej si potom odvodil triedy Zviera a Búrka. Tri úplne rozdielne veci.

K ostatným veciam sa nejdem vyjadrovať, pretože práve chyby v návrhu mi prídu ako hlavný problém celého článku.
0 0 Andrej Mihaliak 10.8.2011 13:24:33
Ďakujem za ohlasy k článku, je to môj prvý článok čo sa týka oop, je to na zorientovanie sa v oop a mvc patterne.Framework sa dá určite ešte vylepšiť ale myslím si že keď niekto hľadá niečo podobné tak php určite do nejakej znalosti pozná a vie si tam dorobiť poprípade prerobiť určité veci.

@Jiri Knesl:
1) myslel som si to tiež ale ak sa robí framework je veľká pravdepodobnosť že bude pracovať aj z nejakou tou databázou, a preto som ho extendoval aj do controlleru aj do modelu, stačí ak si potom do konštrunktora frameworku dá napojenie do db

2) tento článok ukazuje ako ho urobiť najjednoduchšie čo sa týka toho že by si chcel robiť nejaké triedy ktoré niesu controller tak by sa to dalo určite nejako ochrániť to si možno ukážeme nabudúce :) ak nejaké bude

3) 4) 5) 6) 7) myslím si že k tomu nieje nič dodať každý si predsta môže framework upraviť podľa seba, je to len ukážka ako si ho urobiť nikde nieje písané že ho musí tiež používať :)

8) myslím si že to tam má čo robiť, aj kebyže to máš v nejakom inom adresáry ako je root tak by sa tam mohol kto koľvek dostať,táto podmienka to chrány aby sa k tomu nedostalo nijak inak ako cez indexovú stránku

9) je to môj prvý článok tak dúfam že sa zlepším

BTW: dík za kritiku
0 0 Moďerný Občan 10.8.2011 11:59:35
ja osobne by som to skor riesil takto: sprintf($lang['welcome'], $nick, $firstname, $lastname);

Ked uz framework, tak poriadne poodelovat jednotlive vrstvy.
0 0 Juraj Mikláš 10.8.2011 11:56:46
bola to len rada, ziadny problem, casto si hosting nevyberas.
co sa tyka prehladnosti (a myslim ze i rychlosti) mam pocit ze to teda neni nic moc ani s nimi, ak to editor vie highlightnut ide to aj takto:
echo "Hello $nick <small>($firstname $surname)</small>";
0 0 Moďerný Občan 10.8.2011 11:47:17
ad shorttagy.. odporcovia, mate pocit, ze <?php echo 'nieco';?> je lepsie a prehladnejsie nez <?='nieco'?> ? Ja nie. To, ze na niektorych hostingoch su vypnute je pravda, ale do takeho hostingu predsa nepoleziem nie? A shorttagy sa pouzivaju aj tak len vo viewoch (btw aj CI nabada k ich pouzivaniu), takze aky problem?
0 0 Juraj Mikláš 10.8.2011 09:38:49
@Matúš pochybné hostingy so shortagmi nemajú problém, s ich vypnutím som sa naopak stretol na serverovej farme jednej z najväčších internetových spoločností na Slovensku.
0 0 Jiri Knesl 10.8.2011 09:14:53
Tento kód je úplně špatně.
1) není důvod extendovat třídu framework
2) podstrčím-li do URL název nějaké třídy, která není controller, dostanu 500
3) metody jsou příliš dlouhé
4) není zde žádná štábní kultura, občas je název třídy velký, občas malý
5) volani die() způsobí, že se na kód nedají napsat testy, správně by se měla vyhodit vyjímka, controller by měl mít nějaký dispatch, který ji odchytí
6) není důvod, proč neloadovat modely a controllery přes autoloading
7) extract($view_data, EXTR_PREFIX_SAME, "wddx"); - má zkontrolovat spíš zakázané indexy a vyhodit vyjímku, takhle se člověk nedozví, proč se jeho proměnná nepřevedla (resp.prefixovala nějakým nesmyslem, jaký nikdy neuhodne)
8) to if(!defined("BASE_PATH")) exit("No direct script access allowed"); tam taky nemá co dělat, aplikace má být mimo Document Root
9) komentáře nejsou často správně použity, nejhorší je snad: // metóda ktorá vypíše dáta - ta metoda nic nevypisuje, jen vrací
0 0 Michal Mišiak Kvasničák 10.8.2011 00:30:04
Hmm, jedine co ma zaujalo je, preco triedy model aj controller rozsiruju Framework. Nejak mi to unika :) Ale inac je to pekne ako ludom priblizit MVC. :)
0 0 Matúš Jančík 10.8.2011 00:27:25
Clanok je super, este by som urcite prioritne obsah view suboru, tlacil do layoutu, alebo aspon view vypisoval uplne po zbehnuti controllera.

ob_start();
include_once $view;
$content=ob_get_clean();

Daju sa tak lepsie zachytit pripadne chyby vo view a hlavne aj ovplyvnit layout (nastavenie title, pridanie .css .js a pod.)

Ale clanok urcite trochu pomoze zorientovat sa v zlozitejsich MVC frameworkoch.

Co sa tyka shorttags, ja ich pouzivam rovnako ako andrej a verim, ze keby svoj framework zacal profesionalne pouzivat, alebo ho dokoncil a otvoril svetu tak popri pisani komentarov by si aj tie tagy opravil. Dovtedy usetreny cas moze venovat do dalsieho programovania a najma pisania clankov.
0 0 lukas 9.8.2011 23:21:32
@Matus sorry man aj tak nesuhlasim s tebou :-D ale aby som sa tu len nestazoval tak clanok je fajn, skoda, ze som take nevidel pred par rokmi ked som zacinal kodit

tu je tiez fajny tutorial ako na vlastny FW http://net.tutsplus.com/tutorials/php/creating-a-php5-framework-part-1/
0 0 Matúš Koprda 9.8.2011 23:13:23
@Lukas Zend Framework ich pouziva vo velkom, pokial viem :) A nie, fakt nie su, ani nebudu deprecated, iba ich nepodporuju niektore pochybne hostingy (to moze byt jediny dovod preco ich nepouzit). Podla mna setria cas, usetris 7 znakov pri kazdom vypise.. a vypisov byva mrte.
Zajtra.sk > Programovanie > PHP > Tvorba MVC Frameworku


Kritika

Vieš ako robiť veci lepšie? Pomôž našim odvážnejším členom a skritizuj im projekty!

Reklama

Seriály zo Zajtra.sk

Reklama