使用smarty的cache特别要注意的地方: 一定要用多级目录模式,但是默认的有问题,需要自己构造hash目录。本页最下面的评论中有我修改源码的解决方案 — kenvin 2007/09/17 18:17
得到一个数组的大小, 类似于 count($array) :
if $answers|@count eq 0
{% section name=i loop=$list_rand start=0 max=5 step=1 %}
<li> <a href="{%#BaseUrl#%}news/{%$list_rand[i].id %}" >{% $list_rand[i].title %}</a> </li>
{% /section %}
</ul>
</div>
<div style="float:right; width:49%;">
<ul>
{% section name=i loop=$list_rand start=5 step=1 %}
<li> <a href="{%#BaseUrl#%}news/{%$list_rand[i].id %}" >{% $list_rand[i].title %}</a> </li>
{% /section %}
{%if ($key+1) is div by 3 %}<br style="clear:both" /> {%/if%}
得到index的方法: $smarty.section.sectionName.index
模拟for
{assign var="loop" value="5"}{*给定循环次数*}
{section name="loop" loop=$loop}
{$smarty.section.loop.index} {*可以这样取得下标,内部将循环$loop次*}
{/section}
貌似php直接assign(’loop’→5)就可以了:),刚才试了一下
$smarty->caching = true; $tplFile = "user.tpl"; $cache_key = md5("user_tpl_". $user_id ) ; if(!$smarty->is_cached($tplFile, $cache_key ) ) { // ... //代码 $tpl->assign("news_list", $news_list ); } $smarty->caching = 2; $smarty->cache_lifetime = 60*60*24 ; $smarty->display($tplFile, $cache_key );
中文truncate问题:默认的truncate不支持中文。
function smarty_modifier_cn_truncate($string, $strlen = 20, $etc = '...', $keep_first_style = false) { $strlen = $strlen*2; $string = trim($string); if ( strlen($string) <= $strlen ) { return $string; } $str = strip_tags($string); $j = 0; for($i=0;$i<$strlen;$i++) { if(ord(substr($str,$i,1))>0xa0) $j++; } if($j%2!=0) $strlen++; $rstr=substr($str,0,$strlen); if (strlen($str)>$strlen ) {$rstr .= $etc;} if ( $keep_first_style == true && ereg('^<(.*)>$',$string) ) { if ( strlen($str) <= $strlen ) { return $string; } $start_pos = strpos($string,substr($str,0,4)); $end_pos = strpos($string,substr($str,-4)); $end_pos = $end_pos+4; $rstr = substr($string,0,$start_pos) . $rstr . substr($string,$end_pos,strlen($string)); } return $rstr; }
支持UTF-8和GBK的中文截取
function smarty_modifier_truncate_cn($string, $length = 80, $code = 'UTF-8', $etc = '...')
{
if ($length == 0)
return '';
if($code == 'UTF-8'){
$pa = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/";
}
else{
$pa = "/[\x01-\x7f]|[\xa1-\xff][\xa1-\xff]/";
}
preg_match_all($pa, $string, $t_string);
if(count($t_string[0]) > $length)
return join('', array_slice($t_string[0], 0, $length)).$etc;
return join('', array_slice($t_string[0], 0, $length));
}
smarty里可以直接使用自定义的函数,如:
自己写了个函数 function getcode($parm) {} 在smarty里可以这样: { $id|getcode } 这样$id就作为getcode的参数了。
但是如果函数有多个参数怎么办?
function getcode($a,$b,$c,$d) {
echo "a:",$a," b:",$b," c:",$c," d:",$d ;
}
这样写就可以了!!! {% $a|getcode:$b:$c:$d %}
Smarty的Cache有几个地方需要留意 1.带参数列表的php应用,cache的时候注意把完整的参数列表或者构造的SQL用MD5哈希一下,作为Cache的id。 2.display()函数可以被子类覆盖吧,比如我用Smarty的时候就继承了一个Smarty,构造了自己的Smarty_AB类,我研究一下能不能通过函数覆盖把他cache的文件hash掉,再不成可以直接考虑改丫源码。。。。 comment by yp @07-04-30 15:26
嗯,我也重构了。smary好像有很多插件,估计自己不用写能找到。我找找。 — kenvin 2007/05/02 10:48
设置$use_sub_dirs=true可以开启分级目录功能,默认创建2级目录
如果设置display(”template.tpl”, “dir1|dir2|dir3”),可以生成多级目录,我们可以根据自己需要,通过合适的hash函数,从$cache_id来生成hash目录. — shwan
oh,good! 默认的就够了。哈哈。手册了就只有一个 $use_sub_dirs 变量 ,我说怎么没看到呢。 — kenvin 2007/05/16 14:48
smarty cache有点弱智。想多级目录原来要 dir1|dir2|dir3 这样些cache_id 。直接给一个cache_id,smarty居然把cache_id作为一个文件夹,然后把display的文件名hash了。以前没注意这个问题,一个9万条记录的系统,结果一个目录下搞了9万个目录。都快气死我了。只要修改了smarty的源码。如下:将smarty.class.php中 函数_get_auto_filename 修改为:
function _get_auto_filename($auto_base, $auto_source = null, $auto_id = null)
{
$_compile_dir_sep = $this->use_sub_dirs ? DIRECTORY_SEPARATOR : '^';
$_return = $auto_base . DIRECTORY_SEPARATOR;
if(isset($auto_id)) {
// make auto_id safe for directory names
$auto_id = md5($auto_id);
// split into separate directories
$_return .= substr($auto_id, 0,2) . $_compile_dir_sep . substr($auto_id, 2,2). $_compile_dir_sep . $auto_id ;
}
if(isset($auto_source)) {
// make source name safe for filename
$_filename = urlencode(basename($auto_source));
$_crc32 = sprintf('%08X', crc32($auto_source));
$_return .= '%%' . $_crc32 . '%%' . $_filename;
}
return $_return;
}
这丫真有点弱智,默认的hash连模板编译目录都给hash了。没任何意义啊。怎么也不可能有几千个模板吧。我随便将那个给去掉了。 — kenvin 2007/09/17 18:15
以实际项目开发为例,我需要在页面的footer显示数据库内友情链接,写一次,能在任何地方都可用; ①在smarty/plugins/下写一个function.link_list.php文件
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* 友情链接列表
*/
function smarty_function_link_list($params, &$smarty) {
$name = "link_list";
$CI = & get_instance ();
$CI->load->database();
$sql = "SELECT * FROM `links` ORDER BY `cdate` ASC";
$linklist = $CI->db->query($sql)->result_array();
$smarty->assign($name, $linklist);
}
②打开smarty下的Smarty_Compiler.class.php文件,搜索“switch ($tag_command) {”,在其内部添加
case 'link_list':
$this->_push_tag('link_list');
return $this->_compile_link_list_start($tag_args);
break;
case '/link_list':
$this->_pop_tag('link_list');
return "<?php endforeach; endif; unset(\$_from); ?>";
③在该文件内,添加下面函数
function _compile_link_list_start($tag_args)
{
$this->_add_plugin('function', 'link_list');
$attrs = $this->_parse_attrs($tag_args);
$_cache_attrs = '';
$arg_list = $this->_compile_arg_list('function', 'link_list', $attrs, $_cache_attrs);
$output ='<?php ';
$output .= $this->_compile_plugin_call('function','link_list').'(array('.implode(',', $arg_list)."), \$this);";
$output .=' ?>';
$tag_args .=' from=$link_list ';
return $output.$this->_compile_foreach_start($tag_args);
}
这样,在模板页内就可以使用
{%link_list item=link%}
<a href="{%$link.link_url%}" target="_blank">{%$link.title%}</a>
{%/link_list%}
来循环出来所有友情链接
php脚本:
$Action= array("article","soft","news");
$smarty->assign("Action",$Action);
模板:
<!–{if ‘article’|in_array:$Action}–>在数组内<!–{else}–>非数组内的值<!–{/if}–>
— //User:alex_shao@foxmail.com 2009-11-18 10:02:07