Welcome Guest, Not a member yet? Register   Sign In
Default Layout
#1

[eluser]derekmichaeljohnson[/eluser]
Hey guys. Brand new to CI, so forgive me if this is a frequently asked question (I tried searching, swear!).

I'd like to know if there's a way to have EVERY view loaded within a specific area in a DEFAULT layout. I understand many use this method:
Code:
$this->load->view('layout/_header');
$this->load->view('controller-specified view');
$this->load->view('layout/_footer');
But I thought it would be cool if you had a default layout like this:
Code:
<html>
<head>
</head>
<body>

<?php
// controller-specified view is inserted here
?>

</body>
</html>
And, as suggested in the code above, when a controller loads a view, it is always inserted into the default layout and sent to the browser.

Does this make sense? And is it possible with CI? I appreciate the feedback!
#2

[eluser]Dam1an[/eluser]
You could use a template library (such as this one by Colin)

If you don't need a full blown template library, you could just use a nested view
So you create a master view, and then pass the path to the nested view into it (along with any data)

If you want to get clever, you can also make it look for a view in views/controller_name/function_name.php and use that if it exists, and even have a hook to call the final view automatically
#3

[eluser]TheFuzzy0ne[/eluser]
Welcome to the CodeIgniter forums.

You can load views from within views, and simply pass a variable into the container view to load one of the subviews dynamically.
#4

[eluser]derekmichaeljohnson[/eluser]
[quote author="TheFuzzy0ne" date="1242522965"]Welcome to the CodeIgniter forums.

You can load views from within views, and simply pass a variable into the container view to load one of the subviews dynamically.[/quote]Great idea! So I've created a "layout" view like so:
Code:
<html>
<head>
<title>CodeIgniter App</title>
</head>
<body>
<h1>Default Layout</h1>

&lt;?php $this->load->view($view); ?&gt;

&lt;/body&gt;
&lt;/html&gt;
And then my controller(s):
Code:
class Home extends Controller
{
    function Home()
    {
        parent::Controller();
    }
    
    function index()
    {
        $data['view'] = 'home_view';
        $this->load->view('layout',$data);
    }    
}
Works brilliantly, thanks! Any suggestions for making it even easier? Doesn't hurt to ask :-)
#5

[eluser]Dam1an[/eluser]
How about not having to give the name of the view (unless you want one other then what it thinks) and not having to call load->view? Easy enough?

Create MY_Controller in your libraries
Code:
&lt;?php if(!defined('BASEPATH')) exit('No direct script access allowed');
class MY_Controller extends Controller {
    protected $data;
    protected $views;
    
    public function __construct() {
        parent::Controller();
        // Initialise the default views
        $this->views['menu'] = 'template/menu';
        $this->views['sidebar'] = 'template/sidebar';
        $this->views['main'] = 'template/main';
        $this->views['footer'] = 'template/footer';
        
        // See if a default named file exists for this URI
        $uri = $this->router->class.'/'.$this->router->method;
        if(is_file('views/'.$uri.EXT)) {
            $this->views['main'] = $uri;
        }
    }
    
    function render() {
        // We need the views and the data in the master template
        $this->load->view('master', array('data'=>$this->data, 'views'=>$this->views));
    }
}
?&gt;

Enable hooks in config and add this to your hooks config file
Code:
// Will automatically call the render method at the end of the function
$hook['post_controller'] = array(
    'class'    => 'MY_Controller',
    'function' => 'render',
    'filename' => 'MY_Controller.php',
    'filepath' => 'libraries'
);

And here's an example controller using it
Code:
&lt;?php if(!defined('BASEPATH')) exit('No direct script access allowed');
class Authentication extends MY_Controller {
    function login() {
        // Look, I'm not doing anything here
    }
}
?&gt;

So if you go to site.com/authentication/login (I have it routed from just login) and have a file in the authentication view folder called login.php that view will get loaded automatically, as well as any data you set (You need to you $this->data to set data as its in the parent class)

Any questions?
#6

[eluser]CtheB[/eluser]
You could use HMVC to load modules on your page.

See HMVC: http://codeigniter.com/wiki/Modular_Extensions_-_HMVC/

See also this topic where i show how you can load all the modules dynamically:
http://ellislab.com/forums/viewthread/92212/P90/#575322
#7

[eluser]derekmichaeljohnson[/eluser]
What if I just had the "layout" view load the view which is labeled according to the controller class?

Code:
class Blog extends Controller
{
    function index() {

        $this->load->view('layout');

    }
}
Layout view:
Code:
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;CodeIgniter App&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
<h1>Default Layout</h1>

&lt;?php $this->load->view(CONTROLLER_CLASS.'_view'); ?&gt;

&lt;/body&gt;
&lt;/html&gt;
The question is: how do I retrieve the name of the current controller class? By the URI segment?
#8

[eluser]Dam1an[/eluser]
Like I showed in my earlier example
To get the controller name, use
Code:
$this->router->class;
and to get the method name, use
Code:
$this->router->method;
#9

[eluser]derekmichaeljohnson[/eluser]
Damian:

I've altered your suggestion (a few posts ago) to look like this:
Code:
$hook['post_controller'] = array(
                                'class'    => 'MY_Controller',
                                'function' => 'render',
                                'filename' => 'MY_controller.php',
                                'filepath' => 'libraries'
                                );
Code:
class MY_Controller extends Controller
{
    protected $data;
    
    public function __construct()
    {
        parent::Controller();
        
        $this->data['class'] = $this->router->class;
        $this->data['method'] = ($this->router->method == 'index') ? NULL : $this->router->method.'_';
        $this->data['view'] = $this->data['class'].'/'.$this->data['class'].'_'.$this->data['method'].'view';
        // this prints: "home/home_view" for the "home" class and "index" method
        // which is CORRECT, so that's working fine
    }
    
    function render() {
        $this->load->view('layout', $this->data);
    }
}
And my master layout view:
Code:
&lt;body&gt;

<div id="wrapper">
    &lt;?php $this->load->view($view); ?&gt;
</div>

&lt;/body&gt;
And finally my "home" controller:
Code:
class Home extends MY_Controller
{
    function Home()
    {
        parent::Controller();
        
        // $this->load->model('home_model');
        $this->load->library('calendar');
    }
    
    function index()
    {
        $data = array(
                    'cal' => $this->calendar->generate()
                    );
    }    
}
The problem I'm having is that it's not sending my ORIGINAL $data (like $data['cal'] from the Home controller class above) to the final view. So if my "home/home_view" view wants to echo out $cal, it says that $cal hasn't been defined.

Am I missing something? I really appreciate the help.
#10

[eluser]Dam1an[/eluser]
A few things
In the index function, when assigning something to the data array, you need to use
Code:
$this->data['something'] = 'something';
This is so that you use the data array in the parent class, instead of creating a seperate, local data array (local to that function you're in)

When you call the view from your render function and pass it the data array, it only goes one level deep (to the master view), which is why I wrapped it in another array when passing it in
You might be able to get around that by using
Code:
$this->load->vars($this->data);
If that doesn't solve it, you'll have to pass the data array in another array, and then pass the sub data array (the real data) into the second level view

I hope that makes sense




Theme © iAndrew 2016 - Forum software by © MyBB