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.

Using Nested MVC for View partials (Updated)

February 03, 2008 7:56pm

Subscribe [2]
  • #1 / Feb 03, 2008 7:56pm

    wiredesignz

    2882 posts

    It might take a couple of posts for me to describe this, but following are some snippets showing how a plugin can be used as a controller for a view partial.

    EDIT: The only two parts you need are the View Library and your Plugin, the rest of this post serves merely as proof of concept.

  • #2 / Feb 03, 2008 8:03pm

    wiredesignz

    2882 posts

    This is the menu plugin (application/plugins/menu_pi.php) acting as a controller.

    <?php if (!defined('BASEPATH')) exit('No direct script access allowed');
    
     class Menu //plugin acting as psuedo-controller
     {
        var $view;
        
        function Menu()
        {
            $this->view  = new View('admin/menu');
        }
        
        function render()    //all partials require a render() method
        {
            $menu = new Menus_model();
            
            extract($this->view->data); // grab the menu setup from the View
            
            $this->view->set(array(     // build the menu parts
                'shop_menu'     => $model->shop_menu(),
                'users_menu'    => $model->users_menu($access_level, $catcode),
                'category_menu' => $model->category_menu($page, $catcode),
            ));
            
            $this->view->render();
        }
     }

    When the application View Object is told to render() it automatically calls the menu->render() function.

  • #3 / Feb 03, 2008 8:21pm

    wiredesignz

    2882 posts

    This is the View Library (application/libraries/View.php) it is autoloaded at startup.

    <?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
    /**
     * View Library
     * 
     * Useage:
     * 1: Renders a layout with partials (blocks) inside.
     * 2: Renders partials only (header,content,footer. etc).
     * 3. Allows a plugin to render a partial.
     * 
     * Allows a view source directory to be specified.
     * 
     * @author Wiredesignz (c) 2007-12-25
     */
    class View
    {
        var $layout, $data, $partials = array();
        
        function View($file = NULL)            //specify a layout file to use
        {
            $this->layout = $file;
            static $data = array(
                'directory' => '',
                'module'     => '',
            );
            $this->data = &$data;            // make $this->data static
        }
        
        function set($key, $value = NULL)    // set data for this view
        {
            if (is_array($key)) 
            {
                $this->data = array_merge($this->data, $key);    
            }
            elseif ($value != NULL)
            {
                $this->data[$key] = $value;
            }
        }
        
        function load($view, $file = NULL)    //load partials as nested objects
           {
            if (is_array($view))
            {
                foreach ($view as $k => $v) 
                {
                    $this->reload($k, $v);
                }
            }
            else $this->reload($view, $file);    
        }
        
        function reload($view, $file)
        {
            $this->partials[$view] = (is_object($file)) ? $file : new View($file);
        }
      
        function get($key = NULL)            //returns data value(s) from this view
        {
            return ($key) ? (isset($this->data[$key])) ? $this->data[$key] : NULL : $this->data;
        }
            
        function render($render = FALSE)    // create the page (HTML)
        {
            if ($this->layout)
            {
                $CI = &get;_instance();
                $CI->load->vars($this->partials);
                return $CI->load->view($this->data['directory'].$this->layout, $this->data, $render, $this->data['module']);
            }
            else 
            {
                foreach($this->partials as $k => $v) 
                {
                    $v->render();
                }
            }
        }
    }

    View library updated 2008-02-06

  • #4 / Feb 03, 2008 8:26pm

    wiredesignz

    2882 posts

    This is an example of my application admin pages controller (application/controllers/admin/admin_controller.php)
    The point to note here is that the menu plugin is loaded and instantiated as a view partial.

    <?php if (!defined('BASEPATH')) exit('No direct script access allowed');
    
    class Admin_controller extends Controller {
    
        function Admin_controller($page = 'main', $access_level = 2) //set default access level
        {
            parent::Controller();
            $this->load->model('base_model'); // required by all models
            
            $this->load->model('menus_model');
            $this->load->plugin('menu');
            
            $this->load->library('user', $access_level);
            
            $this->view->set(array(
                'access_level'  => $access_level,
                'catcode'       => -1,        //default no category menu
                'page'          => $page,
            ));
            
            $this->view->load(array(        // setup admin pages partials
                'header'    => 'header',    
                'menu'      =>  new Menu(), // create menu object as partial
                'content'   => 'admin/'.$page, 
                'footer'    => 'footer',
            ));
        }
    }

    Plugin classes are not initialised by CI when loaded. (unlike libraries)

  • #5 / Feb 03, 2008 8:49pm

    wiredesignz

    2882 posts

    And finally an example of the users page controller. (application/controllers/admin/users.php)
    Notice that the View isn’t rendered to HTML but stored as an Object until we’re ready to display it.

    <?php if (!defined('BASEPATH')) exit('No direct script access allowed');
    
    require_once(APPPATH.'controllers/admin/admin_controller.php');
    
    class Users extends Admin_controller 
    {
        function Users()
        {
            parent::Admin_controller('users', 3); //set menu + access level
            $this->load->model('users_model', 'users');
        }
        
        function index()
        {        
            $this->users->findAll();
            
            $this->view->set(array(
                'title'       => 'Administration :: Users',
                'active_uid'  => $this->user->uid,
                'data_source' => &$this->users->resultset,
            ));
            
            $this->view->render();  // the page (HTML) is created and output from here.
        }
    }
  • #6 / Feb 04, 2008 3:11am

    xwero

    4145 posts

    could you add it to the wiki in a zip file or another compressed file. Too much code to go through on a Monday morning 😊

    Could you show some examples where the layout or the partial views change?

    Glancing of the code i ask myself the question what is the benefit of this class over the normal way for working other than making it possible to add controllers?

  • #7 / Feb 04, 2008 3:37am

    wiredesignz

    2882 posts

    Using this method your page view fragments (partials) can manage themselves, this seperates building each partial view, away from the page controller.

    Ask yourself how often you repeat the same code within different page controllers? Then you might see the benefit.

    Another advantage is that views aren’t rendered until the page controller code is finished executing, compared to the common $data = load->view() method which renders HTML into variables.

    The only two components you need are the View Library and your Plugin, the rest of this long post serves merely as proof of concept.

    As far as the CI wiki is concerned, I think I’ll wait until something better is developed. 😉

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

ExpressionEngine News!

#eecms, #events, #releases