Model-View-Controller (MVC) is waarschijnlijk een van de meest geciteerde patronen in de web-programmeerwereld van de afgelopen jaren. Iedereen die momenteel werkt in alles wat verband houdt met de ontwikkeling van webtoepassingen, heeft het acroniem honderden keren gehoord of gelezen. Vandaag zullen we verduidelijken wat MVC betekent, en waarom het zo populair is geworden.
MVC is geen ontwerppatroon, het is een architecturaal patroon dat een manier beschrijft om onze applicatie en de verantwoordelijkheden en interacties voor elk onderdeel in die structuur te structureren.
Het werd voor het eerst beschreven in 1979 en de context was duidelijk een beetje anders. Het concept van webapplicatie bestond niet. Tim Berners Lee zaaide begin jaren negentig de zaden van World Wide Web en veranderde de wereld voor altijd. Het patroon dat we vandaag gebruiken voor webontwikkeling is een aanpassing van het oorspronkelijke patroon.
De wilde popularisering van deze structuur voor webapplicaties is te danken aan de opname in twee ontwikkelingskaders die immens populair zijn geworden: Struts en Ruby on Rails. Deze twee omgevingen markeerden de weg voor de honderden raamwerken die later werden gecreëerd.
Het idee achter het architectuurpatroon van Model-View-Controller is eenvoudig: we moeten de volgende verantwoordelijkheden duidelijk gescheiden hebben in onze toepassing:
De applicatie is onderverdeeld in deze drie hoofdcomponenten, die elk verantwoordelijk zijn voor verschillende taken. Laten we een gedetailleerde uitleg en een voorbeeld bekijken.
De controleur beheert de gebruikersaanvragen (ontvangen als HTTP GET of POST-aanvragen wanneer de gebruiker op GUI-elementen klikt om acties uit te voeren). De belangrijkste functie ervan is om de nodige middelen / objecten te bellen en coördineren die nodig zijn om de gebruikersactie uit te voeren. Gewoonlijk belt de controller het juiste model voor de taak en selecteert vervolgens de juiste weergave.
De Model zijn de gegevens en de regels die van toepassing zijn op die gegevens, die concepten vertegenwoordigen die door de toepassing worden beheerd. In elk softwaresysteem wordt alles gemodelleerd als data die we op een bepaalde manier verwerken. Wat is een gebruiker, een bericht of een boek voor een toepassing? Alleen gegevens die moeten worden verwerkt volgens specifieke regels (datum kan niet in de toekomst zijn, e-mail moet een specifiek formaat hebben, naam mag niet langer zijn dan x tekens, enz.).
Het model geeft de controller een gegevensweergave van wat de gebruiker ook heeft gevraagd (een bericht, een lijst met boeken, een fotoalbum, enz.). Dit gegevensmodel zal hetzelfde zijn, ongeacht hoe we het aan de gebruiker willen presenteren, daarom kunnen we elke beschikbare weergave kiezen om het weer te geven.
Het model bevat het belangrijkste onderdeel van onze applicatielogica, de logica die van toepassing is op het probleem waar we mee te maken hebben (een forum, een winkel, een bank, enz.). De controller bevat een meer interne-organisatorische logica voor de applicatie zelf (meer zoals housekeeping).
De Uitzicht biedt verschillende manieren om de gegevens die van het model worden ontvangen te presenteren. Dit kunnen sjablonen zijn waarin die gegevens zijn ingevuld. Er kunnen verschillende weergaven zijn en de controller moet beslissen welke hij moet gebruiken.
Een webapplicatie bestaat meestal uit een set controllers, modellen en views. De controller kan zijn gestructureerd als een hoofdcontroller die alle verzoeken ontvangt en specifieke controllers aanroept die acties voor elke zaak afhandelt.
Stel dat we een online boekwinkel ontwikkelen. De gebruiker kan acties uitvoeren zoals: boeken bekijken, registreren, kopen, items toevoegen aan de huidige bestelling, boeken maken of verwijderen (als hij een beheerder is, enz.). Laten we eens kijken wat er gebeurt als de gebruiker op de knop klikt fantasie categorie om de titels te bekijken die we beschikbaar hebben.
We zullen een bepaalde controller hebben voor alle boeken-gerelateerde acties (bekijken, bewerken, maken, enz.). Laten we het boeken_controller.php noemen voor dit voorbeeld. We zullen ook een model hebben, bijvoorbeeld book_model.php, gegevens en logica verwerken die betrekking hebben op de items in de winkel. Ten slotte zullen we een aantal weergaven hebben om bijvoorbeeld een lijst met boeken, een pagina om boeken te bewerken, enz. Te presenteren.
De volgende afbeelding laat zien hoe de gebruiker om de fantasieboekenlijst te bekijken, wordt behandeld:
De controller (books_controller.php) ontvangt het gebruikersverzoek [1] als een HTTP GET- of POST-aanvraag (we kunnen ook een centrale controller hebben, bijvoorbeeld index.php die het ontvangt en dan books_controller.php aanroept).
De controller onderzoekt het verzoek en de parameters en roept het model aan (book_model.php) vragen hem om de lijst met beschikbare fantasieboeken te retourneren [2].
Het model is verantwoordelijk voor het verkrijgen van die informatie uit de database (of waar deze ook is opgeslagen) [3], past indien nodig filters of logica toe en retourneert de gegevens die de lijst met boeken vertegenwoordigen [4].
De controller gebruikt de juiste weergave [5] om deze gegevens aan de gebruiker te presenteren [6-7]. Als het verzoek afkomstig is van een mobiele telefoon, wordt een weergave voor mobiele telefoons gebruikt, als de gebruiker een specifieke skin heeft geselecteerd, wordt de bijbehorende weergave gekozen, enzovoort.
Het meest voor de hand liggende voordeel dat we behalen met MVC is een duidelijke scheiding tussen presentatie (de interface met de gebruiker) en toepassingslogica.
Ondersteuning voor verschillende soorten gebruikers met verschillende soorten apparaten is tegenwoordig een veel voorkomend probleem. De gepresenteerde interface moet anders zijn als de aanvraag afkomstig is van een desktopcomputer of van een mobiele telefoon. Het model retourneert exact dezelfde gegevens, het enige verschil is dat de controller een andere weergave kiest om ze weer te geven (we kunnen een andere sjabloon bedenken).
Afgezien van het isoleren van het beeld van de bedrijfslogica, vermindert de M-V-C scheiding de complexiteit bij het ontwerpen van grote applicaties. De code is veel meer gestructureerd en daarom gemakkelijker te onderhouden, te testen en opnieuw te gebruiken.
Wanneer u een framework gebruikt, is de basisstructuur voor MVC al voorbereid en hoeft u alleen die structuur uit te breiden door uw bestanden in de juiste directory te plaatsen om te voldoen aan het patroon Model-View-Controller. Ook krijg je veel functionaliteit die al is geschreven en grondig is getest.
Neem cakePHP als voorbeeld MVC-raamwerk. Zodra je het hebt geïnstalleerd, zie je drie hoofddirectory's:
De app map is waar u uw bestanden plaatst. Het is jouw plek om jouw deel van de applicatie te ontwikkelen.
De cake map is waar cakePHP zijn bestanden heeft en waar zij hun rol hebben ontwikkeld (hoofdraamwerkfunctionaliteit).
De vendors map is indien nodig voor externe PHP-bibliotheken.
Uw werkplek (app-map) heeft de volgende structuur:
Nu moet je je controllers in de controllers map, uw modellen in de modellen map en uw weergaven in ... de keer bekeken directory!
Als u eenmaal gewend bent aan uw framework, weet u waar u moet zoeken naar bijna elk stukje code dat u moet aanpassen of maken. Deze organisatie alleen maakt onderhoud een stuk eenvoudiger.
Aangezien deze zelfstudie niet bedoeld is om u te tonen hoe u een toepassing met cakePHP kunt maken, gebruiken we deze alleen om voorbeeldcode weer te geven voor het model, de weergave en de controllercomponenten en commentaar te leveren op de voordelen van het gebruik van een MVC-framework. De code is te simpel en niet geschikt voor echte toepassingen.
Vergeet niet dat we een boekenwinkel en een nieuwsgierige gebruiker hadden die de complete lijst met boeken in de fantasie categorie. We hebben gezegd dat de controller degene is die het verzoek ontvangt en de nodige acties coördineert.
Dus wanneer de gebruiker klikt, vraagt de browser deze URL aan:
www.ourstore.com/books/list/fantasy
CakePHP maakt graag van URL's op in de vorm / controller / actie / param1 / param2, waar actie is de functie om binnen de controller te bellen. In het oude klassieke URL-formaat zou het zijn:
www.ourstore.com/books_controller.php?action=list&category=fantasy
Met behulp van cakePHP framework ziet onze controller er ongeveer zo uit:
set ('books', $ this-> Book-> findAllByCategory ($ category)); functie add () ... functie delete () ... ...?>
Eenvoudig, toch ?. Deze controller wordt opgeslagen als books_controller.php en in / app / controllers geplaatst. Het bevat de lijstfunctie om de actie in ons voorbeeld uit te voeren, maar ook andere functies om andere boekgerelateerde acties uit te voeren (een nieuw boek toevoegen, een nieuw boek verwijderen, enz.).
Het raamwerk biedt veel dingen voor ons en slechts één regel is nodig om de boeken te vermelden. We hebben basisklassen met het basisgedrag van de controller al gedefinieerd, dus we erven van hen (AppController die erft van Controller).
Het enige wat het hoeft te doen in de lijstactie is het model bellen om de gegevens te krijgen en vervolgens een weergave kiezen om deze aan de gebruiker te presenteren. Laten we uitleggen hoe dit is gebeurd.
this-> Book is ons Model en dit deel:
$ This-> Boek-> findAllByCategory ($ categorie)
vertelt het model om de lijst met boeken in de geselecteerde categorie te retourneren (we zullen het model later zien).
De reeks methode in de regel:
$ this-> set ('books', $ this-> Book-> findAllByCategory ($ category));
Is de controller manier om gegevens door te geven aan de weergave. Het zet de boeken variabele naar de gegevens die door het model worden geretourneerd en maakt deze toegankelijk voor de weergave.
Nu moeten we alleen de weergave renderen, maar dit wordt automatisch gedaan door cakePHP als we de standaardweergave willen. Als we een andere weergave nodig hebben, moeten we dit expliciet noemen met behulp van de geven methode.
Het model is nog eenvoudiger:
Waarom leeg? Omdat het overerft van een basisklasse die de nodige functionaliteit biedt en we de conventies voor de CakePHP-naam hebben gevolgd om het kader andere taken automatisch te laten doen. CakePHP weet bijvoorbeeld op basis van namen dat dit model wordt gebruikt in BooksController en dat het toegang krijgt tot een databasetabel met de naam books.
Met deze verklaring hebben we alleen een boekmodel dat gegevens uit de database kan lezen, verwijderen of opslaan
De code wordt opgeslagen als book.php en geplaatst in / app / modellen.
Alles wat we nu moeten doen is een weergave (minstens één) maken voor de lijstactie. De weergave bevat de HTML-code en een paar (zo min mogelijk) PHP-regels om door de boekenreeks van het model te bladeren.
Titel | Schrijver | Prijs |
---|---|---|
Zoals we kunnen zien, levert de weergave geen volledige pagina op, alleen een HTML-fragment (in dit geval een tabel). Dit komt omdat CakePHP een andere manier biedt om de lay-out van de pagina te definiëren en de weergaven in die lay-out worden ingevoegd. Het framework biedt ons ook enkele hulpobjecten om gemeenschappelijke taken gemakkelijk te maken bij het maken van deze HTML-fragmenten (invoegformulieren, links, Ajax of JavaScript).
We maken dit de standaardweergave en bewaren het als list.ctp (lijst is de naam van de actie en ctp betekent caketemplate) en plaatsen het in / app / views / books (in boeken omdat dit views zijn voor boekcontrolleracties).
En hiermee zijn de drie componenten voltooid met behulp van CakePHP-framework!
We hebben geleerd wat nu waarschijnlijk het meest gebruikte architecturale patroon is. We moeten ons er echter van bewust zijn dat wanneer we het hebben over patronen in de programmeerwereld, we het hebben over flexibele frames, die afgestemd moeten zijn op het specifieke probleem. We zullen implementaties vinden die variaties op de structuur introduceren die we hebben gezien, maar het belangrijkste is dat het patroon uiteindelijk ons helpt een duidelijke scheiding te krijgen tussen verantwoordelijkheden en betere onderhoudbaarheid, code-hergebruik en testen.
We hebben ook de voordelen gezien van het gebruik van een MVC-raamwerk dat ons een basaal MVC-skelet en veel functionaliteit biedt, onze productiviteit verbetert en het ontwikkelingsproces eenvoudiger maakt. Bedankt voor het lezen!