2010-01-17 173 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