Part of the EllisLab Network
   
 
layouts?
Posted: 03 August 2007 05:20 PM   [ Ignore ]  
Summer Student
Total Posts:  2
Joined  06-28-2007

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

Profile
 
 
Posted: 03 August 2007 08:37 PM   [ Ignore ]   [ # 1 ]  
Research Assistant
Avatar
RankRankRank
Total Posts:  722
Joined  08-06-2006

http://codeigniter.com/wiki/FAQ/

Profile
 
 
Posted: 04 August 2007 01:25 AM   [ Ignore ]   [ # 2 ]  
Moderator
Avatar
RankRankRankRank
Total Posts:  1827
Joined  07-30-2007

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.

 Signature 

MichaelWales.com

Profile
 
 
Posted: 04 August 2007 02:19 AM   [ Ignore ]   [ # 3 ]  
Lab Assistant
RankRank
Total Posts:  258
Joined  03-12-2007

I wrote a hook that pretty much mimics RoR behavior.

In your config/hooks.php add:

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

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

<?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);
  
}
}  

?>

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:

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

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


<?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.

Profile
 
 
Posted: 04 August 2007 09:27 AM   [ Ignore ]   [ # 4 ]  
Summer Student
Total Posts:  2
Joined  06-28-2007

kudos to teamhurting!

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

*bows to teamhurting*

Profile
 
 
Posted: 04 August 2007 12:02 PM   [ Ignore ]   [ # 5 ]  
Lab Technician
Avatar
RankRankRankRank
Total Posts:  1321
Joined  07-27-2006

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

<h1><?= $title ?></h1>
<
div id="content">
  
<?= $content ?>
</div>

Filling regions from the controller (ideally a controller, but could happen anywhere)

$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)

$name = 'Colin';
$this->template->write($name, 'content', '<div>', array('class' => 'name'));
/* Written to 'content' region:
  <div class="name">Colin</div>
*/

Then the output

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

or, more simply

$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.

 Signature 

Check out the Template Library

Profile
 
 
Posted: 05 August 2007 10:39 PM   [ Ignore ]   [ # 6 ]  
Summer Student
Total Posts:  2
Joined  08-05-2007

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.

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);
    
}

}

Profile
 
 
Posted: 06 August 2007 01:01 AM   [ Ignore ]   [ # 7 ]  
Lab Assistant
RankRank
Total Posts:  157
Joined  04-17-2006

You might want to give the Layout Library a try.

Profile
 
 
Posted: 06 August 2007 07:01 AM   [ Ignore ]   [ # 8 ]  
Lab Assistant
RankRank
Total Posts:  258
Joined  03-12-2007

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.

Profile
 
 
Posted: 06 August 2007 10:31 AM   [ Ignore ]   [ # 9 ]  
Summer Student
Total Posts:  2
Joined  08-05-2007

Bleh, your right! Didn’t even think about that, thanks for the heads up smile

This should fix it.

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);
    
}

}

Profile
 
 
Posted: 06 August 2007 06:14 PM   [ Ignore ]   [ # 10 ]  
Lab Assistant
RankRank
Total Posts:  258
Joined  03-12-2007

Hey tenaciousj,

That will still lock you in assuming default.php exists - which it should if you are using this hook.  Take a look at the original code.  The layout functionality should only take place if $CI->layout is defined.  Otherwise, you will get CI’s default behavior.  If you wanted to add layout support to all controllers without having to explicitly define $layout, you could either use your first rewrite or place a property named $layout in Controller or a subclass of Controller from which all of your application controllers would inherit from.

Profile
 
 
Posted: 02 November 2007 07:34 AM   [ Ignore ]   [ # 11 ]  
Summer Student
Total Posts:  1
Joined  10-31-2007

I changed your code to be more practical.
if you set:

public $layout = 'example';


in your controller, then example.php will be used as layout file. if no, default.php will be used. and if none of them exist, page will directly rendered.

<?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();
        
$default = 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 (
file_exists($requested))
            
{
                $layout
= $CI->load->file($requested, true);
                
$view = str_replace("{yield}", $output, $layout);
            
}
        }
        
else if (file_exists($default))
        
{
            $layout
= $CI->load->file($default, true);
            
$view = str_replace("{yield}", $output, $layout);
        
}
        
else
        
{
            $view
= $output;
        
}
        $OUT
->_display($view);
    
}
}

?>

Profile
 
 
Posted: 25 March 2008 09:50 AM   [ Ignore ]   [ # 12 ]  
Summer Student
Total Posts:  1
Joined  03-25-2008

This is really useful but, I think it would be better if used paths were changed by APPPATH . ‘views/layouts/’. Then, you will be able to change you application_folder to whatever you want and the hook will still work.

Profile
 
 
Posted: 10 April 2008 12:53 PM   [ Ignore ]   [ # 13 ]  
Summer Student
Total Posts:  1
Joined  04-10-2008

My Layout, sending back to the Repo. (SVN habit)

< ? if (!defined('BASEPATH')) exit('No direct script access allowed');
class
Yielder
{
function yield()
{
/*added CI benchmark support. System/Libraries/Output.php _display replace, inherit. */
global $BM;

$CI =& get_instance();
$output = &$CI->output->final_output;

if (!
preg_match("/(.+).php$/", $CI->layout)){
$CI
->layout .= ".php";
}
/*
if you dont want to use layout, use can use this->layout = -1 definition within your controller init function
*/
if ($CI->layout != -1)
{
$requested
= 'application/views/layouts/' . $CI->layout;
$default = 'application/views/layouts/default.php';
if (!
file_exists($default)) die("Hook failed: Yealder 404 $default");
if (
file_exists($requested))
{
$layout
= $CI->load->file($requested,true);
$view = $layout; //almost there is no performance diff
}
else
{
$layout
= $CI->load->file($default, true);
$view = $layout;
}
}
else
{
$view
= $output;
}
/* inherit? */
echo $CI->output->_display($view);
//echo $view;
}
}
?>

Profile
 
 
   
 
 
‹‹ Database issue...      Smiley issue ››
Post Marker Legend
New Topic New posts Hot Topic Hot Topic with new posts New Poll New Poll Moved Topic Moved Topic Sticky Topic Sticky topic
Old Topic No new posts Hot Old Topic Hot Topic with no new posts Old Poll Old Poll Closed Topic Closed Topic Announcement Announcements
Theme
Change Theme
Visitor Statistics
The most visitors ever was 719, on June 06, 2008 10:16 AM
Total Registered Members: 64453 Total Logged-in Users: 24
Total Topics: 80959 Total Anonymous Users: 1
Total Replies: 435689 Total Guests: 194
Total Posts: 516648    
Members ( View Memberlist )