Welcome Guest, Not a member yet? Register   Sign In
cleanest way to implement the main layout
#1

[eluser]Lunaticon[/eluser]
Hey Guys,

I've been working with CodeIgniter for a while now and I think my software design isn't that bad. I've got just a tiny question which has to do with the implementation of a certain view.

I use a main layout and I'm just chaning the content of it.
Code:
class Testcontroller extends App_Controller{
   public function testmethod(){
      ...
      $testdata = array("Hi", "Bye");
      $this->data['content'] = $this->load->view('any_view', $testdata, true);
      $this->load->view('main_layout', $this->data);
   }
}

Thats the way I implement it currently. The problem is I have to load the main layout in every of my controller methods. I tried using the descrutor of my own controller of which all the other controllers are inheriting from. But as you may imagine it doesn't work properly.

So my question is: Is there really no way to avoid implementing that line in every of my controller methods? or is there a clean way to realize this?

Thanks in advance,
Lunaticon
#2

[eluser]Kamarg[/eluser]
You could use the display_override hook. That does limit flexibility somewhat though.
#3

[eluser]sirfilip[/eluser]
Here is my approach. I add render function into MY_Controller.

public $layout = 'layouts/default'; // normally you should put this into the constructor.

function render($view, $data)
{
$data['content'] = $view;
$this->load->view($this->layout, $data);
}

and i use it like this
$this->render('posts/show', array('posts' => $posts));

And the layout file looks like this
<html>
<head>
<title>Title</title>
</head>
<body>
<?php $this->load->view($content); ?>
</body>
</html>
#4

[eluser]Josh Bright[/eluser]
One solution is to create a library, something along these lines:
Code:
class Template {
     public $ci;
     public $default_view;

     public function __construct() {
          $this->ci &= get_instance();
          $this->default_view = "template/render_view";
     }

     public function render($data, $different_view = NULL) {
          if (is_null($different_view)) {
               $this->ci->load->view($this->default_view, $data);
          } else {
               $this->ci->load->view($different_view, $data);
          }
     }
}

Then, in your controller:
Code:
public function index() {
          $data['content'] = "Some data goes here";
          $this->template->render($data);
     }


I haven't used this yet, beyond a little test that I just created, but, it appears to work fine. Up until now i've been just passing all my data to a 'template view', which loads in the 'skeleton' html that goes around the actual content im trying to display. To do this, i'll have a few variables I load in my MY_Controller, things like html_header_view, page_header_view, navigation_view, etc. These things could pretty easily be added to this template class so that everything is in one nice spot. In any case, your no longer having to type in your main view you load on every page request, along with the ability to send in a different 'main_view' if you wanted to.
#5

[eluser]skunkbad[/eluser]
[quote author="Lunaticon" date="1302141057"]Hey Guys,

I've been working with CodeIgniter for a while now and I think my software design isn't that bad. I've got just a tiny question which has to do with the implementation of a certain view.

I use a main layout and I'm just chaning the content of it.
Code:
class Testcontroller extends App_Controller{
   public function testmethod(){
      ...
      $testdata = array("Hi", "Bye");
      $this->data['content'] = $this->load->view('any_view', $testdata, true);
      $this->load->view('main_layout', $this->data);
   }
}

Thats the way I implement it currently. The problem is I have to load the main layout in every of my controller methods. I tried using the descrutor of my own controller of which all the other controllers are inheriting from. But as you may imagine it doesn't work properly.

So my question is: Is there really no way to avoid implementing that line in every of my controller methods? or is there a clean way to realize this?

Thanks in advance,
Lunaticon[/quote]

This is how I do it' and seems like the right way to me. Seems like if you have a controller with a few hundred lines of code, adding a few more to each method doesn't matter so much.
#6

[eluser]wiredesignz[/eluser]
Always use a parent controller and NEVER repeat code if you don't have to.
Code:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

class MY_Controller extends CI_Controller
{    
    function __construct()
    {
        parent::__construct();
        
        $this->load->helper(array('url','form'));
    }    
    
    function _remap($method)
    {
        $data =& $this->load->_ci_cached_vars;

        $data = $this->config->item('settings');
        
        $data['page']    = strtolower(get_class($this));
        $data['method'] = $method;
        
        if (method_exists($this, $method))
        {
            $data['content'] = call_user_func_array(array($this, $method), array_slice($this->uri->segments, 2));
        }
        else
        {
            show_404();
        }
                    
        $this->load->view('layout', $data);
    }
}
EDIT: Added load->vars() to allow page controller view to access config settings
#7

[eluser]Josh Bright[/eluser]
I've never really used _remap before, lets say I had your MY_Controller as my base controller, how would I open a page in a controller that I extend from this one? Lets say I have a basic controller as shown below, what would I be changing to take advantage of this?
Code:
<?php
class Home extends CI_Controller {
     public function index() {
          //List of news items that home/index_view will show
          $data['news_list'] = $this->db->getSomeNews();  

          //A view
          $data['content'] = "home/index_view";

          //template/render_view is a view that loads other views, header, footer, along with whats in $data['content']
          $this->load->view("template/render_view", $data);
     }
}
#8

[eluser]skunkbad[/eluser]
[quote author="wiredesignz" date="1302864529"]Always use a parent controller and NEVER repeat code if you don't have to. ...[/quote]

I don't agree, because I don't see how one line of code per method would be a catastophe, or would be considered repeating code, such as in OP's example:

Code:
// this is really the only line of code that would be repeated from method to method
$this->load->view('main_layout', $this->data);

If you were talking about not reusing a method, or not reusing a callback function, then I'd agree. Having just inherited a CI site where somebody had wild ideas about the way things should be, I think it is worth considering to create things in simple way that everyone can maintain with little effort. Making things more complex just to get ride of one line of code seems like the wrong decision, but that's just my opinion.
#9

[eluser]wiredesignz[/eluser]
[quote author="Josh Bright" date="1302898834"]Lets say I have a basic controller as shown below, what would I be changing to take advantage of this?
Code:
<?php
class Home extends CI_Controller {
     public function index() {
          //List of news items that home/index_view will show
          $data['news_list'] = $this->db->getSomeNews();  

          //A view
          $data['content'] = "home/index_view";

          //template/render_view is a view that loads other views, header, footer, along with whats in $data['content']
          $this->load->view("template/render_view", $data);
     }
}
[/quote]

Code:
<?php

class Home extends MY_Controller {

     public function index()
     {
          //List of news items that home/index_view will show
          $data['news_list'] = $this->db->getSomeNews();  

          //A view
          return $this->load->view("home/index_view", $data, TRUE);

     }
}
#10

[eluser]Josh Bright[/eluser]
Thanks for the reply, have it working and its pretty slick, very impressed!




Theme © iAndrew 2016 - Forum software by © MyBB