从数据库/字符串中获取模板

时间:2012-02-20 02:33:33

标签: php templates template-engine

我将模板存储为文件,并希望有机会将它们存储在MySql数据库中。

我的模板系统

//function of Template class, where $file is a path to a file 
function fetch() {
    ob_start();
    if (is_array($this->vars)) extract($this->vars);
    include($file);
    $contents = ob_get_contents();
    ob_end_clean();
    return $contents;
}

function set($name, $value) {
    $this->vars[$name] = is_object($value) ? $value->fetch() : $value;
}

用法:

$tpl    = & new Template('path/to/template');
$tpl->set('titel', $titel);

模板示例:

<h1><?=titel?></h1>
<p>Lorem ipsum...</p>

我的方法

  1. 从数据库中选择模板作为字符串
  2. 我得到的是$ tpl =“&lt; h1&gt;&lt; ?= $ titel?&gt; ...”;
  3. 现在我想把它传递给模板系统,所以我扩展了我的构造函数和获取函数:
  4. function fetch(){

    if (is_array($this->vars)) extract($this->vars);
    ob_start();
    if(is_file($file)){
        include($file);
    }else{
            //first idea: eval ($file);
        //second idea: print $file;
    }
    $contents = ob_get_contents();
    ob_end_clean();
    return $contents;
    }
    

    'eval'给了我一个Parsing异常,因为它将整个String解释为php,而不仅仅是php部分。 'print'真的很奇怪:它不会在两者之间打印,但我可以在页面的源代码中看到它。 php函数被忽略了。

    那我该怎么办呢?

3 个答案:

答案 0 :(得分:1)

也许不是最好的解决方案,但它很简单,应该可行:

  1. 从db
  2. 获取模板
  3. 使用模板
  4. 编写文件
  5. 包含此文件
  6. (可选:删除文件)
  7. 如果向模板表添加Timestamp列,则可以将文件系统用作缓存。只需比较文件和数据库的时间戳,以确定它是否足以重用该文件。

答案 1 :(得分:1)

如果您将'?>'添加到您的评估中,它应该有效。

<?php
$string = 'hello <?php echo $variable; ?>';
$variable = "world";
eval('?>' . $string);

但你应该知道eval()是一件相当慢的事情。其生成的操作码无法缓存在APC(或类似)中。您应该找到一种在磁盘上缓存模板的方法。对于其中一个,您不必在每次需要时将它们从数据库中提取出来。您可以使用常规的操作码缓存(由APC透明地完成)。

每当我看到一些半生不熟的本土“模板引擎”时,我都会问自己为什么作者不依赖现有的许多现有模板引擎之一?他们中的大多数已经解决了你可能遇到的大部分问题。 Smarty(以及Twig,phpTAL,...)使得从任何地方提取模板源(同时努力保持最佳性能)是一个真正的魅力。您是否有任何特殊原因不使用其中一种?

答案 2 :(得分:1)

我会做与tweber基本相同的事情,除了我更愿意依赖于本地文件时间戳而不是数据库。

这样的事情:每个文件的TTL(到期时间)可以说是60秒。真正的原因是为了避免太难/通常不必要地攻击数据库,您将很快意识到文件系统访问与网络和mysql相比有多快,特别是如果mysql实例在远程服务器上运行。

# implement a function that gets the contents of the file ( key here is the filename )
# from DB and saves them to disk.
function fectchFreshCopy( $filename ) {
    # mysql_connect(); ...
}


if (is_array($this->vars)) extract($this->vars);
ob_start();
# first check if the file exists already
if( file_exits($file) ) {
    # now check the timestamp of the files creation to know if it has expired:
    $mod_timestamp = filemtime( $file );
    if ( ( time() - $mod_timestamp ) >= 60 ) {
        # then the file has expired, lets fetch a fresh copy from DB
        # and save it to disk..
        fetchFreshCopy();
    }
}else{
    # the file doesnt exist at all, fetch and save it!
    fetchFreshCopy();
}

include( $file );
$contents = ob_get_contents();
ob_end_clean();
return $contents;
}

干杯,希望有用