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

[eluser]eriksays[/eluser]
hi all --

i'm a newbie to CI, coming back to PHP after an extensive time in Rails.

with my first project, I was looking for how to handle layouts. Again, coming from Rails, there's usually a layout file, and individual views are set to use a particular layout.

just asking.....

thanks
#2

[eluser]sophistry[/eluser]
http://codeigniter.com/wiki/FAQ/
#3

[eluser]Michael Wales[/eluser]
In Ruby you have a parent layout that controls the entire page - then a particular segment of the page is loaded via the yield variable.

This is possible within CI - but the default action is to have one view for each controller (although you can load multiple views from within that first view).

Personally, I create a global directory to include my header and footer, and then include those 2 views from within all of my other views - but it really depends on personal preference.

Take a look through the documentation - as well as these forums and the wiki - there have been countless discussions, and libraries, developed to support these features.
#4

[eluser]thurting[/eluser]
I wrote a hook that pretty much mimics RoR behavior.

In your config/hooks.php add:

Code:
$hook['display_override'][] = array('class'    => 'Yield',
                                    'function' => 'doYield',
                                    'filename' => 'Yield.php',
                                    'filepath' => 'hooks'
                                   );

Create a file named application/hooks/Yield.php:

Code:
<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');

/**
* Yield  ::  HOOKS
*
* Adds layout support :: Similar to RoR <%= yield =>
* '{yield}' will be replaced with all output generated by the controller/view.
*/
class Yield
{
  function doYield()
  {
    global $OUT;
  
    $CI =& get_instance();
    $output = $CI->output->get_output();
    
    if (isset($CI->layout))
    {
      if (!preg_match('/(.+).php$/', $CI->layout))
      {
        $CI->layout .= '.php';
      }

      $requested = BASEPATH . 'application/views/layouts/' . $CI->layout;
      $default = BASEPATH . 'application/views/layouts/default.php';
      
      if (file_exists($requested))
      {
        $layout = $CI->load->file($requested, true);
        $view = str_replace("{yield}", $output, $layout);
      }
      else
      {
        $layout = $CI->load->file($default, true);
        $view = str_replace("{yield}", $output, $layout);
      }
    }
    else
    {
      $view = $output;
    }
    
    $OUT->_display($view);
  }
}  

?&gt;

Create a folder in views named layouts. In this folder create a file name default.php ... this will serve as your default layout if none is specified in a controller. To add another layout, just create a file in views/layouts and define the variable in your controller. For example if you had a file named views/layouts/example.php and a controller named controllers/example.php:

Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

&lt;html&gt;
  &lt;head&gt;
    &lt;meta http-equiv="Content-type" content="text/html; charset=utf-8" /&gt;
    &lt;title&gt;Example.php&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
{yield}
  &lt;/body&gt;
&lt;/html&gt;


Code:
&lt;?php

class Example extends Controller
{
  public $layout = 'example';
  
  public function __construct()
  {
    parent::Controller();
  }

  public function index()
  {
    $this->load->view('index_view');
  }
}

The string {yield} in your layout file will be replaced with the output generated by the view file loaded from the controller. Not as easy as with Rails, but the behavior is there for the most part. BTW, if the variable $layout is not defined in your controller, CI will do its default behavior... so you can use layouts in some scenarios and not in others.
#5

[eluser]eriksays[/eluser]
kudos to teamhurting!

that is exactly what i was looking for..... thank you

*bows to teamhurting*
#6

[eluser]Colin Williams[/eluser]
I'm close to completing a library that lets you create multiple master-templates filled with regions (or yields, have you). Then, within your controllers, you simply write to those regions. Regions are defined before hand, so your master templates don't get cluttered with a bunch of conditional routines for each region. You can go a step beyond just defining a region and define default content and markup (xhtml and attributes).

Snippet of a master template

Code:
<h1>&lt;?= $title ?&gt;</h1>
<div id="content">
  &lt;?= $content ?&gt;
</div>

Filling regions from the controller (ideally a controller, but could happen anywhere)
Code:
$this->template->write($title, 'title'); // Writes $title to the 'title' region
$this->template->write($intro, 'content'); // Writes $intro to 'content' region
$this->template->write_view('article', $article, 'content'); // Loads $article to the 'article.php' view and appends the rendered view to the 'content' region ($intro remains)

Also possible, but not as likely useful (or recommended)
Code:
$name = 'Colin';
$this->template->write($name, 'content', '<div>', array('class' => 'name'));
/* Written to 'content' region:
  <div class="name">Colin</div>
*/

Then the output
Code:
$this->template->output('template'); // Loads and displays template.php (in the 'views' folder

or, more simply
Code:
$this->template->output(); // Loads and displays master template already set in config

The ability to override the master template on this call any time makes the front-end coding much easier, especially if you have drastically different layouts for different areas of a site.

Theres some other goodies I'm going to add before I release it (mainly message handling, where messages persist across internal redirects). I've used it on a few projects now and have enjoyed it.
#7

[eluser]tenaciousj[/eluser]
Kinda new to CI, but was researching this topic and ran across this thread.

Anyways, I was having troubled getting teamhurting's Yield.php code to cooperate. I did a little rewrite that seems to be work pretty good. I thought I'd share it here incase anyone notices a problem that I might be over looking.

Code:
class Yield {
    
    function doYield() {
        global $OUT;
  
        $CI =& get_instance();
        $output = $CI->output->get_output();
        
        /* Set the default layout file */
        $layoutFile = BASEPATH . 'application/views/layouts/default.php';
    
        if (isset($CI->layout)) {
      
            if (!preg_match('/(.+).php$/', $CI->layout)) {
                  $CI->layout .= '.php';
              }
    
              $requested = BASEPATH . 'application/views/layouts/' . $CI->layout;
            
            // If theres been a request for layout and the file exists
            // replace the dafault layout file
            if (file_exists($requested)) {
                $layoutFile = $requested;
            }
        
        }
        
        $layout = $CI->load->file($layoutFile, true);
        $view = str_replace("{yield}", $output, $layout);

        $OUT->_display($view);
    }

}
#8

[eluser]axle_foley00[/eluser]
You might want to give the Layout Library a try.
#9

[eluser]thurting[/eluser]
Hey tenaciousj,

My code could probably use some cleanup Wink

Just note that your rewrite changes the behavior of the doYield method in that it locks you into using layouts. I guess this is best if you are after true RoR emulation, but it had intentionally been set it up so you could choose between both this added functionality and CI's default behavior. Probably more sloppy that way, but I prefer the flexibility.
#10

[eluser]tenaciousj[/eluser]
Bleh, your right! Didn't even think about that, thanks for the heads up Smile

This should fix it.
Code:
class Yield {
    
    function doYield() {
        global $OUT;
  
        $CI =& get_instance();
        $output = $CI->output->get_output();
        
        /* Set the default layout file */
        $layoutFile = BASEPATH . 'application/views/layouts/default.php';
    
        if (isset($CI->layout)) {
      
            if (!preg_match('/(.+).php$/', $CI->layout)) {
                  $CI->layout .= '.php';
              }
    
              $requested = BASEPATH . 'application/views/layouts/' . $CI->layout;
            
            // If theres been a request for layout and the file exists
            // replace the dafault layout file
            $layoutFile = $requested;
        
        }
        
        // if our selected layout file exists load it into the view
        // else simply load the controller view by itself
        if (file_exists($layoutFile)) {
            $layout = $CI->load->file($layoutFile, true);
            $view = str_replace("{yield}", $output, $layout);
        }
        else {
              $view = $output;
        }
        
        $OUT->_display($view);
    }

}




Theme © iAndrew 2016 - Forum software by © MyBB