You are on page 1of 13

Model View Controller MVC

by Kevin Waterson

Contents
1. 2. 3. 4. 5. #. $. %. &. 1'. 11. 12. 13. Abstract What is MVC The Site Structure The index file The e!istr" The Model The outer The Controller The View Te()lates Sod this* ta+e (e to the download Conclusion Credits

Abstract
Model View Controller. This tutorial will ta+e "ou fro( the be!innin! to the end of buildin! a MVC fra(ewor+. The ob,ect is not sole" to )roduce the finished MVC fra(ewor+* althou!h that will ha))en* but to de(onstrate how MVC wor+s and so(e of the conce)ts that la" behind it..

What is MVCMVC is a desi!n )attern. A .esi!n )attern is a code structure that allows for co((on codin! fra(ewor+s to be re)licated /uic+l". 0ou (i!ht thin+ of a desi!n )attern as a s+eleton or fra(ewor+ on which "our a))lication will be built. 1n the MVC fra(ewor+ that is created in this tutorial* se2eral +e" )oints will be raised. The first is the fra(ewor+s needs a sin!le )oint of entr"* ie3 index.)h). This is where all access to the site (ust be controlled fro(. To ensure that a sin!le )oint of entr" is (aintained* htaccess can be utili4ed to ensure no other file (a" be accessed* and that we hide the index.)h) file in the url. Thus creatin! S56 and user friendl" 7 89s. 1t is be"ond the sco)e of this tutorial to show how to set u) htaccess and (od:rewrite and (ore infor(ation on these can be !ained fro( the A)ache (anual. The .htaccess file itself loo+s li+e this. ewrite5n!ine on ewriteCond ;< 5=75ST:>185?AM5@ ABf ewriteCond ;< 5=75ST:>185?AM5@ ABd ewrite ule CD.EFG index.)h)-rtHG1 I8*=SAJ The .htaccess file will )er(it access to the site 2ia urls such as htt)3KKwww.exa()le.co(KnewsKshow 1f "ou do not ha2e (od:rewrite a2ailable* the entr" to the site will be the sa(e* exce)t that the 7 8 will contain the 2alues needed such as3 htt)3KKwww.exa()le.co(Kindex.)h)-rtHnewsKshow

The Site Structure

1n this tutorial se2eral directories are re/uired to hold the 2arious co()onents that (a+e u) the MVC fra(ewor+. The index.)h) and the .htaccess files will* of course* reside at the to) le2el. We will need a director" to hold the a))lication code* and directories for the (odel 2iew and controllers. The site structure should loo+ li+e this3 ht(l a))lication controller includes (odel 2iews .htaccess index.)h)

The 1ndex >ile


As )re2iousl" (entioned* the index.)h) file is our sin!le )oint of access. As such* it )ro2ides the ideal s)ace for declarin! 2ariables and site wide confi!urations. 1t is in this file that we will also call a hel)er file to initiali4e a few 2alues. This file will be called init.)h) and it will be )laced in includes director" as shown in the direcor" structure. The index file therefore* will be!in li+e this3

<?php /*** error reporting on ***/ error_reporting(E_ALL); /*** define the site path constant ***/ $site_path = realpath(dirname(__F LE__)); define (!__" #E_$A#%!& $site_path); /*** incl'de the init(php file ***/ incl'de !incl'des/init(php!; ?)
The index.)h) file so far onl" sets the error re)ortin!* includes the init file* and defines the site )ath constant. With this file in )lace* and the .htaccess file we can be!in to build the re!istr". 1n this MVC fra(ewor+* the re!istr" ob,ect is )assed to other ob,ects and contains site wide 2ariables without the the use !lobals. To create a new re!istr" ob,ect* we use the init.)h) file in the includes director". 6f course* to create new ob,ect we need to include the re!istr" class definition file. .urin! the buildin! of the MVC fra(ewor+ we will be includin! the a))lication class files directl". An" LML class definition files which are used b" the (odel will be autoloaded as the" can beco(e /uite cu(berso(e with lar!er a))lications. To alle2iate so(e of this LML has the ::autoload function to hel) us out. After the a))lication includes* the ::autoload function will i((ediatel" follow to load class definition files auto(aticall" when the" are re/uired b" the s"ste(. That is* when thenew +e"word is used. The class definitions will be stored in a director" called (odel. The includesKinit.)h) file should now loo+ li+e this.

<?php /*** incl'de the controller class ***/

incl'de __" #E_$A#% ( !/application/! ( !controller_*ase(class(php!; /*** incl'de the registr+ class ***/ incl'de __" #E_$A#% ( !/application/! ( !registr+(class(php!; /*** incl'de the ro'ter class ***/ incl'de __" #E_$A#% ( !/application/! ( !ro'ter(class(php!; /*** incl'de the template class ***/ incl'de __" #E_$A#% ( !/application/! ( !template(class(php!; /*** a'to load model classes ***/ f'nction __a'toload($class_name) , $filename = strtolo-er($class_name) ( !(class(php!; $file = __" #E_$A#% ( !/model/! ( $filename; if (file_e.ists($file) == false) , ret'rn false; / incl'de ($file); / /*** a ne- registr+ o*0ect ***/ $registr+ = ne- registr+; ?)
Mere is should be noted that the autoload function uses a na(in! con2ention for the class definition files to be included. The" (ust all follow the con2ention of endin! in .class.)h) and the class na(e (ust be that of the .class.)h) file na(e. So that to create a new NnewsN ob,ect the class definition file na(e (ust be news.class.)h) and the class (ust be na(ed NnewsN. With these files in )lace we are well on the wa"* howe2er our MVC does not do an"thin! "et. 1n fact* if "ou tried to access the index.)h) file now* "ou would !et (an" errors about (issin! files. Mostl" fro( the files in the a))lication director". So* lets be!in b" creatin! those files each can be blan+ or si()l" contain

<?php ?)
The files to create in the a))lication director" are3

controller:base.class.)h) re!istr".class.)h) router.class.)h) te()late.class.)h)

?ote that althou!h these files are not autoloaded* we ha2e still (aintained the sa(e na(in! con2ention b" callin! the files .class.)h)

The e!istr"

The re!istr" is an ob,ect where site wide 2ariables can be stored without the use of !lobals. O" )assin! the re!istr" ob,ect to the controllers that need the(* we a2oid )ollution of the !lobal na(es)ace and render our 2ariables safe. We need to be able to set re!istr" 2ariables and to !et the(. The )h) (a!ic functions ::setDF and ::!etDF are ideal for this )ur)ose. So* o)en u) the re!istr".class.)h) in the a))lications director" and )ut the followin! code in it3

<?php 1lass 2egistr+ , /* * 3the 4ars arra+ * 3access pri4ate */ pri4ate $4ars = arra+();

/** * * 3set 'ndefined 4ars * * 3param string $inde. * * 3param mi.ed $4al'e * * 3ret'rn 4oid * */ p'*lic f'nction __set($inde.& $4al'e) , $this5)4ars6$inde.7 = $4al'e; / /** * * 3get 4aria*les * * 3param mi.ed $inde. * * 3ret'rn mi.ed * */ p'*lic f'nction __get($inde.) , ret'rn $this5)4ars6$inde.7; /

/ ?)
With the re!istr" in )lace* our s"ste( is wor+in!. 1t does not do an"thin! or dis)la" an"thin!* but we ha2e a functional s"ste(. The ::setDF and ::!etDF (a!ic function now allow us to set 2ariables within the re!istr" and store the( there. ?ow to add the Model and router classes.

The Model
The Model is the NMN in MVC. The (odel is where business lo!ic is stored. Ousiness lo!ic is loosel" defined as database connections or connections to data sources* and )ro2ides the data to the controller. As 1 a( a fan of CAV DController Action ViewF we will blur the line between the Model and Controller. This is not strictl" how MVC should wor+* but this is LML bab". 6ur database connection is a si()le sin!leton desi!n )attern and resides in the classes director" and can be called staticall" fro( the controller and set in the re!istr". Add this code to the init.)h) file we created earlier.

<?php /*** create the data*ase registr+ o*0ect ***/ $registr+5)d* = d*88get nstance(); ?)
8i+e all re!istr" (e(bers* the database is now !loball" a2ailabe to our scri)ts. As the class is a sin!leton we alwa"s !et the sa(e instance bac+. ?ow that re!istr" ob,ects can be created a (ethod of controllin! what is loaded is needed.

The outer
The router class is res)onsible for loadin! u) the correct controller. 1t does nothin! else. The 2alue of the controller co(es fro( the 7 8. The url will loo+ a li+e this3 htt)3KKwww.exa()le.co(Kindex.)h)-rtHnews or if "ou ha2e htaccess a(d (od:rewrite wor+in! li+e this3 htt)3KKwww.exa()le.co(Knews As "ou can see* the route is the rt 2ariable with the 2alue of news. To be!in the router class a few thin!s need to be set. ?ow add this code to the router.class.)h) file in the a))lication director".

<?php class ro'ter , /* * 3the registr+ */ pri4ate $registr+; /* * 3the controller path */

pri4ate $path; pri4ate $args = arra+(); p'*lic $file; p'*lic $controller; p'*lic $action; f'nction __constr'ct($registr+) , $this5)registr+ = $registr+; /
So it does not loo+ li+e (uch "et but is enou!h to !et us started. We can load the router into the re!istr" also. Add this code to the index.)h) file.

/*** load the ro'ter ***/ $registr+5)ro'ter = ne- ro'ter($registr+);


?ow that the router class can be loaded* we can continue with the router class b" addin! a (ethod to set the controller director" )ath. Add this bloc+ of code to the router.class.)h) file.

<?php /** * * 3set controller director+ path * * 3param string $path * * 3ret'rn 4oid * */ f'nction set$ath($path) , /*** chec9 if path i sa director+ ***/ if (is_dir($path) == false) , thro- ne- E.ception (! n4alid controller path8 :! ( $p ath ( !:!); / /*** set the path ***/ $this5)path = $path; /
And to set the controller )ath in the re!istr" is a si()le (atter of addin! this line to the index.)h) file

/*** set the path to the controllers director+ ***/ $ro'ter5)set$ath (__" #E_$A#% ( !controller!);
With the controller )ath set we can load the controller. We will create a (ethod to called loaderDF to !et the controller and load it. This (ethod will call a !etControllerDF (ethod that will decide which controller to load. 1f a controller is not found then it will default bac+ to the index. The loader (ethod loo+s li+e this.

<?php /** * * 3load the controller * * 3access p'*lic * * 3ret'rn 4oid * */ p'*lic f'nction loader() , /*** chec9 the ro'te ***/ $this5)get1ontroller(); /*** if the file is not there diaf ***/ if (is_reada*le($this5)file) == false) , echo $this5)file; die (!;<; =ot Fo'nd!); / /*** incl'de the controller ***/ incl'de $this5)file; /*** a ne- controller class instance ***/ $class = $this5)controller ( !1ontroller_!; $controller = ne- $class($this5)registr+); /*** chec9 if the action is calla*le ***/ if (is_calla*le(arra+($controller& $this5)action)) == false) , $action = !inde.!; / else , $action = $this5)action; /

/*** r'n the action ***/ $controller5)$action(); /


The !etController (ethod that the loaderDF (ethod calls does the wor+. O" ta+in! the route 2ariables fro( the url 2ia G:P5TI9rt9J it is able to chec+ if a contoller was loaded* and if not default to index. 1t also chec+s if an action was loaded. An action is a (ethod within the s)ecified controller. 1f no action has been declared* it defaults to index. Add the !etController (ethod to the router.class.)h) file.

<?php /** * * 3get the controller * * 3access pri4ate * * 3ret'rn 4oid * */ pri4ate f'nction get1ontroller() , /*** get the ro'te from the 'rl ***/ $ro'te = (empt+($_>E#6!rt!7)) ? !! 8 $_>E#6!rt!7; if (empt+($ro'te)) , $ro'te = !inde.!; / else , /*** get the parts of the ro'te ***/ $parts = e.plode(!/!& $ro'te); $this5)controller = $parts6<7; if(isset( $parts6?7)) , $this5)action = $parts6?7; / / if (empt+($this5)controller)) , $this5)controller = !inde.!; / /*** >et action ***/ if (empt+($this5)action))

, $this5)action = !inde.!; / /*** set the file path ***/ $this5)file = $this5)path (!/!( $this5)controller ( !(php!; / ?)

The Controller
The Contoller is the C in MVC. The base controller is a si()le abstract class that defines the structure of all controllers. O" includin! the re!istr" here* the re!istr" is a2ailable to all class that extend fro( the base controller. An indexDF (ethod has also been included in the base controller which (eans all controller classes that extend fro( it (ust ha2e an indexDF (ethod the(sel2es. Add this code to the controller.class.)h) file in the a))lication director".

<?php A*stract 1lass *ase1ontroller , /* * 3registr+ o*0ect */ protected $registr+; f'nction __constr'ct($registr+) , $this5)registr+ = $registr+; / /** * 3all controllers m'st contain an inde. method */ a*stract f'nction inde.(); / ?)
Whilst we are in the controller creatin! (ood* we can create an index controller and a blo! controller. The index controller is the s"te( default and it is fro( here that the first )a!e is loaded. The blo! controller is for an i(a!inar" blo! (odule. When the blo! (odule is s)ecified in the 7 8 htt)3KKwww.exa()le.co(Kblo! then the index (ethod in the blo! controller is called. A 2iew (ethod will also be created in the blo! controller and when s)ecified in the 7 8 htt)3KKwww.exa()le.co(Kblo!K2iew then the 2iew (ethod in the blo! controller will be loaded. >irst lets see the index controller. This will reside in the controller director".

<?php

class inde.1ontroller e.tends *ase1ontroller , p'*lic f'nction inde.() , /*** set a template 4aria*le ***/ $this5)registr+5)template5)-elcome = !@elcome to $%$2A BC1!; /*** load the inde. template ***/ $this5)registr+5)template5)sho-(!inde.!); / / ?)
The indexController class abo2e shows that the indexController extends the baseController class* thereb" (a+in! the re!istr" a2ailable to it without the need for !lobal 2ariables. The indexController class also contains the (andator" indexDF (ethod that ll controllers (ust ha2e. Within itn indexDF (ethod a 2ariable na(ed Nwelco(eN is set in the re!istr". This 2ariable is a2ailable to the te()late when it is loaded 2ia the te()lateBQshowDF (ethod. The blo!Controller class follows the sa(e for(at but has has one s(all addition* a 2iewDF (ethod. The 2iewDF (ethod is an exa()le of how a (ethod other than the indexDF (ethod (a" be called. The 2iew (ethod is loaded 2ia the 7 8 htt)3KKwww.exa()le.co(Kblo!K2iew

<?php 1lass *log1ontroller E.tends *ase1ontroller , p'*lic f'nction inde.() , $this5)registr+5)template5)*log_heading = !#his is the *log de.!; $this5)registr+5)template5)sho-(!*log_inde.!); /

p'*lic f'nction 4ie-(), /*** sho'ld not ha4e to call this here(((( F D BE ***/ $this5)registr+5)template5)*log_heading = !#his is the *log he ading!; $this5)registr+5)template5)*log_content = !#his is the *log co ntent!; $this5)registr+5)template5)sho-(!*log_4ie-!); /

/ ?)

The View
The View* as "ou (i!ht ha2e !uessed* is the V in MVC. The View contains code that relates to )resentation and )resentation lo!ic such as te()latin! and cachin!. 1n the controller abo2e we saw the showDF (ethod. This is the (ethod that calls the 2iew. The (a,or co()onent in the LML 6 MVC is the te()late class. The te()late.class.)h) file contains the class definition. 8i+e the other classes* it has the re!istr" a2ailable to it and also contains a ::setDF (ethod in which te()late 2ariables (a" be set and stored. The show (ethod is the en!ine roo( of the 2iew. This is the (ethod that loads u) the te()late itself* and (a+es the te()late 2ariables a2ailable. So(e lar!er MVC9s will i()le(ent a te()late lan!ua!e that adds a further la"er of abstraction fro( LML. Added la"ers (ean added o2erhead. Mere we stic+ with the s)eed of LML within the te()late* "et all the lo!ic sta"s outside. This (a+es it eas" for MTM8 (on+ies to create websites without an" need to learn LML or a te()late lan!ua!e. The te()late.class.)h) file loo+s li+e this3

<?php 1lass #emplate , /* * 3the registr+ * 3access pri4ate */ pri4ate $registr+; /* * 3Caria*les arra+ * 3access pri4ate */ pri4ate $4ars = arra+(); /** * * 3constr'ctor * * 3access p'*lic * * 3ret'rn 4oid * */ f'nction __constr'ct($registr+) , $this5)registr+ = $registr+; /

/** * * 3set 'ndefined 4ars * * 3param string $inde. * * 3param mi.ed $4al'e * * 3ret'rn 4oid * */ p'*lic f'nction __set($inde.& $4al'e) , $this5)4ars6$inde.7 = $4al'e; /

f'nction sho-($name) , $path = __" #E_$A#% ( !/4ie-s! ( !/! ( $name ( !(php!; if (file_e.ists($path) == false) , thro- ne- E.ception(!#emplate not fo'nd in !( $path); ret'rn false; / // Load 4aria*les foreach ($this5)4ars as $9e+ =) $4al'e) , $$9e+ = $4al'e; / incl'de ($path); /

/ ?)

Te()lates
The te()lates the(sel2es are basicall" MTM8 files with a little LML e(bedded. .o not let the se)aration ?a4i9s tr" to tell "ou that "ou need to ha2e full se)eration of MTM8 and LML. e(e(ber* LML is an e(beddable scri)tin! lan!ua!e. This is the sort of tas+ it is desi!ned for and (a+es an efficient te()latin! lan!ua!e. The te()late files belon! in the 2iews director". Mere is the index.)h) file.

<h?)<?php echo $-elcome; ?)</h?)

Well* that was )rett" a(a4in!.. ?ow for the blo!:index.)h) file.

<h?)<?php echo $*log_heading; ?)</h?)


And finall" the blo!:2iew.)h) file..

<h?)<?php echo $*log_heading; ?)</h?) <p)<?php echo $*log_content; ?)</p)


1n the abo2e te()late files note that the 2ariable na(es in the te()lates* (atch the te()late 2ariables created in the controller.

.ownload Source
The full source code for this MVC >ra(ewor+ is a2ailable for download here. htt)3KKwww.)h)ro.or!KdownloadsK(2cB'.'.4.tar.!4

Update
.ue to the )o)ulariit" of this tutorial and the fra(ewor+* a s(all side )ro,ect has been s)awned that builds on this tutorial and adds so(e )ractical functionalit". 7sers are reco((ended to !et the basics in this tutorial and (o2e on to the next le2el. See (ore at htt)3KK)h)ro.or!KsandboxKs+f and see how si()le and eas" MVC and a))lication de2elo)(ent can be.

Conclusion
1t is ho)ed that "ou ha2e found so(e insi!ht into how MVC wor+s whilst readin! this tutorial. The MVC >ra(ewor+ "ou ha2e build here should be used as a !uide onl"* althou!h it is a full" functional i()le(entation* it is left to the user to build on it and ta+e it to new hi!hts. 1f "ou are usin! this MVC in an" wa"* or ha2e corrections or i()ro2e(ents* si()l"contact us.

Credits
Than+s to Oill Mernande4 of Llano* Texas for errata.

You might also like