2016-01-24 53 views
4

這可能已經問過,但我無法找到答案,我有一些初步的搜索問題,所以在這裏它是:注入PHP變量轉換成HTML代碼

一個非常簡單的我目前的方法的例子注入PHP變量轉換成HTML如下:

HTML(file.php):

<tag><?php echo $variable; ?></tag> 

PHP:

$variable = "value"; 

ob_start(); 
include "file.php"; 
$results = ob_get_clean(); 

這實現了正確的結果,但它每次都需要複製並粘貼這三行代碼才能將變量注入到我的HTML文件中,這讓我很煩惱。我有可能想在以後更改此注入功能的詳細信息,目前它已分散在我的代碼中的幾百個位置。

在一個完美的世界中,我將這三行轉移到一個單獨的函數中,該函數將文件路徑作爲輸入,並返回「編譯」結果。但是,該函數將不再有權訪問調用作用域,並且必須將該變量作爲另一個輸入傳遞。我能想到的這樣做的唯一事情是:

function injectVariables($filePath, array $variables) 
{ 
    //Built-in PHP function, extracts array key => value pairs into variable $key = value pairs in the current scope 
    extract($variables); 

    ob_start(); 
    include $filePath; 
    return ob_get_clean(); 
} 

這肯定能夠完成任務,這將是我實現,如果沒有任何更好的解決方案,但似乎不足對我來說很理想。它涉及每次運行時創建一個數組,只是爲了遍歷它並提取所有變量,這對我來說只是感覺有點不對。

有沒有人知道任何其他可能工作的方法?

+0

它似乎工作得很好,沒有ob_start(); – Michael

+0

如果你忽略它,你會看到什麼? – Michael

+0

如果您直接回顯您的'ob_get_clean'調用(或等效地回顯結果變量),您將得到相同的結果。有或沒有'ob_start'調用,因爲包含該文件將直接輸出給用戶。但是,在我的項目中有很多地方需要將它們保存到一個變量中,而不是直接輸出(例如,將一個文件的結果注入另一個文件中)。 – MPLewis

回答

1

不能確定你所要求的,但這裏是我的回答

我不知道你的代碼的結構,但我希望你用的是MVC方法(或者至少東西哪些交易與類),以便您可以執行以下操作:

在您的主控制器中,您將創建一個類變量,如viewData這將是一個數組。你把它放在裏面你想要的東西

$this->viewData['username'] = $username; 
$this->viewData['myArray'] = array('foo' => 'bar'); 
$this->viewData['menuSubview'] = 'path_to_menu_subview.php'; 

然後,你創建一個渲染函數。

public function render() 
{ 
    extract($this->viewData); 
    ob_start(); 
    include("myfile.php"); 
    return ob_get_clean(); 
} 

而且在myfile.php(與HTML),你可以簡單地做你用什麼到目前爲止

<div id="menu"><?php include($menuSubview);?></div> 
<p><?=$username;?></p> 
<p><?=$myArray['foo'];?></p> 

整個代碼可以是這樣的。

class Something { 

    protected $viewData; 
    protected $viewFile; 

    public function logic() 
    { 
     $this->userProfile(); 
     echo $this->render(); 
    } 

    public function userProfile() 
    { 
     $this->viewData['username'] = 'John The Ripper'; 
     $this->viewFile = 'myFile.php'; 
    } 

    public function render() 
    { 
     extract($this->viewData); 
     ob_start(); 
     include($this->viewFile); 
     return ob_get_clean(); 
    } 
} 
+0

當您在對象中包含文件時,當前作用域被保留。您可以從模板文件中訪問'$ this-> viewData'而不用提取它。 –

+0

我正在使用MVC方法(我只是試圖將問題集中在一個特定的問題上,所以如果將來有人需要類似的東西,那麼問題不會被束縛在一起)。這個解決方案肯定會起作用,但它基本上等同於我發佈的初步解決方案,所以它不能完全回答我的問題。雖然謝謝! – MPLewis

+0

@MPLewis如果您使用的是MVC方法,那麼您需要在模板中顯示的任何內容都應該是您視圖的屬性(或方法)。如果您從該視圖中包含該文件,那麼您應該可以訪問所需的所有內容而無需提取任何內容。 –

1

下面是一個簡化的類,它存儲數據並允許遞歸渲染所有可從初始實例訪問保存數據的文件。

class View { 

    // view data 
    protected $_data = []; 

    /** 
    * Set view data 
    */ 
    public function __set($key, $value) 
    { 
     $this->_data[ $key ] = $value; 
    } 

    /** 
    * Get view data 
    */ 
    public function __get($key) 
    { 
     if(array_key_exists($key, $this->_data)) 
     { 
      return $this->_data[ $key ]; 
     } 
     return null; 
    } 

    /** 
    * Render view file 
    */ 
    public function render($file) 
    { 
     if(is_file($file)) 
     { 
      $view = $this; 
      ob_start(); 
      include($file); 
      return ob_get_clean(); 
     } 
     return 'File not found: '.$file; 
    } 
} 

只需使用變量$視圖中的包含文件內訪問類的數據,或使()另一部分文件,可以做同樣的事情,等等。

// Bootstrap a View instance and add some data 
$view = new View; 
$view->dataOne = 'valueOne'; 
$view->dataTwo = 'valueTwo'; 

// Render main template 
echo $view->render('template.php'); 

內的template.php

<header> 
    <?= $view->render('header.php') ?> 
</header> 

<h1><?= $view->dataOne ?></h1> 
<p><?= $view->dataTwo ?></p> 
1

沒有什麼不對您的injectVariables()功能,它實際上是一個好主意。

  • 你不應該對性能的影響呢(如果這是你的主要關注你在做過早的優化!)
  • 你的觀點(HTML)不應該知道的內部應用程序。 (拆分責任 - 這是我不會深談一個巨大的主題) 你知道,如果事情最終成$變量,它已經建立/格式化,或者是revelent是顯示爲$filePath
    在複雜的系統中,您最終可能會生成一個帶有pdf生成器的變量,爲什麼HTML需要這個變量? HTML的唯一目的是顯示HTML數據。

    從你的邏輯有些變量將結束-Up在$變量幾乎每一次諸如會話信息(目前已登錄),對於你的情況,這是正常的。

    在完美的世界裏,如果你把一個類爲$變量應該只爲哪怕是幾乎相同的對象作爲你的邏輯你的HTML的目的來設計。
    作爲一個例子,我在我的邏輯中設計了一個Session類。它確實有方法,如Logout()EnsureIsAlive()以及如FullName等字段。我的HTML將使用FullName,因爲我想將其顯示在我的頁面的標題中。
    我應該有一個只包含一個FullName場,因爲HTML只有一個工作,是它來顯示數據的HTML會話類。 Login()EnsureIsAlive()是邏輯專用的,與顯示數據完全不相關。 實際上,時間總是一個約束,因爲你從頭開始編寫所有的東西,所以最終可能只是將邏輯Session類發送到$變量中。

    • 設計筆記:我是一個C#程序員,我們總是用類在數組來傳遞參數作爲一個良好的初步實踐,它確實會影響如何通過FullName到你的HTML爲例。在你的情況,而不是創建一個專用於HTML類,你還可以創建一個簡單的數組:

      $variables['Session'] = array('FullName' => $mySession->fullName). 
      

    這樣,你還是避免你的HTML能夠訪問特定於您的邏輯無關的方法。我不知道這是否是在PHP良好的初步實踐...

  • 保持上下文變量乾淨
    如果你調用injectVariables()一次以上(對於不同$PathFile),你可能不希望相同的變量。
    一個injectionVariables()可能是一個小部件,另一個是一個完整的完整的頁面。
    爲什麼TimeWidget需要您的totalInvoice變量?

    您還可以在同一時間準備倍數$變量,因爲每個injectVariables()都會有他自己的參數的能力。

我沒有達到最新的,但我知道phpBB的模板系統使用(回近2000年)完全相同的圖案,你injectVariables())。

你寫過你的每個頁面都叫injectVariables(),你也可以(但可能很複雜)只在一個文件中做 - 比如php frameworks

框架處理HTTP請求到一個特定的文件
(如:http://yoursite.com/hello/worldhttp://yoursite.com/login會致電(internaly)http://yoursite.com/index.php?page=hello&subpage=worldhttp://yoursite.com?page=login)。
然後這個頁面(在我的例子中是index.php)會根據他的GET參數($_GET['page']$_GET['subpage'])包含一個特定的文件(控制器)。
控制器作業將獲取數據,應用邏輯然後填充$變量。
然後index.php將調用injectVariables()與相關的HTML。