Welcome Guest, Not a member yet? Register   Sign In
Using Nested MVC for View partials (Updated)
#1

[eluser]wiredesignz[/eluser]
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

[eluser]wiredesignz[/eluser]
This is the menu plugin (application/plugins/menu_pi.php) acting as a controller.
Code:
<?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

[eluser]wiredesignz[/eluser]
This is the View Library (application/libraries/View.php) it is autoloaded at startup.
Code:
<?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

[eluser]wiredesignz[/eluser]
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.
Code:
<?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

[eluser]wiredesignz[/eluser]
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.
Code:
<?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

[eluser]xwero[/eluser]
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 Smile

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

[eluser]wiredesignz[/eluser]
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. Wink




Theme © iAndrew 2016 - Forum software by © MyBB