Welcome Guest, Not a member yet? Register   Sign In
Yet Another Smarty Thread
#1

[eluser]xtramix[/eluser]
Integration of CI and Smarty has been discussed many times on this forum, yet I've decided to post here my own solution, in the hopes that someone might find it useful.

The only advantage this particular approach offers over other suggested solutions, is its ability to incorporate CI and Smarty code in the same template, rather than forcing you to choose between the two. If your templates contain pure Smarty code, you can load/parse them in a usual fashion, e.g.:
Code:
$this->smarty_parser->parse("template.tpl", $data);
However, if your template started out as a regular CI view, you can switch to Smarty at any time and still keep all the php code in your template intact, knowing that all CI function calls and variables will be processed correctly. Simply prefix the template name with "ci:" to tell Smarty it's a "resource", and it will ask CI to load and pre-parse the view before handing it off to Smarty engine:
Code:
$this->smarty_parser->parse("ci:template.tpl", $data);

The steps necessary to set up Smarty under CI in this case are very similar to those suggested by other authors:

1. Rename Smarty "libs" folder to "smarty", and move it to CI's application/libraries directory.

2. Create Smarty_parser.php file in the same directory and paste the following code:
Code:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

require "smarty/Smarty.class.php";

class Smarty_parser extends Smarty {

    function Smarty_parser($config = array())
    {
        parent::Smarty();
        
        if (count($config) > 0)
        {
            $this->initialize($config);
        }

        // register Smarty resource named "ci"
        $this->register_resource("ci", array($this,
                        "ci_get_template", "ci_get_timestamp", "ci_get_secure", "ci_get_trusted")
        );
                                      
        log_message('debug', "Smarty_parser Class Initialized");
    }

    /**
     * Initialize preferences
     */    
    function initialize($config = array())
    {
        foreach ($config as $key => $val)
        {
            if (isset($this->$key))
            {
                $method = 'set_'.$key;
                
                if (method_exists($this, $method))
                {
                    $this->$method($val);
                }
                else
                {
                    $this->$key = $val;
                }            
            }
        }
    }

    /**
     *  Set the left/right variable delimiters
     */
    function set_delimiters($l = '{', $r = '}')
    {
        $this->left_delimiter = $l;
        $this->right_delimiter = $r;
    }

    /**
     *  Parse a template using Smarty engine
     *
     * Parses pseudo-variables contained in the specified template,
     * replacing them with the data in the second param.
     * Allows CI and Smarty code to be combined in the same template
     * by prefixing template name with "ci:".
     */
    function parse($template, $data, $return = FALSE)
    {
        if ($template == '')
        {
            return FALSE;
        }

        $CI =& get_instance();
        
        $CI->benchmark->mark('smarty_parse_start');
        
        if (is_array($data))
        {
            $this->assign(&$data);
        }
        
        // make CI object directly accessible from a template (optional)
        $this->assign_by_ref('CI', $CI);
        
        $template = $this->fetch($template);

        if ($return == FALSE)
        {
            $CI->output->final_output = $template;
        }
        
        $CI->benchmark->mark('smarty_parse_end');
        
        return $template;
    }

    /**
     * Smarty resource accessor functions
     */    
    function ci_get_template ($tpl_name, &$tpl_source, &$smarty_obj)
    {
        $CI =& get_instance();
        
        // ask CI to fetch our template
        $tpl_source = $CI->load->view($tpl_name, $smarty_obj->get_template_vars(), true);
        return true;
    }
    
    function ci_get_timestamp($view, &$timestamp, &$smarty_obj)
    {
        $CI =& get_instance();
        
        // Taken verbatim from _ci_load (Loader.php, 580):
        $ext = pathinfo($view, PATHINFO_EXTENSION);
        $file = ($ext == '') ? $view.EXT : $view;
        $path = $CI->load->_ci_view_path.$file;
        
        // get file modification date
        $timestamp = filectime($path);
        return ($timestamp !== FALSE);
    }
    
    function ci_get_secure($tpl_name, &$smarty_obj)
    {
        // assume all templates are secure
        return true;
    }
    
    function ci_get_trusted($tpl_name, &$smarty_obj)
    {
        // not used for templates
    }
}
?>

3. Create Smarty_parser.php file in the application/config directory:
Code:
<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');

// Please see Smarty user guide for more info:
// http://smarty.php.net/manual/en/api.variables.php

// The name of the directory where templates are located.
$config['template_dir'] = dirname(FCPATH);

// The directory where compiled templates are located
$config['compile_dir'] = BASEPATH.'cache/';

//This tells Smarty whether or not to cache the output of the templates to the $cache_dir.
$config['caching']        = 0;

// This forces Smarty to (re)compile templates on every invocation.
// When deploying, change this value to 0
$config['force_compile'] = 1;
$config['compile_check'] = TRUE;
?>

4. In your controller, load Smarty library and parse the template, as such:
Code:
// uncomment the line below to load the library under the name "smarty", if desired
// $this->load->_ci_varmap['smarty_parser'] = 'smarty';
$this->load->library('smarty_parser');
$this->smarty_parser->parse("ci:template", $data);

Hope this helps.
#2

[eluser]esra[/eluser]
Nice solution. You might consider placing your entire post on the wiki with a url link back to here.
#3

[eluser]ahmad furqon[/eluser]
yeah, this is cool...
thanks a lot for this solution
#4

[eluser]bijon[/eluser]
Hi ,

This is really nice. I am also think that you should write it to wiki .
#5

[eluser]jargo[/eluser]
hi!
could there be a problem with this smarty wrapper and the new CI version 1.6.0?
I tried to upgrade my application from v1.5.4 to v1.6.0, but all i get is:

Quote:A PHP Error was encountered

Severity: User Warning

Message: Smarty error: unable to read resource: "welcome.html"

Filename: smarty/Smarty.class.php

Line Number: 1095

the welcome.html exists, the specified path seems to be right:
Quote:/var/www/localhost/htdocs/homepage/system/application/views

I also tried to create a simple new application only with out-of-the-box CI-1.6.0 and the smarty wrapper above.
Same problem. :down:

any idea about a solution?

jargo
#6

[eluser]xtramix[/eluser]
jargo,

try changing line 7 in your config/Smarty_parser.php file to:

$config['template_dir'] = BASEPATH . 'application/views' ;

Please note that you will need to revert the changes if you decide to move your smarty templates to the web app root.


- x
#7

[eluser]jargo[/eluser]
hi!
thanks for your reply. I found the problem/solution.
my smarty_parser.php in application/config was written with capital "s".
CI 1.6.0 doesn't like it Smile

Perhaps change this line in your tutorial:
Code:
3. Create Smarty_parser.php file in the application/config directory
to
Code:
3. Create smarty_parser.php file in the application/config directory
jargo
#8

[eluser]MABUS[/eluser]
hey guys.I'm kinda new to smarty. I've used it with some project, but that one didn't have CI in it. Now, I'd like to ask where shall I put my .tpl files? inside the "views" folder? is it supposed to be named as "xxx.tpl" ???

Another thing, this tutorial shows how to make a call to your smarty library, but doesn't show what $data variable is? . I am used to just passing an array to a view file, and use the values of that as variables on the view file. But this time , since smarty is playing along, how do you suppose doing it using these methods discussed here? does that $data array contain an array ? if so, where do we put the values , or the output from that smarty function call?

and last question, is "call_by_pass_reference" really needed to get CI and smarty going together? atleast for this method
#9

[eluser]Avatar[/eluser]
Nice. I like your class. While using it thus far I've found that changing the parse function calls second param to have a default value makes it even nicer.

function parse($template, $data='', $return = FALSE)

notice I added ="" after data param.

Thanks alot. It's just what I was looking for.
#10

[eluser]Avatar[/eluser]
I very much like this class. I use it with modular extensions. see reference below:

http://ellislab.com/forums/viewthread/72580

This way you can load module views in smarty templates to get a themed templated site which is also modulated. I would very much like to hear more on this solution. CI is the greatest framework I've ever found. My cousin works with prado, I've looked at it. but I don't see it comparing with ci. maybe if combining the two would be even more effecting. You see this would be even nicer. because prado is php and asp.net combined. Just have a sys and a prado directory for your frameworks and mix and match the templates and multiple systems. also this maybe overdoing it a little much. Smile




Theme © iAndrew 2016 - Forum software by © MyBB