MVC Without a Framework

Published Saturday 12th of March 2011

MVC (Model - View - Controller) is an excellent way to divide the tasks of an application into different layers that all handle separate things.


Image: Renjith Krishnan / FreeDigitalPhotos.net

Many PHP frameworks use the MVC model but in this article I will try to explain how you can utilize MCV without the use of a framework.

First, I'll try to explain what the different layers all mean.

The Model

The model handles all your data. It won't do anything on its own but is called by the Controller to manipulate data in some way. By data I mean any kind of information on your website, but very commonly a database table.

Each table in your database should be represented by a model, and in some cases you'll have a model representing more than one table (in the case of a poll for example, which has a table for questions and one for answers).

Here's a simple example model:

<?php
    
class Articles {
        public static function 
get ($limit 1000000000) {
            
$rows = array();
            
$res mysql_query('SELECT * FROM articles ORDER BY pub_date DESC LIMIT 0, ' $limit);

            while (
$row mysql_fetch_assoc($res)) {
                
$rows[] = $row;
            }

            return 
count($rows) ? $rows false;
        }

        public static function 
insert ($fields) {
            
mysql_query('INSERT INTO articles (title, content) VALUES ("' $fields['title'] . '", "' $fields['content'] . '")');

            return 
mysql_insert_id();
        }

        public static function 
update ($fields$id) {
            
mysql_query('UPDATE articles SET title = "' $fields['title'] . '" content = "' $fields['content'] . '" WHERE articles_id = ' $id);
        }

        public static function 
delete ($id) {
            
mysql_query('DELETE FROM articles WHERE articles_id = ' $id);
        }
    }
?>

I'm not doing any error-checking or validation or anything, this is just to give you a rough picture of what a model can look like.

With this model at hand we can now manipulate the article-data without writing a single MySQL-query. If we want to insert a new article we'll simply do Articles::insert($_POST) and if we want to delete one we'll go Articles::delete(4).

The idea is that the model should handle everything that has to do with data. Whenever you need data in some other way you'll add it as a method to your model. If you want to create a "Most Commented Articles"-box on your page for example, you'll probably add a Articles::getMostCommented(5)-method to your model.

The View

The view is what you actually see. The visual representation of your data. Most of the time for web development this will obviously be HTML. The view should contain no logic whatsoever. It should only loop data it receives from the controller (which in turn has asked the model for it).

An example view:

<?php $data MostCommentedArticles_Controller::init(); ?>

<div id="most-commented-articles">

    <h2>Most Commented Articles</h2>

    <ol>
        <?php foreach ($data['articles'] as $article) { ?>
            <li><a href="<?php echo $article['url']; ?>"><?php echo $article['title']; ?></a></li>
        <?php ?>
    </ol>

</div>

The Controller

The controller communicates with the model to get or insert data and then passes information to the view for it to display. An example controller can look something like:

<?php
    
class MostCommentedArticles_Controller {
        public function 
init () {
            return array(
'articles' => Articles::getMostCommented(5));
        }
    }
?>

That's a very simple controller because all it does is fetch data from the model. In many cases you'll need to do a little more logic in there like for example insert or delete data as well.

Let's pretend you can log in as an admin and if so there's a little "delete"-button next to every article in the "Most Commented Articles"-view, the controller would handle that too:

<?php
    
class MostCommentedArticles_Controller {
        public static function 
init () {
            
# Delete articles
            
if (isset($_POST['delete_most_commented_article']) and ADMIN) {
                
Articles::delete($_POST['articles_id']);
            }

            
# Get articles
            
return array('articles' => Articles::getMostCommented(5));
        }
    }
?>

I'm using an ADMIN-constant to see whether the user is logged in. As you can see the form in the view would require two fields.

Summary

That's pretty much it. By structuring your code like this you keep your HTML clean and free from PHP logic, and you make your data handling consistent across your application through the use of models.

I also like to divide my code modularly, just like in the example of the MostCommentArticles-module, and then use very simple "page-files" to tie it all together:

  • Models/
    • Articles.php
    • Comments.php
  • Views/
    • MostCommentedArticles.tpl.php
    • ...
  • Controllers/
    • MostCommentedArticles.php
    • ...
  • index.php
  • about-us.php
  • article.php

index.php, about-us.php and article.php are the files that will actually be accessed through the browser, and all they do is include different views:

index.php

<?php
    
include 'views/head.php';
    include 
'views/navigation.php';
    include 
'views/search.php';
?>

<div id="primary-content">

    <?php
        
include 'views/twitter-feed.php';
        include 
'views/latest-articles.php';
    
?>

</div>

<div id="secondary-content">

    <?php
        
include 'views/recent-comments.php';
        include 
'views/style-switcher.php';
    
?>

</div>

<?php
    
include 'views/foot.php';
?>

And that's it. I'll try to dig out some old project that uses this structure so you can download it an check the files.

Edit: I had some really old, unfinished drafts of similar articles on my comp so I decided to stick 'em on exscale.se. If you're eager to learn more about this you may want to check them out.

Tags
Comments
2 comments

Bookmark this Article

  • del.icio.us
  • Digg
  • Furl
  • Google
  • Technorati
  • Ma.gnolia
  • Blinklist
  • Blogmarks
  • Rojo
  • Stumbleupon
blog comments powered by Disqus

Random jQuery Plug-ins

  • Checked checkbox-parent

    This tiny plug-in adds and removes a 'checked'-class to input[type=checkbox]'s parents. Very useful if you want to style the entire wrapping <label>-e...

    Details

  • Form to Link

    Run this plug-in on a form or an input[type=submit] and it will insert a link after the element you run it on which, on click, will submit said form.

    Details

  • Pixastic Editor

    This app/plug-in inserts a (completely stylable) toolbar next to any image in your document that allows the user to apply different Pixastic-effects ...

    Details

More Plug-ins

Recent Comments

Powered by Disqus
Page cached. Loaded in: 0.0255 second(s).
Last DB change: 2012-04-02 11:06:05
Last file change: 2012-04-25 20:30:39
Cache created: 2012-05-18 02:16:43