Autor wpisu: Łukasz Socha, dodany: 03.11.2011 19:00, tagi: oop, php, mvc
pobierz w .pdf(przeznaczone do wydruku)
W ostatniej części artykułu o wzorcu MVC stworzymy pozostałe elementy prostego systemu artykułów.
Dobrą praktyką przy budowaniu aplikacji z użyciem wzorca MVC jest „rozbicie” całego kodu na poszczególne, mniejsze moduły. W poprzedniej części stworzyliśmy fragmenty kodu do obsługi kategorii, teraz zajmiemy się artykułami.
Tworzymy kontroler artykułów
Na początek tworzymy kontroler controllers/articles.php:
<?php /** * @author Łukasz Socha <kontakt@lukasz-socha.pl> * @version: 1.0 * @license http://www.gnu.org/copyleft/lesser.html */ include 'controller/controller.php'; class ArticlesController extends Controller{ public function index() { $view=$this->loadView('articles'); $view->index(); } public function one() { $view=$this->loadView('articles'); $view->one(); } public function add() { $view=$this->loadView('articles'); $view->add(); } public function insert() { $model=$this->loadModel('articles'); $model->insert($_POST); $this->redirect('?task=articles&action=index'); } public function delete() { $model=$this->loadModel('articles'); $model->delete($_GET['id']); $this->redirect('?task=articles&action=index'); } }
I tu także przeanalizujmy reakcje dla następujących adresów URL:
- ?task=articles&action=index – zostanie wywołana metoda index(), która inicjuje obiekt widoku articles, następnie zostaje wywołana metoda index()
- ?task=articles&action=one – zostanie wywołana metoda one(), która inicjuje obiekt widoku articles, następnie zostaje wywołana metoda one()
- ?task=articles&action=add – zostanie wywołana metoda add(), która inicjuje obiekt widoku articles, następnie zostaje wywołana metoda add()
- ?task=articles&action=insert – zostanie wywołana metoda insert(), która inicjuje obiekt modelu articles, następnie zostaje wywołana metoda insert()
- ?task=articles&action=delete – zostanie wywołana metoda delete(), która inicjuje obiekt modelu articles, następnie zostaje wywołana metoda delete()
Musimy jeszcze zmodyfikować plik index.php, by skrypt wywoływał kontroler Articles:
<?php if($_GET['task']=='categories') { include 'controller/categories.php'; $ob = new CategoriesController(); $ob->$_GET['action'](); } else if($_GET['task']=='articles') { include 'controller/articles.php'; $ob = new ArticlesController(); $ob->$_GET['action'](); } else { $ob = new ArticlesController(); $ob->index(); }
Mamy już kontroler. Teraz przejdźmy do modelu.
Tworzymy model artykułów
model/articles.php:
<?php /** * @author Łukasz Socha <kontakt@lukasz-socha.pl> * @version: 1.0 * @license http://www.gnu.org/copyleft/lesser.html */ include 'model/model.php'; class ArticlesModel extends Model{ public function getAll() { $query="SELECT a.id, a.title, a.date_add, a.autor, c.name FROM articles AS a LEFT JOIN categories AS c ON a.id_categories=c.id"; $select=$this->pdo->query($query); foreach ($select as $row) { $data[]=$row; } $select->closeCursor(); return $data; } public function getOne($id) { $query="SELECT a.id, a.title, a.date_add, a.autor, c.name, a.content FROM articles AS a LEFT JOIN categories AS c ON a.id_categories=c.id where a.id=".$id; $select=$this->pdo->query($query); foreach ($select as $row) { $data[]=$row; } $select->closeCursor(); return $data; } public function insert($data) { $ins=$this->pdo->prepare('INSERT INTO articles (title, content, date_add, autor, id_categories) VALUES ( :title, :content, :date_add, :autor, :id_categories)'); $ins->bindValue(':title', $data['title'], PDO::PARAM_STR); $ins->bindValue(':content', $data['content'], PDO::PARAM_STR); $ins->bindValue(':date_add', $data['date_add'], PDO::PARAM_STR); $ins->bindValue(':autor', $data['author'], PDO::PARAM_STR); $ins->bindValue(':id_categories', $data['cat'], PDO::PARAM_INT); $ins->execute(); } public function delete($id) { $del=$this->pdo->prepare('DELETE FROM articles where id=:id'); $del->bindValue(':id', $id, PDO::PARAM_INT); $del->execute(); } }
Tak jak w przypadku kategorii, metody w ArticlesModel dodają, usuwają oraz poobierają dane z bazy danych.
Autor wpisu: Łukasz Socha, dodany: 27.10.2011 16:13, tagi: oop, php, mvc
pobierz w .pdf(przeznaczone do wydruku)
W drugiej części artykułu o wzorcu MVC stworzymy część skryptu, odpowiedzialną za obsługę kategorii.
Tworzymy kontroler kategorii
Na początek stwórzmy plik index.php w głównym katalogu:
<?php include 'controller/categories.php'; if($_GET['task']=='categories') { $ob = new CategoriesController(); $ob->$_GET['action'](); }
Na podstawie zmiennej $_GET['task'] tworzony jest odpowiedni obiekt kontrolera (w tym wypadku CategoriesController). Zmienna $_GET['action'] określa z kolei akcję kontrolera.
Co robi kontroler? Na podstawie przekazanych wartości zmiennych (z adresu lub pól formularza) „wybiera” odpowiednią akcję skryptu oraz inicjuje odpowiednie modele i widoki. Kontroler nie powinien obrabiać danych. Ma on za zadanie tylko wywoływać odpowiednie reakcje logiki aplikacji oraz widoku odpowiedzialnego za wyświetlanie informacji. Przyjrzyjmy się plikowi controller/categories.php:
<?php /** * @author Łukasz Socha <kontakt@lukasz-socha.pl> * @version: 1.0 * @license http://www.gnu.org/copyleft/lesser.html */ include 'controller/controller.php'; class CategoriesController extends Controller{ public function index() { $view=$this->loadView('categories'); $view->index(); } public function add() { $view=$this->loadView('categories'); $view->add(); } public function insert() { $model=$this->loadModel('categories'); $model->insert(&$_POST); $this->redirect('?task=categories&action=index'); } public function delete() { $model=$this->loadModel('categories'); $model->delete($_GET['id']);; $this->redirect('?task=categories&action=index'); } }
Przeanalizujmy reakcje dla następujących adresów URL:
- ?task=categories&action=index – zostanie wywołana metoda index(), która inicjuje obiekt widoku categories, następnie zostaje wywołana metoda index()
- ?task=categories&action=add – zostanie wywołana metoda add(), która inicjuje obiekt widoku categories, następnie zostaje wywołana metoda add()
- ?task=categories&action=insert – zostanie wywołana metoda insert(), która inicjuje obiekt modelu categories, następnie zostaje wywołana metoda insert()
- ?task=categories&action=delete – zostanie wywołana metoda delete(), która inicjuje obiekt modelu categories, następnie zostaje wywołana metoda delete()
Mamy już utworzony kontroler. Przejdźmy teraz do modelu.
Tworzymy model kategorii
Model jest najbardziej istotnym elementem we wzorcu MVC – to on jest odpowiedzialny za logikę aplikacji. Ma za zadanie pobieranie/edycję danych z bazy danych (lub innych źródeł) oraz przetworzenie ich według wymagań skryptu, np: poddać filtracji, wykonać obliczenia itp.
Przeanalizujmy plik model/categories.php:
Autor wpisu: Łukasz Socha, dodany: 20.10.2011 15:46, tagi: oop, php, mvc
pobierz w .pdf(przeznaczone do wydruku)
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:
Autor wpisu: Michal Wachowski, dodany: 27.01.2011 13:23, tagi: framework, mvc, php
Autor wpisu: cojack, dodany: 23.10.2009 09:08, tagi: php, mvc
Tak więc chciałbym rozwinąć swoją myśl w poprzednim wpisie dotyczącym mvc w php, o co mi tu chodzi oraz czy temat i kategoria ma się jakoś do treści tutaj przedstawionej. Otóż uważam że tak, wzorzec mvc jak samo rozwiniecie jego skrótu nam mówi, model, widok, kontroler. Chodzi o prezentacje kodu złożoną z warstw, i połączeniem tego z sobą, dobrze wiemy że kontroler czyli nasz cały mózg operacji powinien wywoływać metody z modelu do pobierania danych z bazy danych, tak że end user nie ma że tak powiem bezpośredniego dostępu do tej że warstwy prezentacji kodu, chyba że jesteśmy na tyle upośledzeni że nie zabezpieczymy sobie katalogów i struktura naszych katalogów pozwala użytkownikowi na przeglądanie zawartości katalogów gdzie mamy poskładane nasze klasy. W różnych książkach można spotkać różnie przedstawione formy zapisu nazewnictwa plików, *.phpm itp ale nie o tym chcę pisać, ponieważ dla mnie to powinno być na tyle intuicyjne i poprawne by nam później było łatwiej się odnaleźć w utworzonej przez nas aplikacji.
Wracając do tematu, bo wydaje mi się że trochę od niego odbiegłem, chciałbym rozwinąć swoją myśl przedstawioną w poprzednim poście (czuje jakbym się powtarzał…). Pisałem o tym że użytkownicy Doctrine dostali narzędzie i ogromnej mocy do utworzenia aplikacji zorientowanej obiektowo oraz o wzorzec MVC, i w cale nie chcę się z tego wycofać a poprzeć tą tezę argumentami.
Do czego bym zachęcał? Otóż by każdy zainteresowany pobrał sobie sandbox’a doctrine z strony projektu, standardowo linki na samym dole. Sandbox jest w pewnym stopniu za nas skonfigurowany, i jeżeli nie czujemy potrzeby modyfikacji jego ustawień proponowałbym zostawić układ taki jaki jest, chociażby dla samego tego artykułu. Ja go osobiście trochę przerobiłem na wzór układu katalogów z symfony ale nie ważne jest to teraz.
Pisałem o tym że nie będziemy musieli ładować w kontrolerach modułów a same widoki (widok), tak zakładam że jeden widok dla jednego kontrolera, jeden model dla jednego kontrolera. Wychodząc z założenia DRY ( Don’t Repeat Yourself ), jedna metoda dla jednej i tej samej akcji, bo po co się powtarzać?
Nie chciałbym by ten topic zszedł do tematu konfiguracji sandboxa, dlatego o konfiguracji Doctrine w innym temacie.
A teraz jak to nam uprzyjemnia życie? A dajmy na to że mamy jakiś kontroler, np HandlerNews
class HandlerNews extends EventHandler { private $_tpl; private $_handle; private $_lang; public function __construct($tpl,$event,$trans) { $this->_tpl = $tpl; $this->_handle = $event; $this->_lang = $trans->getLanguage(); } public function handledEvent($route) { if( $route[2] != '' && method_exists($this,$route[2]) ) { $this->_{$route[2]}(); } else throw new Exception ('Brak akcji'); } private function _show() { $news = Doctrine::getTable('News')->getNews(Route::getId(), $this->_lang); $this->tpl->assign('news',$news); } }
No i nasza metoda getNews wyglądała by mniej więcej tak (plik NewsTable.php):
class NewsTable extends Doctrine_Table { public function getNews( $id, $lang ) { $query = $this->createQuery( 'n' ) ->where( 'n.id = ?', $id) ->andWhere( 'n.lang = ?', $lang) ->execute(); return $query; } }
Oto całe nasze mvc, mamy model, który jest organizowany za pomocą doctrine, mamy plik kontrolera który sobie pobiera z bazy danych dane, wrzuca je do templatki no i jakoś tam musimy wykombinować żeby jeszcze templatke wczytywać, ale to już inna kwestia.
No więc jak widać implementacja takiego wzorca MVC nie jest trudna, i nie uprzykrzajcie sobie ludzie życia wymyślając nie wiadomo co, nie wiadomo jak złożone struktury katalogów jak to jest proste jak budowa cepa
Ja wiem że równie dobrze możemy sobie utworzyć klasę w której będziemy mieli standardowe zapytania do bazy danych np na PDO, z zwykłą składnią SQL’ową. Nikt nie broni, a nawet dlaczego nie? np:
Autor wpisu: cojack, dodany: 03.09.2009 14:02, tagi: mvc, php
Jak każdy tak i ja chcę swoje 3 grosze wrzucić do tego tematu, o czym chciałbym napisać, a o modelach, każdy dobrze wie czym jest mvc (nie czuje że rymuje), a jak nie to proszę wikipedia i tam jest bardzo ładnie opisane, tak więc co z tymi modelami, problem w tym że trzeba by te modele ładować w kontrolerach, albo przy dyspozytorze ładować kontroler, model i widok, ale można też to zrobić trochę inaczej, każdy kto się zdecydował na pracę z Doctrine, ma przecudowne narzędzie do utworzenia aplikacji zorientowanej obiektowo o wzorzec mvc, rozwiązującej problemy w pewnym stopniu z architekturą strukturalną plików i katalogów. A tak po ludzku to chodzi mi o to że Doctrine ładuje za nas modele bazy danych, czyli jak np za pomocą doctrine wygenerujemy modele z bazy danych, to Doctrine utworzy za nas 3 pliki dla każdej z tabel, oraz 1 katalog. Będzie to:
|-------------------------------- |- models/ |- - - generated/ |- - - - BaseArticles.php |- - Articles.php |- - ArticlesTable.php |--------------------------------
A taki przykład, i teraz dzięki Doctrine, w kontrolerach będziemy mogli bezpośrednio odwoływać się do metod w pliku ArticlesTable, a to jest tylko przedsmak tego co dzięki Doctrine jesteśmy w stanie zrobić. Przy następnym wpisie pokażę jak tego użyć, jak to zrobić. Może sami macie jakieś ciekawe propozycje, pomysły, czekam