Introducere in Design Patterns – MVC (ultima parte)
0Am prezentat in ultimile doua articole ale acestui subiec toate articulatiile acestei sistem de lucru. Am evitat pe cat posibil folosirea celor trei termeni ce definesc sistemul MVC : Model, View, Controller. Articolul de astazi va fi o continuare a primei parti, ceva mai detaliata si va face legatura cu cea de-a doua, finalizand astfel un articol destul de dificil de digerat pentru unii. 🙂
Model
Modelul reprezinta partea de hard-programming, partea logica a aplicatiei. El are in responsabilitate actiunile si operatiile asupra datelor, autentificarea utilizatorilor, integrarea diverselor clase ce permit procesarea informatiilor din diverse baze de date.
class Model { protected $name; protected $table; function __construct() { $this->connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME); $this->name = get_class($this); $this->table = strtolower($this->name)."s"; } function __destruct() { } function __clone() { } function __toString() { $class = get_class($this); return $class; } }
Astfel, avem clasa „abstracta” Model creata. De acum avem nevoie de cateva clase care sa interactioneze cu bazele de date. Tutorialul va introduce doar o clasa creata special pentru interactiunea minima cu bazele de date de tip MySQL.
< ?php class MySQLQuery extends Model { /*** Declare instance ***/ private static $instance = NULL; /*** Database handler ***/ private $dbHandle = NULL; /*** Query Result ***/ private $qResult = NULL; /** * the constructor is set to private so nobody can create a new instance using new **/ private function __construct() { /*** maybe set the db name here later ***/ } private function __destruct() { $this->disconnect(); } /** Return DB instance or create intitial connection * @return self::instance * @access public static **/ public static function getInstance() { if(!self::$instance) { self::$instance = $this->connect(); } return self::$instance; } /** Connects to database * @param string $server IP * @param string $username is username which will be used to acces $database * @param string $password of the $username * @param string database name * @return void * @access public **/ public function connect($server, $user, $password, $database) { $this->dbHandle = @mysql_connect($server, $user, $password); if ($this->dbHandle != 0) { return (@mysql_select_db($database, $this->dbHandle)?TRUE:FALSE); } return FALSE; } /** Disconnects from database **/ public function disconnect() { return (@mysql_close($this->dbHandle)!=0); } /** Execute MySQL Query and return the result * @param string $query to be served * @return Mysql Query * @access public **/ public function query($query) { return mysql_query($query, $this->dbHandle); } /** Get number of rows **/ public function getNumRows() { return mysql_num_rows($this->qResult); } /** Free resources allocated by a query **/ public function freeResult() { mysql_free_result($this->qResult); } /** Get error string **/ public function getErrror() { return mysql_error($this->dbHandle); } } ?>
Trebuie subliniat faptul ca aceste clase Model pot fi de la sabloane de interactiune cu diverse baze de date, pana la sisteme de autentificare. Toate acestea vor face operatiile logice asupra aplicatiilor.
View
View-ul se ocupa de afisarea datelor, practic aceasta parte a programului va avea grija de cum vede end-userul informatia procesata de controller. O data ce functiile sunt executate de model, viewului ii sunt oferite rezultatele, iar acesta le va trimite catre browser. In general viewul este o mini-aplicatie ce ajuta la randarea unor informatii, avand la baza diverse template-uri. Un exemplu simplu de View-er este cel de mai jos, care proceseaza template-ul intr-un mod foate simplu. Practic, pentru a folosi variabilele prelucrate de Model si Controller vom seta o variabila in interiorul controllerului care va fi extrasa de Viewer.
class View { public $output = NULL; public $action = NULL; public $viewVars = array(); public $controller = NULL; public function __construct(&$controller,$action) { if(is_object($controller)) $this->controller = $controller; $this->action = $action; } public function render($file, $prefix = null) { if(!empty($prefix)) extract($this->viewVars, EXTR_PREFIX_ALL, $prefix); else extract($this->viewVars); ob_start(); //load necessary files if(file_exists($file)) require_once($file); else if(file_exists(APP_VIEW . DS . '404'. $this->controller->ext)) require_once(APP_VIEW . DS . '404'. $this->controller->ext); else require_once(LIB_TEMPLATES . DS . '404'. $this->controller->ext); $this->output = ob_get_contents(); return $this->output; } }
Controller
Controller-ul reprezinta creierul aplicatiei. Aceasta face legatura intre model si view, intre actiunile userului si partea decizionala a aplicatiei. In functie de nevoile utilizatorului, controllerul apeleaza diverse functii definite special pentru sectiunea de site in care se afla userul. Functia se va folosi de model pentru a prelucra (extrage, actualiza) datele, dupa care informatiile noi vor fi trimise catre view, ce le va afisa apoi prin template-uri.
class Controller extends Object { /** * The name of this controller. Controller names are plural, named after the model they manipulate. * @var string * @access public **/ public $name = NULL; /** * Stores the current URL, relative to the webroot of the application. * * @var string * @access public **/ public $here = NULL; /** * The name of the currently requested controller action. * * @var string * @access public **/ public $action = NULL; /** * Parameters received in the current request: GET and POST data, information * about the request, etc. * * @var array * @access public **/ public $params = NULL; /** * The handler of the View class this controller sends output to. * * @var string * @access public **/ public $view = NULL; /** * File extension for view templates. Defaults ".ftp". * * @var string * @access public **/ public $ext = '.php'; /** * Set to true to automatically render the view * after action logic. * * @var boolean * @access public **/ public $autoRender = TRUE; /** * Set to true to automatically render the layout around views. * * @var boolean * @access public **/ public $autoLayout = TRUE; /** * The output of the requested action. * @var string * @access public **/ public $output = NULL; /** * This controller's primary model class name. * * Example: For a controller named 'Comments', the modelClass would be 'Comment' * * @var string * @access public **/ public $model = NULL; /** * Contains variables to be handed to the view. * * @var array * @access public **/ public $viewVars = array(); /** * Constructor. * **/ public function __construct() { } /** * Destructor. * **/ public function __destruct() { if($this->autoRender == TRUE) { return $this->render($this->action, APP_VIEW . DS . $this->action . DS . $this->action .$this->ext); } } public function startProc() { $this->model =& new $this->model(); $this->view =& new View($this, $this->action); } /** * Saves a variable for use inside a view template. * @param $val1 $values that will be used inside a view template, if $val2 is array then val1 must be array of keys or key handler. * @param $val2 $values that will be used inside a view template. * @return void * @access public **/ public function set($val1 = NULL, $val2 = NULL) { if (is_array($val2) && !empty($val2)) { if(is_array($val1)) { $values = array_combine($val1,$val2); foreach ($values as $key => $val) $this->view->viewVars[$key] = $val; } else if(!empty($val1)) { $this->view->viewVars[$val1] = $val2; } } else if(!empty($val1) && !empty($val2)) { $this->view->viewVars[$val1] = $val2; } } /** * Instantiates the correct view class, hands it its data, and uses it to render the view output. * * @param string $action Action name to render * @param string $file File to use for rendering * @return string Full output string of view contents * @access public **/ public function render($file = null) { $this->beforeRender(); if($this->autoRender == TRUE) { $this->output = $this->view->render($file); $this->autoRender = FALSE; } return $this->output; } /** * Called after the controller action is run, but before the view is rendered. * * @access public **/ public function beforeRender() { } /** * @all controllers must contain an index method. * **/ function index() { } }
Functia set() este functia care trimite variabilele la view-er.
Exemplu de aplicatie in format MVC
Model
Vom folosi un model clasic, fara functii suplimentare privind interogarile.
< ?php class Index extends MysqlQuery { }
View
Acest template este defapt o variabila care se doreste a fi afisata. In controller setam variabila iar fisierul template o afiseaza imediat ce este randata de viewer.
< ?php echo $variabilatest; ?>
1. Controllerul
< ?php class IndexController extends Controller { function test() { $this->set('variabilatest','salut'); } } ?>