MVC w praktyce tworzymy system artykułów. cz. 1 Tworząc różnego rodzaju aplikacje natrafiamy na poważny problem utrzymania dobrej organizacji kodu przejrzystej oraz łatwej w rozbudowie. Z pomocą przychodzą nam wzorce projektowe, które wymuszają na nas pewną organizację kodu aplikacji. W świecie aplikacji www najbardziej popularny jest wzorzec MVC. Jego ideę pokażę w praktyce pisząc prosty system artykułów. Żeby w pełni zrozumieć ideę tego wzorca projektowego czytelnik musi mieć solidne podstawy znajomości PHP oraz potafić programować obiektowo. Trochę teorii... Model-View-Controller został zaprojektowany w 1979 roku przez norweskiego programistę Trygve Reenskaug pracującego wtedy nad językiem Smalltalk w laboratoriach Xerox i początkowo nosił nazwę Model-View-Editor. Ideą tego wzorca jest rozdzielenie kodu odpowiedzialnego za przetworzenie danych od kodu odpowiedzialnego za ich wyświetlanie. Model-View-Controller zakłada podział aplikacji na trzy główne części: Model - jest pewną reprezentacją problemu bądź logiki aplikacji. Widok - opisuje, jak wyświetlić pewną część modelu w ramach interfejsu użytkownika. Kontroler - przyjmuje dane wejściowe od użytkownika i reaguje na jego poczynania, zarządzając aktualizacje modelu oraz odświeżenie widoków. Brzmi strasznie, ale w praktyce okazuje się, że to wcale nie jest takie trudne... No to zaczynamy! Na samym początku stwórzmy szkielet katalogów: config/ controller/ model/ view/ templates/ Mając hierarchię katalogów stwórzmy szkielet plików wzorca MVC: controller/controller.php / @author Łukasz Socha <> @version: 1.0 1/12
@license http://www.gnu.org/copyleft/lesser.html / / This class includes methods for controllers. @abstract / abstract class Controller{ / It redirects URL. @param string $url URL to redirect @return void / public function redirect($url) { / It loads the object with the view. @param string $name name class with the class @param string $path pathway to the file with the class @return object / public function loadview($name, $path='') { / It loads the object with the model. @param string $name name class with the class @param string $path pathway to the file with the class @return object / public function loadmodel($name, $path='') { model/model.php 2/12
/ @author Łukasz Socha <> @version: 1.0 @license http://www.gnu.org/copyleft/lesser.html / / This class includes methods for models. @abstract / abstract class Model{ / object of the class PDO @var object / protected $pdo; / It sets connect with the database. @return void / public function construct() { / It loads the object with the model. @param string $name name class with the class @param string $path pathway to the file with the class @return object / public function loadmodel($name, $path='') { / It selects data from the database. @param string $from Table @param <type> $select Records to select (default (all)) @param <type> $where Condition to query @param <type> $order Order ($record ASC/DESC) @param <type> $limit LIMIT 3/12
@return array / public function select($from, $select='', $where=null, $order=null, $limit=null) { view/view.php / @author Łukasz Socha <> @version: 1.0 @license http://www.gnu.org/copyleft/lesser.html / / This class includes methods for views. @abstract / abstract class View{ / It loads the object with the model. @param string $name name class with the class @param string $path pathway to the file with the class @return object / public function loadmodel($name, $path='') { / It includes template file. @return void / public function render() { / It sets data. @param string $name 4/12
@param mixed $value @return void / public function set($name, $value) { / It gets data. @param string $name @return mixed / public function get($name) { Pliki te zawierają zarys podstawowych metod, które wykorzystamy w tworzeniu systemu artykułów używając wzorca Model-View-Controller. Klasy oznaczyłem jako abstrakcyjne, gdyż będą one dziedziczone po bardziej specjalistycznych elementach wykonujących już konkretne czynności. W dalszej części będziemy je sukcesywnie wypełniać kodem. Tworzenie kodu aplikacji zacznijmy od controller/controller.php / @author Łukasz Socha <> @version: 1.0 @license http://www.gnu.org/copyleft/lesser.html / / This class includes methods for controllers. @abstract / abstract class Controller{ / It redirects URL. @param string $url URL to redirect @return void / 5/12
public function redirect($url) { header("location: ".$url); / It loads the object with the view. @param string $name name class with the class @param string $path pathway to the file with the class @return object / public function loadview($name, $path='view/') { $path=$path.$name.'.php'; $name=$name.'view'; try { if(is_file($path)) { require $path; $ob=new $name(); else { throw new Exception('Can not open view '.$name.' in: '.$path); catch(exception $e) { echo $e->getmessage().'<br /> File: '.$e->getfile().'<br /> Code line: '.$e->getline().'<br /> Trace: '.$e->gettraceasstring(); exit; return $ob; / It loads the object with the model. @param string $name name class with the class @param string $path pathway to the file with the class @return object / public function loadmodel($name, $path='model/') { $path=$path.$name.'.php'; $name=$name.'model'; try { if(is_file($path)) { require $path; 6/12
$ob=new $name(); else { throw new Exception('Can not open model '.$name.' in: '.$path); catch(exception $e) { echo $e->getmessage().'<br /> File: '.$e->getfile().'<br /> Code line: '.$e->getline().'<br /> Trace: '.$e->gettraceasstring(); exit; return $ob; Metoda redirect() służy do przekierowania strony na wskazany adres. Z kolei metody loadmodel() i loadview() inicjują obiekty klas widoku oraz modelu. Plik model/model.php będzie wyglądać tak: / @author Łukasz Socha <> @version: 1.0 @license http://www.gnu.org/copyleft/lesser.html / / This class includes methods for models. @abstract / abstract class Model{ / object of the class PDO @var object / protected $pdo; / It sets connect with the database. @return void / 7/12
public function construct() { try { require 'config/sql.php'; $this->pdo=new PDO('mysql:host='.$host.';dbname='. $dbase, $user, $pass); $this->pdo->setattribute(pdo::attr_errmode, PDO::ERRMODE_EXCEPTION); catch(dbexception $e) { echo 'The connect can not create: '. $e- >getmessage(); / It loads the object with the model. @param string $name name class with the class @param string $path pathway to the file with the class @return object / public function loadmodel($name, $path='model/') { $path=$path.$name.'.php'; $name=$name.'model'; try { if(is_file($path)) { require $path; $ob=new $name(); else { throw new Exception('Can not open model '.$name.' in: '.$path); catch(exception $e) { echo $e->getmessage().'<br /> File: '.$e->getfile().'<br /> Code line: '.$e->getline().'<br /> Trace: '.$e->gettraceasstring(); exit; return $ob; / It selects data from the database. @param string $from Table 8/12
@param <type> $select Records to select (default (all)) @param <type> $where Condition to query @param <type> $order Order ($record ASC/DESC) @param <type> $limit LIMIT @return array / public function select($from, $select='', $where=null, $order=null, $limit=null) { $query='select '.$select.' FROM '.$from; if($where!=null) $query=$query.' WHERE '.$where; if($order!=null) $query=$query.' ORDER BY '.$order; if($limit!=null) $query=$query.' LIMIT '.$limit; $select=$this->pdo->query($query); foreach ($select as $row) { $data[]=$row; $select->closecursor(); return $data; Konstruktor klasy Model ma nawiązać połączenie z bazą danych (używamy do tego PDO). Metoda loadmodel() ma za zadanie stworzyć obiekt z klasą modelu. Natomiast select() będziemy używać do pobieranie danych. Dodajmy jeszcze kod do pliku view/view.php: / @author Łukasz Socha <> @version: 1.0 @license http://www.gnu.org/copyleft/lesser.html / / This class includes methods for views. @abstract / abstract class View{ / 9/12
It loads the object with the model. @param string $name name class with the class @param string $path pathway to the file with the class @return object / public function loadmodel($name, $path='model/') { $path=$path.$name.'.php'; $name=$name.'model'; try { if(is_file($path)) { require $path; $ob=new $name(); else { throw new Exception('Can not open model '.$name.' in: '.$path); catch(exception $e) { echo $e->getmessage().'<br /> File: '.$e->getfile().'<br /> Code line: '.$e->getline().'<br /> Trace: '.$e->gettraceasstring(); exit; return $ob; / It includes template file. @param string $name name template file @param string $path pathway @return void / public function render($name, $path='templates/') { $path=$path.$name.'.html.php'; try { if(is_file($path)) { require $path; else { throw new Exception('Can not open template '. $name.' in: '.$path); 10/12
catch(exception $e) { echo $e->getmessage().'<br /> File: '.$e->getfile().'<br /> Code line: '.$e->getline().'<br /> Trace: '.$e->gettraceasstring(); exit; / It sets data. @param string $name @param mixed $value @return void / public function set($name, $value) { $this->$name=$value; / It gets data. @param string $name @return mixed / public function get($name) { return $this->$name; Metoda loadmodel() działa tak samo jak w poprzednich plikach. Metodę render() będziemy wykorzystywać do dołączania plików z kodem HTML. Tworzymy tabele bazy danych Na zakończenie tej części stwórzmy tabele kategorii i artykułów w bazy danych: CREATE TABLE categories( id integer auto_increment, name varchar(100), primary key(id) ); CREATE TABLE articles( id integer auto_increment, title varchar(100), 11/12
content text, date_add datetime, autor varchar(100), id_categories integer, primary key(id), foreign key(id_categories) references categories(id) ); W pliku config/sql.php zapiszmy dane dostępu do bazy danych. $host='localhost'; $dbase='baza danych'; $user='user'; $pass='hasło'; W kolejnej części cyklu zaczniemy już dokładniej poznawać idee MVC. Stworzymy fragment aplikacji odpowiedzialny za dodawanie kategorii. 12/12