Smarty Forum Index Smarty
The discussions here are for Smarty, a template engine for the PHP programming language.
Dedicated server web hosting provided by Guru-host.eu.
Merging templates by smarty compiler
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Smarty Forum Index -> Smarty Development
View previous topic :: View next topic  
Author Message
XadmozX
Smarty n00b


Joined: 14 Sep 2004
Posts: 4

PostPosted: Thu Apr 14, 2005 10:37 am    Post subject: Merging templates by smarty compiler Reply with quote

Is there any way to have the layout splited into many templates (for usibility reasons) and have the compiled version of this layout in just one (for performance reasons - includes are time consuming)? I mean a simple merge funcionality on compiler side.

Or maybe there is another solution that enables:
- multi templates
- no includes
Back to top
View user's profile Send private message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 5537
Location: Lincoln Nebraska, USA

PostPosted: Thu Apr 14, 2005 1:15 pm    Post subject: Reply with quote

The compiler doesn't work that way, it compiles each physical template to its own physical file so that any template can be included from any other template. However, with caching enabled you get one cache file per display() or fetch() call, avoiding the compiled file includes altogether.
_________________
Monte
http://www.phpinsider.com/
http://mohrt.blogspot.com/
Back to top
View user's profile Send private message Visit poster's website
boots
Administrator


Joined: 16 Apr 2003
Posts: 5608
Location: Toronto, Canada

PostPosted: Thu Apr 14, 2005 2:30 pm    Post subject: Reply with quote

I think an inlining function would be nice. It occurs to me that another template engine does this (Flexy?) but I can't recall.
Back to top
View user's profile Send private message
messju
Administrator


Joined: 16 Apr 2003
Posts: 3327
Location: Oldenburg, Germany

PostPosted: Thu Apr 14, 2005 2:35 pm    Post subject: Reply with quote

some time ago i wrote a prefilter that does this. i never used it in a production environment, so use it on your own risk Smile

prefilter.inline.php
[php:1:6a112e197a]<?php
/**
* Smarty inline prefilter plugin
*
* File: prefilter.inline.php<br>
* Type: prefilter<br>
* Name: inline<br>
* Date: Dec 5, 2003<br>
* Purpose: resolve inlcuded templates at compile-time and include them
* Use: <code>$smarty->load_filter('pre','script_name');</code>
* from application.
* @author Messju Mohr <messju@lammfellpuschen.de>
* @version 0.3
* @param string (the template's sourcecode)
* @param Smarty_Compiler (the compiler)
*/


/*
* - tags like {inline file="foo.php"} are resolved
* - {inline file="foo.tpl" assign="foo"} assigns the contents
* instead of displaying them
* - {inline file="foo.tpl" var1=foo var2=bar} defines custom template
* variables to be used in the included tpl.
*/

function smarty_prefilter_inline($source, &$compiler) {
$ld = $compiler->left_delimiter;
$rd = $compiler->right_delimiter;

if (empty($compiler->_inline_depth)) {
$compiler->_inline_depth = 0;
/* make compiler visbile to inline_callback-function */
$GLOBALS['__compiler'] =& $compiler;
}

$compiler->_inline_depth++;
$source = preg_replace_callback('!' . preg_quote($ld, '!') . 'inline(.*)'
. preg_quote($rd, '!') . '!Us'
, 'inline_callback', $source);

if (--$compiler->_inline_depth==0) {
/* clean up */
unset($GLOBALS['__compiler']);
}

return $source;
}


function inline_callback($match) {
global $__compiler;

$ld = $__compiler->left_delimiter;
$rd = $__compiler->right_delimiter;
$source_content = '';

/* get attributes to {inline...} */
$_attrs = $__compiler->_parse_attrs($match[1]);

/* "file" */
if (!isset($_attrs['file'])) {
$this->syntax_error('[inline] missing file-parameter');
return false;
}
$resource_name = $__compiler->_dequote($_attrs['file']);
unset($_attrs['file']);


/* "assign" */
if (isset($_attrs['assign'])) {
$assign = $_attrs['assign'];
unset($_attrs['assign']);

} else {
$assign = null;
}

/* handle all other attributes as custom-vars */
if (!empty($_attrs)) {
$source_content .= $ld.'php'.$rd;
$source_content .= '$this->assign(array(';
$_sep = '';
foreach ($_attrs as $_name=>$_value) {
$source_content .= "$_sep'$_name'=>$_value";
$_sep = ',';
}
$source_content .= ')); '.$ld.'/php'.$rd;
}

/* read tpl-file */
$params = array('resource_name'=>$resource_name);
if ($__compiler->_fetch_resource_info($params)) {
/* recursion */
$source_content .= smarty_prefilter_inline($params['source_content'], $__compiler);
/* handle assign */
if (isset($assign)) {
$source_content = $ld.'php'.$rd . 'ob_start();' . $ld.'/php'.$rd
. $source_content
. $ld.'php'.$rd . '$this->assign(' . $assign . ', ob_get_contents()); ob_end_clean();' . $ld.'/php'.$rd;
}
}

/* return inline-replacement of tpl-file */
return $source_content;

}


?>
[/php:1:6a112e197a]
Back to top
View user's profile Send private message Send e-mail Visit poster's website
boots
Administrator


Joined: 16 Apr 2003
Posts: 5608
Location: Toronto, Canada

PostPosted: Thu Apr 14, 2005 3:02 pm    Post subject: Reply with quote

@messju: very interesting -- I'll have to give it a whirl. thanks!
Back to top
View user's profile Send private message
pt2002
Smarty Regular


Joined: 05 May 2003
Posts: 89
Location: Porto, Portugal

PostPosted: Sun Dec 18, 2005 11:58 pm    Post subject: Reply with quote

Hi

This piece of code is very nice, thanks.
There is only one problem that i found and would like to know if it possible to fix it.

I have one main.tpl where i include other templates.
{inline file="header.tpl"}
....
....
{inline file=$content}
...
...
{inline file="footer.tpl"}

The tpl var $content is assigned in php
i.e. $tpl->assign("content", "news.tpl") but can be any other template.

With {include file=$content} it's everything ok but with {inline file=$content}, the template is not being included.

Looking at the code, line 92
Code:

$params = array('resource_name'=>$resource_name);


and echoing $resource_name I see the name of the templates and
($this->_tpl_vars['content']) for the template name assigned in php but it isn't beeing fetched in line 93
Code:

if ($__compiler->_fetch_resource_info($params)) {


Is there any workaround for this?

Best regards
Back to top
View user's profile Send private message
messju
Administrator


Joined: 16 Apr 2003
Posts: 3327
Location: Oldenburg, Germany

PostPosted: Mon Dec 19, 2005 12:03 am    Post subject: Reply with quote

pt2002 wrote:
Is there any workaround for this?


no, there isn't. "$this->_tpl_vars['content']" should be evaluated at display time, but the inlining is done at compile time (thus way before display time).

{inline} is static, {include} is dynamic. it seems you want something dynamic if your controller assigns the name of the template.

regards
messju
Back to top
View user's profile Send private message Send e-mail Visit poster's website
pt2002
Smarty Regular


Joined: 05 May 2003
Posts: 89
Location: Porto, Portugal

PostPosted: Mon Dec 19, 2005 12:12 am    Post subject: Reply with quote

Hi

thanks for answering so quickly.
No problem. It reduced seven tpl files to two. Nice work

best regards
Back to top
View user's profile Send private message
mucill
Smarty n00b


Joined: 12 Nov 2006
Posts: 3

PostPosted: Mon Nov 13, 2006 12:49 pm    Post subject: try this Reply with quote

i do not know that my methode will answer this question...but you can try it

i've tried to split many template in my html file and merge them in one mian template

this is the html code
--------------------------------------------------------
[index.html]
<html>
<body>
{$leftcontent}
{$content}
{$rightcontent}
</body>
</html>

[leftcontent.html]
<div>
Put your left content here. You can put such a {$menu} here
</div>

[rightcontent.html]
<div>
Put your right content here. You can put such a {$maillogin} here
</div>

[content.html]
<div>
Put your content here. You can put such a {$news} syntax here
</div>
--------------------------------------------------------
put all html files inside your template folder


this is the php code
----------------------------------------------------------------------
[index.php]
<?
# define template contanta
define ('SMARTY_DIR', './smarty/');
include (SMARTY_DIR . "Smarty.class.php");

# declare template constructor
$smarty = new Smarty;


$smarty->assign(array(
"menu" => "Menu1<br>Menu2<br>Menu3",
"maillogin" => "Put with your own mail form","news" => "News List will show here"));

$smarty->assign(array(
"leftcontent" => $smarty->fetch("leftcontent.html"),
"content" => $smarty->fetch("content.html"),
"rightcontent" => $smarty->fetch("rightcontent.html")
));

$smarty->display("index.html");
?>
---------------------------------------------------------

it's works for me ...... Very Happy
Back to top
View user's profile Send private message
selaz
Smarty Rookie


Joined: 04 Feb 2007
Posts: 14

PostPosted: Sun Feb 24, 2008 5:56 pm    Post subject: Reply with quote

Hi!

I was looking for a way to merge several templates into a single compiled file and I discovered messju's inline prefilter. Great stuff! The thing about dynamic file attribute assignment doesn't bother me (will use include instead), I have a problem with variable assignment. This is the issue:

// main.tpl
{inline file=&quot;L1.tpl&quot; msgMain=&quot;Some message from MAIN, to all templates&quot;}

// L1.tpl
{inline file=&quot;L2a.tpl&quot; value=&quot;Only for L2a.tpl !!!&quot;}
{inline file=&quot;L2b.tpl&quot;}

// L2a.tpl
&lt;h1&gt;Global Msg={$msgMain}&lt;/h1&gt;
&lt;h2&gt;LEVEL 2 A --- value={$value}&lt;/h2&gt;

// L2b.tpl
&lt;h1&gt;Global Msg={$msgMain}&lt;/h1&gt;
&lt;h2&gt;LEVEL 2 B --- value={$value}&lt;/h2&gt;

----------------------------------------------------------------

The thing is I want to see the value only in L2a.tpl, like using include function, 'value' is assigned only to L2a.tpl. Any ideas how to do that?

BTW, why this functionality isn't included in Smarty by default. I use lets say 30 different tiny includes per page and inline prefilter can really help you increase performance.

Thanks!


Last edited by selaz on Wed May 05, 2010 10:39 pm; edited 1 time in total
Back to top
View user's profile Send private message Visit poster's website
Celeb
Administrator


Joined: 17 Apr 2007
Posts: 1025
Location: Vienna

PostPosted: Mon Feb 25, 2008 7:57 am    Post subject: Reply with quote

selaz wrote:
BTW, why this functionality isn't included in Smarty by default. I use lets say 30 different tiny includes per page and inline prefilter can really help you increase performance.

So can enabling caching and using {insert} (which will not be cached) for dynamic output.

What messju's prefilter does is replace
Code:
{inline file='inline.tpl' value='assigned value'}

by something similar to
Code:
{php}$this->assign('value','assigned value');{/php}
[contents of inline.tpl]


I guess you could change the prefilter to add an additional
Code:
{php}$this->clear_assign('value');{/php}

But note, that if $value has been assigned before the {inline} call it's gone for good. You could further change the filter to act like {include} but I'd rather just use {include} then.
_________________
Darn computers always do what I tell them to instead of what I want them to do.
Back to top
View user's profile Send private message
selaz
Smarty Rookie


Joined: 04 Feb 2007
Posts: 14

PostPosted: Tue Feb 26, 2008 9:35 am    Post subject: Reply with quote

Thanks for your reply.

Celeb wrote:

So can enabling caching and using {insert} (which will not be cached) for dynamic output.


The thing is I always need fresh output data, every page displays some db data. My idea was to save up some (open/read/close) file accesses to multiple compiled files and gain some performance. The only drawback I see is the fact the primary file won't be recompiled after some subtemplate is changed.


Still, I need a trick to make inline templates act like includes - variables passed !only! to included template and its subtemplates.

Thanks


Last edited by selaz on Wed May 05, 2010 10:39 pm; edited 1 time in total
Back to top
View user's profile Send private message Visit poster's website
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 2316
Location: Hamburg / Germany

PostPosted: Tue Feb 26, 2008 5:56 pm    Post subject: Reply with quote

The problem is that {inline...} is merging all templates together and the result is then interpreted by Smarty as one big template. Therefor the scope of all Smarty variables like $value is global. The only chance I see is that you use different variable names for the parmeter of each subtemplate.

And yes you are right modifications of the subtemplates will not be automatically detected.
Back to top
View user's profile Send private message
selaz
Smarty Rookie


Joined: 04 Feb 2007
Posts: 14

PostPosted: Tue Feb 26, 2008 6:24 pm    Post subject: Reply with quote

I thing like:
Code:

&lt;?php $_tmp_tpl_vars=$this-&gt;_tpl_vars;

$this-&gt;assign(array('a'=&gt;'123'));?&gt;
This is a subtemplete value: a=&lt;?php echo $this-&gt;_tpl_vars['a']; ?&gt;

&lt;?php $this-&gt;_tpl_vars=$_tmp_tpl_vars;?&gt;


for every inline template would do the trick, but I'm not sure if there's a more elegant way to do it.


Last edited by selaz on Wed May 05, 2010 10:39 pm; edited 1 time in total
Back to top
View user's profile Send private message Visit poster's website
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 2316
Location: Hamburg / Germany

PostPosted: Tue Feb 26, 2008 6:34 pm    Post subject: Reply with quote

Well but this will work only for one level of {inline... } tags. But I think the prefilter does support anyway just one level.

You could also just save and restore just the parameter variable and shuffel not too much of data arround.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Smarty Forum Index -> Smarty Development All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP