Smarty Forum Index Smarty
The discussions here are for Smarty, a template engine for the PHP programming language.

{nocache} Patch
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Smarty Forum Index -> Smarty Development
View previous topic :: View next topic  
Author Message
andre
Smarty Pro


Joined: 23 Apr 2003
Posts: 164
Location: Karlsruhe, Germany

PostPosted: Mon Apr 28, 2003 12:17 pm    Post subject: {nocache} Patch Reply with quote

    ADMIN NOTE (2003-may-24): CVS users should checkout andre's new patch HERE
    UPDATE: (2003-Jun-21): The CVS now includes an alternate to Andre's implementation, though it borrows/uses many of the same ideas that Andre presents here.

Here's a newer version of my "nocache" patch for Smarty 2.5.0:

http://cmsng.sourceforge.net/Smarty/Smarty_nocache.zip

The archive contains both two .diff files for manual patching and ready to use / already patched PHP files.

Features
- Both block and normal functions can be registered as cached or not cached.
- register_block() and register_function() now take a third parameter $cached (default is TRUE). Set it to FALSE to prevent your custom function from caching.
- Cascading cached / not cached blocks is no problem at all.
- Doesn't slow down Smarty if caching is disabled or if you're not using functions which are not cached

Examples
[php:1:4423c80dd0]
// Custom Functions

function smarty_block_nocache($params, $content, &$smarty) {
return $content;
}

function smarty_function_currenttime($params, &$smarty) {
return date("Y-m-d H:i:s");
}
[/php:1:4423c80dd0]

[php:1:4423c80dd0]
// Main Application

$smarty = new Smarty();
$smarty->register_block("nocache", "smarty_block_nocache", false);
$smarty->register_function("currenttime", "smarty_function_currenttime", false);

$smarty->assign("time", date("Y-m-d H:i:s"));

$smarty->caching = 1;
$smarty->display("myTemplate.tpl");

[/php:1:4423c80dd0]

Code:

  {* My Template *}
 
   Example for caching ...
   Current Date & Time (cached): {$time}
   Current Date & Time (not cached): {currenttime}
   Current Date & Time (not cached): {nocache}{$time}{/nocache}



Feel free to test it and report bugs Smile
Back to top
View user's profile Send private message
Wom.bat
Smarty Pro


Joined: 24 Apr 2003
Posts: 107
Location: Munich, Germany

PostPosted: Mon Apr 28, 2003 1:59 pm    Post subject: Reply with quote

unfortunately, I can't test it at the moment, but I hope a feature like this (both {nocache} blocks and caching property for functions/blocks etc) will make it into one of the next Smarty version Wink great job, andre
Back to top
View user's profile Send private message
AZTEK
Smarty Pro


Joined: 16 Apr 2003
Posts: 235
Location: Purdue University

PostPosted: Mon Apr 28, 2003 2:48 pm    Post subject: Reply with quote

Looks good, I will test this when I get home.
_________________
"Imagine a school with children that can read and write, but with teachers who cannot, and you have a metaphor of the Information Age in which we live." -Peter Cochrane
Back to top
View user's profile Send private message Visit poster's website
boots
Administrator


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

PostPosted: Tue Apr 29, 2003 9:27 am    Post subject: Reply with quote

Neat!

I haven't looked at the code yet. It sounds like your code optionally implements a block {insert name="..." script="..."} type pattern for functions. At any rate, very clever.

What kind of code do {nocache} blocks get compiled to? The same that {insert} currently produces?

Is it possible to create non-caching versions of plugins or built-in functions or do they need to be wrapped in a {nocache} block?

Can a function be registered as both cachable and non-cacheable, with both variants at work in the same template (perhaps through a globally available parameter that the engine interprets before calling the function.)

eg. can I do something like {html_table cache=false ...} and {include file="..." cache=false}?

Well, I guess I will have to look! Exciting!
Back to top
View user's profile Send private message
AZTEK
Smarty Pro


Joined: 16 Apr 2003
Posts: 235
Location: Purdue University

PostPosted: Tue Apr 29, 2003 9:58 am    Post subject: Reply with quote

It looks like all it does is return the code evaluated instead of the cached equvilent but I havent even read into his code yet
_________________
"Imagine a school with children that can read and write, but with teachers who cannot, and you have a metaphor of the Information Age in which we live." -Peter Cochrane
Back to top
View user's profile Send private message Visit poster's website
andre
Smarty Pro


Joined: 23 Apr 2003
Posts: 164
Location: Karlsruhe, Germany

PostPosted: Tue Apr 29, 2003 11:08 am    Post subject: Reply with quote

It's simple:

Code:

   Example for caching ...
   Current Date & Time (cached): {$time}
   Current Date & Time (not cached): {currenttime}
   Current Date & Time (not cached): {nocache}{$time}{/nocache}


If caching is ON the above template gets compiled to

[php:1:341109d48b]
Example for caching ...
Current Date & Time (cached): <?php echo $this->_tpl_vars["time"] ?>
Current Date & Time (not cached): <!--{#SMARTYCACHE#currenttime}-->
Current Date & Time (not cached): <!--{#SMARTYCACHE#nocache}--><!--{#SMARTYCACHE#$time}--><!--{#SMARTYCACHE#/nocache}-->
[/php:1:341109d48b]
with "<!--{#SMARTYCACHE#" and "}-->" beeing the tag delimiters.

Then the compiled version is executed. The output is written into the cache file. (Standard Smarty behaviour)

Code:

   Example for caching ...
   Current Date & Time (cached): 12:49:15
   Current Date & Time (not cached): <!--{#SMARTYCACHE#currenttime}-->
   Current Date & Time (not cached): <!--{#SMARTYCACHE#nocache}--><!--{#SMARTYCACHE#$time}--><!--{#SMARTYCACHE#/nocache}-->   


Now the output will be compiled again: Tags delimited by "<!--{#SMARTYCACHE#" and "}-->" will now be replaced by the not cached PHP functions:

[php:1:341109d48b]
Example for caching ...
Current Date & Time (cached): 12:49:15
Current Date & Time (not cached): <?php echo $tpl->_... ?>
Current Date & Time (not cached): <?php ... ?>
[/php:1:341109d48b]

This is now the final template which get's executed and outputted to the user.

The trick is to compile a template two times. The biggest perfomance issue is that the second compiled version is not yet stored into a file so for each call of the template it get's compiled again Shocked But this is not as critical as you may think because normally there are not as many tags that need to be compiled as before. I am using it with a calendar application and it speed up execution time from 7-10 seconds to 1,3 seconds to display all events of the current month Very Happy

If you are NOT using caching or if you are NOT using any "not-cached" function there won't be a performance issue after applying the patch.

The next step of my patch will be the creation of a separate file where the final output will resist so compiling will be done only once. But I haven't had the time to check this yet.

boots wrote:
Can a function be registered as both cachable and non-cacheable, with both variants at work in the same template (perhaps through a globally available parameter that the engine interprets before calling the function.)

No and I am not sure if this would be a good idea. The designed shouldn't need to care about caching at all. This is why a also wouldn't recommend using {nocache} block functions. The designed would need to know too much of your internal application structure.
But you could register one function two times. First using caching and second with caching disabled:
[php:1:341109d48b]
$smarty->register_function("cachingtime", "smarty_function_currenttime", true);
$smarty->register_function("currenttime", "smarty_function_currenttime", false);
[/php:1:341109d48b]
Then both can be used in the same template.

boots wrote:
What kind of code do {nocache} blocks get compiled to? The same that {insert} currently produces?

Nope, in fact the {insert} tags now get compiled as a custom function which was registered as not cached. The old {insert} behaviour was completely removed. That's why you should delete all compiled versions of your templates. Wink
Back to top
View user's profile Send private message
boots
Administrator


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

PostPosted: Tue Apr 29, 2003 11:35 am    Post subject: Reply with quote

@andre: nice post.

Quote:
If you are NOT using caching or if you are NOT using any "not-cached" function there won't be a performance issue after applying the patch.


Okay. I think that choices should be made to allow for caching as often as possible. Also, if I'm not caching, why have nocache support ?? Wink

I've resorted to multiple pass techniques in the past and I always feel a bit bothered by them. Your technique relies on tags surviving the first compilation, so not only are there two passes, but I take it that you have to do some filtering before and after the first pass.

Quote:
The next step of my patch will be the creation of a separate file where the final output will resist so compiling will be done only once. But I haven't had the time to check this yet.


You go!

Code:

  $smarty->register_function("cachingtime", "smarty_function_currenttime", true);
  $smarty->register_function("currenttime", "smarty_function_currenttime", false);


I figured I could do that, but I thought it would be interesting to have it selectable at the template level, your concerns not withstanding.

Quote:
This is why a also wouldn't recommend using {nocache} block functions.


Hmmm. Why not just use insert then?

I will definately look at your code. Thanks for taking the time to explain things here!
Back to top
View user's profile Send private message
andre
Smarty Pro


Joined: 23 Apr 2003
Posts: 164
Location: Karlsruhe, Germany

PostPosted: Tue Apr 29, 2003 11:52 am    Post subject: Reply with quote

boots wrote:
Okay. I think that choices should be made to allow for caching as often as possible. Also, if I'm not caching, why have nocache support ??


Some of my templates are cached others are not. (I use caching since I have implemented my patch). So it's essential for me to not slow down my old templates in any way but allow new ones to use the nocache functionality.

Quote:
I've resorted to multiple pass techniques in the past and I always feel a bit bothered by them. Your technique relies on tags surviving the first compilation, so not only are there two passes, but I take it that you have to do some filtering before and after the first pass.

I have modified the _compile_tag() function of Smarty_Compiler to recognize if a tag is cached or not. So "surviving" is perhaps the wrong word because I'm not using any tricks to make them survive the first compiling process. No pre- or postfiltering is required. That's why you need to register functions explicitly to be not cached so the compiler knows them during compilation.

Quote:

Quote:
This is why a also wouldn't recommend using {nocache} block functions.

Hmmm. Why not just use insert then?

I don't like insert either Wink Instead of creating insert functions I would recommend creating just normal custom functions and register them as not cached. This way the behaviour of caching / not caching is completely transparent for your designer.
Example: You have a News page. For each news item you have several comments. It wasn't cached at all but now you decide the news entries should be cached but the number of comments should not. Now tell the designer to replace all {countComments id="News-ID"} by {insert name="countComments" id="News-ID"}? Ok, no really good example but I hope you understand what I mean. Registering "countComments" as not-cached function is fully transparent and you even don't need to change the existing templates. For the designer it doesn't matter what portions of the templates are cached and which are not.
Back to top
View user's profile Send private message
Wom.bat
Smarty Pro


Joined: 24 Apr 2003
Posts: 107
Location: Munich, Germany

PostPosted: Tue Apr 29, 2003 12:11 pm    Post subject: Reply with quote

andre:
I am currently doing

3574f626854313961b2ec322ec8308611361b1c35d1757bc5bff7ffc788ca592-CommentInfo.long-news_news.newsId/14

to achieve what you wrote
then, I fetch() the template and give the output to a function which postprocesses the output (outputfilters don't work here, as they are executed BEFORE output is written to the cache)

the ugliest thing on this method is that I have to create an additional PHP-file including the replacements.
I don't just want to print out the number of comments, but something like "no comments", "1 comment", "2 comments"; plus, there are several different formats, for example only the number of comments, or "none", "1", "2", ... even in different languages)
This entire issue has caused serious headache to me Wink so I guess I will have a look into your thingie, as I could then just do

Code:

{nocache}
 {getCommentCount source="news_news.newsId" item=$entries.newsId assign="commentCount"}
 {if ($commentCount == 0)}
  {if ($_SESSION.language == "DE")}keine Kommentare
  {elseif ($_SESSION.language == "EN")}no comments
  {/if}
 {elseif ($commentCount == 1)}
  {if ($_SESSION.language == "DE")}1 Kommentar
  {elseif ($_SESSION.language == "EN")}1 comment
  {/if}
 {else}
  {if ($_SESSION.language == "DE")}{$commentCount} Kommentare
  {elseif ($_SESSION.language == "EN")}{$commentCount} comments
  {/if}
 {/if}
{/nocache}

but I somehow would like to wait until this is officially integrated into Smarty, as I always prefer to stay as near to official syntax as possible, if you understand what I mean (no blame on your code, I'm sure it kicks ass Wink)
Back to top
View user's profile Send private message
boots
Administrator


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

PostPosted: Tue Apr 29, 2003 12:54 pm    Post subject: Reply with quote

Quote:
I have modified the _compile_tag() function of Smarty_Compiler to recognize if a tag is cached or not.

[snip]

Registering "countComments" as not-cached function is fully transparent and you even don't need to change the existing templates. For the designer it doesn't matter what portions of the templates are cached and which are not.


Cool. I see what you are getting at and I agree that your technique of registering functions as caching or not is superior to the current state of insert Wink.

You make a good point about keeping caching issues out of the template design. I have to agree that this seems like the sane approach.

Heres a Q:

How would I go about implementing a page that was cached but had a block that was not cached. Here's the caveat: the uncached block is actually to be determined by the user priority. Level 1 gets a cached block with a 1 hour refresh; Level 2 gets a cached block with a 30 minute refresh; Level 3 gets a cached block with a 15 minute refresh; Level 4 gets an uncached block.

I guess I could set up a switch in my PHP code and setup smarty as appropriate. Or use a compile_id?? What if I wanted to do this in template Very Happy ?

What would you suggest?
Back to top
View user's profile Send private message
andre
Smarty Pro


Joined: 23 Apr 2003
Posts: 164
Location: Karlsruhe, Germany

PostPosted: Tue Apr 29, 2003 1:34 pm    Post subject: Reply with quote

boots wrote:
How would I go about implementing a page that was cached but had a block that was not cached. Here's the caveat: the uncached block is actually to be determined by the user priority. Level 1 gets a cached block with a 1 hour refresh; Level 2 gets a cached block with a 30 minute refresh; Level 3 gets a cached block with a 15 minute refresh; Level 4 gets an uncached block.


Same here in my project. I'm going another way. Here's some pseudo code:

[php:1:624d3d0ac7]
/**
* Display a block
*/
function smarty_function_block($block_id, &$smarty) {
$newSmarty = $smarty; // create a copy of smarty object
$newSmarty->caching = 1;
if ($level == 1)
$newSmarty->cache_lifetime = 60*60;
else if ($level == 2)
$newSmarty->cache_lifetime = 60*30;
else if ($level == 3)
$newSmarty->cache_lifetime = 60*15;
else
$newSmarty->caching = 0;
$newSmarty->assign("content", getBlockContent($block_id));
return $newSmarty->fetch(getBlockTemplate($block_id));
}
[/php:1:624d3d0ac7]

[php:1:624d3d0ac7]
/**
* Main Application
*/
$smarty = new Smarty;

// Blocks implement their own caching routine so we set
// caching flag to FALSE
$smarty->register_function ("block", "smarty_function_block", false);

// ... assign some values
$smarty->assign("foo", "bar");

// enable caching for master template
$smarty->caching = 1;
$smarty->cache_lifetime = 60 * 60 * 24; // one day lifetime
$smarty->display("myTemplate.tpl");
[/php:1:624d3d0ac7]

Code:

  {* My Template *}
  ... some content ...
  {block id="whoIsOnline"}
  ... some content ...
  {block id="newestHeadlines"}
  ... some content ...


Hope you understood what I meant?! This is the way I'm using Smarty. Not 100% clean code (copying objects is ugly in my eyes) but it works very nice Wink
Back to top
View user's profile Send private message
boots
Administrator


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

PostPosted: Tue Apr 29, 2003 2:22 pm    Post subject: Reply with quote

Thanks andre.

One thing I don't get: I thought that once you set a cache lifetime for a given object, you couldn't change it later unless you used a different cache_id. Did you just leave that detail out or is that something else your patch does?
Back to top
View user's profile Send private message
andre
Smarty Pro


Joined: 23 Apr 2003
Posts: 164
Location: Karlsruhe, Germany

PostPosted: Tue Apr 29, 2003 2:25 pm    Post subject: Reply with quote

boots wrote:
One thing I don't get: I thought that once you set a cache lifetime for a given object, you couldn't change it later unless you used a different cache_id. Did you just leave that detail out or is that something else your patch does?


Oops Embarassed You're right. So set the cache id to the block's ID + $level or something like this.

[php:1:1235a0bf27]
// ... [snip]
$newSmarty->assign("content", getBlockContent($block_id));
$cache_id = $block_id."|".$level;
return $newSmarty->fetch(getBlockTemplate($block_id), $cache_id);
// ... [snip]
[/php:1:1235a0bf27]
Back to top
View user's profile Send private message
mohrt
Administrator


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

PostPosted: Tue Apr 29, 2003 2:37 pm    Post subject: Reply with quote

Quote:

Cool. I see what you are getting at and I agree that your technique of registering functions as caching or not is superior to the current state of insert Wink.


Smarty will be getting some caching facelifts soon, that is the next big project. We have a pretty good idea how it is going to work, and we have Andre's code to compare against. It's all good stuff to have. Smile

The caching will definately be by registeration, keeping things out of the templates as much as possible. You can think of {insert} as just a custom function registered as non-cached.

Monte
Back to top
View user's profile Send private message Visit poster's website
andre
Smarty Pro


Joined: 23 Apr 2003
Posts: 164
Location: Karlsruhe, Germany

PostPosted: Tue Apr 29, 2003 2:59 pm    Post subject: Reply with quote

Hi Monte,

I have already mailed with Messju and he explained a bit of your ideas to me (in german language Wink )

Sounds very interessting!


An idea I just had and I'm not sure if it would be practical but what if I just replace the not-cached code within a cache file with pure PHP tags so the cached file gets just included if displayed?!

The way I'm doing it now: Cached template:
Code:

   Example for caching ...
   Current Date & Time (cached): 12:49:15
   Current Date & Time (not cached): <!--{#SMARTYCACHE#currenttime}-->
   Current Date & Time (not cached): <!--{#SMARTYCACHE#nocache}--><!--{#SMARTYCACHE#$time}--><!--{#SMARTYCACHE#/nocache}-->   


The way I could do it:
Code:

   Example for caching ...
   Current Date & Time (cached): 12:49:15
   Current Date & Time (not cached): <?php $this->_plugins["functions"]... ?>
   Current Date & Time (not cached): <?php ... ?>


Then I wouldn't need another file. Would this break something? I have to think about it ... Rolling Eyes
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