web development articles and portfolio

Custom PHP MVC Tutorial: Part 4, Models

Posted on 14-10-2011

In part 3, we discussed creating the controller classes, and the example used (the Home controller) to show how a controller class might look didn't seem to reference a model at all. Technically, the model in that example was inbuilt into the method of the controller - not ideal. In this part 4, I'll cover how you may go about improving on that design with a concept sometimes referred to as Skinny Controller, Fat Model.

Of course, in our aforementioned example in part 3, the entire model was just a simple string, and a pretty small one at that. You can probably get away without separating models from controllers when they're like that. However, in the real world, it is pretty rare a string is the only thing we need to send our view. We often need to send records from a database, page titles, HTML metadata, session data, and an endless list of other stuff, all in one hit. Having all this code sit in a method of our controller class will not only make your controllers extremely messy very quickly, it is also terrible for code reusability - a pillar of Object Orientation.

This is where models come in. Models are basically just data setters and getters. In the context of this PHP MVC framework, a model is a class you can create an instance of in your controller's action method to get data from for the view to display. A model instance should also take data that users input for saving, or whatever it is you need to do with it. It effectively means controller methods are kept as lean as possible, and if you design your models well, they won't be so bad either because the same model can be used across multiple controller methods/actions where possible.

How you actually go about logically separating your model classes is up for debate. In some projects, it may make sense to create a model class for all controllers, and match the two method to method. In other projects, it may make sense to create models that more closely resembling your database structure. In other projects still, your controller structure may already be much like your database. It really comes down to your individual requirements at the time. In the following example, the model, which would exist in /models/home.php, is simply a reflection of the controller's structure:

class HomeModel {
public function Index() {
return array("Value 1", "Value 2", "Value 3");
}
}

And how do we use this Model? Like so, in our controller:

class Home extends BaseController {
protected function Index() {
$viewmodel = new HomeModel();
$this->ReturnView($viewmodel->Index(), true);
}
}

What we have here now is the controller's Index action/method creating an instance of the model, and then sending the return data of the Index method for that model to the ReturnView controller method, which is the method defined in the abstract BaseController class allowing the controller to combine model with view. In this example we end up sending an array to the view. Keep in mind the name of the model class and its method is irrelevant and can be anything - all that matters is we have the actual data layer of the application neatly contained.

Before we move past the model and start talking about the view, it's worth mentioning that, like our controller classes, the model classes could also extend from a base class of its own. It won't be necessary for all model classes, but in some projects most of your models may need something in common, like database access. Rather than create an instance of your DB in every model, you could just create a class like this:

abstract class BaseModel {
protected $database;
public function __construct() {
$this->database = new PDO("mysql:host=localhost;dbname=test", "username", "password");
}
}

If a model class extends from this class, it will have access to the database from $this->database. The usefulness of this can obviously be extended to a lot more than just database access though - you could create an instance of a validator class for common validation patterns across models (e.g. email), a sanitization class for models to easily clean any input data, and so on.

Now that we have our model and controller relationship sorted, we can move on to the final piece of the puzzle - the view.

Part 1 - Introduction
Part 2 - URL mapping and index.php
Part 3 - Controllers
Part 4 - Models
Part 5 - Views
Part 6 - Where to now

Social

Tags

Comments

comments powered by Disqus
TweakTown