2013-07-25 48 views
8

我在我的一個類方法中包含了一個文件,並且該文件具有html + php代碼。我在該代碼中返回一個字符串。我明確地寫道{{newsletter}},然後在我的方法,我做了以下內容:在php文件中替換{{string}}

$contactStr = include 'templates/contact.php'; 
$contactStr = str_replace("{{newsletter}}",$newsletterStr,$contactStr); 

但是,它不替換字符串。我這樣做的唯一原因是因爲當我嘗試將變量傳遞給包含的文件時,它似乎無法識別它。

$newsletterStr = 'some value'; 
$contactStr = include 'templates/contact.php'; 

那麼,我該如何實現字符串替換方法呢?

+0

貴'include'有'return'? –

+0

包含文件是否觸發頁面內部的返回?不要這麼想,你應該包含文件,然後調用返回字符串的函數。 – RelevantUsername

+0

@RelevantUsername [「可以在包含文件中執行return語句,以便終止該文件中的處理,並返回到調用它的腳本。此外,還可以從包含的文件中返回值。你可以使用正常函數。「](http://uk3.php.net/manual/en/function.include.php) – IMSoP

回答

28

您可以使用PHP作爲模板引擎。不需要{{newsletter}}構造。

假設您在模板文件中輸出變量$newsletter

// templates/contact.php 

<?php echo $newsletter; ?> 

要更換變量做到以下幾點:

$newsletter = 'Your content to replace'; 

ob_start();   
include('templates/contact.php'); 
$contactStr = ob_get_clean(); 

echo $contactStr; 

// $newsletter should be replaces by `Your content to replace` 

通過這種方式,你可以建立自己的模板引擎。

class Template 
{ 
    protected $_file; 
    protected $_data = array(); 

    public function __construct($file = null) 
    { 
     $this->_file = $file; 
    } 

    public function set($key, $value) 
    { 
     $this->_data[$key] = $value; 
     return $this; 
    } 

    public function render() 
    { 
     extract($this->_data); 
     ob_start(); 
     include($this->_file); 
     return ob_get_clean(); 
    } 
} 

// use it 
$template = new Template('templates/contact.php'); 
$template->set('newsletter', 'Your content to replace'); 
echo $template->render(); 

最好的事情是:你可以在你的模板中立即使用條件語句和循環(完整的PHP)。

+3

如果你想保護包含文件免受變量污染(*即'$ this' *),你可以將它封裝在反彈關閉中:'' call_user_func(Closure :: bind(function(){include func_get_arg(0);},null),$ path);' – Dan

+0

@Bracketworks好點..感謝。 – bitWorking

+0

也許我錯了,但據我瞭解這個例子,你只是用相同的值覆蓋你之前聲明的變量'$ newsletter'。 因爲你必須在之後回顯變量,所以這個例子對我來說似乎是無效的,相當於'$ x ='foo'; echo $ x;' –

0

不,不包括這個。 include正在執行php代碼。和它的返回值是值包含文件的回報 - 或者,如果沒有回報:1.

你想要的是file_get_contents()

// Here it is safe to use eval(), but it IS NOT a good practice. 
$contactStr = file_get_contents('templates/contact.php'); 
eval(str_replace("{{newsletter}}", $newsletterStr, $contactStr)); 
+1

使用'eval'是非常不安全的,在一些安裝中不允許。 – Gustav

+1

其實,我只是[閱讀文檔](http://uk3.php.net/manual/en/function.include.php);如果包含失敗(我不確定它爲什麼不是布爾值「true」,但這就是文檔所說的),則'include'語句的默認返回值是'1'或'false'。 – IMSoP

+1

@Gustav它和在這個上下文中包含一個文件一樣安全。你不是在用戶輸入。 (和eval不能用香草php禁用,它需要額外的擴展...) – bwoebi

12

這是我使用的模板代碼,應該竅門

if (preg_match_all("/{{(.*?)}}/", $template, $m)) { 
     foreach ($m[1] as $i => $varname) { 
     $template = str_replace($m[0][$i], sprintf('%s', $varname), $template); 
     } 
    } 
+0

您的意思是sprintf('$%s',$$ varname)? – crafter

+2

實際上它看起來應該是sprintf('%s',$$ varname) –

3

將output_buffers與PHP變量一起使用。它更安全,兼容和可重用。

function template($file, $vars=array()) { 
    if(file_exists($file)){ 
     // Make variables from the array easily accessible in the view 
     extract($vars); 
     // Start collecting output in a buffer 
     ob_start(); 
     require($file); 
     // Get the contents of the buffer 
     $applied_template = ob_get_contents(); 
     // Flush the buffer 
     ob_end_clean(); 
     return $applied_template; 
    } 
} 

$final_newsletter = template('letter.php', array('newsletter'=>'The letter...')); 
4

可能有點晚,但我看起來像這樣。

問題是,包括不返回文件內容,更簡單的解決方案可能是使用file_get_contents函數。

$template = file_get_contents('test.html', FILE_USE_INCLUDE_PATH); 

$page = str_replace("{{nombre}}","Alvaro",$template); 

echo $page; 
0

基於@噠炒作

<?php 
$template = "hello {{name}} world! {{abc}}\n"; 
$data = ['name' => 'php', 'abc' => 'asodhausdhasudh']; 

if (preg_match_all("/{{(.*?)}}/", $template, $m)) { 
    foreach ($m[1] as $i => $varname) { 
     $template = str_replace($m[0][$i], sprintf('%s', $data[$varname]), $template); 
    } 
} 


echo $template; 
?>