2010-01-17 175 views
0

我正在为自己的项目编写基本模板类。基本用法是这样的:如何模拟模板类

$template = new Template('template_file.php'); 
$template->assignVariable('pageTitle', 'Home page'); 
$template->render(); 

'template_file.php' 的内容:

<?php print $pageTitle; ?> 

这一步什么模板类确实步:在私人阵列

  1. 房屋变量当调用assignVariable方法时
  2. 当调用render方法时,提取存储的变量,包含模板文件ob_start()ob_end_clean()块。将输出存储在变量ob_get_contents()中,然后打印存储的输出。

我知道这是一个非常简单的模板类,但按预期工作。问题是我应该将包含模板文件委托给另一个类?我在为这堂课写单元测试时遇到了这个问题。我认为应该封装文件系统交互。你怎么看?如果你认为它不应该,我怎么可以在我的测试中包含一个文件?

也许我只是通过模板文件的内容到类像这样:

$templateContent = file_get_contents('template_file.php'); 
$template = new Template($templateContent); 
... 

编辑:我决定来封装模板类的输入过程,写出更好的单元测试的缘故和封装。但正如johannes指出的那样,我需要使用eval()来达到这个目的,这看起来并不正确。 Johannes向我指出了在单元测试中嘲笑包含的流式封装的方向。但是这给我一个新想法。这是我要做的事情;我将继续在我的模板类中使用include(),但这次使用流封装。初始化时,我会将协议处理程序传递给我的模板类。通过这种方式,我可以创建自己的流封装以从数据库获取模板数据或使用局部变量。以下是示例:

$template = new Template('file://template_file.php'); 

stream_wrapper_register('database', 'My_Database_Stream'); 
$template = new Template('database://templates/3'); // templates table, row id 3 

stream_wrapper_register('var', 'My_Var_Stream'); 
$myTemplate = '<?php print "Hello world!"; ?>'; 
$template = new Template('var://myTemplate'); 

我已经为本地变量实现了自定义流包装。那就是:

class My_Var 
{ 
    protected $position; 
    protected $variable; 
    function stream_open($path, $mode, $options, &$openedPath) { 
     $url = parse_url($path); 
     global $$url['host']; 
     $this->variable = $$url['host']; 
     $this->position = 0; 

     return true; 
    } 
    public function stream_read($count) { 
     $ret = substr($this->variable, $this->position, $count); 
     $this->position = strlen($ret); 
     return $ret; 
    } 
    public function stream_eof() { 
     return $this->position >= strlen($this->variable); 
    } 
} 


stream_wrapper_register('var', 'My_Var'); 
$myvar = '<?php print "mert"; ?>'; 
include 'var://myvar'; 
exit; 

回答

0

使用的file_get_contents传递()的内容和这样的,你必须使用eval()执行这是坏的多种方式。其中最重要的一点是操作码缓存不能缓存文件。做一个include('template_file.php');让我们APC或其他人缓存编译的脚本。无论EVAL VS使用包括,回答你的问题的万恶之

+0

是的,但是当使用include函数时,我需要一个虚拟模板文件在我的测试文件夹中。我也不应该只测试模板类吗?另外我将如何模拟包含功能? – matte 2010-01-17 13:19:01

+0

您可以使用自定义流包装器或数据提供程序来发送模拟数据。 http://php.net/stream_wrapper_register http://php.net/manual/en/wrappers.data.php – johannes 2010-01-17 13:44:36

+0

嗨Johannes,谢谢!你为我启发了一个新想法。我编辑了这个问题,并添加了我提出的解决方案。 – matte 2010-01-17 18:40:47

0

,我不得不同意,并使用一个单独的类来封装解决方案的I/O方面。

虽然这似乎有点小题大做(因为这将是在大多数情况下),这可能是唯一明智的方式提供控制/依赖注入的,你是以后的隔离。

0

的问题是,我应该委托包括模板文件到另一个类?

的问题是,为什么不呢?

+0

也许矫枉过正? – matte 2010-01-17 17:46:44

+0

只有“矫枉过正”是你的单元测试答案。 ;) – 2010-01-17 18:45:49

+0

不是过度的课程。我想出了一个完全封装我的模板类的解决方案。我已经将解决​​方案添加到了我的问题中。 – matte 2010-01-17 18:45:57

1

我一直很喜欢这个家伙的办法:

http://www.massassi.com/php/articles/template_engines/

此方法采用的是PHP已经开始为模板引擎的事实。 (作者还指出,在PHP中编写一个臃肿的模板引擎是愚蠢的,因为它实际上本身就是一个模板引擎。)它可能不会直接回答你的问题,但也许它可以帮助你。

+0

我的模板类与他非常相似,实际上是相同的。但我的问题是,我应该封装包括文件?如果我需要解析从db中获取的文本,该怎么办? – matte 2010-01-17 17:45:27

+0

上述链接中描述的方法与Zend Framework中处理视图脚本的方式并不相距数百万英里。视图脚本位于父视图对象的上下文中,允许您调用(然后通常代理插件)到辅助方法。例如,如果您需要转义(例如,您可以执行<?php echo $ this-> escape($ this-> var);),这会很有帮助。 – berty 2010-01-17 18:49:28