MVC Without a Framework

Published Friday, July 17, 2009 in Unfinished Articles

MVC is a programming design pattern that encourages separation of data, presentation and logic. Many frameworks are built on MVC but you don't necesarily need a framework to structure your code in an MVC manner.

This tutorial will try to explain how you can start using MVC today, with nothing but standard PHP. We will build a very simple blog/article publishing system. I will not cover comments or tags but after this article you should be able to easily add it yourself.

First I thought I'd try to, in a very basic way, explain each letter in the acronym. There's definitely more to it than this and I recommend you pick up a book on the area if you're really interested.

M

M in MVC stands for "model" and is supposed to be a model of your data. This could be anything from a database table to a set of files you treat equally. Basically, what we want to use the model for is anything that has to do with our data.

In the case of our blog we'll have one model called "Articles" which will handle everything that has to do with articles. Any time you want to edit, fetch, insert or delete articles you will use the model. There should be no (in this case) SQL-queries outside the model.

V

V stands for "view" and is a visual representation of your data. In the case of our articles this will be a list of the latest 5 or so articles in summary on the front-page and the whole article on each article page.

When doing web development most of your views will be HTML, but we'll create an RSS-feed as well and that will obivously be just that; RSS.

C

C stands for "controller" and its job is to either fetch, insert or delete data using the model, and then pass it on to the view so it can be displayed.

Depending on different user input the controller can do different things. For example, most blogs allow comments and the comments controller can display either the form for posting comments, or, after a comment has been posted, it might display a "Thank you"-text or similar.

The controller should handle all the logic behind a certain part of your application. The view should be nothing but presentation that is based on what the controller decides.

Modular Design

Many frameworks that use MVC treat one controller as one page on the site. Personally I prefer to structure my code in a more modular manner where each and every unique part of the page has one view and one controller. That way it can be moved around or deleted with a breeze.

Directory Structure

We'll put all our views and models in directories named the same. Each view will contain both the PHP logic and the HTML. This is a bit unorthodox but we'll still separate the logic from the presentation. In some cases the view won't even need any logic though, and in most cases only a few lines of model-calling is required. I've done it this way for simplicity but you could pretty easily separate the view and controller completely by providing a class or separate file with all the logic for each view.

For every different page on the site we'll create a very simple PHP-file in the root-directory that does nothing but include views. We'll only need 3 pages for our super-simple blog: home-page (displays the latest 5 articles), articles-page (displays all articles), article-page (displays one article).

Here's a list of all the dirs and files we'll create:

  • models
    • articles.php # the articles model - handles all communication with the articles table in the database
  • views
    • header.php # the header - contains all the stuff that's common to all page's heads
    • footer.php # the footer - contains all the stuff that's common to all page's foots
    • articles.php # the articles view - displays more than one article
    • article.php # the article view - displays one article
    • articles-rss.php # the articles RSS feed
  • index.php # the home-page
  • article.php # each article-page
  • articles.php # list of all articles

The Articles Database Table

....

The Articles Model

We'll wrap the articles model in a class called Articles. We'll create a bunch of static functions for everything we ever want to do with articles. We don't have to come up with everything now, it's OK to go back and fill this with functions as you need them. I've seen models that are several thousand lines of code :)

class Articles {
    /**
     * getArticles
     *
     * Retrieves articles based on params
     * 
     * @param $sort String - which column-name to sort the results by
     * @param $order String - in which order to sort them ('ASC' or 'DESC')
     * @param $start Int - where to start fetching articles from
     * @param $limit Int - how many articles to fetch
     * @returns $articles Array || false - an array of all articles or false if no articles matched the criteria
     **/
    public static function getArticles ($sort = '1', $order = 'ASC', $start = 0, $limit = 1000000000) {
        $articles = array();
        $qry = '
            SELECT 
                * 
            FROM 
                articles 
            ORDER BY 
                ' . mysql_real_escape_string($sort) . ' ' . mysql_real_escape_string($order) . ' 
            LIMIT
                ' . mysql_real_escape_string($start) . ' ' . mysql_real_escape_string($limit) . ' 
        ';

        $res = mysql_query($qry) or die(mysql_error() . $qry);

        if (mysql_num_rows($res)) {
            while ($row = mysql_fetch_assoc($res)) {
                $articles[] = $row;
            }

            return $articles;
        }
        else {
            return false;
        }
    }

    /**
     * getArticleBySlug
     *
     * Retrieves one article based on slug (URL)
     * 
     * @param $slug String - the article's slug
     * @returns $article Array || false - article array or false if no article existed
     **/
    public static function getArticleBySlug ($slug) {
        $qry = '
            SELECT 
                * 
            FROM 
                articles 
            WHERE
                slug = "' . mysql_real_escape_string($slug) . '"
            LIMIT 1
        ';

        $res = mysql_query($qry) or die(mysql_error() . $qry);

        if (mysql_num_rows($res)) {
            return mysql_fetch_assoc($res);
        }
        else {
            return false;
        }
    }

    /**
     * deleteArticle
     *
     * Deletes an article based on ID
     * 
     * @param $id Int - the article's ID
     **/
    public static function deleteArticle ($id) {
        mysql_query('DELETE FROM articles WHERE articles_id = ' . mysql_real_escape_string($id));
    }

    /**
     * updateArticle
     *
     * Updates an article based on ID
     * 
     * @param $id Int - the article's ID
     **/
    public static function updateArticle ($id) {
        # Homework :)
    }

    /**
     * insertArticle
     *
     * Inserts a new article
     * 
     * @param $article Array - An article array
     **/
    public static function updateArticle ($article) {
        # Homework :)
    }
}

As you can see, with this class in our hands we can do everything we need to do with our articles. If we want the latest 5 articles we'll simply go Articles::getArticles('pub_date', 'DESC', 0, 5); and if we want the article on /test-article/ we'll simply go Articles::getArticlesBySlug('test-article');

Like I said, you can add more functions to this class any time you need to do something new with articles (like getArticlesByTagSlug() or getMostCommentedArticles() etc etc).

The Views

Like I mentioned before most of our views will be pure HTML but they'll also contain the necesary logic required to display their contents.

Header & Footer

These will contain the HTML that will be displayed on each and every page. Typically the html, head and body elements but also our logo and copyright-information.

Header

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

    <head>

        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
        <meta http-equiv="Content-Style-Type" content="text/css" />

        <meta name="author" content="You" />
        <meta name="copyright" content="Copyright (c) 2010 You" />

        <link rel="alternate" type="application/rss+xml" title="articles" href="views/articles-rss.php" />
        <link rel="stylesheet" type="text/css" media="screen,projection" href="css/style.css" />

        <title>My Blog</title>

    </head>

    <body>

        <div id="wrapper">

            <div id="header">

                <h1><a href="/">MyBlog.com</a></h1>

                <p>Just another MVC blog</p>

            </div>

Footer

            <div id="footer">

                <p>Copyright &copy; 2010 You</p>

                <ul>
                    <li><a href="#" title="Top of Page">Top</a></li>
                    <li><a href="#" title="Get Firefox!">Firefox</a></li>
                    <li><a href="#" title="Valid XHTML">XHTML</a></li>
                    <li><a href="#" title="Valid CSS">CSS</a></li>
                </ul>

            </div>

        </div>

    </body>

</html>

These two files will be included first and last on every page. As you can see they're nothing but pure HTML. No PHP logic needed here.

The Articles View

The articles view will however require some logic. Like I mentioned before we'll still separate the PHP and HTML. If you like you could move all the PHP in the top to its own file in a new directory called controllers/ and include that instead of having it in the same file like me.

<?php
    
# The controller...
    
if ($homePage) {
        
$articles    Articles::getArticles('pub_date''DESC'05);
        
$title        'The Latest Articles';
    }
    else {
        
$articles    Articles::getArticles('pub_date''DESC');
        
$title        'All Articles';
    }

    
# The view...
?>
<?php 
if (count($articles)) { ?>
    <h2><?php echo $title?></h2>

    <ul>
        <?php foreach ($articles as $article) { ?>
            <li>
                <h3>
                    <a href="article.php?slug=<?php echo $article['slug']; ?>">
                        <?php echo $article['title']; ?>
                    </a>
                </h3>

                <p><small><?php echo $article['pub_date']; ?></small></p>

                <p><?php echo substr($article['content'], 0200); ?></p>
            </li>
        <?php ?>
    </ul>
<?php } else { ?>
    <h2>No Articles/h2>

    <p>Sorry no articles were found.</p>
<?php ?>

The Article View

<?php
    
# Make sure ?slug= is set
    
if (isset($_GET['slug'])) {
        
$article Articles::getArticleBySlug($_GET['slug']);

        
# If it's not a valid slug - die
        
if (!$article) {
            die(
'FAIL');
        }
    }
    
# Else die
    
else {
        die(
'FAIL');
    }
?>
<h2><?php echo $article['title']; ?></h2>

<p><small><?php echo $article['pub_date']; ?></small></p>

<p><?php echo $article['content']; ?></p>

The Articles RSS View

...

The Different Pages

The different pages (or files in root) will simply include the views they need to display the page.

The Home Page

<?php
    
include 'views/header.php';

    
$homePage true;
    include 
'views/articles.php';

    include 
'views/footer.php';
?>

The Articles Page

<?php
    
include 'views/header.php';
    include 
'views/articles.php';
    include 
'views/footer.php';
?>

The Article Page

<?php
    
include 'views/header.php';
    include 
'views/article.php';
    include 
'views/footer.php';
?>


Bookmark It

  • del.icio.us
  • Digg
  • Furl
  • Google
  • Technorati
  • Ma.gnolia
  • BlinkList
  • Blogmarks
  • Rojo
  • StumbleUpon

Comments

6 comments so far, why don't you post one too?

HarrellFrancine29

Wednesday, December 28, 2011 | View all comments by HarrellFrancine29

This is hard a little bit to finish best essay writing just about this topic! Find the superior writing services to have an academic benefit or buy custom essay papers here!

essay writing service

Thursday, December 29, 2011 | View all comments by essay writing service

You interested me in your nice theme. Thus, I will try to notice the experienced essay writing service to buy the essays for sale connected with your issue.

professional writing service

Thursday, December 29, 2011 | View all comments by professional writing service

Are willing your research papers to be referenced by specialists? It's not a problem at all! The research paper services will cope with all you want easily. Thence, why not do it?

buy custom essay papers

Saturday, December 31, 2011 | View all comments by buy custom essay papers

People will buy custom essay papers and the written essay just about this good post. Good text! Thank you for that!

article submission

Sunday, January 01, 2012 | View all comments by article submission

That requires a long time to add your good facts like this post hand-operated. Hence, submit article service and journal article submission exist for you and we could use it.

custom essay

Saturday, January 07, 2012 | View all comments by custom essay

The essay writing about this good topic, students would see at the writing service. Purchase the pre written essay and custom essay just about this good post.


Say Something

No (X)HTML allowed, no need to use &gt; or &lt;
Markdown supported. Gravatars supported.
Put code in [code][/code]-tags and it will be syntax highlighted.
Fields marked with * are mandatory.



Post It

From June 02 to April 23

  1. Mogrify is what you're looking for if you want to convert multiple images to multiple other images in ImageMagick
  2. Tommorrow, finally, the inFamous demo will be friggin availble on PSN!! Suweeeeeeeeet
  3. Fuck canvas is cool, I've started playing around with old 3D-shit again :)

February 2012

S M T W T F S
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


Recent Comments

  1. buy thesis on A Modular Design Pattern:
    Choosing buy dissertation service a...
  2. research papers on A Modular Design Pattern:
    Want to find cheap literature essay...
  3. professional resume service on A Modular Design Pattern:
    Yeah doubtless very constructive f...
  4. website submission service on A Modular Design Pattern:
    Are willing to get Search engine op...

Style Switcher

The style switcher allows you to change the look and feel of exscale.se.
Only CSS and JavaScript are changed. The XHTML stays the same.

For more information about the styles, check the styles page.


Categories


Random Quote

The climate is made up of "weather"; whether it is nice out depends on whether it is raining or not. A wether is just a castrated sheep. - Unknown


Random Images




Answer This!

Do you find the "scroll-pagination" annoying? (If you don't know what it is, scroll to the bottom of the first-page)


Blog Roll