MVC Pattern
Ik ben nu bezig om OOP te leren zoals je het echt zou moeten gebruiken. Geen classes met enkel proceduele code maar dingen echt als objecten zien.
Ik wil een gastenboek gaan maken volgens het MVC model. Ik heb nu het hele DB gedeelte(DB interface, DB class en 3 SQL classes(MySQL, MySQLi, PgSQL)) en de systemExceptionclass af.
Ook heb ik een mappenstructuur gemaakt:
* Includes
- Interfaces
- Classes
- Models
- Views
- Controllers
- JavaScript
- Styles
*
index.php
.htaccess
Nu heb ik hierover enkele vragen:
- Hoe moet ik een control-, model- en viewclass maken voor dat gastenboek?
- Ik heb eraan gedacht om een class Message te maken, dus elk bericht als een object. Dit lijkt mij toch niet helemaal de beste oplossing. Klopt dat?
- Hoe pak ik het aan met een TPL parser? Een TPL parser gebruiken zoals bijvoorbeeld Smarty, Template Power of er zelf 1 maken?
PS
Ik heb "CodeIgniter" en het "Zend Framework" beide bekeken en ik werd er niet veel wijzer van. Wel heb ik nu dit:
Class: guestbookController:
addMessage
editMessage
deleteMessage
getMessages
getAllMessages
Class: guestbookModel:
Class: guestbookView:
Maar verder kom ik helaas niet.....
Alvast bedankt!
Gewijzigd op 01/01/1970 01:00:00 door Gebruiker PHP
Quote:
- Hoe moet ik een control-, model- en viewclass maken voor dat gastenboek
Ik zou het als volgt doen:
De controller bevat de methods om berichten te plaatsen, weer te geven en te verwijderen. Dus zeg eens:
> showMessages()
> showMessage($messageId)
> editMessage(optioneel $messageId)
Meer heb je er niet echt nodig. editMessage() kan prima gebruikt worden voor het nieuw aanmaken van een bericht naar mijn idee. Gewoon een leeg Model voeren :)
Iedere method van de controller geeft een instantie van een klasse die de interface View implementeert terug. De interface View bevat maar 1 eis: de method 'draw'. Je kan nog wel wat meer eisen - ik eis zelf ook nog de functie isEmbedded bijvoorbeeld - maar dat is voor een gastenboek niet echt nodig.
De methods van de controller doen dus hun ding met de models - kom ik zo op terug bij je 2e vraag - en geven vervolgens een instantie van View terug - kom ik bij je 3e vraag op terug.
Quote:
- Ik heb eraan gedacht om een class Message te maken, dus elk bericht als een object. Dit lijkt mij toch niet helemaal de beste oplossing. Klopt dat?
Zou ik wel doen. Iedere instantie van Message representeert dan een bericht, en dus een enkele regel in de database. Of nog niet :) Je Model, Message in dit geval bevat in ieder geval 2 methods: save() en delete(). Dezen voeren de query uit die het bericht opslaat of invoert, of verwijdert. De Model is dus in staat zichzelf toe te voegen en te verwijderen uit de database.
Verder bevat de Model properties die gelijk zijn aan de veldnamen van de tabel in de database. Ik zou trouwens Message::$id wel even protected maken, en een method id() of ROWID() toevoegen om deze uit te kunnen lezen. Zo is het onmogelijk om die van buiten te veranderen - zoals het hoort.
Via je SQL klasse maak je dan voor iedere row in het resultaat een nieuwe instantie aan, of je kloont er eentje. PDO heeft daar bijvoorbeeld 'FETCH_CLASS' en 'FETCH_INTO' voor.
Quote:
- Hoe pak ik het aan met een TPL parser? Een TPL parser gebruiken zoals bijvoorbeeld Smarty, Template Power of er zelf 1 maken?
Een template parser is hoogstens een hulpmiddel om de amateur-modus van Dreamweaver te kunnen gebruiken, je medewerkers de vrijheid te ontnemen of op te scheppen, of om jezelf te leren presentatie van de rest te scheiden.
De view doet dat laatste ook wel, daarvoor kun je dus gewoon PHP gebruiken in je View, en hoef je op zich niet ingewikkeld te gaan doen met templates compilen.
Een voorbeeldje van een simpele View klasse:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php
interface View {
public function draw();
}
class SimpleView implements View {
protected
$_delegate,
$_template;
public function __construct($delegate = null)
{
if(is_object($delegate)) {
$this->_delegate = $delegate;
} else {
$this->_delegate = $this;
}
}
public function setTemplate($file)
{
$this->_template = $file;
}
public function __get($key)
{
return $this->_delegate->$key;
}
public function __isset($key)
{
return isset($this->_delegate->$key);
}
public function draw()
{
include $this->_template;
}
}
?>
interface View {
public function draw();
}
class SimpleView implements View {
protected
$_delegate,
$_template;
public function __construct($delegate = null)
{
if(is_object($delegate)) {
$this->_delegate = $delegate;
} else {
$this->_delegate = $this;
}
}
public function setTemplate($file)
{
$this->_template = $file;
}
public function __get($key)
{
return $this->_delegate->$key;
}
public function __isset($key)
{
return isset($this->_delegate->$key);
}
public function draw()
{
include $this->_template;
}
}
?>
Je controller maakt dus een instantie van die klasse aan, geeft hem vervolgens alle variabelen die je in je template wilt gebruiken mee. Of je geeft gewoon in 1 keer een $delegate mee, dan haalt hij daar zijn waarden weg.
Je template is dan gewoon een simpel PHP bestandje zoals deze:
met als controller dan dus bijvoorbeeld dit:
Code (php)
Roep je nu [TestController]->groet()->draw() aan, dan krijg je "Pindakaas" in grote letters te zien :) Alles mooi gescheiden, maar in dit voorbeeld gebruik ik nog geen Models.
Quote:
Maar verder kom ik helaas niet.....
Enige wat nu nog mist is iets dat de Controller aanroept: een Router. Een Router doet niets meer dan aan de hand van de opgevraagde URL dit uitvoeren:
Code (php)
1
2
3
4
5
2
3
4
5
<?php
$controllerInstance = new $controller();
$viewInstance = $controllerInstance->$method();
$viewInstance->draw();
?>
$controllerInstance = new $controller();
$viewInstance = $controllerInstance->$method();
$viewInstance->draw();
?>
Je kan hem nog wat uitbreiden en opsplitsen, bijvoorbeeld een 2e view erbij doen om de standaard-zooi te laten afhandelen. Stel je maakt er nog even een MainController bij:
Code (php)
met als index.phtml:
en als router:
Code (php)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
<?php
$mainControllerInstance = new MainController();
$controllerInstance = new $controller();
$viewInstance = $controllerInstance->$method();
$mainController->default($viewInstance)->draw();
?>
$mainControllerInstance = new MainController();
$controllerInstance = new $controller();
$viewInstance = $controllerInstance->$method();
$mainController->default($viewInstance)->draw();
?>
Gewijzigd op 01/01/1970 01:00:00 door Jelmer -
Allereerst bedankt voor je uitgebreide reactie! Helaas gaat een groot deel hiervan boven mijn pet.
Wel heb ik een aantal dingen geprobeerd en daar is dit uitgekoment: http://www.syncie.nl/Project%20-%20MVC.rar
Als je eens tijd hebt zou je het eens willen doornemen en vertellen waar ik verbeteringen kan aanbrengen?
- URL geupdate: 01/10/07 08:00 -
Alvast bedankt!
Gewijzigd op 01/01/1970 01:00:00 door Gebruiker PHP
http://www.cakephp.org kunnen kijken. Dit is een zeer snelle ruby on rails like ontwerpmethode. In eerste instantie gebruik je scaffolding: een methode om snel add/edit/delete/view methoden te maken. Vervolgens 'bake' je deze, en heb je een set aan views en controllers.
Je zou ook Ik vind het niets om andermans framework te gebruiken. Ik maak dingen liever zoveel mogelijk zelf. Toch bedankt voor je suggestie.
Ivo van B. schreef op 30.09.2007 19:37:
Ik heb nu het hele DB gedeelte(DB interface, DB class en 3 SQL classes(MySQL, MySQLi, PgSQL)) en de systemExceptionclass af.
Welke PHP versie draait er bij jou? Als je gebruik maakt van versie 5.1 (of nieuwer :P) Heb je beschikking over PHP Data Objects (PDO)
In plaats van zelf een class aan te maken voor de verschillende SQL versies, zou ik eens naar PDO kijken.
Klik voor een tut/uitleg
Gewijzigd op 01/01/1970 01:00:00 door Gebruiker PHP
Maar even over je RAR-bestandje. Tis een beetje lastig om daar nu echt commentaar op te leveren omdat iedereen MVC met z'n eigen draai doet.
Ik zie dat jij bijvoorbeeld de messages aan een guestbook wilt toevoegen via de controller, terwijl ik dit de message altijd zelf laat doen. De controller geeft hem alleen z'n waarden en roept save() aan.
Ook heb je een aparte view voor je guestbook, maar het is niet meer dan een standaard-oplossing. Het lijkt me niet echt toepasselijk om hem dan alleen voor je guestbook te gebruiken. De templates voor het guestbook zijn daarentegen wel weer specifiek.
Gewoon proberen en veel bij anderen afkijken, daar kom je een heel eind mee. Op een gegeven moment heb je dan, na een heleboel minder goeie implementaties een hele goeie implementatie.
Quote: "Ik zie dat jij bijvoorbeeld de messages aan een guestbook wilt toevoegen via de controller, terwijl ik dit de message altijd zelf laat doen. De controller geeft hem alleen z'n waarden en roept save() aan."
Ik volg je helaas niet helemaal. Zou je daar een klein voorbeeldje van kunnen maken.
Quote: "Ook heb je een aparte view voor je guestbook, maar het is niet meer dan een standaard-oplossing. Het lijkt me niet echt toepasselijk om hem dan alleen voor je guestbook te gebruiken. De templates voor het guestbook zijn daarentegen wel weer specifiek."
Jij adviseert dus dat ik 1 TPL parser-class moet maken i.p.v. er 1 speciaal voor het gastenboek?
Alvast bedankt
bump
En wat betreft dat add/delete e.d. Je geeft je Model, Message is jouw geval, de methods save en delete. Dezen zijn dan verantwoordelijk voor het daadwerkelijke toevoegen en verwijderen. Je controller heeft nog wel methods voor het bewerken, toevoegen en verwijderen, maar deze doen niets meer dan al dan niet de Model ophalen en de View klaarzetten.
Maar de edit/add method van de controller kan je samenvoegen op zich, het enige verschil is immers dat je bij add een leeg Model gebruikt, en bij edit een gevulde variant. Vervolgens roept de method save of delete van het Model aan waneer het formulier - wat in je template zit neem ik aan - is verstuurd.
Bedankt! En nog even die PDO vraag, "Ik heb mijn eigen Exceptionclass gemaakt, hoe kan ik die gebruiken i.p.v. een PDO Exception?".
Andere vraag: Waarom wil je je eigen exception-klasse gebruiken? Voor de display-functie die erin zit? Als het goed is is er maar 1 uitweg voor de Exception, maar 1 catch-blok waar hij uiteindelijk uit kan komen & naar de eindgebruiker zichtbaar gemaakt hoeft te worden. Het lijkt mij niet nodig om daar een functie voor te maken, aangezien je die maar 1 maal zal gebruiken. Je kan die code dan beter in dat catch-blok plaatsen.
Daarnaast, het voordeel van al de verschillende Exceptions is dat je selectief kan opvangen, en eventueel een alternatieve actie kan ondernemen.
wat een heerlijk taal gebruik:P
Johan Versteeg schreef op 03.10.2007 21:49:
heerlijk, snap der geen ene fuck van, hihi
wat een heerlijk taal gebruik:P
wat een heerlijk taal gebruik:P
Als je het wil begrijpen, vraag maar wat je niet begrijpt en ik doe mijn best het in Nijntje-taal uit te leggen.
Als je het gewoon leest voor het verdrijven van tijd, dan heb je geluk. Want je kan mijn verhaaltjes lezen zo vaak als je maar wilt, iedere keer zie je er weer iets anders staan, en snap je er nog geen zak van. Muhahahaha! >:)
Gewijzigd op 01/01/1970 01:00:00 door Jelmer -
Sjit he, ik wist niet dat je meerdere Exceptions kon catchen met 1 try-block. HArtstikke bedankt! Dat helpt me een stuk opweg.
@ Johan,
Ik moet het ook eerst een paar keer lezen voordat ik snap wat Jelmer zegt hoor:P