Simple Blog – Example 4: MVC

Simple Blog is a multi-part series. Check out The Index

In example 1, we started out by writing some PHP scripts that executed pretty much top to bottom. In example 2, we re-factored our code and markup into reusable function and templates to minimize repetition in the development process. In example 3, we identified a couple candidate objects which we rolled into classes to enhance code maintainability. Throughout this process, we’ve extracted our data logic from our base pages, however, application logic and presentation layer are still mixed.

In this example, we’ll decouple application logic and presentation logic by moving all of our presentation logic into new files we’ll call views. Once we’ve performed this decoupling, our code will be nicely separated into three distinct types: models, views, and controllers.

Models

Our model is just the Post class we created in Example 3. I’ve renamed the file to ‘post.model.php’ and moved it into a directory called models, but other than these two administrative changes, the Post class is unchanged.

Views

Simple Blog has three views: List View, Read View, and Upsert View. The List View displays a list of posts. The Read View displays a single post. The Upsert View displays an HTML form for either creating a new post or editing an existing post. So, let’s take a look at our three views. Note, there is zero new code here, the only thing we’re changing is how the code is organized.

List View

<?php require_once(VIEW_PATH.'header.inc.php'); ?>

	<?php foreach($posts as $post): ?>

		<h4>
			<a href="read.php?id=<?php 
				echo $post->id;?>"><?php 
				echo $post->title;?>
			</a>
		</h4>

		<p>
			<?php echo $post->content;?>
			<?php echo $post->created;?>
		</p>

	<?php endforeach; ?>

<?php require_once(VIEW_PATH.'footer.inc.php'); ?>

Read View

<?php require_once(VIEW_PATH.'header.inc.php'); ?>

	<h3><?php echo $post->title; ?></h3>
	
	<p>
		<?php echo $post->content; ?>
		<?php echo $post->created; ?><br />
			
		<a href="update.php?id=<?php echo $post->id; ?>">Update</a>
		<a href="delete.php?id=<?php echo $post->id; ?>" 
			onClick = "javascript: return confirm
				('Are you sure you want to delete?');">Delete</a>
	</p>

<?php require_once(VIEW_PATH.'footer.inc.php'); ?>

Upsert View

<?php require_once(VIEW_PATH.'header.inc.php'); ?>

	<form method="POST" action="<?php 
		echo sanitize_output($_SERVER['REQUEST_URI']);?>">

		<p>						
			<label for="title">Title</label><br />									
			<input id="title" name="title" type="text" value="<?php 
				echo sanitize_output($title); ?>" autofocus/></p>

		<p>
			<label for="content">Content</label><br />
			<textarea id="content" name="content"><?php 
				echo sanitize_output($content);?></textarea></p>
		
		<p>
			<input type="submit"/></p>

	</form>

<?php require_once(VIEW_PATH.'footer.inc.php'); ?>
  • Notice that we’ve consolidated the view code from our create and update pages into a single view file called ‘upsert.view.php’.

Controllers

Now that we’ve stripped all data and presentation logic out of our base pages, our base pages have become our controllers. The controller will receive the initial user request and figure out what to do with it. If it needs blog post data, the controller will call the model. If it needs to display something, the controller will call the view. Notice, that our controllers are almost identical to our base pages from Example 3. The only difference is that our view code is now imported into the page as needed using PHP’s require_once function.

List Controller

// Initialize site configuration
require_once('includes/config.inc.php');

// Get posts from database
$posts = Post::getAll();

// Include page view
require_once(VIEW_PATH.'index.view.php');

Create Controller

// Initialize site configuration
require_once('includes/config.inc.php');

// Initialize form values
$title = NULL;
$content = NULL;

// Check for page postback
if ($_SERVER['REQUEST_METHOD'] == 'POST') {

	// Get user input from form
	$title = $_POST['title'];
	$content = $_POST['content'];

	// Execute database query
	$post = new Post();
	$post->title = $title;
	$post->content = $content;
	$post->save();
		
	// Redirect to site root
	redirect_to('.');
}

// Include page view
require_once(VIEW_PATH.'upsert.view.php');

Read Controller

// Initialize site configuration
require_once('includes/config.inc.php');

// Check the querystring for a numeric id
if (isset($_GET['id']) && intval($_GET['id']) > 0) {
	
	// Get id from querystring
	$id = $_GET['id'];
	
	// Execute database query
	$post = Post::getById($id);
	
} else {

	// Redirect to site root
	redirect_to('.');
}

// Include page view
require_once(VIEW_PATH.'read.view.php');

Update Controller


// Initialize site configuration
require_once('includes/config.inc.php');

// Check the querystring for a numeric id
if (isset($_GET['id']) && intval($_GET['id']) > 0) {

	// Initialize form values
	$title = NULL;
	$content = NULL;

	// Get id from querystring
	$id = $_GET['id'];
		
	// Check for inital page request
	if ($_SERVER['REQUEST_METHOD'] == 'GET') {

		// Execute database query
		$post = Post::getById($id);
							
		// Set form values
		$title = $post->title;
		$content = $post->content;
	} 
	
	// Check for page postback
	if ($_SERVER['REQUEST_METHOD'] == 'POST') {
				
		// Get user input from form
		$title = $_POST['title'];
		$content = $_POST['content'];

		// Execute database query
		$post = new Post();
		$post->id = $id;
		$post->title = $title;
		$post->content = $content;
		$post->save();
					
		// Redirect to site root
		redirect_to('.');	
	} 

} else {

	// Redirect to site root
	redirect_to('.');	
}

// Include page view
require_once(VIEW_PATH.'upsert.view.php');

Delete Controller

// Initialize site configuration
require_once('includes/config.inc.php');

// Check the querystring for a numeric id
if (isset($_GET['id']) && intval($_GET['id']) > 0) {
	
	// Get id from querystring
	$id = $_GET['id'];
	
	// Execute database query
	$post = new Post();
	$post->id = $id;
	$post->delete();	
}

// Redirect to site root
redirect_to('.');

Next

Playing around with our data access layer. Migrating to MySqli.
Simple Blog – Example 5

Download

You can download the source code for each example at box.net.
Download Source

Advertisements

One thought on “Simple Blog – Example 4: MVC

  1. Why not a Posts Controller instead of the seperate controllers you use here? But nice article to show the differences in coding and the benefits of some of them. Thanks!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s