How would you structure the below page in Codeigniter?
I thought about creating seperate controllers for each section
Excluding the content section (as this changes depending on the link on the left nav and content nav used as a kinda sub-menu). All the other sections remain roughly the same
I thought about doing:
Class User_Profile extends Controller
{
function index()
{
$this->load_controller('Left_Nav');
$this->load_controller('Content_Nav');
$this->load_controller('Login_Name');
$this->load_controller('Leaderboard', 'Board');
$this->Left_Nav->index(array('highlight_selected_page' => 'blah'));
$this->load('User');
$content_data = $this->User->get_profile_details();
$this->view->load('content', $content_data);
$this->Login_Name->index();
$this->Board->index();
}
}
Obviously this load_controller
does not exist but this functionaility would be useful. The controller for each section gets the data required from the model and then loads the page through $this->view->load()
It could be a headache to have this code in all the left nav links like News, Users, About Us, etc.. But then again not every nav link has all those sections so I need that flexability of having the sections as a "partial view"
Can anyone suggest a better way of doing this?
@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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With