How would you structure the below page in Codeigniter?
I thought about creating seperate c
have you considered templates? There are many decent ones available with a little searching - check the CI wiki.
templates do more or less exactly what you are after. You define one master template and "sections", and these are loaded for you each time
don't want to plug too much so this might get you started - template libraries in CI
What I've done (in Kohana 2) is have the 1 template with all the sub sections (like left menu, top header), and a single controller that populates the variables that will be replaced in the template.
Then, the variables for every sub-section can be generated by functions called in the controller itself. You can also have those functions be in a separate controller class's constructor, with every controller of yours extending that one so they're automatically ran and set as class variables for easy access.
For slightly nicer templates you can have the subsections in separate files, and the big template include them:
<?php include 'leftMenu.php'; ?>
@Reinis answer probably hit the spot correctly for older versions of CI less than 2.0 however alot has changed since then, so I thought I'd answer this question with an up to date method of what I've done.
Most of it is similar to @Reinis method and also described here:http://codeigniter.com/wiki/MY_Controller_-_how_to_extend_the_CI_Controller
However here are the updates ive done:
Step 1: Create a MY_Controller.php file and store it in /application/core
Step 2: In your MY_Controller.php file put in the following contents:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Controller extends CI_Controller {
function __construct()
{
parent::__construct();
}
function _output($content)
{
// Load the base template with output content available as $content
$data['content'] = &$content;
echo($this->load->view('base', $data, true));
}
}
Step 3: Create a sample controller to base off of MY_Controller.php, in this case I will create a welcome.php controller inside of application/controllers/ with the following content:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Welcome extends MY_Controller {
function __construct()
{
parent::__construct();
}
public function index()
{
$this->load->view('welcome_message');
}
}
Once you have these controllers set, do the following:
Step 4: Create a base view inside of /application/views and name the file base.php, the content of the file should be similar to this:
<!DOCTYPE html>
<!--[if IE 7 ]><html lang="en" class="ie7"><![endif]-->
<!--[if IE 8 ]><html lang="en" class="ie8"><![endif]-->
<!--[if gt IE 8]><!--><html lang="en"><!--<![endif]-->
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title></title>
<link rel="stylesheet" href="<?php echo base_url(); ?>stylesheets/reset.css" media="screen" />
</head>
<body>
<div id="section_main">
<div id="content">
<?php echo $content; ?>
</div>
</div>
<?php $this->load->view('shared/scripts.php'); ?>
</div>
</body>
</html>
Step 5: Create another view in /application/views and name this view welcome_message.php, the content of this file will be:
<h1>Welcome</h1>
Once, all this is complete, you should see the following output:
<!DOCTYPE html>
<!--[if IE 7 ]><html lang="en" class="ie7"><![endif]-->
<!--[if IE 8 ]><html lang="en" class="ie8"><![endif]-->
<!--[if gt IE 8]><!--><html lang="en"><!--<![endif]-->
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title></title>
<link rel="stylesheet" href="http://somedomain.local/stylesheets/reset.css" media="screen" />
</head>
<body>
<!-- BEGIN: section_main -->
<div id="section_main">
<div id="content">
<h1>Welcome</h1>
</div>
</div>
<!-- END: section_main -->
<script src="/path/to/js.js"></script>
</div>
</body>
</html>
As you can see <h1>Welcome</h1>
was put into the base template.
Resources:
Hope this helps anyone else coming across this technique.
I can't vouch that this is the best approach, but I create a base controller like this:
class MY_Controller extends CI_Controller {
public $title = '';
// The template will use this to include default.css by default
public $styles = array('default');
function _output($content)
{
// Load the base template with output content available as $content
$data['content'] = &$content;
$this->load->view('base', $data);
}
}
The view called 'base' is a template (a view that includes other views):
<?php echo doctype(); ?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<?php $this->load->view('meta'); ?>
</head>
<body>
<div id="wrapper">
<?php $this->load->view('header'); ?>
<div id="content">
<?php echo $content; ?>
</div>
<?php $this->load->view('footer'); ?>
</div>
</body>
</html>
What this achieves is that every controller wraps its output in the base template, and that views have valid HTML instead of opening tags in one view and closing in another. If I'd like a specific controller to use a different or no template, I could just override the magic _output()
method.
An actual controller would look like this:
class Home extends MY_Controller {
// Override the title
public $title = 'Home';
function __construct()
{
// Append a stylesheet (home.css) to the defaults
$this->styles[] = 'home';
}
function index()
{
// The output of this view will be wrapped in the base template
$this->load->view('home');
}
}
Then I could use its properties in my views like this (this is the 'meta' view that populates the <head>
element):
echo "<title>{$this->title}</title>";
foreach ($this->styles as $url)
echo link_tag("styles/$url.css");
I like my approach because it respects the DRY principle and the header, footer and other elements get included just once in the code.
I would make a MY_Controller to take care of all this. You can top it with a layout(template)/navigation library to generate all the layouts, navigation, showing/highlighting selected menu item, loading views etc.
I'd say it's not the right way to do it, if you're using a controller for each page section. You can to make use of views and nested views for that.
My Template library can handle all of this. You create a single (or multiple) layout file(s) that contain the partials and a tag for where the main body content will go.
Syntax as simple as:
// Set the layout: defaults to "layout" in application/views/layout.php
$this->template->set_layout('whatever')
// Load application/views/partials/viewname as a partial
$this->template->set_partial('partialname', 'partials/viewname');
// Call the main view: application/views/bodyviewname
$this->template->build('bodyviewname', $data);
Simples right?
Put some of that into MY_Controller and its even easier.