Introduction

This tutorial will show you an example on how to use template in Codeigniter 3. In an web application a template is recommended because there are certain regions or areas which are common to all pages and only the body portion of the page gets changed. Common areas like header, footer, left sidebar or right sidebar are mainly common areas for most of the web applications. So we will fix those common areas in the template file so that every page will use those common areas in the application and body portion of each page will contain content which is specific to the page.

We will use here Colin Williams template library to demonstrate the template system in Codeigniter 3. Nowadays the Williams Codeigniter Template library is no longer being supported or improved, the last version produced was 1.4.1. So to make it work with Codeigniter 3, I have done a little modification to it.

If you want to use Template library with Codeigniter 2 then you can read https://www.roytuts.com/using-template-in-codeigniter/.

Now we will see step by step process how can we use the template library in Codeigniter 3 application.

Prerequisites

XAMPP in Windows

Netbeans 8.1

Codeigniter 3.0.6 3.1.10, PHP 7.0

Example with Source Code

Configuring XAMPP and Netbeans

From Netbeans IDE go to Tools->Options. Click on PHP. Now on tab “General” browse the file for “PHP 5 Interpreter”. The php interpreter file generally placed inside the <physical drive in Windows OS>:xamppphpphp.exe

Configuring Codeigniter and Netbeans

Create a new PHP project in Netbeans. Then remove the index.php file from the newly created project. Now copy the extracted files from Codeigniter 3.0.6 3.1.10 to the newly created project directory.

Working with Template

Step 1. Create a template.php file under application/config directory with below source code. This is the template configuration file used define as many as template view files with different regions. These regions can be replaced by dynamic content for each page. Here we are using only one template as a view file for entire application so we have only one template group. If you need to know how to use multiple template files for an application then you can look at https://www.roytuts.com/separating-front-end-and-back-end-in-codeigniter/

We have defined two regions title and content because those two regions will be changing according to the page content. You can also define other regions if you want them to be updated according to the page content. We have used the Codeigniter’s default parser to parse the template regions. We have used parse_template to TRUE to parse the template.

<?php if (!defined('BASEPATH')) exit('No direct script access allowed'); /* |-------------------------------------------------------------------------- | Active template |-------------------------------------------------------------------------- | | The $template['active_template'] setting lets you choose which template | group to make active. By default there is only one group (the | "default" group). | */ $template['active_template'] = 'public'; /* |-------------------------------------------------------------------------- | Explaination of template group variables |-------------------------------------------------------------------------- | | ['template'] The filename of your master template file in the Views folder. | Typically this file will contain a full XHTML skeleton that outputs your | full template or region per region. Include the file extension if other | than ".php" | ['regions'] Places within the template where your content may land. | You may also include default markup, wrappers and attributes here | (though not recommended). Region keys must be translatable into variables | (no spaces or dashes, etc) | ['parser'] The parser class/library to use for the parse_view() method | NOTE: See http://codeigniter.com/forums/viewthread/60050/P0/ for a good | Smarty Parser that works perfectly with Template | ['parse_template'] FALSE (default) to treat master template as a View. TRUE | to user parser (see above) on the master template | | Region information can be extended by setting the following variables: | ['content'] Must be an array! Use to set default region content | ['name'] A string to identify the region beyond what it is defined by its key. | ['wrapper'] An HTML element to wrap the region contents in. (We | recommend doing this in your template file.) | ['attributes'] Multidimensional array defining HTML attributes of the | wrapper. (We recommend doing this in your template file.) | | Example: | $template['default']['regions'] = array( | 'header' => array( | 'content' => array('<h1>Welcome</h1>','<p>Hello World</p>'), | 'name' => 'Page Header', | 'wrapper' => '<div>', | 'attributes' => array('id' => 'header', 'class' => 'clearfix') | ) | ); | */ /* |-------------------------------------------------------------------------- | Default Template Configuration (adjust this or create your own) |-------------------------------------------------------------------------- */ //public template $template['public']['template'] = 'templates/template'; $template['public']['regions'] = array( 'title', 'header', 'content', 'footer' ); $template['public']['parser'] = 'parser'; $template['public']['parser_method'] = 'parse'; $template['public']['parse_template'] = TRUE; /* End of file template.php */ /* Location: ./application/config/template.php */

Step 2. Now we will see the template library file. Put the below source code in Template.php file under application/libraries directory. The original template class is little different from what I presented here because here I changed the class name from CI_Template to Template and also I have added one extra region _meta => array() for giving provision for every page to add meta key/value.

<?php if (!defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * * An open source application development framework for PHP 4.3.2 or newer * * @package CodeIgniter * @author ExpressionEngine Dev Team, a little modification by https://www.roytuts.com * @copyright Copyright (c) 2006, EllisLab, Inc. * @since Version 1.0 * @filesource */ // -------------------------------------------------------------------- class Template { var $CI; var $config; var $template; var $master; var $regions = array( '_scripts' => array(), '_styles' => array(), '_meta' => array() ); var $output; var $js = array(); var $css = array(); var $meta = array(); var $parser = 'parser'; var $parser_method = 'parse'; var $parse_template = FALSE; /** * Constructor * * Loads template configuration, template regions, and validates existence of * default template * * @access public */ function __construct() { // Copy an instance of CI so we can use the entire framework. $this->CI = & get_instance(); // Load the template config file and setup our master template and regions include(APPPATH . 'config/template' . '.php'); if (isset($template)) { $this->config = $template; $this->set_template($template['active_template']); } } // -------------------------------------------------------------------- /** * Use given template settings * * @access public * @param string array key to access template settings * @return void */ function set_template($group) { if (isset($this->config[$group])) { $this->template = $this->config[$group]; } else { show_error('The "' . $group . '" template group does not exist. Provide a valid group name or add the group first.'); } $this->initialize($this->template); } // -------------------------------------------------------------------- /** * Set master template * * @access public * @param string filename of new master template file * @return void */ function set_master_template($filename) { if (file_exists(APPPATH . 'views/' . $filename) or file_exists(APPPATH . 'views/' . $filename . '.php')) { $this->master = $filename; } else { show_error('The filename provided does not exist in <strong>' . APPPATH . 'views</strong>. Remember to include the extension if other than ".php"'); } } // -------------------------------------------------------------------- /** * Dynamically add a template and optionally switch to it * * @access public * @param string array key to access template settings * @param array properly formed * @return void */ function add_template($group, $template, $activate = FALSE) { if (!isset($this->config[$group])) { $this->config[$group] = $template; if ($activate === TRUE) { $this->initialize($template); } } else { show_error('The "' . $group . '" template group already exists. Use a different group name.'); } } // -------------------------------------------------------------------- /** * Initialize class settings using config settings * * @access public * @param array configuration array * @return void */ function initialize($props) { // Set master template if (isset($props['template']) && (file_exists(APPPATH . 'views/' . $props['template']) or file_exists(APPPATH . 'views/' . $props['template'] . '.php'))) { $this->master = $props['template']; } else { // Master template must exist. Throw error. show_error('Either you have not provided a master template or the one provided does not exist in <strong>' . APPPATH . 'views</strong>. Remember to include the extension if other than ".php"'); } // Load our regions if (isset($props['regions'])) { $this->set_regions($props['regions']); } // Set parser and parser method if (isset($props['parser'])) { $this->set_parser($props['parser']); } if (isset($props['parser_method'])) { $this->set_parser_method($props['parser_method']); } // Set master template parser instructions $this->parse_template = isset($props['parse_template']) ? $props['parse_template'] : FALSE; } // -------------------------------------------------------------------- /** * Set regions for writing to * * @access public * @param array properly formed regions array * @return void */ function set_regions($regions) { if (count($regions)) { $this->regions = array( '_scripts' => array(), '_styles' => array(), '_meta' => array() ); foreach ($regions as $key => $region) { // Regions must be arrays, but we take the burden off the template // developer and insure it here if (!is_array($region)) { $this->add_region($region); } else { $this->add_region($key, $region); } } } } // -------------------------------------------------------------------- /** * Dynamically add region to the currently set template * * @access public * @param string Name to identify the region * @param array Optional array with region defaults * @return void */ function add_region($name, $props = array()) { if (!is_array($props)) { $props = array(); } if (!isset($this->regions[$name])) { $this->regions[$name] = $props; } else { show_error('The "' . $name . '" region has already been defined.'); } } // -------------------------------------------------------------------- /** * Empty a region's content * * @access public * @param string Name to identify the region * @return void */ function empty_region($name) { if (isset($this->regions[$name]['content'])) { $this->regions[$name]['content'] = array(); } else { show_error('The "' . $name . '" region is undefined.'); } } // -------------------------------------------------------------------- /** * Set parser * * @access public * @param string name of parser class to load and use for parsing methods * @return void */ function set_parser($parser, $method = NULL) { $this->parser = $parser; $this->CI->load->library($parser); if ($method) { $this->set_parser_method($method); } } // -------------------------------------------------------------------- /** * Set parser method * * @access public * @param string name of parser class member function to call when parsing * @return void */ function set_parser_method($method) { $this->parser_method = $method; } // -------------------------------------------------------------------- /** * Write contents to a region * * @access public * @param string region to write to * @param string what to write * @param boolean FALSE to append to region, TRUE to overwrite region * @return void */ function write($region, $content, $overwrite = FALSE) { if (isset($this->regions[$region])) { if ($overwrite === TRUE) { // Should we append the content or overwrite it $this->regions[$region]['content'] = array($content); } else { $this->regions[$region]['content'][] = $content; } } // Regions MUST be defined else { show_error("Cannot write to the '{$region}' region. The region is undefined."); } } // -------------------------------------------------------------------- /** * Write content from a View to a region. 'Views within views' * * @access public * @param string region to write to * @param string view file to use * @param array variables to pass into view * @param boolean FALSE to append to region, TRUE to overwrite region * @return void */ function write_view($region, $view, $data = NULL, $overwrite = FALSE) { $args = func_get_args(); // Get rid of non-views unset($args[0], $args[2], $args[3]); // Do we have more view suggestions? if (count($args) > 1) { foreach ($args as $suggestion) { if (file_exists(APPPATH . 'views/' . $suggestion . '.php') or file_exists(APPPATH . 'views/' . $suggestion)) { // Just change the $view arg so the rest of our method works as normal $view = $suggestion; break; } } } $content = $this->CI->load->view($view, $data, TRUE); $this->write($region, $content, $overwrite); } // -------------------------------------------------------------------- /** * Parse content from a View to a region with the Parser Class * * @access public * @param string region to write to * @param string view file to parse * @param array variables to pass into view for parsing * @param boolean FALSE to append to region, TRUE to overwrite region * @return void */ function parse_view($region, $view, $data = NULL, $overwrite = FALSE) { $this->CI->load->library('parser'); $args = func_get_args(); // Get rid of non-views unset($args[0], $args[2], $args[3]); // Do we have more view suggestions? if (count($args) > 1) { foreach ($args as $suggestion) { if (file_exists(APPPATH . 'views/' . $suggestion . '.php') or file_exists(APPPATH . 'views/' . $suggestion)) { // Just change the $view arg so the rest of our method works as normal $view = $suggestion; break; } } } $content = $this->CI->{$this->parser}->{$this->parser_method}($view, $data, TRUE); $this->write($region, $content, $overwrite); } // -------------------------------------------------------------------- /** * Dynamically include javascript in the template * * NOTE: This function does NOT check for existence of .js file * * @access public * @param string script to import or embed * @param string 'import' to load external file or 'embed' to add as-is * @param boolean TRUE to use 'defer' attribute, FALSE to exclude it * @return TRUE on success, FALSE otherwise */ function add_js($script, $type = 'import', $defer = FALSE) { $success = TRUE; $js = NULL; $this->CI->load->helper('url'); switch ($type) { case 'import': $filepath = base_url() . $script; $js = '<script type="text/javascript" src="' . $filepath . '"'; if ($defer) { $js .= ' defer="defer"'; } $js .= "></script>"; break; case 'embed': $js = '<script type="text/javascript"'; if ($defer) { $js .= ' defer="defer"'; } $js .= ">"; $js .= $script; $js .= '</script>'; break; default: $success = FALSE; break; } // Add to js array if it doesn't already exist if ($js != NULL && !in_array($js, $this->js)) { $this->js[] = $js; $this->write('_scripts', $js); } return $success; } // -------------------------------------------------------------------- /** * Dynamically include CSS in the template * * NOTE: This function does NOT check for existence of .css file * * @access public * @param string CSS file to link, import or embed * @param string 'link', 'import' or 'embed' * @param string media attribute to use with 'link' type only, FALSE for none * @return TRUE on success, FALSE otherwise */ function add_css($style, $type = 'link', $media = FALSE) { $success = TRUE; $css = NULL; $this->CI->load->helper('url'); $filepath = base_url() . $style; switch ($type) { case 'link': $css = '<link type="text/css" rel="stylesheet" href="' . $filepath . '"'; if ($media) { $css .= ' media="' . $media . '"'; } $css .= ' />'; break; case 'import': $css = '<style type="text/css">@import url(' . $filepath . ');</style>'; break; case 'embed': $css = '<style type="text/css">'; $css .= $style; $css .= '</style>'; break; default: $success = FALSE; break; } // Add to js array if it doesn't already exist if ($css != NULL && !in_array($css, $this->css)) { $this->css[] = $css; $this->write('_styles', $css); } return $success; } // -------------------------------------------------------------------- /** * Dynamically include meta tags in the template * * @param string $key meta name * @param string $value meta content * @return bool */ function add_meta($key, $val) { $success = FALSE; $meta = '<meta name="' . $key . '" content="' . $val . '" />'; if (!in_array($meta, $this->meta)) { $this->meta[] = $meta; $this->write('_meta', $meta); $success = TRUE; } return $success; } /** * Render the master template or a single region * * @access public * @param string optionally opt to render a specific region * @param boolean FALSE to output the rendered template, TRUE to return as a string. Always TRUE when $region is supplied * @return void or string (result of template build) */ function render($region = NULL, $buffer = FALSE, $parse = FALSE) { // Just render $region if supplied if ($region) { // Display a specific regions contents if (isset($this->regions[$region])) { $output = $this->_build_content($this->regions[$region]); } else { show_error("Cannot render the '{$region}' region. The region is undefined."); } } // Build the output array else { foreach ($this->regions as $name => $region) { $this->output[$name] = $this->_build_content($region); } if ($this->parse_template === TRUE or $parse === TRUE) { // Use provided parser class and method to render the template $output = $this->CI->{$this->parser}->{$this->parser_method}($this->master, $this->output, TRUE); // Parsers never handle output, but we need to mimick it in this case if ($buffer === FALSE) { $this->CI->output->set_output($output); } } else { // Use CI's loader class to render the template with our output array $output = $this->CI->load->view($this->master, $this->output, $buffer); } } return $output; } // -------------------------------------------------------------------- /** * Load the master template or a single region * * DEPRECATED! * * Use render() to compile and display your template and regions */ function load($region = NULL, $buffer = FALSE) { $region = NULL; $this->render($region, $buffer); } // -------------------------------------------------------------------- /** * Build a region from it's contents. Apply wrapper if provided * * @access private * @param string region to build * @param string HTML element to wrap regions in; like '<div>' * @param array Multidimensional array of HTML elements to apply to $wrapper * @return string Output of region contents */ function _build_content($region, $wrapper = NULL, $attributes = NULL) { $output = NULL; // Can't build an empty region. Exit stage left if (!isset($region['content']) or !count($region['content'])) { return FALSE; } // Possibly overwrite wrapper and attributes if ($wrapper) { $region['wrapper'] = $wrapper; } if ($attributes) { $region['attributes'] = $attributes; } // Open the wrapper and add attributes if (isset($region['wrapper'])) { // This just trims off the closing angle bracket. Like '<p>' to '<p' $output .= substr($region['wrapper'], 0, strlen($region['wrapper']) - 1); // Add HTML attributes if (isset($region['attributes']) && is_array($region['attributes'])) { foreach ($region['attributes'] as $name => $value) { // We don't validate HTML attributes. Imagine someone using a custom XML template.. $output .= "$name=\"$value\""; } } $output .= ">"; } // Output the content items. foreach ($region['content'] as $content) { $output .= $content; } // Close the wrapper tag if (isset($region['wrapper'])) { // This just turns the wrapper into a closing tag. Like '<p>' to '</p>' $output .= str_replace('<', '</', $region['wrapper']) . "n"; } return $output; } } // END Template Class /* End of file Template.php */ /* Location: ./application/libraries/Template.php */

Step 3. So we need to load the template library only once and the template library will be used in subsequent requests. So autoload it using autoload.php configuration under application/config directory.

$autoload['libraries'] = array('template');

Also do the following

$autoload['helper'] = array('url', 'form');

Step 4. Add below config to the file application/config/config.php

/* |-------------------------------------------------------------------------- | Website name | |-------------------------------------------------------------------------- */ $config['website_name'] = 'www.roytuts.com';

Step 5. Create an assets directory in parallel with application folder as shown in below figure.

Please note that we are now using Codeigniter 3.1.10 and project root directory is now Codeigniter-3.1.10-template but the directory structure is same as old.

Download here assets

Step 6. Create a template view file template.php under application/views/templates directory

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <!-- page title specific to the page --> <title><?php echo $this->config->item('website_name'); ?> | {title}</title> <!-- meta keywords specific to the page --> {_meta} <!-- common style sheets for every page --> <link rel="stylesheet" type="text/css" href="<?php echo base_url() . 'assets/reset.css'; ?>"> <link rel="stylesheet" type="text/css" href="<?php echo base_url() . 'assets/960.css'; ?>"> <link rel="stylesheet" type="text/css" href="<?php echo base_url() . 'assets/menu.css'; ?>"> <!-- style sheets specific to the page --> {_styles} <!-- js files specific to the page --> {_scripts} </head> <body> <div class="container_12"> {header} <div class="clear"></div> {content} <div class="clear"></div> {footer} <div class="clear"></div> </div> </body> </html>

Step 7. Create common regions view files header.php and footer.php files under application/views/templates/snippets.

header.php

<div class="grid_12"> <div id="menu" class="menu"> <ul class="nav"> <li> <a href="<?php echo site_url(); ?>">Home</a> </li> <li> <a href="<?php echo site_url('signin'); ?>">Signin</a> </li> <li> <a href="">About</a> </li> </ul> </div> </div>

footer.php

<div class="grid_12" id="site_info"> <div class="box"> <p> Copyright © <?php echo date('Y') . ' '; ?> <a href="<?php echo site_url(); ?>"><?php echo $this->config->item('website_name'); ?></a>. All Rights Reserved. </p> </div> </div>

Step 8. Now we will change our application/core/MY_Controller.php file to use template

<?php (defined('BASEPATH')) OR exit('No direct script access allowed'); /** * Description of my_controller * * @author https://www.roytuts.com */ class MY_Controller extends CI_Controller { function __construct() { parent::__construct(); //default title $this->template->write('title', 'Roy Tutorials', TRUE); //default meta description $this->template->add_meta('description', 'An example of a page description.'); //it is better to include header and footer here because these will be used by every page $this->template->write_view('header', 'templates/snippets/header'); $this->template->write_view('footer', 'templates/snippets/footer'); } } /* End of file MY_Controller.php */ /* Location: ./application/core/MY_Controller.php */

Step 9. Now change application/modules/site/controllers/site.php to use template

<?php (defined('BASEPATH')) OR exit('No direct script access allowed'); /** * Description of site * * @author https://www.roytuts.com */ class Site extends MY_Controller { function __construct() { parent::__construct(); } function index() { $this->template->write('title', 'Welcome to Roy Tutorials', TRUE); /** * if you have any js to add for this page */ //$this->template->add_js('assets/js/niceforms.js'); /** * if you have any css to add for this page */ $this->template->add_css('assets/css/page.css'); $this->template->write_view('content', 'home', '', TRUE); $this->template->render(); } } /* End of file site.php */ /* Location: ./application/modules/site/controllers/site.php */

Step 10. Change the view file in application/modules/site/views/home.php

<div id="container"> <h1>Welcome to CodeIgniter Template</h1> <div id="body"> <p>Example on using Template with Codeigniter 3.1</p> <p>If you would like to edit this page you'll find it located at:</p> <code>application/modules/site/views/home.php</code> <p>The corresponding controller for this page is found at:</p> <code>application/modules/site/controllers/site.php</code> </div> <p class="footer">Page rendered in <strong>{elapsed_time}</strong> seconds. <?php echo (ENVIRONMENT === 'development') ? 'CodeIgniter Version <strong>' . CI_VERSION . '</strong>' : '' ?></p> </div>

Step 11. Also change application/modules/signin/controllers/signin.php to use template

<?php if (!defined('BASEPATH')) exit('No direct script access allowed'); /** * Description of signin * * @author https://www.roytuts.com */ class Signin extends MY_Controller { function __construct() { parent::__construct(); $this->load->library('form_validation'); } function index() { $data['title'] = 'Signin'; $this->form_validation->set_rules('username', 'Username', 'required'); $this->form_validation->set_rules('password', 'Password', 'required'); if ($this->form_validation->run() === FALSE) { $this->template->write('title', 'Signin to Roy Tutorials', TRUE); /** * if you have any js to add for this page */ //$this->template->add_js('assets/js/niceforms.js'); /** * if you have any css to add for this page */ $this->template->add_css('assets/css/page.css'); $this->template->write_view('content', 'signin', '', TRUE); $this->template->render(); } else { redirect(); } } } /* End of file signin.php */ /* Location: ./application/modules/signin/controllers/signin.php */

Step 12. Change the view file in application/modules/signin/views/signin.php

<div id="container"> <h1>Signin Here!</h1> <?php echo validation_errors(); ?> <div id="body"> <?php echo form_open('signin'); ?> <p> <label for="title">Username</label> <input type="input" name="username" /><br /> </p> <p> <label for="text">Password</label> <input type="password" name="password" /><br /> </p> <p> <input type="submit" name="submit" value="Signin" /> </p> <?php echo form_close(); ?> </div> </div>

Testing the Application

Home page

Signin Page

Source Code

download source code

Thanks for reading.