HMVC: an Introduction and Application

HMVC: an Introduction and Application

Tutorial Details
  • Technologies: HMVC, PHP, CodeIgniter
  • Difficulty: Intermediate
  • Estimated Completion Time: 60 minutes

This tutorial is an introduction to the Hierarchical Model View Controller(HMVC) pattern, and how it applies to web application development. For this tutorial, I will use examples provided from the CodeIgniter from Scratch series and demonstrate how HMVC can be a valuable modification to your development process. This introduction assumes you have an understanding of the Model View Controller (MVC) pattern. We suggest you read our introduction to MVC to get acquainted with the topic before tackling this tutorial.


What is HMVC?

HMVC is an evolution of the MVC pattern used for most web applications today. It came about as an answer to the salability problems apparent within applications which used MVC. The solution presented in the JavaWorld web site, July 2000, proposed that the standard Model, View, and Controller triad become layered into a “hierarchy of parent-child MCV layers“. The image below illustrates how this works:

Each triad functions independently from one another. A triad can request access to another triad via their controllers. Both of these points allow the application to be distributed over multiple locations, if needed. In addition, the layering of MVC triads allows for a more in depth and robust application development. This leads to several advantages which brings us to our next point.


Why should I use HMVC?

Key advantages to implementing the HMVC pattern in your development cycle:

  • Modularization: Reduction of dependencies between the disparate parts of the application.
  • Organization: Having a folder for each of the relevant triads makes for a lighter work load.
  • Reusability: By nature of the design it is easy to reuse nearly every piece of code.
  • Extendibility: Makes the application more extensible without sacrificing ease of maintenance.

These advantages will allow you to get M.O.R.E out of your application with less headaches.


Setting up HMVC in CodeIgniter

To add extra depth to the CodeIgniter from Scratch series, we will be viewing today’s examples in CodeIgniter. I will lead us though the steps needed to get CodeIgniter working with HMVC. Once we’re done with that, I’ll provide a couple of examples. Let’s begin!

Preface

To run web applications, you need a web server on your computer if you are not working remotely. Here are recommendations with links to installation instructions:


Step 1. Download and Install CodeIgniter

Go to codeigniter.com and click the “Download CodeIgniter” link. If you know how to install it and want to skip past this step click here

Extract the contents of the zip file to your web server’s document root.

Rename the “CodeIgniter_1.7.2” folder to “hmvcExample“.

Move the “hmvcExample/system/application” folder to “hmvcExample/application“. This is common practice with CodeIgniter. The purpose of doing this is to separate the application from the core of the framework. We should now have a directory that looks like the image below:

Open “hmvcExample/application/config/config.php” in your editor of choice.

Edit the site base url to match the location of your install. In my case I would change

$config['base_url'] = "http://example.com/";

into

$config['base_url'] = "http://localhost/hmvcExample/";

Save your changes and close “hmvcExample/application/config/config.php

Test that we have a working version of CodeIgniter. Open your browser and check your “http://yourhost/hmvcExample/”.
You should be greeted with the “Welcome to CodeIgniter” screen below:

That’s it! You have successfully downloaded and installed CodeIgniter. Now we will move on to making it work with the HMVC extension.


Step 2. Download and Install HMVC Extension

Download version 5.2 of the modular extension from the CodeIgniter Wiki.

In the contents of the zip file are three php files:

Move these three files into the “hmvcExample/application/libraries/” folder.

Recheck your browser. You should still see the Welcome to CodeIgniter screen.

It’s time to add the modules. Create the following directory structure “application/modules/welcome/controllers/“.

Move the “application/controllers/welcome.php” to “application/modules/welcome/controllers/welcome.php“.

Recheck your browser. You should still see the Welcome to CodeIgniter screen.

Create the folder “application/modules/welcome/views/

Move the “application/views/welcome_message.php” to “application/modules/welcome/views/welcome_message.php“.

Do a final check on your browser. You should still see the Welcome to CodeIgniter screen.

That’s it! Modular Extensions is installed correctly.


Login Module Example

Now that we have our HMVC enabled instance of CodeIgniter, I will demonstrate some short examples. For our first example I will show how you can apply user access restrictions to pages or entire modules.

Download and unzip CodeIgniter from Scratch Day 6 source files into your web server. You should end up with a folder called “ci_day6/” alongside our “hmvcExample/

Create the “login” module in our “hmvcExample/application” directory. It should end up looking like this

	hmvcExample/application/modules/login/controllers/
	hmvcExample/application/modules/login/models/
	hmvcExample/application/modules/login/views/

Create the “site” module in our “hmvcExample/application” directory. It should end up looking like this

	hmvcExample/application/modules/site/controllers/
	hmvcExample/application/modules/site/models/
	hmvcExample/application/modules/site/views/

TIP: When working with modules I keep a folder named RENAME with the three empty folders controllers, models and views. This saves me a little bit of time anytime I wish to create a new model.

Now we copy over the login module files from “ci_day6/” to our “hmvcExample/“.

	ci_day6/application/controllers/login.php
	ci_day6/application/models/membership_model.php
	ci_day6/application/views/login_form.php
	ci_day6/application/views/signup_form.php
	ci_day6/application/views/signup_successful.php

Copy/Move each of the above files over as listed below

	hmvcExample/application/modules/login/controllers/login.php
	hmvcExample/application/modules/login/models/membership_model.php
	hmvcExample/application/modules/login/views/login_form.php
	hmvcExample/application/modules/login/views/signup_form.php
	hmvcExample/application/modules/login/views/signup_successful.php

Next we copy over the site module files from “ci_day6/” to our “hmvcExample/“.

	ci_day6/application/controllers/site.php
	ci_day6/application/views/logged_in_area.php

Copy/Move each of the above files over as listed below

	hmvcExample/application/modules/site/controllers/site.php
	hmvcExample/application/modules/site/views/logged_in_area.php

The last files to copy over are the global views and CSS and image files. The asterisk (*) denotes folder and all its contents including sub folders

ci_day6/css/*
ci_day6/img/* 
ci_day6/application/views/includes/*

Copy each of the above folders and all their content over as listed below

hmvcExample/css/*
hmvcExample/img/*
hmvcExample/application/views/includes/*

Open “hmvcExample/application/config/autoload.php” and edit it to look like the this:

$autoload['libraries'] = array('database', 'session');	// Need to Autoload DB and Session
/*
| -------------------------------------------------------------------
|  Auto-load Helper Files
| -------------------------------------------------------------------
| Prototype:
|
|	$autoload['helper'] = array('url', 'file');	
*/

$autoload['helper'] = array('url', 'form');		// Need to autoload url and form.

If you have not already done so from step one, open “hmvcExample/application/config/config.php” and edit it so that the base url is set to your appropriate location.

$config['base_url'] = "http://localhost/hmvcExample/";	// web address. WARNING keep trailing / 

Open “hmvcExample/application/config/database.php” and add the appropriate links to your database.

$db['default']['hostname'] = "localhost";		// location of DB server
$db['default']['username'] = "YOUR USERNAME HERE";	// username you use to connect
$db['default']['password'] = "YOUR PASSWORD HERE";	// associated password
$db['default']['database'] = "ci_series";		// The database you want to use

Open your browser to test that the login page displays “http://localhost/hmvcExample/index.php/login

Now to make this login function, we need to create the membership database table. For this, we need to create a table in your PHPMyAdmin.

Select or create your “ci_series” database.

In the sQL tab, paste the code below into the textarea and click go

CREATE TABLE  `ci_series`.`membership` (
`id` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`first_name` VARCHAR( 32 ) NOT NULL ,
`last_name` VARCHAR( 32 ) NOT NULL ,
`email_address` VARCHAR( 64 ) NOT NULL ,
`username` VARCHAR( 32 ) NOT NULL ,
`password` VARCHAR( 32 ) NOT NULL
) ENGINE = MYISAM ;

With the membership table created, we click on the create account link on the login page and add a user to the database.

Login in as the user and confirm that you are now in the “site/members_area” of the site. It should look similar to the image below:

Click “logoff” link and try to manually go back to the members area. you will see that you no longer have permission to do so.

So we have our triads grouped, but we are still not quite in HMVC mode yet. In the site controller we find a function called is_logged_in().

	function is_logged_in()
	{
		$is_logged_in = $this->session->userdata('is_logged_in');
		if(!isset($is_logged_in) || $is_logged_in != true)
		{
			echo 'You don\'t have permission to access this page. Login';	
			die();		
		}		
	}

This is a login related function. In MVC mode, this is required because site cannot access login. With HMVC we can fix this.

Cut the is_logged_in() function out of “applications/modules/site/controllers/site.php

Save site.php without the is_logged_in() function.

Open “applications/modules/login/controllers/login.php“.

Paste the is_logged_in() function into the class.

Save login.php

Open “applications/modules/site/controllers/site.php“.

	function __construct()
	{
		parent::Controller();
        $this->is_logged_in();
	}

In the __Construct() function, we make the HMVC call to login’s is_logged_in() function, as seen below:

	function __construct()
	{
		parent::Controller();
        // Format: modules::run('module/controller/action', $param1, $param2, .., $paramN);
        modules::run('login/is_logged_in');
	}

MVC 101 Complete

There you have it! We have successfully altered day six code into HMVC format. The site module now requests the login check instead of having to use its own. While outwardly we observe no difference, the site design has fundamentally been changed. All login functions are now where they belong: inside the login triad. This may seem like a lot of work with small reward but it is not so. Any login changes can be made once. The internal structure of the triad can be edited without having to change the entire application in response. Code replication for other controllers is no longer required. Last but not least, all the related code is in one handy location. This tiny step may not WOW you but when we delve deeper into bigger, complex applications, the M.O.R.E. apparent it will become how effective the HMVC pattern is.


Members Section Example

We are now going to uncover more of HMVC’s power. We just demonstrated how to call a module from a controller. There are other places you can do that as well. HMVC was build with the User Interface (UI) in mind. We get to call modules from our views as a result. This is where the power of HMVC can really shine.

When calling HMVC from a view you will use the same modules::run(). There is only one requirement when doing this. The resulting output from the call must be a html snippet and not a complete view. This is because we are already inside a view at the time we call the run function. We will see this in action down the page as we edit the site module views.


Step 1. Edit Login Controller

We are going to create a block which appears on the top of every page with our user’s name, important links, and logout option. Widgets like this are commonplace on sites today. The image below illustrates the end result.

Open “applications/modules/login/controllers/login.php“.

    function cp()
    {
        if( $this->session->userdata('username') )
        {
            // load the model for this controller
            $this->load->model('membership_model');
            // Get User Details from Database
            $user = $this->membership_model->get_member_details();
            if( !$user )
            {
                // No user found
                return false;
            }
            else
            {
                // display our widget
                $this->load->view('user_widget', $user);
            }			
        }
        else
        {
            // There is no session so we return nothing
            return false;
        }
    }

Paste/Write the code above into the login controller.

cp() receives information from the membership_model function, get_member_details(), which we create in the next step. If a user is found we will display the view snippet detailed in step three. From there we should get the desired block illustrated above.

Save the changes you made to login.php


Step 2. Edit Membership Model

You will notice that we called a get_member_details() from the membership_model. This function gets our user information from the database and will be accessed from a few different sources. We are going to work on that now.

Open “applications/modules/login/models/membership_model.php“.

	function get_member_details($id=false)
	{
		if( !$id )
		{
			// Set Active Record where to the current session's username
			if( $this->session->userdata('username') )
			{
				$this->db->where('username', $this->session->userdata('username'));
			}
			else
			{
				// Return a non logged in person from accessing member profile dashboard
				return false;
			}
		}
		else
		{
			// get the user by id
			$this->db->where('id', $id);
		}
		// Find all records that match this query
		$query = $this->db->get('membership');
		// In this case because we don't have a check set for unique username 
		// we will return the last user created with selected username.
		if($query->num_rows() > 0)
		{
			// Get the last row if there are more than one
			$row = $query->last_row();
			// Assign the row to our return array
			$data['id'] = $row->id;
			$data['first_name'] = $row->first_name;
			$data['last_name'] = $row->last_name;
			// Return the user found
			return $data;
		}
		else 
		{
			// No results found
			return false;
		}

Comment your code! It’s a best practice and will help others understand what you wrote.

Line 01: The function call has a default variable $id. This allows us an option of finding a user by ID rather than by username. This made optional by setting it to false in the declaration.

The rest of the function is straight forward and well commented. We query the membership table for a user via username or ID. The result is saved to the $data array and returned. All other outcomes return false.

Save the changes you made to membership_model.php


Step 3. Create User Widget View

The third and final piece to the widget we are creating is the xhtml snippet, which we can put into any other view. This is called by the login controller’s cp() function which we just wrote.

Open “applications/modules/login/views/user_widget.php“.

<code style="font-family: Monaco, Verdana, Sans-serif; 
                 font-size: 12px; 
                 background-color: #f9f9f9; 
                 border: 1px solid #D0D0D0; 
                 color: #002166; 
                 display: block; 
                 margin: 14px 0 14px 0; 
                 padding: 12px 10px 12px 10px;">
	<?php echo $first_name.' '.$last_name; ?> &middot; 
	<?php echo anchor('site/members_area', 'Dashboard'); ?> | 
	<?php echo anchor('site/profile/'.$id, 'Profile'); ?> | 
    <?php echo anchor('site/messages/'.$id, 'Messages'); ?> | 
	<?php echo anchor('login/logout', 'Logout'); ?>
</code>

Note: It is not a good practice to use inline styling. I opted to put this one instance of inline style for the sake of remaining on topic.

This styled code block takes the information passed from the cp() function. We generate the links using CodeIgniter’s URL helper’s anchor() function. More information about the user guide can be found on codeigniter.com.

After working on those three files we will test the “login/cp” page. We should see something like the image below. Note: You need to be logged int to see it. Be sure to do so before checking the page or you will see nothing.


Step 4. Edit Site Controller

The links in the snippet to profile and messages will return an error for the moment. This is ok because we have not created those functions yet. Lets do that now.

Open “applications/modules/site/controllers/site.php“.

<?php
class Site extends Controller 
{
	function __construct()
	{
		parent::Controller();
	}

	function members_area()
	{
		modules::run('login/is_logged_in');
		$this->load->view('logged_in_area');
	}

__construct()
For the purpose of this example we shall remove the…

modules::run('login/is_logged_in');

…from the function so that we can make specific parts private and have other parts public.

members_area()
We want only logged in users to access the members dashboard area. So we will use the modules:run HMVC function and call the is_logged_in check from the login controller. We then load the logged_in_area view file which will be edited further down the page.

	function messages()
	{
		modules::run('login/is_logged_in');
		$this->load->model('login/membership_model');
		$user = $this->membership_model->get_member_details($this->uri->segment(3));
		if( !$user )
		{
			// No user found
			return false;
		}
		else
		{
			// display our widget
			$this->load->view('member_messages', $user);
		}				
	}

messages()
Like members_area(), we only want logged in users so we have included the is_logged_in check. We have already written the code on how to get user details from the database so we will load the login model, membership_model. This will allow us to get the user information via the get_member_details() function. The third URI segment being passed into that function is an id for the user we wish to get messages for. For example, if the url was:


http://localhost/hmvcExample/index.php/site/messages/43

Then our function get_member_details() would be receiving “43″ as an input variable. Depending on the result of get_member_details(), we are either shown the view: member_messages or we get nothing (as a result of a failed query).

	function profile()
	{
		$this->load->model('login/membership_model');
		$user = $this->membership_model->get_member_details($this->uri->segment(3));
		if( !$user )
		{
			// No user found
			$data['main_content'] = 'member_profile';
			$data['notice'] = 'you need to view a profile id';
			$this->load->view('includes/template', $data);
		}
		else
		{
			// display our widget
			$user['main_content'] = 'member_profile';
			$this->load->view('includes/template', $user);
		}		
	}
}

profile()
Just like any social network; we want the profile pages to be public. So we have not included the is_logged_in check. Just like messages, we call the login triad’s membership_model and query the database for our desired user. In this case, if no user is found, we quit a bit more gracefully. We also notify the visitor that an id needs to be specified. With a successful result, we see the member’s profile.


Step 5 Edit Logged In Area View

Open “applications/modules/site/views/logged_in_area.php“.

<!DOCTYPE html>
<html lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
	<title>untitled</title>
</head>
<body>
	<?php echo modules::run('login/cp');?>
	<h2>Welcome Back, <?php echo $this->session->userdata('username'); ?>!</h2>
     <p>This section represents the area that only logged in members can access.</p>
</body>
</html>	

Overwrite the contents of the file with the code above.

Line 08: HMVC is put into action here. Our view calls the “login/cp” function, and echoes out the html snippet exactly where we tell it. Notice how we didn’t have to prepare anything ourselves? It’s all handled internally by login for us. Handy isn’t it?

Save the changes you made to logged_in_area.php. Your finished page should display like:


Step 6. Create Member Messages View

Create a new view: “applications/modules/site/views/member_messages.php“.

<!DOCTYPE html>
<html lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
	<title>untitled</title>
</head>
<body>
	<?php echo modules::run('login/cp');?>
	<h2><?php echo $first_name; ?>'s Messages</h2>
     <p>This could be where the messaging system gets displayed</p>
</body>
</html>	

Write or paste the code above into the newly created file.

This view is pretty much just a clone of the members area to test that login holds on multiple pages. There is one difference: we fished some information from the login module’s membership_model. This is shown as the $first_name variable.

The point of getting user information here would be to pass it on to a module which would return a snippet with the user’s messages.

Save the changes you made to member_messages.php. Your finished page should display like:


Step 7. Create Member Profile View

Create a new view: “applications/modules/site/views/member_profile.php“.

	<?php echo modules::run('login/cp');?>
    <?php if( isset($notice) ): ?>
    <h2>Member Profile Pages</h2>
    <p><?php echo $notice; ?></p>
    <?php else: ?>
	<h2><?php echo $first_name; ?>'s Profile</h2>
     <p>Put all the good wholesome profile info here!</p>
	<?php endif; ?>

Write or paste the code above into the newly created file.

We have an if statement which detects whether a user was found or not. If not, we get brought to an error page stating we need an ID to view a profile.

Again, we retrieve the user information. Just like messages we would use this to retrieve the user’s friend list, latest blog entry, and activity feed, etc.

Save the changes you made to member_profile.php. Your finished page should display like:

What Happens When We Logoff?

Because we want the profile pages to be public, it should still display. Minus the user widget of course.

When logged in, and we go to profile without a third uri segment we see our own profile. Logded off, we will be shown the error below.

We should not be able to view the message or dashboard. When we check the messages page we are greeted with this:

We’re Done

That’s it! We have added more depth to our initial example and demonstrated the different ways to use HMVC.

  • Call modules::run() from a controller.
  • Echo modules::run() from a view to display a HTML snippet.
  • Load a model from another module.

I hope this has been an enlightening experience. HMVC is an extraordinary pattern which makes applications more robust. It is well worth the investment. Give it a try. I promise you won’t ever want to go back to vanilla MVC!

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://www.jeba.in Jeba

    that’s pretty detailed tutorial :)

  • pablo

    it seems this technique is only useful when you are developing a large app.

  • http://www.daniel-petrie.com Daniel Petrie

    Sweet, more CodeIgniter goodness.

  • Ed

    Very interesting!!!

    I’m a huge fan of CodeIgnitor and MVC so this was very relevant to me.

    I would just change the title from HVMC: an Introduction and Application to HMVC: an Introduction and Application – no biggy but kind of threw me at first…

  • http://www.developtus.com/ Developtus

    nice but zend framework is better

    • aryan

      I also vote for Zend tutorial series.

      • http://www.johnsthomas.com John

        Third

      • Affaf

        I also agree. It seems CI is always featured..

    • http://www.kevinbradwick.co.uk Kevin

      I agree, this is not a new technique and is already implemented in Zend. I currently work with Yii – the best PHP framework around!

  • http://philsturgeon.co.uk/ Phil Sturgeon

    This is a very detailed article, but there are two important things left to point out.

    Modular Extensions has one powerful feature over Modular Separation, the ability to cross-load modules. Basically you can tell it to “run a controller” which is a very strange way of doing things. This is the main point of ME so is worth mentioning in your article.

    Also worth noting is that Modular Extensions is an older, heavier modular system which is no longer actively developed. Instead the original developer created a different modular system called Modular Separation which I am currently maintaining.

    Finally, Modular Extensions does not work on CodeIgniter 2.0, but Modular Separation does.

    Give it a try, it has a bunch of features over Modular Extensions and won’t break your apps when you upgrade:

    http://codeigniter.com/wiki/Modular_Separation

    • Barry Cogan
      Author

      Hey Phil

      This is merely an introduction to HMVC as best as it can be applied to CodeIgniter. I do touch on running the controllers in the second example of this tutorial. Rather than running the entire controller(much like you would a model) i focus on running specific functions from the view. I believe this method is more true to the nature of HMVC as a pattern.

      I will of course give Modular Separation a look. If it is more for organisational benefit I don’t think it would be of use for the purpose of demonstrating HMVC.

    • http://www.point4media.nl Wijnand

      Interesting article. Although CI is a nice framework, hacking the core to support such an important feature doesn’t sound right to me. The funny thing is that I started developing my own framework already 4 years ago and very soon came across the request -> controller -> model -> view limitation.

      That’s why I developed a function load_module to load other controllers into the current controller handling the request.

      Why is it so strange to run a controller? In my framework I have multiple instances of modules which can interact with each other and load core objects and module objects.

      If your argument is that it’s against the MVC principles i would suggest you wake up and start coding right now to support cross-load modules in Modular Seperation because in my opinion that’s the way to go.

      • Barry Cogan
        Author

        It needs to be said that “Modular Extensions” does not involve any editing of the framework’s core files. It extends the current functionality.

        There is misunderstanding of the HMVC pattern here. Modular Separation is a step towards, but is not an implementation of, HMVC. The principle aim of the pattern is to give the MVC triads (or modules as the are called in CodeIgniter,) the ability to request information from another triad via it’s controller.

        Just having the MVC triads grouped in folders is not HMVC. I too mistakenly though it was until I studied the topic. There’s a lot more to it than just being a useful organisation feature I’m afraid.

        So as it stands, HMVC for CodeIgniter 1.7.2 is best implemented with Modular Extensions as demonstrated above. I am sure there will be an implementation of HMVC for CodeIgniter 2.0 by the time it is released

      • http://brettic.us Brett Millett

        “Hacking the core” is an unfair assessment. There are 3 library files that go in the application folder. Only one overrides any native Codeigniter functionality: MY_Router.php. And it simply extends the core CI_Router.php file (as is very easy to do with Codeigniter because this is the way Codeigniter was designed to work.) Yes, it’d be nice if Codeigniter supported this out of the box (perhaps 2.0?) but then again, many developers like CI because it’s not bloated (like Zend FW for example.)

      • http://www.point4media.nl Wijnand

        Ok your right, I meant that a framework has to support HMVC out of the box (like Kohana, Doophp or my own framework ;-)

        The problem I had with CI is that you’ll very soon run to its limitations, like HMVC or the problem where you’re not allowed to share module widgets across different pages (Like a poll or something).

        Modular extensions is a great step forward to support HMVC and share components across pages and controllers and I would strongly advise CI to adopt this feature in future versions instead of Modular Separation (Sorry Phil)

        I once joined a discussion on Sitepoint forums where people run into similar problems because of the limitation of one controller par request (A page often has different components) The solutions provided where really bloated with view factories and decorator patterns all because of the fact it’s against the MVC principles.

        In my opinion when a framework does not meet your requirements it’s a bad framework. Thus developers should not always ask themselves is it MVC or not and have endless discussions about it. The real question would be: does it help people develop faster.

        Hehe don’t talk about Zend, some really useful components, but requires about a zillion classes to print Hello world. I hate glueing…

    • http://brettic.us Brett Millett

      @phil, What a great opp for you to do a Modular Separation tutorial on nettuts! Can we really vote around here?

    • 2think

      Wijnand,

      Phil was clearly not stating that HMVC is against MVC. You would know that from the following:

      1. His maintenance and significant contributions to both HMVC and Modular Separation and CodeIgniter in general over the years

      2. His hundreds of posts in the Codeigniter community that cover a range of topics – all within MVC

      3. His CMS, PyroCMS, which had HMVC (I think Matchbox) but may be migrating to Modular Separation (and downloaded several hundred times I believe)

      4. His blog where he offers up helpful techniques for new and experienced CI developers

      I think his post was quite clear and unambiguous; nowhere does he argue that any of this is against MVC.

      Why you felt the need to tell someone to “…wake up…” (and thereby implying the person is somehow not fully aware) by stating your own inaccurate assumption is puzzling.

      Some of the work Phil and several others have contributed to CodeIgniter – quite a few to name here – make just these types of tutorials possible.

      • http://www.point4media.nl Wijnand

        2think

        I never stated that the contributions Phil made where arguable, so I don’t understand why you’re bringing this up. Second I never wanted to offend Phil and I do read his blog. I love the simpleness off CI and I really do appreciate the work of Phil and others. He’s is a great coder.

        The point is that Modular Separation and Modular extension are two different systems. In my opinion Modular Separation is noting more than just organizing your controllers and models etc into folders.

        That’s why I commented that Modular Separation isn’t such a great feature over Modular extensions. Therefor I really would like to see if Modular Separation gets implemented in CI 2.0 it will be including cross-module loading and loading modules from the view.

        Just my 2 cents…

  • http://www.pockyworld.com pocky

    HMVC in a PHP4 framework => OH YEAH.

  • Ümit Ünal

    Thanks @Barry Cogan.Nice tutorial.

    • Barry Cogan
      Author

      You are most welcome Ümit. I am delighted to be able to give back to the community.

  • Kelly Te Huna

    Kohana 3 does HMVC straight out of the box and it’s style is VERY similar to Codeigniter, since it was originally a CI fork. That’s another option for you :)

  • EllisGL

    Kohana PHP 3 has the “H” from the get go, and it’s PHP 5 only =)
    I’ve covered in my Kohana PHP 3 tutorial series (http://www.dealtaker.com/blog/2010/02/25/kohana-php-3-0-ko3-tutorial-part-5/)

    • Barry Cogan
      Author

      Indeed it does, Ellis. I chose CodeIgniter precisely because it does not have native support for HMVC. In addition this tutorial dovetails nicely with the CI From Scratch series here at net.tuts.

      • EllisGL

        I did forget one thing: Great job on the tutorial. =)

  • http://www.xeoscript.com Muhammed K K

    Thanks, I really like this article. I am a huge fan of CodeIgniter.

  • Bumpy

    HMVC ? Kohana 3 for sure !

  • http://ds.laroouse.com esranull

    very nice article thanks a lot

  • http://firs.org.ua Yura

    Thanks for the lesson.
    Do not show you in Yii framework is HMVC?
    Sorry for my english;)

  • http://aftrclass.com Afiqfaidhy

    Nicely written, I’ve been trying to apply mvc on my application written for educational purpose and this small introduction will be able to help me alot just like the videos series :) Thanks again.

  • Marshall

    Just a note, you should change the mac instructions under the “preface” section to use MAMP, because by default, Web Sharing doesn’t support php, you have to do a bunch of manual editing to configuration files to get it to work.

    MAMP is pretty much the mac equivalent of XAMPP (I know XAMPP does run on both systems, but MAMP is more of a native mac app).

  • Jam

    I’m thinking of a new, BETTER pattern. This pattern will place each line of code into its own folder, which itself will be split into two subfolders: one for a commented description of the line of code, and one for the code itself. These code line folders will, of course, exist in MVC-style parent directories.

    What do you guys think? It’s the web development pattern of the future. Hop on board now!

    • John

      Make sure you use the ActionScript /com/domainname/MVC_directories layout too, for everything.

    • http://brettic.us Brett Millett

      Kidding aside, MVC really is a good model for application development, but yes, there are about 10 billion PHP frameworks out there it seems. Thanks a lot Rails…no really, I mean it! :)

    • http://dynamicsearch.com.au Dale

      MVC is actually quite good way to bring together an application and make a lot of use of previously written code. I decided to employ it for a WordPress plugin, one which is a lot bigger then your usual plugin, and it has made the development process a lot faster.

    • Iceman

      +1 Exactly what I was thinking. This “new pattern” just seemed like another case of over-engineering (if you’ve read the book Code Complete 2, you’ll know what I’m talking about). I’m all about the MVC pattern and modularization of components in order to reduce dependency issues in applications, whether it be desktop or web-based. But there is a certain point when you start to use, as I would call it, “a shotgun to kill a mosquito”. I’m sure this has its place somewhere, like you know, an operating system, satellite tech, missile guidance systems, etc.

      The most important lesson we should be learning here is, “the right solution for the right problem”. Not some newfangled, let’s all jump on the bandwagon ’cause this is the new web 4.0 way to write an web application.

      Example, it’s like a programmer asking a fellow programmer how to write a procedure for a certain web related problem in JavaScript, and the other programmer tells him, “You don’t, you use jQuery.”

      • Barry Cogan
        Author

        Let me first clarify that this is not some “new pattern” It has been around on some form since 1983.

        Your quote: “I’m all about the MVC pattern and modularization of components in order to reduce dependency issues in applications, whether it be desktop or web-based” is pretty much HMVC misinterpreted, or almost implemented. To make it actually HMVC, the modules need to be able to request information from one another which creates a whole new level of interaction. It also has the added bonus of simplifying code and provides a write-once-use-anywhere development approach.

        It is not as “overkill” as you make it sound.

      • Robby

        Hey your example should read, Its like a programmer asking a fellow programmer how to write an MVC application that scales well and remains easy to maintain, and the other programmer tells him, ” you don’t, you use HMVC.”

        You clearly didn’t read the first two paragraphs of the tutorial =]

      • http://www.point4media.nl Wijnand

        Very true Barry, the shotgun comes in when you try to reach modular separation in a framework when its not designed to have it in the first place.

        If you adopt the whole (H)MVC pattern you will definitely come to a point where you want to share modules or components amongst each other and use it in your views. It’s not a new way of developing, it’s a core feature every serious framework should have.

  • http://davgothic.com Dav

    Very nice and in-depth tutorial!

    Would much rather it have been based on Kohana 3 though as it’s HMVC from the off and in my opinion, it’s a much better framework and deserves some recognition.

  • Andrea

    That’s seems sweet :) but what is now the security level and is there some performance improvment?

  • http://www.sz-media.org snaKeSz

    Great one, i started with codeigniter a few weeks ago and i had to stop at one important point:

    create an index site, where you can load your content in the middle and a login/latest news… controller at a sidebar.

    I would be soooooo happy if you can do another tutorial for this problem!

    NETTUTS rules!

    • Barry Cogan
      Author

      Once you get through the tutorial it should be possible for you to do that, without too much difficulty, using the second example. :)

    • http://dynamicsearch.com.au dale

      Hello SnakeSz and world

      I would also love to see a tut (could be premium) which does an end-to-end application in CI rather then just modules.

      Dale

      • Barry Cogan
        Author

        Hey Dale,

        That is indeed something I will demonstrate in the future.

  • http://spotdex.com Davidmoreen

    Lol, and i was just getting use to using MVC…

    • Barry Cogan
      Author

      It’s the next step from the CI From Scratch series you were following. Once you get used to it you’ll never want to go back!

  • http://www.jsxtech.com Jaspal Singh

    Nice tutorial on HMVC.
    CodeIgniter is best.
    Thanks for sharing.

  • http://www.codeforest.net Codeforest

    Thanks for sharing and effort. Great tut.

  • http://www.engram.nu Niklas

    Hi Barry,

    Thanks for this article! I have implemented HMVC in a client project and I’m very satisfied with the result. I especially like the way you can divid user and admin actions into two controllers and with a bit of .htaccecss magic get http://www.example.com/user and http://www.example.com/admin/user to point to your user module and select the correct controller.

    Splendid!

  • begs

    Thank you for this very nice and well written tutorial.

    I have one question:
    Having different modules containing Models Views and Controllers for easy reuse in other projects is a very good thing for sure.

    But if you place your CSSS,JS and Images in only one global folder, it gets very hard to find the files for each module.

    Is there a way to “modularize” assets (CSS, JS, Images etc.) also?

    • Barry Cogan
      Author

      Hey Begs,

      There are so many different options here. Anything from simply splitting files into sub directories to building a template system. The sky’s the limit.

  • http://www.kieransenior.co.uk Kezzer

    Is this not just the same as areas in ASP.NET MVC? Where your MVC’s are grouped into logical areas so they are self-contained yet provide the concept of a hierarchical structure to your website?

    • Barry Cogan
      Author

      If the logical areas can make requests to other ones within the one http request, yes.

      If it is just for structure, then no.

  • http://threadbarecanvas.com Siriquelle

    Interesting article for morning coffee reading.

  • Marcin

    Thanks for the excellent article – right on time for my current project.

    As a sidenote, it seems that someone is making sure that you have an off-site backup of your content :-) – http://www.2mknetwork.com/hvmc-an-introduction-and-application.html

    • Barry Cogan
      Author

      Your welcome Marcin.

      Yes that’s the second one of those I’ve seen. Thank you for the heads up.

  • Marcus Schumann

    This was a splendid tutorial! Great job. I like the HMVC better than MVC now. Hadn’t even heard of it before this artice.

    Any tips on where I can find tutorials on how to code a framework with HMVC? And I mean the framework core code, not the application.

    • Barry Cogan
      Author

      A quick google search will lead you to a few good tutorials for building your own framework with HMVC or alternatively you could use the Kohana framework which has native HMVC support.

  • http://twitter.com/rafib Rafi B.

    Kohana 3 is the most amazing light-weight framework around. It is built from grounds up with HMVC in mind. It’s OOP and inheritance are truly almost perfect, so it boggles my mind why people would choose CodeIgniter over Kohana 3…

    • Djkanna

      I would presume that the more newer to PHP frameworks would choose CodeIgniter because of it’s extensive documentation and extremely helpful (not to mention large) userbase,
      which the last time I looked Kohana doesn’t have extensive documentation sure it has documentation but compare theirs to CodeIgniter’s and you’ll most likely see the difference between them and why it looks so good, not only to the newer people to this field but the ones that have been here for awhile.

      “Kohana 3 is the most amazing light-weight framework around.” – That’s clearly your opinion I cannot comment on this because I’ve rarely used Kohana so honestly I wouldn’t know but I sure do love CodeIgniter!

      As much as the whole framework thing is debatable why bother? In all seriousness if Kohana is more suitable for you then fair enough just as some people think Zend Framework is more suitable for them.
      Use the one you find the best for your project(‘s’).

      To the author;
      Great tutorial it was defiantly an interesting read I’ve not really done anything with a HMVC pattern maybe now I will.

  • Marcin

    In my case, one reason would be the availability of truly excellent and exhaustive documentation, plus abudance of high-quality tutorials (kudoz to you, nettuts).

    My projects are not overly complex and I’ve been able to complete them very rapidly thanks to CI. They add some features to a site visited by 250,000 uu monthly, and I’m very happy with the performance. So, why complicate matters?

    With time, and as my needs grow, I may look to other frameworks.

  • http://www.escodent.de Daniel S

    First: Very Good Tutorial!
    I never heard about HMVC before, but its an interesting thing. But i think your example for HMVC is not the best (a simple function is_logged_in() would be right) – and i don’t know what could be an good example for HMVC.

  • http://www.cbesslabs.com Bratu Sebastian

    Yeah, the idea is great. I do wonder however if I would actually use it in a large production website. And the more complex these engineering patterns go, the more I think that there should be a simpler approach.

    Great tutorial !

  • 3may

    Nice tutorial, I like it….

  • Michel

    Very interesting tutorial, and ideal for a CMS that Im working on. Congrats!

  • Ihab

    Great work, nice tutorial and straight to the point
    Keep up the good work Barry Cogan. CHEERS :)

    I am wondering what is the best practice to implement dx_auth and template libraries with modular extensions library.

    Indeed many thanks.

    Junior Developer
    Ihab Arnous.

    • Barry Cogan
      Author

      I gave up on trying to integrate Authentication libraries/Plugins and wrote my own. Using the basic login system from the tutorial is a great place to start.

  • http://www.soamazing.eu Rick

    This may not ‘wow’ me?! Damn I have been looking for this for a long while! I knew I could do work way much more organized by grouping function, I just never figured out how. HMVC seems the way to go for me! Thanks for this tutorial!

    • Barry Cogan
      Author

      Glad you like it Rick! I hope it works out for you :)

  • http://superdit.com aditia

    why not use KohanaPHP 3 instead, it have hmvc on the default

    • Barry Cogan
      Author

      CodeIgniter was chosen because we have a series dedicated to it. This provides an extra layer of depth to the series.

  • ben

    I had the tutorial working until I got to the part where I pasted in

    modules::run(‘login/is_logged_in’);

    After I did this and tried to login, I get this error.

    Fatal error: Call to undefined method Modules::run() in C:\wamp\www\modularci\ci\application\modules\site\controllers\site.php on line 9

    Any help?

    • ben

      Nevermind. I had the Modular Separation files in the “libraries” folder instead of the modular extention ones. Sorry!

      • Barry Cogan
        Author

        Not to worry! I am glad you got it figured out! :)

  • http://www.ifadey.com Fawad Hassan

    Wao!
    HMVC is simply amazing. I always faced problem when modularizing my apps.
    Thanks for such a great tut :)

    • Barry Cogan
      Author

      You are most welcome Fawad!

  • http://www.pcbsd.pl piker

    Nice tutorial – with minor mistakes

    in config/autoload.php you should add ‘form’ helper

    in this function
    function get_member_details($id=false)

    this character } is missing at the and

    • Barry Cogan
      Author

      Thank you for pointing those out.

      We’ll get those article typos corrected.

  • http://zackhovatter.com Zack Hovatter

    I’ve had a hard time understanding the HMVC design pattern until now.. Thanks again NetTuts :)

  • Bhavani

    Awesome Tutorial!
    This place is so good. I wish I had known about this website. It would have saved my $120,000 spent at college.

  • Maderic

    How can separete frontend and backend using this ? thanks

    • Barry Cogan
      Author

      I may be misunderstanding your question but it should be just as simple using different modules. I’ve stopped looking at applications as frontend and backend. Now I go by usergroup. It just makes more sense for me personally.

      • Cristian

        Barry, very nice tutorial. You brought some light on the HMVC implementation in CodeIgniter.

        But I had to ask you what about the usergroup replacement for frontend/backend approach!?!? What do you mean?!!?

        Thanks!

      • Barry Cogan
        Author

        Cristian,

        It’s a little much to explain in a comment but I’ll try put it in a nutshell.

        Essentially you design the backend into the frontend. If a user and admin visit the same page the admin can edit/moderate right there without having to go into a separate backend. Think of it as WYSIWYG administration.

        I hope that clears things up a little for you.

      • Cristian

        Thanks Barry for explaining that. I thought you mean that, but I am the kind that sticks to the backend approach.

  • http://www.mahbubblog.com Mahbub

    It’s unfortunate that it doesn’t work in CI 2.0. I couldn’t simply upgrade one of my app to ci 2.0 just because i used HMVC there. Now to port it to 2.0 i have to change a lot :S

    • http://www.tejassuthar.co.in Tejas Suthar

      What a detailed tutorial…!! I really appreciate this kind of artile on this site.

      Many Thanks to net tuts. I am always a huge fan of net tuts.

  • http://jatazoulja.com Peter Eman Abastillas

    any good templating library that works well with HMVC? I tried the parser lib and I had some issues with it…

  • kendelarama

    Hi, nice read, but i have this specific error that when i tried to load a view file inside a module that is inside a folder it gives me an error that it cannot load,

    example:

    application/modules/views/folder_a/my_form.php
    it dind’t work if i try to $this->load->view( ‘folder_a/my_form’ );

    but if i put the file 1 folder up it works.
    application/modules/views/my_form.php

    how can i access the my_form.php if i put it inside a folder?

  • David

    Thank you very much! I love MVC, but after reading about HMVC, I think this is what I wanted – modules. :D

  • http://www.pcbsd.pl piker

    It’s OK
    but this construction does not work:

    class Ztm1 extends Controller
    {

    function Ztm1()
    {
    parent::Controller();
    $this->template['module'] = ‘modul1′;
    }

    function run($view){

    var_dump($this->template);
    $this->template['view'] = $view;
    var_dump($this->template);
    $this->load->vars($this->template);

    $this->load->view(‘loader’);
    }

    function index(){
    $this->run(‘include’);
    }

    }

  • http://www.tiffanybestsilver.com Discount Silver Jewelry

    This is the wonderful thing i spend long time to find it.