这节来看下该CMS涉及到的缓存和模板方面的原理,以文章显示为例,在根目录下有个 add_edit_del_show_list_article.php文件,这是和文章的添加、编辑、删除、显示、文章列表等有关的入口文件,...

    这节来看下该CMS涉及到的缓存和模板方面的原理,以文章显示为例,在根目录下有个 add_edit_del_show_list_article.php文件,这是和文章的添加、编辑、删除、显示、文章列表等有关的入口文件,之所以叫 入口文件,是因为实际的添加,编辑等操作代码并不在该文件中,该文件只是加载类缓存,并根据get或post请求上来的数据,判断应该调用类的哪个方法。 在该文件的开头有如下代码:

include 'common_fun/file_func.php';
i_need_func('article,err',__FILE__,true); //最后的参数为true时,file_cache中会生成调试版本的缓存。
//i_need_func('article,err',__FILE__);
include $my_need_files;

import_request_variables("gpc","rvar_");
$article = new article(true,true);

    上面的代码先加载common_fun目录下的file_func.php文件,加载此文件的目的是为了能调用后面的i_need_func函数,先来看下file_func.php中两个比较重要的数组结构:

$my_need_file_deps = array('err'=>array('help','tpl'),
        'conf'=>'',
        'sql'=>array('err','conf'),
        'sess'=>'',
        'tpl'=>'',
        'user'=>array('tpl','sql','conf','err','sess','help'),
        'auth'=>array('sess'),
        'article'=>array('sess','sql','err','tpl','conf',

                   'user','sec','permis','help','tags'),
        'sec'=>array('sess','sql','err','tpl','user','permis','help','conf'),
        'permis'=>array('sess','sql'),
        'cache'=>array('tpl','sec','conf'),
        'help'=>array('conf'),
        'archive'=>array('permis','sess','sql','conf','err','tpl'),
        'admin'=>array('permis','sess','sql','tpl','conf','serverinfo'),
        'tags'=>array('sql','conf','tpl','help'),
        'comment'=>array('sql','permis','help','err','tpl','conf','article'),
        'db'=>array('sql','help','permis','conf','user'),
        'serverinfo'=>array('conf'),

        );

    上面的my_need_file_deps数组里存放了各个类相互之间的依赖关系,例如 'article'=>array('sess','sql','err','tpl','conf','user',
'sec','permis','help','tags'),
是 指article类当中的方法又依赖sess(会话类),sql(数据库操作类),err(错误显示类),tpl(模板解析类),conf(配置文 件),user(用户登录注册注销相关的类),sec(栏目管理类),permis(权限控制类),help(辅助函数库),tags(标签操作类)。

$my_need_file_paths = array('err'=>'common_fun/error_class.php',
        'conf'=>'config.php',
        'sql'=>'common_fun/sql_class.php',
        'sess'=>'common_fun/session_class.php',
        'tpl'=>'common_fun/tpl_class.php',
        'user'=>'common_fun/user_class.php',
        'auth'=>'common_fun/auth_class.php',
        'article'=>'common_fun/article_class.php',
        'sec'=>'common_fun/section_class.php',
        'permis'=>'common_fun/permission_class.php',
        'cache'=>'common_fun/cache_class.php',
        'help'=>'common_fun/help_func.php',
        'archive'=>'common_fun/archive_class.php',
        'admin'=>'common_fun/admin_class.php',
        'tags'=>'common_fun/tags_class.php',
        'comment'=>'common_fun/comment_class.php',
        'db'=>'common_fun/db_class.php',
        'serverinfo'=>'common_fun/serverinfo_class.php',

        )

    上面的my_need_file_paths数组存放的是各个类别名对应的具体文件路径信息。

function i_need_func($funcstr,$file_cache,$debug=false)
{
    global $my_need_file_paths;
    global $my_need_funcs;
    global $my_need_func_paths;
    global $my_need_files;
    global $zengl_cms_filecache_dir;
    $func_array = explode(',', $funcstr);
    func_deps($func_array); //通过func_deps函数根据用户提供的funcstr参数转化的func_array数组,从my_need_file_deps依赖关系数组中 找出所有依赖的类,并将这些类别名写入到my_need_funcs数组中。
    $my_need_funcs = array_unique($my_need_funcs); //将重复的依赖类别名去除
    foreach ($my_need_funcs as $dep) //循环得到所有依赖类的类文件路径,并存放到my_need_func_paths数组中。
    {
        if($my_need_file_paths[$dep] == '')
            die("$dep's file_path is null ,please check file_func.php file!");
        $my_need_func_paths[] = $my_need_file_paths[$dep];
    }
    $file_cache = basename($file_cache,'.php'); //由file_cache参数得到将要生成的类缓存文件名。
    $file_cache = $zengl_cms_filecache_dir . $file_cache .'_cache_inc.php'; //生成类缓存的绝对路径
    $my_need_files = $file_cache; //将file_cache赋值给my_need_files全局变量,这样调用该函数的外部脚本就可以加载类缓存。
    import_files_array($my_need_func_paths,$debug); //通过import_files_array函数依次将所有的类文件读取并写入缓存文件中。
}

    add_edit_del_show_list_article.php在调用i_need_func生成了所有依赖类的缓存文件后,再通过include $my_need_files;将缓存文件加载进来,这样就只需加载一个文件就可以得到所有需要的类。

import_request_variables("gpc","rvar_");
$article = new article(true,true);
.............................//省略N行代码
else if($rvar_hidden == 'show')
    $article->show_article();
.............................//省略N行代码

    在加载类成功后,如果用户请求的参数是show的话,就调用article类中的show_article方法来显示文章内容界面,show_article方法如下:

function show_article()
{
        global $zengl_cms_tpl_dir;
        global $zengl_theme;
        global $zengl_old_theme;
        if(file_exists($zengl_theme_tpl_class = $zengl_cms_tpl_dir . $zengl_theme . '/class/show_article_class.php')) //如果在当前主题的class目录中存在show_article_class.php文件,那么就通过include加载执行该php文件,在该php文件中进行具体的数据库查询和模板解析工作。
            include $zengl_theme_tpl_class;
        else if(file_exists($zengl_theme_tpl_class = $zengl_cms_tpl_dir . $zengl_old_theme .
                '/class/show_article_class.php')) //否则就加载以前的主题风格中的php文件
        {
            $zengl_theme = $zengl_old_theme;
            include $zengl_theme_tpl_class;
        }
        else
            die('tpl class file show_article_class.php does not exist!'); //如果都不存在,那么就弹出错误!
}

    在show_article_class.php开头有如下代码:

.............................//省略N行代码
$filetpl = $zengl_cms_tpl_dir . $zengl_theme .'/show_article.tpl'; //指定当前需要解析的模板文件路径。例如本例中就是主题模板目录下的show_article.tpl文件
//$filecache = $zengl_cms_tpl_dir . 'show_article_cache'. $rvar_articleID .'.php';
$filecache = $zengl_cms_tpl_dir . 'cache/show_article_cache.php'; //指定模板文件对应的模板缓存文件路径,当生成了缓存文件后,如果模板文件没发生改变,那么下次就会直接加载缓存文件,就不需要再进行模板解析了。

.............................//省略N行代码
$sql = new sql('utf8'); //初始化数据库操作类
$sql->query("select * from $sql->tables_prefix" . "articles where articleID = " . $rvar_articleID); //从articles表中读取某篇文章的信息。
$sql->parse_results();
.............................//省略N行代码
$tpl = new tpl($filetpl, $filecache); //初始化模板类
.............................//省略N行代码
$tpl->setVar('ishtml','echo $adminHtml_genhtml',true); //进行模板的标签解析。
$tpl->setVar('keyword','echo $tagstr',true);
$tpl->cache(); //通过cache方法生成模板缓存。
include $filecache; //加载缓存文件。

.............................//省略N行代码
if($flaghtml) //如果是静态化操作,则生成静态化文件。
{
    //$sec_dirpath = $this->GetSecDirFullPath($rvar_sec_ID);
    mkdirs($sec_dirpath);
    file_put_contents($sec_dirpath . '/article-' . $rvar_articleID . '.html',ob_get_contents()); //通过ob_get_contents得到要输出的内容,并将内容通过file_put_contents输出到静态文件中。
    ob_end_clean(); //清空输出缓存。
    echo "生成文章 {$article_title} $sec_dirpath/article-" .
          "$rvar_articleID.html 成功<br/>"; //打印出生成静态文件成功的信息
    flush_buffers(); //将信息通过flush方法直接输出。
}
    tpl模板类的setVar方法其实就是简单的替换操作:

class tpl
{


.............................//省略N行代码   
    function setVar($tagname,$tagvar,$boolphp = false)
    {
        if($boolphp == true)
            $tagvar = '<?php '.$tagvar.' ?>';
        $this->outstring = str_replace("{zengl ". $tagname ."}", $tagvar, $this->outstring); //通过str_replace将模板中的{zengl ....}标签替换为php标签。
    }

.............................//省略N行代码   
}

    这种方法使用简单,执行效率高,可以随意的定义标签名,以后会考虑加入其他的高级点的模板解析方法。

    上面给出的代码片段中,棕色的注释都是本文为了说明而添加的,在源代码中并没有。

   
最后的最后,如果转载请注明来源 http://www.zengl.com   , OK , 先到这里,休息,休息一下 O(∩_∩)O~

上下篇

下一篇: zenglcms sqlite和mysql数据库操作类

上一篇: zenglcms CKEditor在线编辑器

相关文章

zenglcms v1.2.0发布版

zenglcms CKEditor在线编辑器

zenglcms sqlite和mysql数据库操作类

zenglcms v1.2.0 正则表达式模板引擎

zenglcms 目录结构

zenglcms v1.2.0 数据库结构