Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Modules routing nightmare
  • HarroHarro
    Accepted Answer
    Not sure what you mean by "theme stuff in a module", and why it would be bad.

    A theme by definition is global for your app, you want a uniform look and feel for all pages. Which means that if your components/widgets that are being called using HMVC calls by your front controller return a View, it should be a view from the current theme.

    Modules are supported by Fuel's theme engine, either as part of the theme file structure, or within the module itself (for example if you want to distribute a module including theme support).

    So your front controller starts with a theme, and setting up a Theme instance with that theme. The theme defines different sections, like header, footer, sidebar, body, etc. The front controller will also load the theme's page template for the requested page. The way this works is shamefully but loosly based on Joomla's theme engine. ;-)

    It will then use the URI to do a lookup (we use a nestedset table to store the web tree), to see if a page definition for that URI exists, and if so, which sections and components it defines. Once done it will loop over the result, do HMVC calls, and assign the View objects returned as partials to the different theme sections. And once that's done, the front controller renders the theme and finishes the request.

    There are no cross-module calls in the scenario, but the HMVC call isn't done in strict isolation since it needs to access the current theme instance. If you want isolation, you can have the front controller pass the theme instance to the component method on the HMVC request, and access it in the method using $this->param(). But since that means that it will always depend on a theme instance, we haven't bothered, and even use a global function theme() that would return the theme instance.

    The main reason for us to set it up this way, it that it allows you to add a GUI to this system, and have an instant CMS type application, where the user can design their own page structure for the site, and add components to sections on each page. Create components that can display an image or a block of HTML, and your CMS core is up and running.
  • Thanks for that extensive answer.

    you said: "Not sure what you mean by "theme stuff in a module", and why it would be bad."


    That was what confused me about my first way of doing, which was not the way you do indeed.

    In a complete HMVC architecture I'd see more the front controller as a container for other parts. And thus, with not so much logic other than loading a part of the template by module call.

    More, I see only one main template, others views being only parts of it, as a blog index in my example above or a menu, a navbar etc.
    In my mind I don't see that main controller to be responsible of the content loaded by those modules.

    Maybe i can implement a kind of white list modules for each partials... what do you think?
    I don't like classes with many responsibilities.

    About theming stuff, I noticed that it was illusive to want to have perfect isolation in modules. Using \Theme::instance() is good enough.

    About your application, i'm far from wanting such flexibility in mine. But thanks for the advise ;)

    If i understand well, you have your whole application's pages saved in a DB, with templates and modules to call for each of them. So no need to deal with is_hmvc(), i get it now.
  • HarroHarro
    Accepted Answer
    Correct, the logic of how to build a page is entirely handled by the front controller.

    it uses a nestedset table to do a lookup of the requested URI, it will check which theme (and which page template of that theme) is needed for that page, it will check which sections are defined by that page, which widgets are defined for those sections, it will call the controller methods that generate those widgets, and finally it will generate the page.

    This make it very easy to have a completely dynamic application. For example if you swap a theme with a right sidebar with a theme without one, it will simply not call those widget controllers and not render it.

    If you don't need this flexibility, you can swap bits of this logic with hardcoded stuff, like if you have a fixed header, footer or sidebar menu. There is no need to make such an elaborate database design, you can easily make a simpler stucture in a config file that will give you the same sort of flexibility, something like:

    return array(

        // default sections for very page
        '__default' => array(
            'header' => function() { return \View::forge('default/header'); },
            'footer' => function() { return \View::forge('default/footer'); }
            'sidebar' => 'homepage/sidebar',
        ),

        // defined uri's for this application
        'uri' => array(

            // homepage
            '/' => array(
                'body' => 'homepage/index',
            ),

            // admin, override the sidebar
            '/admin' => array(
                'body' => 'views/homepage',
                'sidebar' => 'admin/sidebar',
            ),

        ),
    );

    Then you can quickly check if the requested URI exists, default defaults for every page, support both static views and widget controllers, simply by doing a lookup, and if found, merge it with "__defaults", do your HMVC calls where needed, and feed the result to your page template.
  • Hi Harro and good sunday!

    Thanks to share with us some of your thoughts and tricks.

    Interesting, a kind of static routing like my old days with Borland Delphi 5.0 Web framework. ;)

    A question, you put forward the non modules cross calls, but though in the HMVC specs this is present. What drawbacks do you see by cross calls? Dependencies?
  • Yes, and the complexity of making sure modules are loaded at the correct time.

    Your HMVC request should always be wrapped in a try/catch block to catch the possible HttpNotFoundException, so you can deal with missing dependencies gracefully. With static calls you would have to check if it's callable before actually calling it.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion