ExpressionEngine CMS
Open, Free, Amazing

Thread

This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.

The active forums are here.

Nested MVC

January 31, 2008 9:08pm

Subscribe [14]
  • #16 / Feb 02, 2008 7:58am

    Edemilson Lima

    241 posts

    I don’t intend to use this feature for simple features like my header and footer though.

    No, the simple header and footer is not what I want too. At this moment I am trying to figure out how I will better organize the structure of my first CI-based web site. What I will need to do is to create libraries for each sub modules, that in fact should be sub controllers, that will load their own views and models. Using libraries is not the perfect way to do this and don’t keep the things in a more logic structure. These sub controllers do not need to be directly accessed by the URI, but we need to send user data to them, for example, which sub controller function will be executed and what parameters it will get. This must come by the URI. How do you think is the best way to manage this?

    If are in the plans of the EllisLab to release such feature soon, I think is better wait for it and start my application with nested MVC than create libraries and need to rewrite everything after. Anyway, this is a real good feature for CodeIgniter.

  • #17 / Feb 02, 2008 9:05am

    BizComputing

    60 posts

    Rick: I’m not aware of layouts in CI, my exposure is still along the lines of what I have needed to get me started building CI infrastructure up to service the apps I build on a day to day basis.  My general approach is that every view uses the 3rd argument as TRUE so every view is managed as a string of html.  My controllers are all extensions of my own base controller (which extends CI Controller), in my base controller I have a method which stitches together the final page by having a master view which is the only view that does not return as a string.  That allows me maximum flexibility in view within view within view… as well as allows easy reorg of a screen.

    With that said, my index function of my “sub_controller” returns an array, one of the keys of that array is “view” which is a string of html, the parent controller is then free to place that fragment whereever it needs.  This means that all my sub_controller index’s are called before my main controller view is called so that these view fragments can be laid out in the main controller.

    Edemilson: I really can’t comment on best practice for passing info over the URI since I have a very special way of passing data.  I have no need for my apps to be searchable by search engines which allows me flexibility in my URI.  Hence, my URI is encrypted.  In all actuality, the data in my URI is an encrypted array which contains not only the requested URI, but structured argument data needed by that URI.  This whole feature required a pre_system hook so that I could decrypt the URI, place the decrypted URI portion in the REQUEST_URI for CI consumption, and the data portion as decrypted goes into the $_GET.

  • #18 / Feb 02, 2008 11:56am

    Edemilson Lima

    241 posts

    It is very interesting the way you did. Could you show us some code examples here?

    In my case, my layout could looks like:

    Main view:
    +-------------------------------------------------------------+
    | HTML HEADER                                                 |
    | Page Title                                                  |
    +-------------------------------------------------------------+
    | HTML BODY                                                   |
    | +---------------------------------------------------------+ |
    | | Container                                               | |
    | | +-----------------------------------------------------+ | |
    | | | HEADER                                              | | |
    | | | Logomark, Menu, Search Field, Login Status, etc.    | | |
    | | +----------------+----------------------+-------------+ | |
    | | | Left Side      | Center Contents      | Right Side  | | |
    | | |                |                      |             | | |
    | | | +------------+ | +------------------+ | +---------+ | | |
    | | | | Sub-Menu   | | | Product Offers   | | | Banners | | | |
    | | | +------------+ | +------------------+ | +---------+ | | |              
    | | | | Product    | | | News             | | | Stats   | | | |
    | | | | Categories | | +------------------+ | +---------+ | | |
    | | | +------------+ | | Top Selling      | | | Links   | | | |
    | | | | Top Brands | | | Products         | | | or Tags | | | |
    | | | +------------+ | +------------------+ | +---------+ | | |
    | | +----------------+----------------------+-------------+ | |
    | | | FOOTER                                              | | |
    | | +-----------------------------------------------------+ | |
    | +---------------------------------------------------------+ |
    +-------------------------------------------------------------+

    First, I don’t want to break the HTML of my Main View into pieces for the header, the contents and the footer. I don’t want to have invalid HTML code in my views, with unclosed tags and things like that.

    The Header don’t change too much. Only a few information, like Login Status or the last user search may change on it. The Footer also do not change often. But it may contain the current date, the used memory and the elapsed time.

    The Left Side, Center and Right Side changes a lot. They may change in every page request and also changes if the user is logged in or not.

    “Sub-menu”, “Product Categories”, “Top Brands”, “Product Offers”, “News”, “Top Selling Products”, “Banners”,  “Stats” and “Links or Tags” are modules of my application. They could be sub_controllers with their own views and models. It do not need to load directly by the URI, but the user could pass information to them by the URI. As for example, which sub_controller function will executed and what parameters will be passed.

    What I need is to find a way to load them inside my Main View, without to build every module first in arrays, every time, within my requested controllers, and after pass them to the Main View. The only thing I would like to do is to specify in the requested controller which sub_controllers I want to load and they will do the job themselves. The loaded sub_controllers could be executed, and return all processed data to the requested controller, which will send it to the Main View.

    I know that I can do this using libraries. But how can i do this without manually load the views and build everything in arrays in each controller and each controller’s function? I think a Nested MVC is the best answer to my pray. Isn’t it?

    Also I need to change the Page Title accordingly. This can be done by the requested controller.

    The layout above apply to the Home, but in sub pages it may not have the Right Side and modules change in each sub page. For example, in the Product Details sub page, it will display other modules, related to the product selected by the user.

    In the old days I was used to simple use INCLUDE(‘file.php’) or, in the case of dynamic content, just use INCLUDE($file.’.php’). Everything else was automatically done by PHP. The templates did load other PHP scripts, which in turn did load another templates or PHP scripts and so on. All I needed before was to specify what will be inside of what. Now, what is the best practice with CI to achieve the same, without a Nested MVC?

  • #19 / Feb 02, 2008 2:26pm

    BizComputing

    60 posts

    my main view has the html tags, head tags, body tags etc. for a fully valid html page

    the head tags have a variable for adding in js, and additional styles

    the body tag is a series of variables
    $header
    $menu
    $content
    $footer

    each variable is populated by various other views that return their html as a string.

    the $content variable is made up of multiple views that my controllers assemble.

    All of this is easily achieved without nested MVC.

    My need for nested MVC is so that I can take my views that are a screen fragment and have their own associated controller and model so the whole fragment is it’s own little module that can be loaded or not loaded on demand and can be attached to different controllers for reuse.

    At this time I can’t present any code because the code is proprietary and covered under copyright.  Depending on time, I do hope to make the code generic so I can release it to the community.

  • #20 / Feb 03, 2008 8:38am

    Edemilson Lima

    241 posts

    The MVC way of coding forces us to build every module of our application in strings first, and in the end it put everything together to send to the client. I am wondering if this is not a waste of web server’s memory. The old way of building PHP web sites using include() and require() makes PHP to flow a logic order and it just build the whole page in a buffer to output after, if the output buffering is on. With a MVC, don’t we need to take more care about the strings and arrays we use to do not spend more memory than necessary? Could a Nested MVC help us on this, by automating the process of collecting the return of each module?

  • #21 / Feb 03, 2008 8:51am

    wiredesignz

    2882 posts

    Its not MVC that forces you to do this, it is CodeIgniter’s $data[‘part’] = load->view(‘file’ $data) method.

    I have created a View Object that stores all my view partials as file names and raw $data only, and then use it to render the page only when I tell it to.

  • #22 / Feb 03, 2008 9:23am

    Edemilson Lima

    241 posts

    File names? Does it store data on disk?

  • #23 / Feb 03, 2008 7:43pm

    wiredesignz

    2882 posts

    Its an Object, it has variables to store data.

    I have just finished adapting my View Object to use Plugins as psuedo-controllers so I am now able to nest an MVC triad as a partial view.

    See the Ignited Code forum.
    http://ellislab.com/forums/viewthread/70629/

  • #24 / Feb 06, 2008 7:39am

    Edemilson Lima

    241 posts

    http://ellislab.com/forums/viewthread/70629/

    There are some solutions to bring nested MVC to CodeIgniter, but is very hard to adopt one, because these things change the way we code the whole application. The ideal scenario was if we had a solution from the CI developers. If CodeIgniter have its own HMVC, it becomes a standard, so the feature goes to the docs. If another developer need to change anything in my code, he/she will look at CI documentation and easily understand what I have done.

    At this moment I am stucked and I have no idea what I will do…  🙄

  • #25 / Feb 06, 2008 9:18am

    wiredesignz

    2882 posts

    I think, the whole point of using CI is to try new things that work for you, and then use them. You never know, your coding style might actually improve.

    I see a lot of new people struggling to fit all their code into one controller. But I’m sure as they learn about MVC they will think up better ways to do things. Nested MVC is one way.

  • #26 / Feb 06, 2008 2:34pm

    Edemilson Lima

    241 posts

    Instead of put everything in a base controller, I did created some helpers, but I am not sure if it is the best way to do my application…

    The “application/helper” folder is ideal for extending/replacing core helpers (since 1.6.0) and to put my sporadic functions, like my own string/date format/validate functions or things like that.

    The “application/libraries” folder is ideal for extending/replacing core libraries and to put my proprietary libraries, with things like my own template parser, my own session management, file management, etc.

    May I could use the “application/plugins” folder to put my application modules/partials, but the name “plugins” suggests me that such folder is for third part applications, like for example, a plug-in to import/export data from another web site.

    One option could be use the “application/models” folder to put my modules/partials as models, but I don’t think this is a good pratice too. My modules/partials are more like controllers than models. They will have their own models and will load their own views.

    In my opinion, to create helpers, libraries or plug-ins and use them as my application modules/partials are not the best pratice, because helpers/libraries/plug-ins are things related to the low level of my application, which rarely deals with my application logic.

    Actually I must build my modules/partials in strings in every controller and every function, and then pass everything to the main view at the end of every function. The best way to not repeat code is made them as a helper, library or plug-in and load them in the controller contructor. But as I said above, the modules/partials are not helpers, nor libraries, nor plug-ins.

    I could extend the Loader class and create a new folder exclusive for my modules. But anyway, may I need to load them into every controller and every function, passing them to the main view in the end of every function of my controllers. I really don’t like to do that… It is a very repetitive task anyway.

    I think a Nested MVC is the answer to put everything in a more logic structure and make the hierarchy work for us by itself.

  • #27 / Feb 06, 2008 2:35pm

    Edemilson Lima

    241 posts

    I was thinking in something like this:  (well, this is just a sketch)

    My “main” view:

    <div id="header"><?=$header?></div>
    <div id="content">
      <div id="leftside"><?=$leftside?></div>
      <div id="center"><?=$center?></div>
      <div id="rightside"><?=$rightside?></div>
    </div>
    <div id="footer"<?=$footer?></div>

    My “main” controller:

    class Main extends Controller {
    
      function Main() {
        parent::Controller();
        $header['title']="Welcome!";
        $data['header']=$this->load->module('header',$header);
        $data['leftside']=$this->load->module('products/categories');
        $data['center']=$this->load->module('home');
        $data['rightside']=$this->load->module('publish/banners');
        $data['footer']=$this->load->module('footer');
        $this->load->view('main_view',$data);
      }
    }

    Notice the “load->module” lines above. The modules goes to a “modules” folder.

    My “categories” module:

    class Categories extends Module {
    
      function Categories() {
        parent::Module();
        $this->load->model('products/categories');
        $data['categories']=$this->products->get_categories_list();
        $this->load->view('categories_view',$data);
      }
    }

    My “home” module:

    class Home extends Module {
    
      function Home() {
        parent::Module();
        $data['offers']=$this->load->module('products/offers');
        $data['news']=$this->load->module('press/news');
        $data['top10']=$this->load->module('products/top10');
        $this->load->view('home_view',$data);
      }
    }

    Suppose my main menu have a link that points to “/products/”.
    It will load a “products” controller like this:

    class Products extends Controller {
    
      function Products() {
        parent::Controller();
        $header['title']="Our Products";
        $data['header']=$this->load->module('header',$header);
        $data['leftside']=$this->load->module('products/categories');
        $data['center']=$this->load->module('products/home');
        $data['rightside']=$this->load->module('publish/banners_two');
        $data['footer']=$this->load->module('footer');
        $this->load->view('main_view',$data);
      }
    }

    As you can see, the products controller will load the header, categories and footer modules, as the main controller do, but instead of the home module, it will load its own modules. Another page title is also passed to the header module as a parameter.

    My “products/home” module:

    class Home extends Module {
      
      function Home() {
        parent::Module();
        $data['product_list']=$this->load->module('products/list');
        $data['suggestions']=$this->load->module('products/suggestions');
        $this->load->view('products/home_view',$data);
      }
    
      function details($id) {
        $module['id']=$id;
        $data['part']=$this->load->module('products/details',$module);
        $this->load->view('products/details_view',$data);
      }
    
      function add() {
        $this->load->view('products/insert');
      }
    
      function edit($id) {
        $module['id']=$id;
        $data['part']=$this->load->module('products/edit',$module);
        $this->load->view('products/edit_view',$data);
      }
    
      function remove($id) {
      }
    }

    As you can see from these examples, if we have a feature like this, you will not need to use the third parameter of load->view(), because the output of a view called by a module must always be buffered and returned to the caller module or controller. This will enable the hierarchy to work.

    Each module could load sub_modules, which in turn could load more sub_modules. And each module could load their own models and views, completely independent of everything else in the application. But modules could get user data and manage it as controllers do.

    The main problem is when you call an URI like “/products/details/123”. Will the CI engine know that is to call the “details” function inside the “products/home” module, loaded by “products” controller and pass the “123” to the function first parameter? I don’t think so. May be a more elegant structure like an HMVC is necessary, but these examples are the basic idea.

    But is such thing too hard to implement in CodeIgniter?

    I have found this thread about a View Library very interesting:
    http://ellislab.com/forums/viewthread/49910/

  • #28 / Feb 11, 2008 12:41pm

    Edemilson Lima

    241 posts

    Here is Rick Jolly’s View-centric Nested Controllers:

    http://ellislab.com/forums/viewthread/58405/

    I must agree with Rick, this is a much better solution for Nested Controllers, because it decouples the caller controller from the view partials. The only drawback is that I would like to have these partials separated from my libraries. It could go to a another folder called “modules” or “partials”. Instaed of create a helper, I think we could extend the Loader and add a new method like “$this->load->module()” or “$this->load->partial()” to be used into the views. And within these partials, instead of return the data as an string, the Loader could use the PHP output buffering to get the result that will be returned to the caller controller.

    May anybody here can tell me if this is possible?

  • #29 / Feb 12, 2008 9:34pm

    BizComputing

    60 posts

    Sorry, I started this thread and then disappeared.  I had an HDD crash and my backup strategy has been decidedly lazy of late, so, restoration turned out to be a nightmare.  Thankfully nothing of importance lost, and I’m mostly back in the saddle.

    As for having my nested controllers as something other than a libary, already done.  I extended the CI_Loader class to add 2 features.  First feature allows loading libaries without instantiation.  This allows loading the class definition for self instantiation using new.  Second change was to add a load module (my current name for my sub controllers). The load module is basically a rip of the libary loading with minor exceptions.  Module loader auto loads without instantiation my base module library ( All my modules extend this library ).  Module loader loads libraries from my application/modules folder instead of my application/libraries folder.

    My module base class used to build modules follows a pattern I’m using in my controllers.  Each of my controllers handles 1 page, so, method index is used for page display.  A pages actions( links internal to page and form posting ) go to a method called submit.  Therefore, my modules (sub controllers) have an index method and a submit method.  Both methods accept an array of arguments.  So the parent controller is responsible for building the array of data necessary for the subcontroller and calling the subcontrollers appropriate method ( index, or submit depending on what method is executing in the parent controller ).  Both methods also return a data array.  The index return data array contains a key called ‘view’ which is a string of HTML generated by the module, this then puts the responsiblity for placement of the view fragment on the parent controller.  Other return values are based on how the module is being used.  For instance, one of my modules has a close button which should close the parent controllers page, so, the submit method of this module puts $data[‘result’] = ‘close’ as a return value when the close button is selected.  The parent controller is then responsible for checking for this returned key/value pair and execute whatever code it needs to to close itself.

    I do have some additional methods on my modules that are to support other uses of modules.  Currently in the application I am porting to CI, my modules are for reusablility.  I have a few different screens that share some common functionality and display fragments.  So the module provides the common functionality and loads the common display fragment as it’s own view, and, loads it’s own model in support of the common functionality.  The additional methods on my modules are to support using modules as portions of a screen that load or not based on current configuration or the rights of the currently logged in user, or in the case of a workflow application, the current state of the workflow.  This use of modules is not absolutely necessary, but does greatly help to simplify the main controller since the main controller would be responsible for gluing together all the module views and dispatching all the module posts.

  • #30 / Feb 13, 2008 8:22pm

    Edemilson Lima

    241 posts

    I extended the CI_Loader class to add 2 features.  First feature allows loading libraries without instantiation.  This allows loading the class definition for self instantiation using new.  Second change was to add a load module (my current name for my sub controllers).

    Very interesting! Will you pleasure us with an example of it? 😊

    Module loader loads libraries from my application/modules folder instead of my application/libraries folder.

    That is something I’m looking for.

    Therefore, my modules (sub controllers) have an index method and a submit method.

    Can I have how many methods I want? Can I define in my views which method will be called? (for example, in a form action)?

.(JavaScript must be enabled to view this email address)

ExpressionEngine News!

#eecms, #events, #releases