Part of the EllisLab Network
   
1 of 3
1
Modulated Templated CMS system
Posted: 05 March 2008 02:02 PM   [ Ignore ]  
Lab Assistant
Avatar
RankRank
Total Posts:  203
Joined  09-07-2007

Here I will explain how to build a smarty templated modulated CMS.
please follow the instructions on this thread to setup your smarty templates system
http://codeigniter.com/forums/viewthread/60050/
also please see this thread for modules setup instructions:
http://codeigniter.com/forums/viewthread/73177
configure your routes.php file like this:

$route['default_controller'"default_controller";
$route['scaffolding_trigger'"";
$route['(.*)''default_controller/$1'

now create a controller called default_controller like so in your app/controllers directory:

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

class 
Default_controller extends Controller
{
    
function Default_controller()
    
{
        parent
::Controller();
        
$this->load->library('smarty_parser');
        
$this->load->helper('modules');
        
$this->init();
    
}
    
var $method;
    var 
$data=array();
    function 
_remap($page$content '')
    
{
        modules
::load('search');
        
$data['page']=$page;
        switch (
$page)
        
{
            
case 'index':
            case 
'home':
                    
$content modules::run('home',$data,$this->method);
                break;
        case 
'user':
            
$content modules::run($page,'',$this->method);
        break;
            default:
                
//$content = modules::run('home');
                
show_404();
        
}        

        $this
->render($content);
    
}
    
function init()
    
{
        
if($this->uri->segment(2)!='')
        
{
            $this
->method=$this->uri->segment(2);
        
}
        
else
        
{
            $this
->method='index';
        
}
    }
    
    
function render($content)
    
{       
        $default_template 
= array(
            
'template'=> $content
        
);
        
/*default_layout only contains this string <?=$template?>*/
        
$this->smarty_parser->parse("ci:default_layout",$default_template);
    
}

now create a view inside you app/views directory called default_layout.php like so:

<?=$template?> 
 Signature 

Restrict who can interact with your PHP application
Get Developer Access

Profile
 
 
Posted: 05 March 2008 02:08 PM   [ Ignore ]   [ # 1 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  203
Joined  09-07-2007

now for the fun part. copy over the modular_extentsions.php to your app/libs and modular_helper.php to app/helpers, make sure that your smarty templates folder is located inside app/views and inside the smarty folder create a folder default_template and templates inside the templates directory all your site templates will go, your structure should looks like this.

app/
      
views/
            
smarty/
                  
default_template/
                        
css/
                        
images/
                        
tpl_index.php
                        tpl_content
.php
                  templates
/
                        
dark/
                              
css/
                              
images/
                              
tpl_index.php
                              tpl_content
.php
                        light
/
                              
css/
                              
images/
                              
tpl_index.php
                              tpl_content
.php 

for now the code will be loading the light template.

 Signature 

Restrict who can interact with your PHP application
Get Developer Access

Profile
 
 
Posted: 05 March 2008 02:15 PM   [ Ignore ]   [ # 2 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  203
Joined  09-07-2007

now for the modules:
in your app/ directory make sute to have a directory named modules, this is where all your modules will go. Structure like this:

app/
      
modules/
            
home/
                  
controllers/
                  
models/
                  
modules/
                  
views/ <- you can statically link this in linux with ln -sf /full/path/to/smarty/templates views(your modules will then use them

now inside app/modules/home/controllers/ or in app/modules/home/ create a file named home.php

$this->environ->template holds the path to the active template which is easy enough to figure out so I won’t go into details ex. smarty/templates/$template

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

class 
Home extends Module
{
    
function Home()
    
{
        parent
::Module();
        
//modules::debug($this);
    
}
   
    
function index($data)
    
{
        $data 
= array(
            
'breadcrumb_tpl'=>'ci:'.$this->environ->template.'tpl_breadcrumb'.EXT,
            
'content_tpl'=>'ci:'.$this->environ->template.'tpl_content'.EXT,
//load module located inside app/modules/home/modules/home_page/controllers/home_page.php
            
'content'=>modules::run('content',$data),
            
'footer'=>modules::run('footer'),$data)
        ); 

//since your using smarty to parse your templates after CI finishes you get to have the best of both worlds
        
return $this->render('ci:'.$this->environ->template.'tpl_index',$data);

    
}

    
function render($template,$data)
    
{       
        
return $this->smarty_parser->parse($template,$data,true);
    
}
 Signature 

Restrict who can interact with your PHP application
Get Developer Access

Profile
 
 
Posted: 05 March 2008 02:18 PM   [ Ignore ]   [ # 3 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  203
Joined  09-07-2007

this way you can load modules within modules and have them either display there module/view or a template from the templates folder ditermined by the template environ variable. Enjoy. I’ve been waiting for something like this for a while myself. Any comments at all would be greatly appreciated.

 Signature 

Restrict who can interact with your PHP application
Get Developer Access

Profile
 
 
Posted: 05 March 2008 03:03 PM   [ Ignore ]   [ # 4 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  203
Joined  09-07-2007

tpl_index.php will be located in app/views/smarty/templates/$template like so:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<
html xmlns="http://www.w3.org/1999/xhtml">
<
head>
<
meta http-equiv="content-type" content="text/html; charset=utf-8" />
<
meta name="keywords" content="{$meta}/>
<
link rel="shortcut icon" href="media/favicon.ico" type="image/ico" />
<
title>{$title}</title>
{foreach from=$theme_css item=theme}{$theme}{/foreach}
{foreach from
=$theme_js item=theme}{$theme}{/foreach}


</head>
<
body>
<
div id="container" >
        <
div id="headerWrap">
            <
div id="header">
            
{$site_name}
                
            
<ul>{foreach from=$main_menu item=menu}<li>{$menu}</li>{/foreach}</ul>
                
            </
div>
        </
div>
        <
div id="content">
            <
div id="contentHeader">
                <
div id="siteDescription">{$site_slogan}</div>
            </
div>
        
            <
div id="main">
                
{include file="$breadcrumb_tpl"}            
                         
                {include file
="$content_tpl"}    
                {$content}        
                
<br />
                
{$content2}
              
            
</div>
        
            
        </
div>
        <
div id="footer">
{$footer}
</div>
</
div>
</
body>
</
html
 Signature 

Restrict who can interact with your PHP application
Get Developer Access

Profile
 
 
Posted: 07 March 2008 01:46 AM   [ Ignore ]   [ # 5 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  203
Joined  09-07-2007

Any comments would be greatly appreciated

 Signature 

Restrict who can interact with your PHP application
Get Developer Access

Profile
 
 
Posted: 07 March 2008 03:41 AM   [ Ignore ]   [ # 6 ]  
Summer Student
Total Posts:  13
Joined  07-05-2007

On a quick glanze, this is what I have been planning to do myself but I bet not on this scale. I don’t have time to test it now but it sure looks promising. Thanks for your effort :D

Profile
 
 
Posted: 07 March 2008 05:59 AM   [ Ignore ]   [ # 7 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  203
Joined  09-07-2007

no problem, let me know what you think once you test it

 Signature 

Restrict who can interact with your PHP application
Get Developer Access

Profile
 
 
Posted: 16 March 2008 12:07 PM   [ Ignore ]   [ # 8 ]  
Lab Assistant
RankRank
Total Posts:  122
Joined  04-03-2007
yingyes - 05 March 2008 07:15 PM

now for the modules:
in your app/ directory make sute to have a directory named modules, this is where all your modules will go. Structure like this:

app/
      
home/
            
controllers/
            
models/
            
modules/
            
views/ <- you can statically link this in linux with ln -sf /full/path/to/smarty/templates views(your modules will then use them

now inside app/modules/home/controllers/ or in app/modules/home/ create a file named home.php

Is this directory correct? (app/modules/home/controllers/)  Or did you mean app/home/modules/controllers/

I’m trying to get the basic understanding of using HMVC from your tutorial here, although I haven’t used smarty, so I’m trying to get the point without smarty involved.

I also tried looking at the InkType blog setup, but that server is down so I didn’t get far with that one.  I think another good reference example may have been to use bambooinvoice.org.  A common ‘hello world’ example would be beneficial for all user extensions.

Profile
 
 
Posted: 16 March 2008 07:51 PM   [ Ignore ]   [ # 9 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  203
Joined  09-07-2007

@a&w;- yes your modules will be located inside the app/modules/ directory like this:

app/
      
modules/
            
module1/
                  
config/
                  
controllers/
                  
helpers/
                  
language/
                  
libraries/
                  
methods/
                  
models/
                  
modules/*only if you want sibling modules*/
                  
views/
            
module2/
                  
controllers/
                        
module2.php
                  models
/
                        
module2_model.php
                  views
/
                        
module2_view.php 

module one is just how I’ve decided to implement my home(main) module that is mapped to in your default controller

function _remap()
    
{
        modules
::load('search');

        
$module $this->uri->segment(1) OR $module 'home';
        
$method $this->uri->segment(2) OR $method 'index';

        
$this->data=$this->lang->language;//sets my language variables, autoloaded

        
$this->data['current_page']=$module//used inside my modules

    
$this->data['current_action']=$method//used inside my modules
//if you want to load modules into views? from here you can
    //$this->data['header']=modules::run('header',$this->data,'index');//I don't do this from my default controller
        
if(modules::exists($module,$module)!=NULL)//I've modified modules_helper.php to include a exists() method
        
{
            $content 
= ($module=='admin')?modules::run($module$this->data$method):modules::run($module$this->data'index');  
        
}
        
else
        
{
            redirect
('');
        
}
        
        $this
->render($content);

and a render method inside default_controller.php

function render($content)
    
{       

        
//This calls the active template index page
        
$default_template = array(
            
'template'=> $content//$this->smarty_parser->parse('ci:'.$this->template.'/index',$content,true)
        
);
        
/*contains only <?=$template?>*/
        
$this->smarty_parser->parse("ci:default_layout",$default_template);
    

exists method inside modules_helper.php version 4.0.19
makes it so that if a module doesn’t exist it will redirect to default module and will not show
this line from modules_helper.php

show_error("Unable to locate the requested file: ".$path2file); 
function exists($file$path ''$base 'controllers/')
    
{
        $file 
.= strpos($file'.') ? '' EXT;
        
        if ((
$pos strrpos($file'/')) !== FALSE)
        
{
            $path  
substr($file0$pos);
            
$file  substr($file$pos 1);
        
}
        
        $path 
.= '/';
        
        
$path2file $path.$base.$file;
        
        
$paths2scan = array(MODBASE.$path.$baseMODBASE.$pathMODBASE.$baseMODBASE);
        
        if (!
in_array($base, array('controllers/''libraries/''methods/')))
        
{
            $paths2scan 
array_merge($paths2scan, array(APPPATH.$baseAPPPATH.$base.$path));
        
}
          
        
foreach ($paths2scan as $path2)
        
{                
            
foreach (array($fileucfirst($file)) as $name)
            
{
                
if (is_file($path2.$name))
                {
                    
return TRUE;
                
}
            }
        }
        
return FALSE// I don't understand why it returns NULL even though I have this set
    

default_controller.php doesn’t have to be so overweight from the bulk of the data being passes in teh views. I use a custom library to do this, which just loads all the options inside the data array upon initialization and then just array_merge that array into your data array inside default_controller.php :) You could load the content into a view instead of a smarty template system just as easy by changing your render method to do this. I’ve added an exists method because I could see a way without one inside modules_helper.php all it is, is just a modified version of the path_to() method. The reason why I use smarty is because it makes my views look much cleaner. So if I am not good at design but Iknow how to do this then a designer can take a gander at the views without knowing how to code. Any more questions are welcome. I gives me more ideas, hope this helps someone.

 Signature 

Restrict who can interact with your PHP application
Get Developer Access

Profile
 
 
Posted: 16 March 2008 09:05 PM   [ Ignore ]   [ # 10 ]  
Lab Assistant
RankRank
Total Posts:  122
Joined  04-03-2007

Thanks.  I’m getting a better picture now.  Thanks for elaborating so well.  Please note, that I think in Post#2 your directory structure is different, hence my seeking clarification on the structure.  Your ‘home’ folder is not inside ‘modules’.

I had not even considered nesting the modules folder, where you’ve shown it being a child folder.  Interesting.  Not sure when it would ever come to practice, but good to know.

What is the difference between modules::load and modules::run?  A cursory look at the code looks like run also loads the module passed.

With reference to the line below, do you check if data[‘current_action’] isset in your index method of the controller then?

$this->data['current_action']=$method//used inside my modules 

This next part is probably application specific, nonetheless, anything interesting to note with the following snippet?

$content = ($module=='admin')?modules::run($module$this->data$method):modules::run($module$this->data'index');  
        
}
        
else
        
{
            redirect
('');
        

I didn’t quite follow you when you say you use a custom library to load all the options inside the data array upon initialization and then just array_merge.  I’m a bit rusty on CI (took a sabatical for a few months learning javascript), but I thought when libraries were loaded, CI automatically checked for a similarly named config file.  Seems like there would be a way befitting of the “CI way” to have the modules check for a config file and to load that.  So when a module is loaded, go ahead and load the config array associated with it.  Not sure if that would connect to the module, or maybe one of the views.

Profile
 
 
   
1 of 3
1