bookmark_borderCodeigniter 4 HMVC just like in Codeigniter 3 but simpler.

Ok so you have downloaded CodeIgniter 4, taken a look at it and wondered… How do I incorporate HMVC like I did in CodeIgniter 3?

Well that is exactly what I pondered once I had my fresh, new, shiny installation of CodeIgniter 4 installed on my local server.

My first thought was, “So, how do I setup HMVC on this thing”?

Well after a lot of reading of the CodeIgniter 4 users guide ( you do read that don’t you?) and some messing around, it turns out that it is rather simple.

CodeIgniter 4 has been totally re-written to fully utilise the goodness of PHP 7 but the Key that unlocks it all is “Namespaces”.

Back in CodeIgniter 3 Land, the framework does a lot of the hard thinking for you in regards to “where files, etc” lived.  Having played with CodeIgniter 4 a fair bit now, all I can say is, that was a lazy way to code. On the one hand, you didn’t have to think too hard to get things done. On the other hand, you didn’t have to think too hard ( yes they are the same point). Which resulted in you not thinking too hard.

With CodeIgniter 4, you now have to think a bit more. You have to follow some real OOP rules and do some typing. But a lecture is not needed here. You came here to see how to do this magic HMVC Thing (which might explain things a little bit better).

A basic representation of the CI 4 Folder Structure

So an out of the Box Installation of CodeIgniter 4 folder structure is something like…

  • app\
    • Config\
    • Controllers\
    • Database\
    • Filters\
    • Helpers\
    • Language\
    • Models\
    • ThirdParty
    • Views\
  • system\
    • < stuff in here >
  • public\
    • < The public Files/Folders which could be renamed to public_html>
  • writeable\
    • < stuff in here>

Now, where would you put your Modules Folder? Well there are at least 2 answers. The CodeIgniter User Guide talks about creating a new Folder Outside of app\. So we could put our Modules Folder there ( I have done this and it works).

But for reasons unknown, I opted to put it inside my app/ folder.

So we would have something like…

  • app\
    • Config\
    • Controllers\
    • Database\
    • Filters\
    • Helpers\
    • Language\
    • Models\
    • Modules\
    • ThirdParty
    • Views\

Creating an Admin Module

So let’s say we want to create an Admin Module. In our Module, we will have a Controllers and a View Folder, We will also have an Admin.php Controller, and for good measure, a View file.

  • app\
    • Modules\
      • Admin\
        • Controllers\
          • Admin.php
        • Views\
          • coming_soon_view.php

Now Here Comes the Magic

Our Admin Controller is going to look like…

<?php 
namespace App\Modules\Admin\Controllers;

use App\Controllers\BaseController;

/**
 * Class Admin
 */
class Admin extends BaseController {

    public function index() {
      echo view('App\Modules\Admin\Views\coming_soon_view')
    }
}

The very important things to note here are…

CodeIgniter has No Clue as to where our new Admin Module resides. So we have to tell it. This is where those magic keywords “namespace” and “use” save the day.

Right now, if you were to type into your URL something like http://mywebsite.com/admin and press Enter, you are going to be very sad. It won’t work.

Consider this… CodeIgniter is Expecting any Controllers to live in the Controllers Folder. The same applies with Models and Views etc.

If you had noticed, for instance, this line for showing the view…

echo view('App\Modules\Admin\Views\coming_soon_view')

Apart from the very new way to load a view using “view()” and not $this->load->view(). Did you notice the very long namespace (Kind of like a path) for the View?

As Our View is living in app/Modules/Admin/Views we have to specifically inform PHP, where to find it. So the notation used is…

App\Modules\Admin\Views\ and the view filename is coming_soon_view. So we get…
echo view(‘App\Modules\Admin\Views\coming_soon_view);

The Rule is, Specify Exactly where something resides… No MORE GUESSING! Which might be a bad thing, if you are lazy, or a great thing as it fully qualifies, documents where everything lives.

So that deals with the View. How about the Controller itself?

Notice the very very 1st Line ( well in my case it is the 2nd line…) which has the namespace command.

namespace App\Modules\Admin\Controllers;

This is declaring where in the world ( well in your project ), this Controller resides. It’s effectively a Label. You can think of it as a path, but it’s a unique location where this controller lives.

Now our Admin Class is extending the provided BaseController ( we will change this when we get to building a real project ). So we need to tell PHP where this Class lives.

HINT: Any class you use in your, in this case, Controller Class needs to be fully specified.

So we have to fully qualify what it is and where it lives.

use App\Controllers\BaseController;

How can we call our new Admin Controller from the URL?

I call these kind of Modules or Controllers, FrontEnd Modules/Controllers. FrontEnd Modules/Controllers are those that are accessed directly via the URL.

All the others (Non FrontEnd Modules/Controllers) are called by FrontEnd Controllers. These are your workhorse or task specific Modules/Controllers that are NOT Callable Directly from the URL.

Again, if you attempted to call this from the URL with something like… http://mywebsite.com/admin, you will still be sad as it will not be found. Remember, that this is NOT in the default area where CodeIgniter is expecting to find Controllers. Which is under app\Controllers by default.

So how do we rectify this? The answer is Routes.

In our app/Config/Routes.php file, we have to tell CodeIgniter where our new admin controller lives.

We can use two lines such as…

$routes->get('/admin', '\App\Modules\Admin\Controllers\Admin::index');
$routes->get('/admin/(:any)', '\App\Modules\Admin\Controllers\Admin::$1');

Note: You will need to read up about Routes in the CodeIgniter User Guide. I’ve just covering the basics here.

Line 1. covers the case where we are just calling /admin. i.e http://mysite.com/admin

Line 2. covers the case where are adding a method name or a method name and other parameters etc.

Note: These are both GET commands (HTTP Verbs), which is what a basic web page does when it accesses your website via a browser. It performs a GET action. Again, read the CodeIgniter Users Guide

So right now, if you followed along and tried this out, hopefully it worked for you. if not, drop me a comment and I’ll do my best to help out.

But when things do go wrong, it’s a process of asking yourself some basic questions. Questions like…
Do I have the right “namespaces” declared?
Do I have the right “use” commands?
Do I have the routes set up correctly?

PHP needs to know, where your folders/Files are located. CodeIgniter needs to know what Routes to use.

So we’ve created a FrontEnd Admin Module. This is the Admin Controller we can access directly from the URL. All of our Supporting or Workhorse, Task Specific Modules/Controllers use the very same namespace, use rules as we’ve already learned with the exception of NOT creating any Routes for them.

So in the next Post we will look at how to create and use those.

Cheers!