What is MVC?
From Wikipedia–
Model–View–Controller (MVC) is an architectural pattern used in software engineering. Successful use of the pattern isolates business logic from user interface considerations, resulting in an application where it is easier to modify either the visual appearance of the application or the underlying business rules without affecting the other. In MVC, the model represents the information (the data) of the application; the view corresponds to elements of the user interface such as text, checkbox items, and so forth; and the controller manages the communication of data and the business rules used to manipulate the data to and from the model.
- Model – represents applications behavior and data. It is also commonly known as the domain. The domain represents the problem you are trying to solve.
- View – represents the presentation. It can query the model about its state and generate the presentation of the model objects.
- Controller – represents applications workflow, it processes the request parameters and decides what to do based on them. This, usually, involves manipulating the model and displaying the data in the selected view.
As I think about the MVC pattern I can see only one negative aspect and several positive aspects. The negative is that the MVC pattern introduces complexity into the project which can be a burden for simple applications, but as your application grows this negative aspect is over weighted by positive aspects. I am going to describe few positive aspects I can think of.
MVC separates the model from the view, that is, the data from its representation. The separation of a model from its representation is one of the basic rules of a good software design. When you separate a model from its representation you can easily add many different representations of the same model. For example, a web application typically has HTML representation, used by web browsers, and JSON representation used by JavaScript AJAX clients.
A distinctive MVC role allows us to better distribute manpower on a big project. For example, domain and database experts can work on a model while web designers work on a view. Because each part is developed by specialized developers, an application can be of better quality. This also affects development time, projects can be build quicker because specialized developers can work simultaneously, each in their area of expertise, without affecting other developers work (to much).
Maintenance and upgrades of a complex application are easier because a developer can look at the application as a series of “modules” each consisting of Model, View and the Controller part. A developer can modify one “module” and does not need to worry that the changes he introduced will affect other parts of the system (I believe that this is called separation of concerns). Also, when adding new functionality to the application, a developer can simply create a new “module”.
Example application
For this tutorial I created simple contacts manager which supports basic CRUD operations. User can add a new contact, delete it, display a contact detail and display list of all contacts. I will refer to these operations as actions. Therefore, this application has four different actions: add contact, delete contact, show contact and list contacts. You can see the result of the list contacts action in the screenshot below:
The implementation
The implementation consists of the index.php file and several files placed in the model, view and controller directories:
The index.php script is central access point, all requests go through it.
The controller is defined in the controller directory:
- ContactsController.php file.
Application views are defined in the view directory:
- contact-form.php is responsible for displaying “Add new contact” form to the user
- contact.php is responsible for displaying contact details, contacts.php is responsible for displaying the contacts list
- error.php is responsible for diplaying errors.
The model is defined in the model directory:
It consists of three parts:
- ContactsGateway.php is a table data gateway to the database table I’ll show you later, the
- ContactsService.php object defines the model API that is used by the controller.
- ValidationException.php is an exception thrown from the model and catched by the controller in case of any validation errors. Using the ValidationException the model can alert the controller about validation errors and the controller can pass them to the view so they can be displayed.
The model
Before I explain source code, you must know something about the model. The model has a single entity – Contact which is persisted in the contacts table. The Contact has no behavior so I used SQL table structure to define it:
CREATE TABLE `contacts` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(128) NOT NULL, `phone` varchar(64) DEFAULT NULL, `email` varchar(255) DEFAULT NULL, `address` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) )
There is no class in the model that represents the Contact entity, instead I used standard PHP objects automatically created from the database record (I know, it is not very OO but it was quick).
What can we do with that incredible model? Here is the public interface of the ContactsService class where you can see all the features of the model:
class ContactsService { private $contactsGateway = NULL; private function openDb() { if (!mysql_connect("localhost", "root", "")) { throw new Exception("Connection to the database server failed!"); } if (!mysql_select_db("mvc-crud")) { throw new Exception("No mvc-crud database found on database server."); } } private function closeDb() { mysql_close(); } public function __construct() { $this->contactsGateway = new ContactsGateway(); } public function getAllContacts($order) { try { $this->openDb(); $res = $this->contactsGateway->selectAll($order); $this->closeDb(); return $res; } catch (Exception $e) { $this->closeDb(); throw $e; } } public function getContact($id) { try { $this->openDb(); $res = $this->contactsGateway->selectById($id); $this->closeDb(); return $res; } catch (Exception $e) { $this->closeDb(); throw $e; } return $this->contactsGateway->find($id); } private function validateContactParams( $name, $phone, $email, $address ) { $errors = array(); if ( !isset($name) || empty($name) ) { $errors[] = 'Name is required'; } if ( empty($errors) ) { return; } throw new ValidationException($errors); } public function createNewContact( $name, $phone, $email, $address ) { try { $this->openDb(); $this->validateContactParams($name, $phone, $email, $address); $res = $this->contactsGateway->insert($name, $phone, $email, $address); $this->closeDb(); return $res; } catch (Exception $e) { $this->closeDb(); throw $e; } } public function deleteContact( $id ) { try { $this->openDb(); $res = $this->contactsGateway->delete($id); $this->closeDb(); } catch (Exception $e) { $this->closeDb(); throw $e; } } }
ContactsService object does not work with the database directly; instead it uses the ContactsGateway object which in return issues queries to the database. This technique is called Table Data Gateway.
The source
First let’s look at the index.php source:
<?php require_once 'controller/ContactsController.php'; $controller = new ContactsController(); $controller->handleRequest(); ?>
This script has simple role, it instantiates the controller object and hands it control over the application via the handleRequest method.
All requests must go through the index.php script because MVC requires that all requests are handled by the controller which is called from the index.php script. Web MVC applications usually redirects all requests to go through the index.php which can be done in server configuration.
Let’s look at the handleRequest method of the controller.
class ContactsController { ... public function handleRequest() { $op = isset($_GET['op'])?$_GET['op']:NULL; try { if ( !$op || $op == 'list' ) { $this->listContacts(); } elseif ( $op == 'new' ) { $this->saveContact(); } elseif ( $op == 'delete' ) { $this->deleteContact(); } elseif ( $op == 'show' ) { $this->showContact(); } else { $this->showError("Page not found", "Page for operation ".$op." was not found!"); } } catch ( Exception $e ) { $this->showError("Application error", $e->getMessage()); } } ... }
The handleRequest method acts as a dispatcher for the actions. The method decides which action should it invoke based on a value of the HTTP GET “op” parameter and invokes the method that implements the action. If any exception is thrown from the action methods the handleRequest method catches them and prints the error message.
Now, let’s look at the action methods:
class ContactsController { private $contactsService = NULL; public function __construct() { $this->contactsService = new ContactsService(); } public function redirect($location) { header('Location: '.$location); } public function handleRequest() { $op = isset($_GET['op'])?$_GET['op']:NULL; try { if ( !$op || $op == 'list' ) { $this->listContacts(); } elseif ( $op == 'new' ) { $this->saveContact(); } elseif ( $op == 'delete' ) { $this->deleteContact(); } elseif ( $op == 'show' ) { $this->showContact(); } else { $this->showError("Page not found", "Page for operation ".$op." was not found!"); } } catch ( Exception $e ) { // some unknown Exception got through here, use application error page to display it $this->showError("Application error", $e->getMessage()); } } public function listContacts() { $orderby = isset($_GET['orderby'])?$_GET['orderby']:NULL; $contacts = $this->contactsService->getAllContacts($orderby); include 'view/contacts.php'; } public function saveContact() { $title = 'Add new contact'; $name = ''; $phone = ''; $email = ''; $address = ''; $errors = array(); if ( isset($_POST['form-submitted']) ) { $name = isset($_POST['name']) ? $_POST['name'] :NULL; $phone = isset($_POST['phone'])? $_POST['phone'] :NULL; $email = isset($_POST['email'])? $_POST['email'] :NULL; $address = isset($_POST['address'])? $_POST['address']:NULL; try { $this->contactsService->createNewContact($name, $phone, $email, $address); $this->redirect('index.php'); return; } catch (ValidationException $e) { $errors = $e->getErrors(); } } include 'view/contact-form.php'; } public function deleteContact() { $id = isset($_GET['id'])?$_GET['id']:NULL; if ( !$id ) { throw new Exception('Internal error.'); } $this->contactsService->deleteContact($id); $this->redirect('index.php'); } public function showContact() { $id = isset($_GET['id'])?$_GET['id']:NULL; if ( !$id ) { throw new Exception('Internal error.'); } $contact = $this->contactsService->getContact($id); include 'view/contact.php'; } public function showError($title, $message) { include 'view/error.php'; } }
First, we have the listContacts method which has a simple workflow, it reads a parameter required for sorting the contacts, gets sorted contacts from the model, stores it in the contacts variable and, finally, includes the view.
Second, we have the deleteContact method which reads an id of the contact and tells the model to delete it. Finally, it redirects the user back to the index.php script which in return invokes the list contacts action. The delete contact action can not work without the id parameter, so, the method will throw an exception if the id of a contact is not set.
Third method is the showContact method which is similar to the deleteContact method so I will not waste space explaining it.
Finally, the saveContact method displays the “Add new contact” form, or, processes the data passed from the form if it was submitted. If any ValidationException occurred in the model, errors are collected from the exception and passed to the view. Ideally the view should display it (and indeed it does, as you will see soon).
Now let’s look at some views, first I want to show you the contacts.php view which is straightforward:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Contacts</title> <style type="text/css"> table.contacts { width: 100%; } table.contacts thead { background-color: #eee; text-align: left; } table.contacts thead th { border: solid 1px #fff; padding: 3px; } table.contacts tbody td { border: solid 1px #eee; padding: 3px; } a, a:hover, a:active, a:visited { color: blue; text-decoration: underline; } </style> </head> <body> <div><a href="index.php?op=new">Add new contact</a></div> <table border="0" cellpadding="0" cellspacing="0"> <thead> <tr> <th><a href="?orderby=name">Name</a></th> <th><a href="?orderby=phone">Phone</a></th> <th><a href="?orderby=email">Email</a></th> <th><a href="?orderby=address">Address</a></th> <th> </th> </tr> </thead> <tbody> <?php foreach ($contacts as $contact): ?> <tr> <td><a href="index.php?op=show&id=<?php print $contact->id; ?>"><?php print htmlentities($contact->name); ?></a></td> <td><?php print htmlentities($contact->phone); ?></td> <td><?php print htmlentities($contact->email); ?></td> <td><?php print htmlentities($contact->address); ?></td> <td><a href="index.php?op=delete&id=<?php print $contact->id; ?>">delete</a></td> </tr> <?php endforeach; ?> </tbody> </table> </body> </html>
The contacts.php view, which is used by the list contacts action, requires the contacts variable to be filled with contact objects. The variable is filled in the listContacts method and passed to the view using the PHP scoping rules and then the view uses the data from it to display the contacts as an HTML table.
Scripts like the contacts.php script are called templates. With a template developer defines a fixed structure that is filled with variable values from the application (at run-time) and then presented to the user. Templates contain only presentation logic, because of this, they are understandable by non-programmers (designers, …) which makes them quite usefull and frequently used in web applications.
Now let’s take a look at more complex view, the contact-form.php view:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title> <?php print htmlentities($title) ?> </title> </head> <body> <?php if ( $errors ) { print '<ul>'; foreach ( $errors as $field => $error ) { print '<li>'.htmlentities($error).'</li>'; } print '</ul>'; } ?> <form method="POST" action=""> <label for="name">Name:</label><br/> <input type="text" name="name" value="<?php print htmlentities($name) ?>"/> <br/> <label for="phone">Phone:</label><br/> <input type="text" name="phone" value="<?php print htmlentities($phone) ?>"/> <br/> <label for="email">Email:</label><br/> <input type="text" name="email" value="<?php print htmlentities($email) ?>" /> <br/> <label for="address">Address:</label><br/> <textarea name="address"><?php print htmlentities($address) ?></textarea> <br/> <input type="hidden" name="form-submitted" value="1" /> <input type="submit" value="Submit" /> </form> </body> </html>
This view, also an template, is used by the add contact action and it displays the “Add new contact” form to the user. All variables required by the template are filled in the saveContact action method including the errors variable which, if set, is used by the template to display errors that occurred in the model while trying to create a new contact so the user can fix invalid data causing them.
This template shows us usefulness of controller-view separation, because, without it we would put controller logic from the saveContact method into the contact-form.php script. I say script because if a template contains any controller logic in it, it is no more a template.
Conclusion
I hope you understood the MVC and that you i it, try to implement some sample application using your own simple MVC framework, but do not reinvent the wheel because there are many excellent MVC frameworks out there, for any programming language. Just google it up.
As always if you have any questions or suggestions don’t hesitate to write them in the comment form below.
Download Complete Project:

Hi, My name is Masud Alam, love to work with Open Source Technologies, living in Dhaka, Bangladesh. I’m a Certified Engineer on ZEND PHP 5.3, I served my first Fifteen years a number of leadership positions at AmarBebsha Ltd as a CTO, Winux Soft Ltd, SSL Wireless Ltd, Canadian International Development Agency (CIDA), World Vision, Care Bangladesh, Helen Keller, US AID and MAX Group where I worked on ERP software and web development., but now I’m a founder and CEO of TechBeeo Software Company Ltd. I’m also a Course Instructor of ZCPE PHP 7 Certification and professional web development course at w3programmers Training Institute – a leading Training Institute in the country.
Excellent
Thanks for your efforts
It’s very…very….very… nice..
Thanks 🙂
Excellent ;-D
A 2013 article and still using the old way of connecting to a mysql database? You should use PDO instead.
I believe that the author can do that, but as he said, he wanted to be quick about the creation of the model. The whole point was to explain MVC.
lol.. go to a pdo tutorial then
very nice article
plis DEMO
very very helpful tutorial for beginners using MVC pattern, but quiet difficult because i dont work on OOPS .. Thanks a lot
very helpful tutorial, but bit difficult because i dont know OOPS and MV framework at all, Thanks a lot
thanks.
can you also include the update operation.. the ‘U’ in the CRUD 😛
I 2nd that, please include an update section of the this simple CRUD. I working on adding one now but am stuck with how to pass in the data for $contacts->name, $contacts->phone,$contacts->email and $contacts->address on the edit form page. Any suggestions?
NVM, finally got it… took me awhile to understand the workflow on how you were pulling in the templates from the controller. I was instead trying to edit the template with code logic in it instead of driving it from the controller. I ended up creating another method for edit obviously and another method to show the fields for show contact. There is probably a better way to do this, but it finally worked……….. 🙂
Will you please share your update script….
PLEASE DO SHARE WHAT YOU HAVE CREATED IN EDIT AND SHOW THE EDITED DATA. TNX
YES PLEASE
Thanks! What framework do you use to generate the mvc code?
great tutorial…
if we want to add .htaccess file for this project, how to do it?
I’m so glad if you want to reply, I want to learn more about MVC design pattern concept before I move and learn several frameworks.
thanks 🙂
Great tutorial, it’s so usefull…
I’ve problem, maybe you or any body can give an advice, I want to include some css files, but always not working, when i look page source, then i check the path, i get “page not found” response. Maybe there are many way to include css files..?
regards..
I still don’t understand the benefit of using “Table Data Gateway” pattern with the use of ContactsService class. To me, it seems quite redundant because you can interact directly between ContactsController and ContactsGateway. Pls elaborate.
very….very…. useful
thank you!
This is what I have been looking for for a long time. Thank you so much!
Hey, it’s great tutorial..
i’ve same problem with astro, that’s include a file *.css to html in folder view..
In this tutorial still join with one file.. i want to join that file with bootstrap, but still not work..
Maybe u have way to do that, or u can explain about how to do that, or any body can help me, i want to built my system with MVC design pattern..
thanks a lot..
Thanks much.
You did not show how the form save button was handled in your ur life routing
Sorry, I’m a bit baffled. What actually is in the ContactsGateway.php file? You mentioned in the tutorial that you would explain it later, but unless I’ve missed something, there was nothing further.
I’ve just noticed that there’s a link to download the source code. Apologies for missing it on the first read through – I’ll get the code now.
This is my first time visit at here and i am truly impressed to read all at one
place.
thanks can you also include the update operation
please share the update and login code it is most important
this tutorial is very useful for begginners and sir please put update functionality
Thank you sir
this is very useful for me, but it will be better if there is an update function. Thanks.
Muito obrigado por compartilhar seu conhecimento, me ajudou muito a entender o padrao MVC de trabalhar, achei seu codigo bem enxuto, ficou otimo, parabens!
Great Tutorial. This was really Helpful
dil khush kar diya bhai tune toh masha allah.
i am JAva developer.
Its a same style we code using servlet jsp.
kindly send me your personal email id just to be in touch
Update function is all about passing ID and mysql update query.
Application error
No contacts database found on database server.
very useful work on the MVC .thanks
very usefull and easy to learn MVC. but how about update contact? on this example just only show.. not update.. i try to change this but failed. any information about this?
Nice man. thanks for this 🙂
ITs really very useful and simple code of mvc compare than other ..thanks
Good tutorial 🙂
Please email me , and please send me the complete source code , I need to study it , thank you!
Whats the best IDE that can cater for PHP MVC?
Thanks for this both simple and helpful tutorial
Hello,thanks for your example shared, this is a good study.
However, i have a one question.
If i would like to select two tables from mysql and show in one page, how can i do it?
This article is very helpful thanks the admin
Interesting and educative. Am glad to find this page. Keep up with the good work…site Already bookmarked on my browser.
Regards,
Bob Michael
Very informative. Thanks for the work. Thanks for working with World Vision 🙂
very informative and educative for MVC beginners
do for update also
Thank you so much for your tutorial. This is very helpful
tnk sir, you have simple crud operation code in mvc in php??
plz send : puakbari@gmail.com
thanks for great help.
, here i found some tutorial on Code for Insert View Update Delete In Php MySQL for more detail Click Here
is a great source, thank u !!
Thanks for tips, it really helps me out
Thanks for this tutorial, can you please send me the source code. The link is broken.. Thanks 😀
HI,
I can not download the source code the page is not found.kindly give the source code
Great tutorial, helped me a lot in the studies … sorry that it is not possible to download the files (broken link). Thank you anyway.
Hello
Can you enable link of source code about this tutorial, please
can i download this source code