Adding Layouts c.q. data format to CI

Derek Jones edited this page Jul 5, 2012 · 12 revisions
Clone this wiki locally

Category:Plugin::Data_Presentation @todo: Detecting missing layout and give an error message accordingly @todo: Add examples @todo: Move hardcoded settings to config

See also: http://alessandrovermeulen.me/2009/04/16/extending-the-v-in-mvc/

Version: 0.10

In this article I'll explain why this snippet is a nice thing to have when developping large applications which need to present their data in different formats. (i.e. .xhtml; .rss/xml; .xml; .csv; .msg; etc...)

If we take a look on a popular application on the web today, the blog, you see people adding posts and comments. Those posts and comments are then displayed in xhtml. A large portion of a blog is it's feeds. Now you wouldn't want to have to write a lot of extra code just to be able to provide those feeds as they provide essentially the same data as the html pages.

This is where layouts step in. They control in which data format the provided is shown. There is no need to regulate this from within your controller (but you could ofcourse) as the appropiate format is automatically determined from the url. This makes adding rss feeds to your blog quite easy. It's just a questing of writing the code for the generating the feed code itself and nothing more.

Compare the following urls:

http://someurl/blog/latest/10

Shows the latest 10 blog posts in the standard way. Showing a menu, a sidebar, an header, etc... Nice for humans. Consider the following url:

http://someurl/blog/latest.rss/10

Here the code automagically selects the correct layout (rss) when you request a view from within your controller. The only thing you have to specify is which view should be loaded. I'll tackle that problem in an other article.

Usage

Controller

```php

<?php class Blog extends MY_Controller { public function post() { $this->view('blog/post'); } } ?>


<h4>View</h4>
/views/xhtml/blog/post.php
```php

&lt;?php
//Do some preprocessing here
//Maybe include an header or something
$this->view('xhtml/_header'); // here we have to specify the layout in the path (notice: the header is a partial, more about those later)
?&gt;
<div id="content">
  <h1>Hi</h1>
</div>
&lt;?php
// Do something like including a footer
?&gt;

/views/rss/blog/post.php


&lt;?xml version="1.0" encoding="UTF-8"?&gt;
<channel>
</channel>

Ofcourse you should be using the DOMDocument here.

Directory

```php

views D rss D blog F post.php D xhtml D blog F post.php


Wow, this looks fabulous! How do I use it?

Add the following code to you copy of CI:
<h3>Code</h3>
```php

class MY_Controller extends Controller {
  protected $layout = 'xhtml';

  /**
   * This function remaps the url and retrieves the desired extension from it. It then calls the appropiate controller method.
   *
   * @param string $aMethod
   */
  function _remap($aMethod) {
    $lParams = $this->uri->segment_array();
    array_shift($lParams);array_shift($lParams);
    
    $lMethod = $aMethod; 
    if (strpos($lMethod, '.') !== False) 
      list($lMethod, $this->layout) = explode('.', $lMethod);
      
    $lMethod = (empty($lMethod) ? 'index' : $lMethod);
    
    # Let's be sure that we only call a public method
    if (method_exists($this, $lMethod) && !method_exists(__CLASS__, $lMethod)) {
      call_user_func_array(array($this, $lMethod), $lParams);
    } 
    else {
      show_404($lMethod);
    }
  }

  /**
   * This function provides a shortcut to the load->view function. It also appends the current layout so you won't get lost.
   *
   * @param string $aView
   */
  protected final function view($aView, $aData=array()) {
    $this->load->view($this->layout.DIRECTORY_SEPARATOR.$aView, $aData);
  }
}

Well, that's really all there is to it. If you have any questions, feel free to ask them in the discussion topic.