Please help designing HMVC

From reading a lot, i decided to implement a framework with HMVC pattern, because it suits my needs - CMS with completely modular structure (so i can install/uninstall modules), possibility to use as widgets (like main CMS menu should be stand-alone module).

I cant decompose the controller structure. Questions as follows:

  1. In HMVC, should there be a ‘root’ controller for any page, or there can be many ‘root’ controllers for each section. For example:

index/pages, index/languages, index/users
or
pages/action, languages/action, users/action ?

  1. No matter is it single or multiple controllers, who dispatches that root controller? Is it a different front controller, or a regular controller?

My current structure is as follows:
an Application class that does as system-setup stuff (like ‘Core’ class in Kohana)
folders ‘admin’, ‘shared’, ‘application’. In ‘shared’ i will put modules that are needed both by admin and public. Each of them have ‘modules’ folder. Each module have own controllers, models, views. Other folders not shown here.

admin
   +------ modules
              +------ login
              +------ settings                   

application
   +------ modules

shared
   +------ modules
              +------ products
                         +------ backend
                         |
                         +------ frontend

I have more questions, but cant describe them clearly, I’m sure they will arise along discussion. Thank you :slight_smile:

Czaries, so you basically have special front controller between that is dispatched first and then passed to generic controllers?

I’m thinking of something similiar, now i have a:
Application class (which initializes autoloads, php settings etc.)
Route class (which knows everything about the request URI and corresponding module folder)

Now I thinking either making a front controller between initial request and modules, or trying to implement all in generic controller class.
I want to implement intercepting filters also (such as authorization checks, language setup and anything), but they are better to be executed only once (thats a +1 for front controller).
Also i want be able to dispatch a controller directly in a view to avoid making special widgets, for example:


<div id="sidebar">
<?=$this -> request ('widgets', 'banners')?>
<?=$this -> request ('widgets', 'categories')?>
</div>

where ‘widgets’ is a controller, ‘banners’/‘categories’ is an action.

I have actually been through this whole process with Cont-xt, my own CMS.

  1. Each request is parsed with the AppKernel Router ([URL=“http://github.com/actridge/AppKernel/blob/master/examples/routes_rest.php”]example), and then handed to the “Page” module, which in turn handles everything on that page and dispatches to other modules as needed to build the page content.

  2. My Kernel object is passed to controllers through dependency injection, and is used for all the dispatching. Controller actions are expected to either throw an exception, or return one of:
    a) Boolean false (no content - triggers 404 response if still boolean false when response is being sent)
    b) String Content (in case of JSON requests, etc.)
    c) View object (__toString triggers template render)
    d) Any object with __toString method

Here’s how the application flow ended up for me:

Excellent discussion. My only 2 cents are to take the time to work out a design that you understand, feel comfortable with, and which is flexible enough that you’ll be able to extend it in the ways you anticipate having to grow in the future.

Also, live by abstraction. As long as your OOP classes make sense, have good semantic names that define the abstractions you’re created, and their class members make sense for the abstraction you’ll be able to tweak and modify pretty sensibly into the future. If you break abstraction, you’ve broken the connection between what your code does and what you think it ought to do. There are many rules you can bend in OOP, but if you’ve lost the ability to determine what’s going on, you’re in a lot of trouble.

Now just need to decide how to dynamically call XXXController, depending on URL.

This is typically refered to as routing. Look at Zend as it’s approach is much more flexible than simpler frameworks like CodeIngitor. It can be simple to design and build with some thought but it can equally be easy to get wrong and the result is your stuck with a URI scheme that might need change in a few months.

You will best off implmenting a front controller which uses the router to determine which controller and action get invoked based on the URI.

Cheers,
Alex

Regarding view output, there’s much clearear. Every controller action decides wheather they need to output anything.


class LoginController extends PageController {
    public function indexAction() {
        //do some stuff
        //render with full page layout
        return $this -> view -> render ('index.tpl');
    }

    public function loginAction() {
        //do some stuff
        if ($login_ok) {
            //just redirect
        }
    }

    public function someAction() {
        //this should render view without a layout/wrappers
        return $this -> view -> renderPartial('other.tpl'); 
    }
}

I just come up with this solution, what do you think?

class View {
    protected $data;
    
    public function assign ($key, $value) {
        $this -> data[$key] = $value;
    }
    
    public function render() {
        $html = '';
        
        if (!empty($this -> data)) {
            foreach ($this -> data as $key => $value) {
                $html .= $key." = ".$value."<br />";
            }
        }
        
        return $html;
    }
}

abstract class Controller {
    protected $childs = array();
    protected $view;
    
    public function __construct() {
        $this -> view = new View();
    }
    
    public function dispatch ($controller, $action, $params=array()) {
        $controllerClass = $controller.'Controller';
        $func = $action.'Action';

        if (empty($this -> childs[$controllerClass])) {
            $c = new $controllerClass;
            
            $this -> childs[$controllerClass] = $c;
            return $c -> $func ($params);
        } else {
            return $this -> childs[$controllerClass] -> $func($params);
        }
    }
}

class MyController extends Controller {
    public function indexAction() {
        $this -> view -> assign ('My2', $this -> dispatch('My2','index'));
        return $this -> view -> render();
    }
}

class My2Controller extends Controller {
    public function indexAction() {
        $this -> view -> assign ('My2Inner', '111');
        return $this -> view -> render();
    }    
}

$controller = new MyController();
echo $controller -> indexAction();

Now just need to decide how to dynamically call XXXController, depending on URL.