MVC-model PM-systeem
Deze avond zit ik mij wederom te verdiepen in OOP en ik kwam tot de ontdekking dat het 3-lagen systeem heel mooi werk. Maar ik weet niet zeker of ik het goed begrijp want ik heb er nu zoveel over gelezen dat ik de kluts een beetje kwijt ben.
Ik heb nu een situatie geschetst en mij vraag is wordt het MVC-model hier goed toegepast.
Het gaat om een PM systeem
ModelPM
+ getPMById(iId)
+ getAllPM()
+ SendPM($iFromUser, $iToUser, $sSubject, $sPm)
+ DeletePM($iId)
+ SetRead($iId)
+ SetUnread($iId)
ViewPM
+ Mijn basic Template parser of smarty oid
ControllerPM
De controllor 'bedenkt' welke actie er ondernomen moet worden (leidt hij bevoorbeeld af aan de get-waarden) en roept vervolgens deze actie's aan bij het model. Vervolgens propt hij de verkregen data zo in de view (template) en tádá, je werkt.
Op die manier kan je door simpelweg een andere view te nemen een xml bestand maken, een html bestand maken, etc.
Klopt dit?
Groetjes Freek
Zie je models als objecten. Een ModelPM stelt dan een PM voor en bevat dus alleen methods (acties) die op 1 PM toegespast kunnen worden. De method getAllPM() hoort dan dus ook niet thuis in dit model.
Bekijk dus nog eens goed welke models je nu hebt en welke je nog nodig hebt.
ModelPMLijst (weet ff geen andere naam ModelPMInbox miss?)
+ GetPMs($iUser)
+ etc
ModelPm
+ getPM(iId)
+ SendPM($iFromUser, $iToUser, $sSubject, $sPm)
+ DeletePM($iId)
+ SetRead($iId)
+ SetUnread($iId)
ViewBasic
+ Mijn basic Template parser of smarty oid
Maar dan kom ik niet helemaal uit de models, hoe zouden die eruit zien en welke methods zouden ze (minimaal) hebben?
Dan zou ik er een klasse naast maken, bijvoorbeeld PMMapper, beetje a la jouw ModelPMLijst, die vervolgens de PM's uit de database kan halen (en er instanties van PM van maakt, en die in een array teruggeeft) en PM-instanties in de database kan zetten. Je model bevat dan geen SQL, alleen maar controle over wie en hoe je PM object aangepast mag worden. Je Mapper bevat de SQL code en is verantwoordelijk voor het opslaan. Deze mapper is specifiek voor het model, maar niet voor de instantie. Je hebt dus maar 1 instantie van PMMapper nodig, waar je meerder instanties van verschillende PM's hebt.
Idee erachter is dat je op deze manier relatief gemakkelijk de manier van opslaan van een PM kan veranderen. Nu wordt hij bijvoorbeeld opgeslagen in een database, maar het kost niet veel moeite om hem zo aan te passen dat hij een IMAP server gebruikt om de PM's als echte emailtjes op te slaan en te versturen, of een HTTP webservice o.i.d. Dat zou slechts een kwestie zijn van een andere mapper-klasse gebruiken, je hoeft dan je model & de rest van je code amper aan te passen.
Voor je views kan je een template parser gebruiken, hoeft op zich niet. Je moet er gewoon voor zorgen dat er geen wijzigingen & data ophalen in de view gebeuren. Binnen de view alleen logica die verantwoordelijk is voor de presentatie van de data. Het maakt verder niet uit of het een template-parser is, of een aparte klasse die er een RSS feed van maakt via DOM. Ikzelf heb gewoon een kleine klasse die middels include & extract een PHP bestand inlaadt waarin je dan gewoon heel simpel echo $var kan doen. Wel zo simpel, zolang je jezelf in bedwang kan houden en niet de verkeerde logica op de verkeerde plek zet. Logica in je view kan je niet voorkomen (of je gaat heel omslachtig te werk) want je zal altijd lussen en if/else-statements nodig hebben.
Even uitgaande van een database is het versturen van een PM niets meer dan een nieuw record in een bepaalde tabel opslaan. Je zou er dus voor kunnen kiezen om de PM 'zichzelf' te laten versturen via een method zonder parameters in de PM klasse. Of zou je deze methode ook in de PMMapper klasse onderbrengen waarbij je de betreffende instantie van PM als parameter meegeeft?
Ik had vroeger altijd een link naar een instantie van de Mapper in de Model zitten, zodat je [Model]->save() kon doen. Maar ik gebruik nu gewoon [Mapper]->save([Model]) en dat is eigenlijk veel gemakkelijker dan [Model]->save() omdat je exact weet met welke mapper je te maken hebt, en er geen magic nodig is om de mapper in de model te krijgen.
Wat twijfelachtig zijn relaties. Stel dat een PM een ontvanger-property heeft, een User dus. Dan zou je een method kunnen maken die de bijbehorende instantie van het User-model teruggeeft (wel zo logisch) maar hoe moet het dan met mapper voor het user-model? Moet het PM-model een instantie hebben of opvragen van de User-mapper, of gebruik je een Registery-klasse die daarvoor zorgt? Of laat je de PM-mapper vanzelf de joins regelen zodat hij ook meteen de user ophaalt (waardoor je dus het User-model & het PM-model gaat mixen) Ik ben er nog niet helemaal uit, maar gebruik meestal de manier dat het PM-model via een registery of iets vergelijkbaars aan de User-mapper kan komen, en daar de User-instantie vandaan kan toveren. Het voordeel is dat alle User-model gerelateerde acties door de mapper gaan, en bij wijzigingen ik alleen deze hoef aan te passen, en het gemakkelijk is om hier dingen te optimaliseren en caches toe te voegen. Nadeel is dat het lastiger is om gebruik te maken van JOINS en de voordelen van een lekker ingewikkelde SQL query. Daar moet je dus een beetje afwegen.
Gewijzigd op 01/01/1970 01:00:00 door Jelmer -
Gewijzigd op 01/01/1970 01:00:00 door Jelmer -
Het idee is blijven liggen maar ik heb nu weer even tijd.
Hoe ik het nu in gedachten heb:
PMMapper
- aObjectenPm
+ __construct(PDO $oDb, $oGebruiker)
+ lijst($sMap = 'inbox') //outbox, prullebak
+ delete ($iId)
+ bekijken ($iId)
+ nieuw ($iNaar, $sOnderwerp, $sBericht)
// eventueel nog wat functies om bijv Gelezen weer op ongelezen te zetten
PM
- id
- van_id
- naar_id
- bericht
- onderwerp
- tijd
- status //ongelezen, gelezen, prullebak
+ __get($sVariabel, $mValue)
+ __set($sVariabel)
Zou dit een mooie opzet zijn? Tips? Iets veranderen?
Gewijzigd op 01/01/1970 01:00:00 door Citroen Anoniem Graag
PMMapper:
- (intern misschien iets van een soort cache-array)
- PDO $resource
+ __construct(PDO $resource)
+ getMessages($folder = 'inbox')
+ getMessageById($id)
+ getMessageOfUser(User $user)
+ put(PM $message)
en PM:
- id
- sender_id
- receiver_id
- subject
- message
- timestamp
- status
+ __construct(User $sender, User $reciever)
+ timestamp() -> geeft DateTime terug bijv.
+ receiver() -> geeft User object terug
+ sender() -> idem.
+ message()
+ setMessage($message)
+ markRead()
+ markDeleted()
Opslaan (en invoegen) gaat dan via $mapper->put(new PM(...)); (uiteraard stel je PM eerst in). Ik gebruik graag getters & setters omdat je dan objecten zoals DateTime achteraf kan aanmaken op basis van dat wat je vers uit de database hebt getrokken, en maak je dus alleen de objecten aan wanneer je ze ook werkelijk gebruikt. Daarnaast heb ik ze het liefst gewoon simpel in aparte methods, zodat je bij het maken van callbacks en andere situaties waar je de functienaam moet opgeven geen ingewikkelde constructies hoeft te maken.
Trouwens, is het handig om deleted als status in plaats van als map te definiëren? Het is nu onmogelijk om ongelezen berichten te hebben in je prullenmand :)
Gewijzigd op 01/01/1970 01:00:00 door Jelmer -
Gewijzigd op 01/01/1970 01:00:00 door Jelmer -