【发布时间】:2010-01-17 13:10:58
【问题描述】:
我正在为我自己的项目编写一个基本的模板类。基本用法是这样的:
$template = new Template('template_file.php');
$template->assignVariable('pageTitle', 'Home page');
$template->render();
'template_file.php'的内容:
<?php print $pageTitle; ?>
这是模板类一步一步做的:
- 在调用 assignVariable 方法时将变量存储在私有数组中
- 调用渲染方法时,提取存储的变量,将模板文件包含在
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;
【问题讨论】:
标签: php unit-testing